
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick.Scene3D 2.14
import Qt3D.Core 2.14
import Qt3D.Render 2.14
import Qt3D.Input 2.14
import Qt3D.Extras 2.14


Entity {
    property var win_amd_card: config.IsWinGpuAmdCard()
    
    id: lasers
    property bool visible: true
    Entity {
        id: laserPoints
        Material {
            id: laserPointsMaterial
            property real pointSize: 3.0 + pointxyziMaterial.pointSize
            effect: Effect {
                id: laserPointsEffect
                parameters: [
                    Parameter { name: "xyz"; value: Qt.vector3d( 0.0, 0.0, 0.0) },
                    Parameter { name: "i"; value: 1.0 },
                    Parameter { name: "color_mode"; value: 0 },
                    Parameter { name: "max_distance"; value: 500.0 },
                    Parameter { name: "color_bound"; value: pointxyziMaterial.colorBound },
                    Parameter { name: "brightness"; value: pointxyziMaterial.brightness },
                    Parameter { name: "point_size"; value: pointxyziMaterial.pointSize },
                    Parameter { name: "color_list[0]"; value: pointxyziMaterial.colorlist},
                    Parameter { name: "trans_list[0]"; value: pointxyziMaterial.translist},
                    Parameter { name: "position_list[0]"; value: pointxyziMaterial.positionlist},
                    Parameter { name: "color_rate_bias"; value: pointxyziMaterial.colorrate},
                    Parameter { name: "below_color"; value: pointxyziMaterial.belowrangeColor},
                    Parameter { name: "above_color"; value: pointxyziMaterial.aboverangeColor},
                    Parameter { name: "point_length"; value: pointxyziMaterial.pointlength}
                ]
                techniques: [
                    Technique {
                        graphicsApiFilter {
                            api: GraphicsApiFilter.OpenGL
                            profile: GraphicsApiFilter.CoreProfile
                            majorVersion: 3
                            minorVersion: 0
                        }
                        filterKeys: [ FilterKey { name: "renderingStyle"; value: "forward" } ]
                        renderPasses: [
                            RenderPass {
                                shaderProgram: ShaderProgram {
                                    vertexShaderCode:  loadSource((win_amd_card) ? "file:glsl/point.vert" : "file:glsl/pointxyzi.vert")
                                    geometryShaderCode: { 
                                        if (win_amd_card) 
                                            return loadSource("file:glsl/point.geom") 
                                        else 
                                            return null
                                    }
                                    fragmentShaderCode: loadSource(pointxyziMaterial.colorMap) + loadSource((win_amd_card) ? "file:glsl/point.frag" : "file:glsl/pointxyzi.frag")
                                }
                                renderStates: [
                                    DepthTest { depthFunction: DepthTest.Less },
                                    PointSize {
                                        sizeMode: PointSize.Fixed
                                        value: laserPointsMaterial.pointSize
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        }
        GeometryRenderer {
            id: laserPointsGeometry
            primitiveType: GeometryRenderer.Points
            geometry: Geometry {
                boundingVolumePositionAttribute: laserPointsXYZ
                attributes: [
                    Attribute {
                        id: laserPointsXYZ
                        attributeType: Attribute.VertexAttribute
                        vertexBaseType: Attribute.Float
                        vertexSize: 3
                        count: modelData.laserCount
                        byteOffset: 0
                        byteStride: 4 * 4 // 1 vertex (=3 coordinates) * sizeof(float)
                        name: "xyz"
                        buffer: laserVertexBuffer
                    },
                    Attribute {
                        id: laserPointsI
                        attributeType: Attribute.VertexAttribute
                        vertexBaseType: Attribute.Float
                        vertexSize: 1
                        count: modelData.laserCount
                        byteOffset: 3 * 4
                        byteStride: 4 * 4 // 1 vertex (=3 coordinates) * sizeof(float)
                        name: "i"
                        buffer: laserVertexBuffer
                    }
                ]
            }
            Buffer {
                id: laserVertexBuffer
                type: Buffer.VertexBuffer
                data: {
                    gc()
                    return modelData.laserPoints
                }
            }
        }
        components: lasers.visible ? [laserPointsMaterial, laserPointsGeometry] : []
    }
    Entity {
        id: laserLines
        LineMaterial {
            id: line_material
        }
        PhongAlphaMaterial  {
            id: phong_alpha_material
            alpha: 0.5
            ambient: 'gray'
        }
        GeometryRenderer {
            id: laserLinesGeometry
            primitiveType: GeometryRenderer.Lines
            geometry: Geometry {
                boundingVolumePositionAttribute: laserLinesPosition
                attributes: [
                    Attribute {
                        id:  laserLinesPosition
                        attributeType: Attribute.VertexAttribute
                        vertexBaseType: Attribute.Float
                        vertexSize: 3
                        count: 1 + modelData.laserCount
                        byteOffset: 0
                        byteStride: 3 * 4
                        name: defaultPositionAttributeName
                        buffer: laserLinesVertexBuffer
                    },
                    Attribute {
                        attributeType: Attribute.IndexAttribute
                        vertexBaseType: Attribute.UnsignedInt
                        vertexSize: 1
                        count: 2 * modelData.laserCount
                        byteOffset: 0
                        byteStride: 1 * 4
                        buffer: laserLinesIndexBuffer
                    }
                ]
            }
            Buffer {
                id: laserLinesVertexBuffer
                type: Buffer.VertexBuffer
                data: {
                    gc()
                    var vertexes = new Float32Array(3*(modelData.laserCount+1))
                    vertexes[0] = vertexes[1] = vertexes[2] = 0.0
                    var laserPoints = new Float32Array(modelData.laserPoints)
                    for (var i = 0; i < modelData.laserCount; i++) {
                        vertexes[3*(i+1)+0] = laserPoints[4*i+0]
                        vertexes[3*(i+1)+1] = laserPoints[4*i+1]
                        vertexes[3*(i+1)+2] = laserPoints[4*i+2]
                    }
                    return vertexes
                }
            }
            Buffer {
                id: laserLinesIndexBuffer
                type: Buffer.IndexBuffer
                data: {
                    var indexes = new Uint32Array(2 * modelData.laserCount);
                    for (var i = 0; i < modelData.laserCount; i++) {
                        indexes[2*i] = 0
                        indexes[2*i+1] = i+1
                    }
                    return indexes
                }
            }
        }
        components: lasers.visible ? [config.IsWinGpuAmdCard()?line_material:phong_alpha_material, laserLinesGeometry] : []
    }
}