Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[Example] Falling Textured Cubes. Panda3D Bullet Physics Wrapper. PyQt5 (PySide2) + Bullet + OpenGL 3.3



  • I tried to use PyBullet but it is very complicated and I cannot understand haw to use it with OpenGL. The Panda3D Bullet wrapper is only one way that I found. And there is a very great manual: https://docs.panda3d.org/1.10/python/programming/physics/bullet/index I hope I will not have unresolved problems with using the Panda3D Bullet wrapper with Qt and OpenGL.

    I use:

    • the Panda3D Bullet wrapper for Physics
    • PyQt5 (and PySide2) for creating a window
    • OpenGL 3.3 for rendering

    I created a textured cube with Blender and GIMP. I exported the cube to dae (COLLADA) and imported it to my program with built-in Qt XML parser.

    Source:

    textured_cubes_bullet_pyqt5.gif

    PyQt5:

    import sys
    import numpy as np
    from OpenGL import GL as gl
    from PyQt5.QtWidgets import QApplication, QOpenGLWidget
    from PyQt5.QtGui import QOpenGLShaderProgram, QOpenGLShader, QOpenGLBuffer
    from PyQt5.QtGui import QOpenGLTexture, QImage
    from PyQt5.QtGui import QMatrix4x4, QVector3D, QQuaternion
    from PyQt5.QtXml import QDomDocument, QDomElement
    from PyQt5.QtCore import Qt, QFile, QIODevice
    from PyQt5.QtCore import QTimer, QElapsedTimer
    
    from panda3d.bullet import BulletWorld
    from panda3d.core import TransformState, Vec3, Quat, Point3
    from panda3d.bullet import BulletBoxShape
    from panda3d.bullet import BulletRigidBodyNode
    
    # Assets:
    # Cube Texture: https://dl.dropboxusercontent.com/s/tply9ubx3n3ycvv/cube.png
    # Cube Model: https://dl.dropboxusercontent.com/s/0aktc37c3nx9iq3/cube.dae
    # Plane Texture: https://dl.dropboxusercontent.com/s/3iibsnvyw0vupby/plane.png
    # Plane Model: https://dl.dropboxusercontent.com/s/e0wktg69ec3w8pq/plane.dae
    
    class VertexBuffers:
        vertex_pos_buffer = None
        normal_buffer = None
        tex_coord_buffer = None
        amount_of_vertices = None
    
    class Locations:
        mvp_matrix_location = None
        model_matrix_location = None
        normal_matrix_location = None
    
    class Object3D:
        position = QVector3D(0, 0, 0)
        rotation = QVector3D(0, 0, 0)
        scale = QVector3D(1, 1, 1)
        mvp_matrix = QMatrix4x4()
        model_matrix = QMatrix4x4()
        normal_matrix = QMatrix4x4()
    
        def __init__(self, vert_buffers, locations, texture, world, mass, pos):
            self.vert_pos_buffer = vert_buffers.vert_pos_buffer
            self.normal_buffer = vert_buffers.normal_buffer
            self.tex_coord_buffer = vert_buffers.tex_coord_buffer
            self.amount_of_vertices = vert_buffers.amount_of_vertices
            
            self.mvp_matrix_location = locations.mvp_matrix_location
            self.model_matrix_location = locations.model_matrix_location
            self.normal_matrix_location = locations.normal_matrix_location
            
            self.texture = texture
    
            self.shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))
            self.node = BulletRigidBodyNode('Box')
    
            self.position = pos
            self.mass = mass
            self.node.setMass(self.mass)
    
            p = Point3(self.position.x(), self.position.y(), self.position.z())
            q = Quat.identQuat()
            s = Vec3(1, 1, 1)
    
            self.transform = TransformState.make_pos_quat_scale(p, q, s)
            self.node.setTransform(self.transform)
    
            self.node.addShape(self.shape)
            self.world = world
            self.world.attachRigidBody(self.node)
    
        def draw(self, program, proj_view_matrix):
            program.bind()
    
            self.vert_pos_buffer.bind()
            program.setAttributeBuffer(0, gl.GL_FLOAT, 0, 3)
            program.enableAttributeArray(0)
    
            self.normal_buffer.bind()
            program.setAttributeBuffer(1, gl.GL_FLOAT, 0, 3)
            program.enableAttributeArray(1)
    
            self.tex_coord_buffer.bind()
            program.setAttributeBuffer(2, gl.GL_FLOAT, 0, 2)
            program.enableAttributeArray(2)
    
            self.position.setX(self.node.getTransform().pos.x)
            self.position.setY(self.node.getTransform().pos.y)
            self.position.setZ(self.node.getTransform().pos.z)
            hpr = self.node.getTransform().getHpr()
            pandaQuat = Quat()
            pandaQuat.setHpr(hpr)
            quat = QQuaternion(pandaQuat.getX(), pandaQuat.getY(), pandaQuat.getZ(), pandaQuat.getW())
            
            self.model_matrix.setToIdentity()
            self.model_matrix.translate(self.position)
            self.model_matrix.rotate(quat)
            self.model_matrix.scale(self.scale)
            self.mvp_matrix = proj_view_matrix * self.model_matrix
            
            self.normal_matrix = self.model_matrix.inverted()
            self.normal_matrix = self.normal_matrix[0].transposed()
            
            program.bind()
            program.setUniformValue(self.mvp_matrix_location, self.mvp_matrix)
            program.setUniformValue(self.model_matrix_location, self.model_matrix)
            program.setUniformValue(self.normal_matrix_location, self.normal_matrix)
            
            self.texture.bind()
    
            gl.glDrawArrays(gl.GL_TRIANGLES, 0, self.amount_of_vertices)
    
    class Window(QOpenGLWidget):
    
        def __init__(self):
            super().__init__()
            self.setWindowTitle("Bullet Physics")
            self.resize(268, 268)
    
        def initializeGL(self):
            gl.glClearColor(0.2, 0.2, 0.2, 1)
            gl.glEnable(gl.GL_DEPTH_TEST)
            vertShaderSrc = """
                #version 330 core
    
                in vec4 aPosition;
                in vec4 aNormal;
                in vec2 aTexCoord;
    
                uniform mat4 uMvpMatrix;
                uniform mat4 uModelMatrix;
                uniform mat4 uNormalMatrix;
    
                out vec3 vPosition;
                out vec3 vNormal;
                out vec2 vTexCoord;
    
                void main()
                {
                    gl_Position = uMvpMatrix * aPosition;
                    vPosition = vec3(uModelMatrix * aPosition);
                    vNormal = normalize(vec3(uNormalMatrix * aNormal));
                    vTexCoord = aTexCoord;
                }
            """
            fragShaderSrc = """
                #version 330 core
    
                const vec3 lightColor = vec3(0.8, 0.8, 0.8);
                const vec3 lightPosition = vec3(5.0, 7.0, 2.0);
                const vec3 ambientLight = vec3(0.3, 0.3, 0.3);
    
                uniform sampler2D uSampler;
    
                in vec3 vPosition;
                in vec3 vNormal;
                in vec2 vTexCoord;
    
                void main()
                {
                    vec4 color = texture2D(uSampler, vTexCoord);
                    vec3 normal = normalize(vNormal);
                    vec3 lightDirection = normalize(lightPosition - vPosition);
                    float nDotL = max(dot(lightDirection, normal), 0.0);
                    vec3 diffuse = lightColor * color.rgb * nDotL;
                    vec3 ambient = ambientLight * color.rgb;
                    gl_FragColor = vec4(diffuse + ambient, color.a);
                }
            """
            self.program = QOpenGLShaderProgram()
            self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, vertShaderSrc)
            self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, fragShaderSrc)
            self.program.link()
            self.program.bind()
            self.program.bindAttributeLocation("aPosition", 0)
            self.program.bindAttributeLocation("aNormal", 1)
            self.program.bindAttributeLocation("aTexCoord", 2)
            locations = Locations()
            self.program.bind()
            locations.mvp_matrix_location = self.program.uniformLocation("uMvpMatrix")
            locations.model_matrix_location = self.program.uniformLocation("uModelMatrix")
            locations.normal_matrix_location = self.program.uniformLocation("uNormalMatrix")
            self.vert_buffers = self.initVertexBuffers("assets/cube.dae")
            self.proj_view_matrix = QMatrix4x4()
            self.proj_matrix = QMatrix4x4()
            self.view_matrix = QMatrix4x4()
            self.view_matrix.lookAt(
                QVector3D(2, 3, 5),
                QVector3D(0, 0, 0),
                QVector3D(0, 1, 0))
            
            self.texture = QOpenGLTexture(QOpenGLTexture.Target2D)
            self.texture.create()
            self.texture.setData(QImage("assets/cube.png"))
            self.texture.setMinMagFilters(QOpenGLTexture.Linear, QOpenGLTexture.Linear)
            self.texture.setWrapMode(QOpenGLTexture.ClampToEdge)
    
            self.world = BulletWorld()
            self.world.setGravity(Vec3(0, -9.81, 0))
    
            self.obj = Object3D(self.vert_buffers, locations, self.texture, self.world, mass=0, pos=QVector3D(0, -3, 0))
            self.obj2 = Object3D(self.vert_buffers, locations, self.texture, self.world, mass=1, pos=QVector3D(0.8, 3, 0))
            
            #self.move_dir = 1 # move direction: 1 - up, -1 - down
            #self.move_speed = 0.002
            
            self.timer = QTimer()
            self.timer.timeout.connect(self.animationLoop)
            self.elapsed_timer = QElapsedTimer()
            self.elapsed_timer.start()
            self.delta_time = 0
            self.timer.start(1000/60)
            
        def animationLoop(self):
            self.delta_time = self.elapsed_timer.elapsed()
            self.elapsed_timer.restart()
            self.world.doPhysics(self.delta_time / 1000)
            self.update()
            
        def paintGL(self):
            gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
            self.proj_view_matrix = self.proj_matrix * self.view_matrix
            self.obj.draw(self.program, self.proj_view_matrix)
            self.obj2.draw(self.program, self.proj_view_matrix)
    
        def resizeGL(self, w, h):
            gl.glViewport(0, 0, w, h)
            self.proj_matrix.setToIdentity()
            self.proj_matrix.perspective(50, float(w) / float(h), 0.1, 100)
            
        def initVertexBuffers(self, path):
            xml_doc = QDomDocument()
            file = QFile(path)
            if not file.open(QIODevice.ReadOnly):
                print("Failed to open the file: " + path)
            xml_doc.setContent(file)
            file.close()
            
            vert_pos_array = []
            normal_array = []
            tex_coord_array = []
            index_array = []
            
            root = xml_doc.documentElement()
            dae_elem = root.firstChildElement()
            while not dae_elem.isNull():
                if dae_elem.tagName() == "library_geometries":
                    geom_elem = dae_elem.firstChildElement()
                    if geom_elem.tagName() == "geometry":
                        mesh_elem = geom_elem.firstChildElement()
                        if mesh_elem.tagName() == "mesh":
                            mesh_child_elem = mesh_elem.firstChildElement()
                            while not mesh_child_elem.isNull():
                                float_array_elem = mesh_child_elem.firstChildElement()
                                str_array = float_array_elem.firstChild().toText().data().split(" ")
                                if mesh_child_elem.attribute("id").endswith("-mesh-positions"):
                                    vert_pos_array = list(map(float, str_array))
                                if mesh_child_elem.attribute("id").endswith("-mesh-normals"):
                                    normal_array = list(map(float, str_array))
                                if mesh_child_elem.attribute("id").endswith("-mesh-map-0"):
                                    tex_coord_array = list(map(float, str_array))
                                if mesh_child_elem.tagName() == "triangles" or mesh_child_elem.tagName() == "polylist":
                                    p_child_elem = mesh_child_elem.firstChildElement()
                                    while not p_child_elem.isNull():
                                        if p_child_elem.tagName() == "p":
                                            str_indices = p_child_elem.firstChild().toText().data().split(" ")
                                            index_array = list(map(int, str_indices))
                                        p_child_elem = p_child_elem.nextSiblingElement()
                                mesh_child_elem = mesh_child_elem.nextSiblingElement()
                dae_elem = dae_elem.nextSiblingElement()
            # print(vert_pos_array)
            # print(normal_array)
            # print(tex_coord_array)
            # print(index_array)
            
            num_of_attributes = 3
            vert_positions = []
            normals = []
            tex_coords = []
            for i in range(0, len(index_array), num_of_attributes):
                vert_pos_index = index_array[i + 0]
                vert_positions.append(vert_pos_array[vert_pos_index * 3 + 0])
                vert_positions.append(vert_pos_array[vert_pos_index * 3 + 1])
                vert_positions.append(vert_pos_array[vert_pos_index * 3 + 2])
                
                normal_index = index_array[i + 1]
                normals.append(normal_array[normal_index * 3 + 0])
                normals.append(normal_array[normal_index * 3 + 1])
                normals.append(normal_array[normal_index * 3 + 2])
                
                tex_coord_index = index_array[i + 2]
                tex_coords.append(tex_coord_array[tex_coord_index * 2 + 0])
                tex_coords.append(tex_coord_array[tex_coord_index * 2 + 1])
            # print(vert_positions)
            # print(normals)
            # print(tex_coords)
            
            output = {}
    
            vert_positions = np.array(vert_positions, dtype=np.float32)
            vert_pos_buffer = QOpenGLBuffer()
            vert_pos_buffer.create()
            vert_pos_buffer.bind()
            vert_pos_buffer.allocate(vert_positions, len(vert_positions) * 4)
            
            normals = np.array(normals, dtype=np.float32)
            normal_buffer = QOpenGLBuffer()
            normal_buffer.create()
            normal_buffer.bind()
            normal_buffer.allocate(normals, len(normals) * 4)
            
            tex_coords = np.array(tex_coords, dtype=np.float32)
            tex_coord_buffer = QOpenGLBuffer()
            tex_coord_buffer.create()
            tex_coord_buffer.bind()
            tex_coord_buffer.allocate(tex_coords, len(tex_coords) * 4)
    
            vert_buffers = VertexBuffers()
            vert_buffers.vert_pos_buffer = vert_pos_buffer
            vert_buffers.normal_buffer = normal_buffer
            vert_buffers.tex_coord_buffer = tex_coord_buffer
            vert_buffers.amount_of_vertices = int(len(index_array) / 3)
            
            return vert_buffers
    
    def main():
        QApplication.setAttribute(Qt.AA_UseDesktopOpenGL)
        app = QApplication(sys.argv)
        w = Window()
        w.show()
        sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main()
    

    PySide2:

    import sys
    import numpy as np
    from OpenGL import GL as gl
    from PySide2.QtWidgets import QApplication, QOpenGLWidget
    from PySide2.QtGui import QOpenGLShaderProgram, QOpenGLShader, QOpenGLBuffer
    from PySide2.QtGui import QOpenGLTexture, QImage
    from PySide2.QtGui import QMatrix4x4, QVector3D, QQuaternion
    from PySide2.QtXml import QDomDocument, QDomElement
    from PySide2.QtCore import Qt, QFile, QIODevice
    from PySide2.QtCore import QTimer, QElapsedTimer
    
    from panda3d.bullet import BulletWorld
    from panda3d.core import TransformState, Vec3, Quat, Point3
    from panda3d.bullet import BulletBoxShape
    from panda3d.bullet import BulletRigidBodyNode
    
    # Assets:
    # Cube Texture: https://dl.dropboxusercontent.com/s/tply9ubx3n3ycvv/cube.png
    # Cube Model: https://dl.dropboxusercontent.com/s/0aktc37c3nx9iq3/cube.dae
    # Plane Texture: https://dl.dropboxusercontent.com/s/3iibsnvyw0vupby/plane.png
    # Plane Model: https://dl.dropboxusercontent.com/s/e0wktg69ec3w8pq/plane.dae
    
    class VertexBuffers:
        vertex_pos_buffer = None
        normal_buffer = None
        tex_coord_buffer = None
        amount_of_vertices = None
    
    class Locations:
        mvp_matrix_location = None
        model_matrix_location = None
        normal_matrix_location = None
    
    class Object3D:
        position = QVector3D(0, 0, 0)
        rotation = QVector3D(0, 0, 0)
        scale = QVector3D(1, 1, 1)
        mvp_matrix = QMatrix4x4()
        model_matrix = QMatrix4x4()
        normal_matrix = QMatrix4x4()
    
        def __init__(self, vert_buffers, locations, texture, world, mass, pos):
            self.vert_pos_buffer = vert_buffers.vert_pos_buffer
            self.normal_buffer = vert_buffers.normal_buffer
            self.tex_coord_buffer = vert_buffers.tex_coord_buffer
            self.amount_of_vertices = vert_buffers.amount_of_vertices
            
            self.mvp_matrix_location = locations.mvp_matrix_location
            self.model_matrix_location = locations.model_matrix_location
            self.normal_matrix_location = locations.normal_matrix_location
            
            self.texture = texture
    
            self.shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))
            self.node = BulletRigidBodyNode('Box')
    
            self.position = pos
            self.mass = mass
            self.node.setMass(self.mass)
    
            p = Point3(self.position.x(), self.position.y(), self.position.z())
            q = Quat.identQuat()
            s = Vec3(1, 1, 1)
    
            self.transform = TransformState.make_pos_quat_scale(p, q, s)
            self.node.setTransform(self.transform)
    
            self.node.addShape(self.shape)
            self.world = world
            self.world.attachRigidBody(self.node)
    
        def draw(self, program, proj_view_matrix):
            program.bind()
    
            self.vert_pos_buffer.bind()
            program.setAttributeBuffer(0, gl.GL_FLOAT, 0, 3)
            program.enableAttributeArray(0)
    
            self.normal_buffer.bind()
            program.setAttributeBuffer(1, gl.GL_FLOAT, 0, 3)
            program.enableAttributeArray(1)
    
            self.tex_coord_buffer.bind()
            program.setAttributeBuffer(2, gl.GL_FLOAT, 0, 2)
            program.enableAttributeArray(2)
    
            self.position.setX(self.node.getTransform().pos.x)
            self.position.setY(self.node.getTransform().pos.y)
            self.position.setZ(self.node.getTransform().pos.z)
            hpr = self.node.getTransform().getHpr()
            pandaQuat = Quat()
            pandaQuat.setHpr(hpr)
            quat = QQuaternion(pandaQuat.getX(), pandaQuat.getY(), pandaQuat.getZ(), pandaQuat.getW())
            
            self.model_matrix.setToIdentity()
            self.model_matrix.translate(self.position)
            self.model_matrix.rotate(quat)
            self.model_matrix.scale(self.scale)
            self.mvp_matrix = proj_view_matrix * self.model_matrix
            
            self.normal_matrix = self.model_matrix.inverted()
            self.normal_matrix = self.normal_matrix[0].transposed()
            
            program.bind()
            program.setUniformValue(self.mvp_matrix_location, self.mvp_matrix)
            program.setUniformValue(self.model_matrix_location, self.model_matrix)
            program.setUniformValue(self.normal_matrix_location, self.normal_matrix)
            
            self.texture.bind()
    
            gl.glDrawArrays(gl.GL_TRIANGLES, 0, self.amount_of_vertices)
    
    class Window(QOpenGLWidget):
    
        def __init__(self):
            super().__init__()
            self.setWindowTitle("Bullet Physics")
            self.resize(268, 268)
    
        def initializeGL(self):
            gl.glClearColor(0.2, 0.2, 0.2, 1)
            gl.glEnable(gl.GL_DEPTH_TEST)
            vertShaderSrc = """
                #version 330 core
    
                in vec4 aPosition;
                in vec4 aNormal;
                in vec2 aTexCoord;
    
                uniform mat4 uMvpMatrix;
                uniform mat4 uModelMatrix;
                uniform mat4 uNormalMatrix;
    
                out vec3 vPosition;
                out vec3 vNormal;
                out vec2 vTexCoord;
    
                void main()
                {
                    gl_Position = uMvpMatrix * aPosition;
                    vPosition = vec3(uModelMatrix * aPosition);
                    vNormal = normalize(vec3(uNormalMatrix * aNormal));
                    vTexCoord = aTexCoord;
                }
            """
            fragShaderSrc = """
                #version 330 core
    
                const vec3 lightColor = vec3(0.8, 0.8, 0.8);
                const vec3 lightPosition = vec3(5.0, 7.0, 2.0);
                const vec3 ambientLight = vec3(0.3, 0.3, 0.3);
    
                uniform sampler2D uSampler;
    
                in vec3 vPosition;
                in vec3 vNormal;
                in vec2 vTexCoord;
    
                void main()
                {
                    vec4 color = texture2D(uSampler, vTexCoord);
                    vec3 normal = normalize(vNormal);
                    vec3 lightDirection = normalize(lightPosition - vPosition);
                    float nDotL = max(dot(lightDirection, normal), 0.0);
                    vec3 diffuse = lightColor * color.rgb * nDotL;
                    vec3 ambient = ambientLight * color.rgb;
                    gl_FragColor = vec4(diffuse + ambient, color.a);
                }
            """
            self.program = QOpenGLShaderProgram()
            self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, vertShaderSrc)
            self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, fragShaderSrc)
            self.program.link()
            self.program.bind()
            self.program.bindAttributeLocation("aPosition", 0)
            self.program.bindAttributeLocation("aNormal", 1)
            self.program.bindAttributeLocation("aTexCoord", 2)
            locations = Locations()
            self.program.bind()
            locations.mvp_matrix_location = self.program.uniformLocation("uMvpMatrix")
            locations.model_matrix_location = self.program.uniformLocation("uModelMatrix")
            locations.normal_matrix_location = self.program.uniformLocation("uNormalMatrix")
            self.vert_buffers = self.initVertexBuffers("assets/cube.dae")
            self.proj_view_matrix = QMatrix4x4()
            self.proj_matrix = QMatrix4x4()
            self.view_matrix = QMatrix4x4()
            self.view_matrix.lookAt(
                QVector3D(2, 3, 5),
                QVector3D(0, 0, 0),
                QVector3D(0, 1, 0))
            
            self.texture = QOpenGLTexture(QOpenGLTexture.Target2D)
            self.texture.create()
            self.texture.setData(QImage("assets/cube.png"))
            self.texture.setMinMagFilters(QOpenGLTexture.Linear, QOpenGLTexture.Linear)
            self.texture.setWrapMode(QOpenGLTexture.ClampToEdge)
    
            self.world = BulletWorld()
            self.world.setGravity(Vec3(0, -9.81, 0))
    
            self.obj = Object3D(self.vert_buffers, locations, self.texture, self.world, mass=0, pos=QVector3D(0, -3, 0))
            self.obj2 = Object3D(self.vert_buffers, locations, self.texture, self.world, mass=1, pos=QVector3D(0.8, 3, 0))
            
            #self.move_dir = 1 # move direction: 1 - up, -1 - down
            #self.move_speed = 0.002
            
            self.timer = QTimer()
            self.timer.timeout.connect(self.animationLoop)
            self.elapsed_timer = QElapsedTimer()
            self.elapsed_timer.start()
            self.delta_time = 0
            self.timer.start(1000/60)
            
        def animationLoop(self):
            self.delta_time = self.elapsed_timer.elapsed()
            self.elapsed_timer.restart()
            self.world.doPhysics(self.delta_time / 1000)
            self.update()
            
        def paintGL(self):
            gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
            self.proj_view_matrix = self.proj_matrix * self.view_matrix
            self.obj.draw(self.program, self.proj_view_matrix)
            self.obj2.draw(self.program, self.proj_view_matrix)
    
        def resizeGL(self, w, h):
            gl.glViewport(0, 0, w, h)
            self.proj_matrix.setToIdentity()
            self.proj_matrix.perspective(50, float(w) / float(h), 0.1, 100)
            
        def initVertexBuffers(self, path):
            xml_doc = QDomDocument()
            file = QFile(path)
            if not file.open(QIODevice.ReadOnly):
                print("Failed to open the file: " + path)
            xml_doc.setContent(file)
            file.close()
            
            vert_pos_array = []
            normal_array = []
            tex_coord_array = []
            index_array = []
            
            root = xml_doc.documentElement()
            dae_elem = root.firstChildElement()
            while not dae_elem.isNull():
                if dae_elem.tagName() == "library_geometries":
                    geom_elem = dae_elem.firstChildElement()
                    if geom_elem.tagName() == "geometry":
                        mesh_elem = geom_elem.firstChildElement()
                        if mesh_elem.tagName() == "mesh":
                            mesh_child_elem = mesh_elem.firstChildElement()
                            while not mesh_child_elem.isNull():
                                float_array_elem = mesh_child_elem.firstChildElement()
                                str_array = float_array_elem.firstChild().toText().data().split(" ")
                                if mesh_child_elem.attribute("id").endswith("-mesh-positions"):
                                    vert_pos_array = list(map(float, str_array))
                                if mesh_child_elem.attribute("id").endswith("-mesh-normals"):
                                    normal_array = list(map(float, str_array))
                                if mesh_child_elem.attribute("id").endswith("-mesh-map-0"):
                                    tex_coord_array = list(map(float, str_array))
                                if mesh_child_elem.tagName() == "triangles" or mesh_child_elem.tagName() == "polylist":
                                    p_child_elem = mesh_child_elem.firstChildElement()
                                    while not p_child_elem.isNull():
                                        if p_child_elem.tagName() == "p":
                                            str_indices = p_child_elem.firstChild().toText().data().split(" ")
                                            index_array = list(map(int, str_indices))
                                        p_child_elem = p_child_elem.nextSiblingElement()
                                mesh_child_elem = mesh_child_elem.nextSiblingElement()
                dae_elem = dae_elem.nextSiblingElement()
            # print(vert_pos_array)
            # print(normal_array)
            # print(tex_coord_array)
            # print(index_array)
            
            num_of_attributes = 3
            vert_positions = []
            normals = []
            tex_coords = []
            for i in range(0, len(index_array), num_of_attributes):
                vert_pos_index = index_array[i + 0]
                vert_positions.append(vert_pos_array[vert_pos_index * 3 + 0])
                vert_positions.append(vert_pos_array[vert_pos_index * 3 + 1])
                vert_positions.append(vert_pos_array[vert_pos_index * 3 + 2])
                
                normal_index = index_array[i + 1]
                normals.append(normal_array[normal_index * 3 + 0])
                normals.append(normal_array[normal_index * 3 + 1])
                normals.append(normal_array[normal_index * 3 + 2])
                
                tex_coord_index = index_array[i + 2]
                tex_coords.append(tex_coord_array[tex_coord_index * 2 + 0])
                tex_coords.append(tex_coord_array[tex_coord_index * 2 + 1])
            # print(vert_positions)
            # print(normals)
            # print(tex_coords)
            
            output = {}
    
            vert_positions = np.array(vert_positions, dtype=np.float32)
            vert_pos_buffer = QOpenGLBuffer()
            vert_pos_buffer.create()
            vert_pos_buffer.bind()
            vert_pos_buffer.allocate(vert_positions, len(vert_positions) * 4)
            
            normals = np.array(normals, dtype=np.float32)
            normal_buffer = QOpenGLBuffer()
            normal_buffer.create()
            normal_buffer.bind()
            normal_buffer.allocate(normals, len(normals) * 4)
            
            tex_coords = np.array(tex_coords, dtype=np.float32)
            tex_coord_buffer = QOpenGLBuffer()
            tex_coord_buffer.create()
            tex_coord_buffer.bind()
            tex_coord_buffer.allocate(tex_coords, len(tex_coords) * 4)
    
            vert_buffers = VertexBuffers()
            vert_buffers.vert_pos_buffer = vert_pos_buffer
            vert_buffers.normal_buffer = normal_buffer
            vert_buffers.tex_coord_buffer = tex_coord_buffer
            vert_buffers.amount_of_vertices = int(len(index_array) / 3)
            
            return vert_buffers
    
    def main():
        QApplication.setAttribute(Qt.AA_UseDesktopOpenGL)
        app = QApplication(sys.argv)
        w = Window()
        w.show()
        sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main()
    

  • Lifetime Qt Champion

    Hi,

    Before searching too far, you should add all the error checks that are missing to ensure that what you load and and build passes correctly (shaders, etc.)


Log in to reply