예제 #1
0
    def __init__(self, fmt: QSurfaceFormat, parent=None, *args, **kwargs):
        QOpenGLWidget.__init__(self, parent, *args, **kwargs)
        QOpenGLExtraFunctions.__init__(self, *args, **kwargs)
        self.width, self.height = 1280, 720

        self.program = QOpenGLShaderProgram()
        self.vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
        self.ebo = QOpenGLBuffer(QOpenGLBuffer.IndexBuffer)
        self.vao = QOpenGLVertexArrayObject()

        self.model_loc = None
        self.projection_loc = None
        self.camera_loc = None
        self.attrib_loc = None

        self.shape = Cube()
        self.models = []
        self.model = None
        self.projection = None

        self.camera = Camera()
        self.last_pos = QPoint(self.width / 2.0, self.height / 2.0)

        self.setFormat(fmt)
        self.context = QOpenGLContext(self)
        if not self.context.create():
            raise RuntimeError("Unable to create GL context")

        self.timer = QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(1000.0/FPS)
예제 #2
0
    def __init__(self, parent=None):
        QOpenGLWidget.__init__(self, parent)
        QOpenGLFunctions.__init__(self)

        self.core = "--coreprofile" in QCoreApplication.arguments()
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.lastPos = 0
        self.logo = Logo()
        self.vao = QOpenGLVertexArrayObject()
        self.logoVbo = QOpenGLBuffer()
        self.program = QOpenGLShaderProgram()
        self.projMatrixLoc = 0
        self.mvMatrixLoc = 0
        self.normalMatrixLoc = 0
        self.lightPosLoc = 0
        self.proj = QMatrix4x4()
        self.camera = QMatrix4x4()
        self.world = QMatrix4x4()
        self.transparent = "--transparent" in QCoreApplication.arguments()
        if self.transparent:
            fmt = self.format()
            fmt.setAlphaBufferSize(8)
            self.setFormat(fmt)
예제 #3
0
    def initialize_geometry_on_gpu(self):
        self.vao = QOpenGLVertexArrayObject(self.parent())
        if not self.vao.create():
            raise ValueError('Could not create VAO')
        self.vao.bind()

        self.vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
        if not self.vbo.create():
            raise ValueError('Could not create VBO')
        self.vbo.bind()
        self.vbo.setUsagePattern(QOpenGLBuffer.StaticDraw)
        vertices_data = self.vertices.tostring()
        self.vbo.allocate(len(vertices_data))
        self.vbo.write(0, vertices_data, len(vertices_data))

        self.program.enableAttributeArray(self.arg_pos['in_coords'])
        self.program.setAttributeBuffer(self.arg_pos['in_coords'],
                                        gl.GL_FLOAT,
                                        0,
                                        3,
                                        self.vertices.shape[1] *
                                        self.vertices.dtype.itemsize)

        self.program.enableAttributeArray(self.arg_pos['in_tex_coords'])
        self.program.setAttributeBuffer(self.arg_pos['in_tex_coords'],
                                        gl.GL_FLOAT,
                                        3 * self.vertices.dtype.itemsize,
                                        2,
                                        self.vertices.shape[1] *
                                        self.vertices.dtype.itemsize)

        self.vao.release()
        self.vbo.release()
예제 #4
0
    def __init__(self, parent=None):
        QOpenGLWidget.__init__(self, parent)

        # shaders etc
        triangleTutoDir = os.path.dirname(__file__)
        trianglePardir = os.path.join(triangleTutoDir, os.pardir)
        mediaDir = os.path.join(trianglePardir, "media")
        shaderDir = os.path.join(mediaDir, "shaders")
        availableShaders = ["triangle", "triangle2"]
        self.shaders = {
            name: {
                "fragment": os.path.join(shaderDir, name + ".frag"),
                "vertex": os.path.join(shaderDir, name + ".vert")
            } for name in availableShaders
        }
        self.core = "--coreprofile" in QCoreApplication.arguments()

        # opengl data related
        self.context = QOpenGLContext()
        self.vao1 = QOpenGLVertexArrayObject()
        self.vbo1 = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
        self.vao2 = QOpenGLVertexArrayObject()
        self.vbo2 = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)

        self.program1 = QOpenGLShaderProgram()
        self.program2 = QOpenGLShaderProgram()

        # some vertex data for corners of triangle
        self.vertexData1 = np.array(
            [0.9, 0.9, 0.0,  # x, y, z
             0.9, 0.7, 0.0,  # x, y, z
             0.7, 0.9, 0.0],  # x, y, z
            dtype=ctypes.c_float
        )
        self.vertexData2 = np.array(
            [-0.9, -0.9, 0.0,  # x, y, z
             -0.9, -0.7, 0.0,  # x, y, z
             -0.7, -0.9, 0.0],  # x, y, z
            dtype=ctypes.c_float
        )
        # triangle color
        self.triangleColor1 = QVector4D(1.0, 0.0, 0.0, 0.0)  # yellow triangle
        self.triangleColor2 = QVector4D(
            0.0, 0.0, 0.5, 0.0)  # not yellow triangle
예제 #5
0
    def __init__(self, parent=None):
        QOpenGLWidget.__init__(self, parent)
        QOpenGLFunctions.__init__(self)
        self.setMinimumSize(32, 32)

        self.info = ""
        self._supported_images = [
            "TGA", "PNG", "JPG", "JPEG", "TIF", "TIFF", "BMP", "DDS"
        ]

        # indices
        indices = [0, 1, 3, 1, 2, 3]
        self._indices = array('I', indices)

        # vertices
        # 3 position | 2 texture coord
        vertex = [
            1.0,
            1.0,
            0.0,
            1.0,
            1.0,  # top right
            1.0,
            -1.0,
            0.0,
            1.0,
            0.0,  # bottom right
            -1.0,
            -1.0,
            0.0,
            0.0,
            0.0,  # bottom left
            -1.0,
            1.0,
            0.0,
            0.0,
            1.0  # top left
        ]
        self._vertex = array('f', vertex)

        # opengl data related
        self._program = QOpenGLShaderProgram()
        self._program_bg = QOpenGLShaderProgram()
        self._vao = QOpenGLVertexArrayObject()
        self._vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
        self._texture = None
        self._texture_size = (1, 1)
        self._location = ()

        self._colors_default = (QColor.fromRgbF(0.65, 0.65, 0.65, 1.0),
                                QColor.fromRgbF(0.90, 0.90, 0.90, 1.0))
        self._u_colors = self._colors_default
        self._height = QVector4D(0, self.height(), 0, 0)

        self._u_channels = QMatrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
                                      0, 0)
예제 #6
0
    def __init__(self, parent=None):
        "Constructor"
        QOpenGLWidget.__init__(self, parent)
        tutoTutoDir = os.path.dirname(__file__)
        tutoPardir = os.path.join(tutoTutoDir, os.pardir)
        tutoPardir = os.path.realpath(tutoPardir)
        mediaDir = os.path.join(tutoPardir, "media")
        shaderDir = os.path.join(mediaDir, "shaders")
        #
        availableShaders = ["rectangle", "triangle"]
        self.shaders = {
            name: {
                "fragment": os.path.join(shaderDir, name + ".frag"),
                "vertex": os.path.join(shaderDir, name + ".vert")
            }
            for name in availableShaders
        }
        self.core = "--coreprofile" in QCoreApplication.arguments()

        # opengl data related
        self.context = QOpenGLContext()
        self.program = QOpenGLShaderProgram()
        self.vao = QOpenGLVertexArrayObject()
        self.vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
        self.indices = np.array(
            [
                0,
                1,
                3,  # first triangle
                1,
                2,
                3  # second triangle
            ],
            dtype=ctypes.c_uint)

        # vertex data of the panel that would hold the image
        self.vertexData = np.array(
            [
                # viewport position || colors           ||   texture coords
                0.5,
                0.5,
                0.0,  # top right
                0.5,
                -0.5,
                0.0,  # bottom right
                -0.5,
                -0.5,
                0.0,  # bottom left
                -0.5,
                0.5,
                0.0,  # top left
            ],
            dtype=ctypes.c_float)

        self.rectColor = QVector4D(0.0, 1.0, 1.0, 0.0)
예제 #7
0
    def initGl(self):
        self.program = QOpenGLShaderProgram(self)
        self.vao = QOpenGLVertexArrayObject()
        self.vbo = QOpenGLBuffer()

        format = self.context.format()
        useNewStyleShader = format.profile() == QSurfaceFormat.CoreProfile
        # Try to handle 3.0 & 3.1 that do not have the core/compatibility profile
        # concept 3.2+ has. This may still fail since version 150 (3.2) is
        # specified in the sources but it's worth a try.
        if (format.renderableType() == QSurfaceFormat.OpenGL
                and format.majorVersion() == 3 and format.minorVersion() <= 1):
            useNewStyleShader = not format.testOption(
                QSurfaceFormat.DeprecatedFunctions)

        vertexShader = vertexShaderSource if useNewStyleShader else vertexShaderSource110
        fragmentShader = fragmentShaderSource if useNewStyleShader else fragmentShaderSource110
        if not self.program.addShaderFromSourceCode(QOpenGLShader.Vertex,
                                                    vertexShader):
            raise Exception("Vertex shader could not be added: {} ({})".format(
                self.program.log(), vertexShader))
        if not self.program.addShaderFromSourceCode(QOpenGLShader.Fragment,
                                                    fragmentShader):
            raise Exception(
                "Fragment shader could not be added: {} ({})".format(
                    self.program.log(), fragmentShader))
        if not self.program.link():
            raise Exception("Could not link shaders: {}".format(
                self.program.log()))

        self.posAttr = self.program.attributeLocation("posAttr")
        self.colAttr = self.program.attributeLocation("colAttr")
        self.matrixUniform = self.program.uniformLocation("matrix")

        self.vbo.create()
        self.vbo.bind()
        self.verticesData = vertices.tobytes()
        self.colorsData = colors.tobytes()
        verticesSize = 4 * vertices.size
        colorsSize = 4 * colors.size
        self.vbo.allocate(VoidPtr(self.verticesData),
                          verticesSize + colorsSize)
        self.vbo.write(verticesSize, VoidPtr(self.colorsData), colorsSize)
        self.vbo.release()

        vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao)
        if self.vao.isCreated():  # have VAO support, use it
            self.setupVertexAttribs()
예제 #8
0
class ViewportPlane():

    vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
    vao = QOpenGLVertexArrayObject()

    vertices = np.array([
        -1.0, -1.0, 0.0, 0.0, 0.0,
        1.0, -1.0, 0.0, 1.0, 0.0,
        1.0, 1.0, 0.0, 1.0, 1.0,

        1.0, 1.0, 0.0, 1.0, 1.0,
        -1.0, 1.0, 0.0, 0.0, 1.0,
        -1.0, -1.0, 0.0, 0.0, 0.0
        ], dtype = c_float)
    
    @classmethod
    def initGL(cls, shaderProgram):
        cls.vbo.create()
        cls.vao.create()
        cls.vbo.bind()
        cls.vbo.allocate(cls.vertices.tobytes(), cls.vertices.size * sizeof(c_float))

        cls.vao.bind()
        shaderProgram.setAttributeBuffer(0, GL.GL_FLOAT, 0, 3, 5 * sizeof(c_float))
        shaderProgram.setAttributeBuffer(1, GL.GL_FLOAT, 3 * sizeof(c_float), 2, 5 * sizeof(c_float))
        shaderProgram.enableAttributeArray(0)
        shaderProgram.enableAttributeArray(1)
        cls.vao.release()

    def __init__(self):
        pass

    def draw(self, shaderProgram, glFunctions):
        self.__class__.vao.bind()
        shaderProgram.bind()

        glFunctions.glDrawArrays(GL.GL_TRIANGLES, 0, self.__class__.vertices.size / 2)

        self.__class__.vao.release()
        shaderProgram.release()
예제 #9
0
class Plane(TransformableObject):

    vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
    vao = QOpenGLVertexArrayObject()

    vertices = np.array([
        -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0,
        -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, -1.0, 0.0, -1.0,
        0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0,
        -1.0, 0.0, 1.0, 0.0, -1.0, 0.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, -1.0,
        0.0, -1.0, 0.0, -1.0, 0.0, -1.0, 0.0, 1.0, 0.0, -1.0, 0.0, -1.0, 0.0,
        -1.0, 0.0, 1.0, 0.0, -1.0, 0.0
    ],
                        dtype=c_float)

    @classmethod
    def initGL(cls, shaderProgram):
        cls.vbo.create()
        cls.vao.create()
        cls.vbo.bind()
        cls.vbo.allocate(cls.vertices.tobytes(),
                         cls.vertices.size * sizeof(c_float))

        cls.vao.bind()
        shaderProgram.setAttributeBuffer(0, GL.GL_FLOAT, 0, 3,
                                         6 * sizeof(c_float))
        shaderProgram.setAttributeBuffer(1, GL.GL_FLOAT, 3 * sizeof(c_float),
                                         3, 6 * sizeof(c_float))
        shaderProgram.enableAttributeArray(0)
        shaderProgram.enableAttributeArray(1)
        cls.vao.release()

    def __init__(self,
                 name,
                 scene=None,
                 material=None,
                 translation=QVector3D(),
                 rotation=QVector3D(),
                 scale=QVector3D(1.0, 1.0, 1.0)):
        super().__init__(name, scene, material, translation, rotation, scale)

    def draw(self, shaderProgram, glFunctions, camera=None):
        self.__class__.vao.bind()
        shaderProgram.bind()

        #calculate view
        if not camera:
            camera = self.scene.getCamera()
        view = camera.getViewMatrix()
        projection = camera.getProjectionMatrix()

        shaderProgram.setUniformValue("model", self.model)
        shaderProgram.setUniformValue("view", view)
        shaderProgram.setUniformValue("projection", projection)
        shaderProgram.setUniformValue("inColor",
                                      self.material.getEditorColor())

        glFunctions.glDrawArrays(GL.GL_TRIANGLES, 0,
                                 self.__class__.vertices.size / 2)

        self.__class__.vao.release()
        shaderProgram.release()

    def area(self):
        return 2 * self.scaleVec.x() * 2 * self.scaleVec.z()
예제 #10
0
    def __init__(self, parent=None):
        QOpenGLWidget.__init__(self, parent)

        # camera
        self.camera = QtCamera()
        self.camera.position = QVector3D(0.0, 0.0, 3.0)
        self.camera.front = QVector3D(0.0, 0.0, -1.0)
        self.camera.up = QVector3D(0.0, 1.0, 0.0)
        self.camera.movementSensitivity = 0.05

        # shaders etc
        tutoTutoDir = os.path.dirname(__file__)
        tutoPardir = os.path.join(tutoTutoDir, os.pardir)
        tutoPardir = os.path.realpath(tutoPardir)
        mediaDir = os.path.join(tutoPardir, "media")
        shaderDir = os.path.join(mediaDir, "shaders")

        availableShaders = ["cube"]
        self.shaders = {
            name: {
                "fragment": os.path.join(shaderDir, name + ".frag"),
                "vertex": os.path.join(shaderDir, name + ".vert")
            }
            for name in availableShaders
        }
        self.core = "--coreprofile" in QCoreApplication.arguments()
        imdir = os.path.join(mediaDir, "images")
        imFName = "im"
        imageFile1 = os.path.join(imdir, imFName + "0.png")
        self.image1 = QImage(imageFile1).mirrored()
        imageFile2 = os.path.join(imdir, imFName + "1.png")
        self.image2 = QImage(imageFile2).mirrored()

        # opengl data related
        self.context = QOpenGLContext()
        self.vao = QOpenGLVertexArrayObject()
        self.vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
        self.program = QOpenGLShaderProgram()
        self.texture1 = None
        self.texture2 = None
        self.texUnit1 = 0
        self.texUnit2 = 1

        # vertex data
        self.cubeVertices = np.array(
            [
                # pos vec3 || texcoord vec2
                -0.5,
                -0.5,
                -0.5,
                0.0,
                0.0,
                0.5,
                -0.5,
                -0.5,
                1.0,
                0.0,
                0.5,
                0.5,
                -0.5,
                1.0,
                1.0,
                0.5,
                0.5,
                -0.5,
                1.0,
                1.0,
                -0.5,
                0.5,
                -0.5,
                0.0,
                1.0,
                -0.5,
                -0.5,
                -0.5,
                0.0,
                0.0,
                -0.5,
                -0.5,
                0.5,
                0.0,
                0.0,
                0.5,
                -0.5,
                0.5,
                1.0,
                0.0,
                0.5,
                0.5,
                0.5,
                1.0,
                1.0,
                0.5,
                0.5,
                0.5,
                1.0,
                1.0,
                -0.5,
                0.5,
                0.5,
                0.0,
                1.0,
                -0.5,
                -0.5,
                0.5,
                0.0,
                0.0,
                -0.5,
                0.5,
                0.5,
                1.0,
                0.0,
                -0.5,
                0.5,
                -0.5,
                1.0,
                1.0,
                -0.5,
                -0.5,
                -0.5,
                0.0,
                1.0,
                -0.5,
                -0.5,
                -0.5,
                0.0,
                1.0,
                -0.5,
                -0.5,
                0.5,
                0.0,
                0.0,
                -0.5,
                0.5,
                0.5,
                1.0,
                0.0,
                0.5,
                0.5,
                0.5,
                1.0,
                0.0,
                0.5,
                0.5,
                -0.5,
                1.0,
                1.0,
                0.5,
                -0.5,
                -0.5,
                0.0,
                1.0,
                0.5,
                -0.5,
                -0.5,
                0.0,
                1.0,
                0.5,
                -0.5,
                0.5,
                0.0,
                0.0,
                0.5,
                0.5,
                0.5,
                1.0,
                0.0,
                -0.5,
                -0.5,
                -0.5,
                0.0,
                1.0,
                0.5,
                -0.5,
                -0.5,
                1.0,
                1.0,
                0.5,
                -0.5,
                0.5,
                1.0,
                0.0,
                0.5,
                -0.5,
                0.5,
                1.0,
                0.0,
                -0.5,
                -0.5,
                0.5,
                0.0,
                0.0,
                -0.5,
                -0.5,
                -0.5,
                0.0,
                1.0,
                -0.5,
                0.5,
                -0.5,
                0.0,
                1.0,
                0.5,
                0.5,
                -0.5,
                1.0,
                1.0,
                0.5,
                0.5,
                0.5,
                1.0,
                0.0,
                0.5,
                0.5,
                0.5,
                1.0,
                0.0,
                -0.5,
                0.5,
                0.5,
                0.0,
                0.0,
                -0.5,
                0.5,
                -0.5,
                0.0,
                1.0
            ],
            dtype=ctypes.c_float)
        # cube worldSpace coordinates
        self.cubeCoords = [
            QVector3D(0.2, 1.1, -1.0),
            QVector3D(2.0, 5.0, -15.0),
            QVector3D(-1.5, -2.2, -2.5),
            QVector3D(-3.8, -2.0, -12.3),
            QVector3D(2.4, -0.4, -3.5),
            QVector3D(-1.7, 3.0, -7.5),
            QVector3D(1.3, -2.0, -2.5),
            QVector3D(1.5, 2.0, -2.5),
            QVector3D(1.5, 0.2, -1.5),
            QVector3D(-1.3, 1.0, -1.5)
        ]
        self.rotateVector = QVector3D(0.7, 0.2, 0.5)
예제 #11
0
class Disc(TransformableObject):

    vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
    vao = QOpenGLVertexArrayObject()

    vertices = []
    
    @classmethod
    def createDiscArray(cls):
        numSegments = 200
        arr = []
        for i in range(numSegments, 0, -1):
            x = math.cos((i / numSegments) * 2 * math.pi)
            z = math.sin((i / numSegments) * 2 * math.pi)
            next_x = math.cos(((i - 1) / numSegments) * 2 * math.pi)
            next_z = math.sin(((i - 1) / numSegments) * 2 * math.pi)
            arr[len(arr):] = 0.0, 0.0, 0.0, 0.0, 1.0, 0.0
            arr[len(arr):] = x, 0.0, z, 0.0, 1.0, 0.0
            arr[len(arr):] = next_x, 0.0, next_z, 0.0, 1.0, 0.0
            arr[len(arr):] = 0.0, 0.0, 0.0, 0.0, -1.0, 0.0
            arr[len(arr):] = next_x, 0.0, next_z, 0.0, -1.0, 0.0
            arr[len(arr):] = x, 0.0, z, 0.0, -1.0, 0.0
        return arr

    @classmethod
    def initGL(cls, shaderProgram):
        cls.vertices = np.array(cls.createDiscArray(), dtype = c_float)
        cls.vbo.create()
        cls.vao.create()
        cls.vbo.bind()
        cls.vbo.allocate(cls.vertices.tobytes(), cls.vertices.size * sizeof(c_float))

        cls.vao.bind()
        shaderProgram.setAttributeBuffer(0, GL.GL_FLOAT, 0, 3, 6 * sizeof(c_float))
        shaderProgram.setAttributeBuffer(1, GL.GL_FLOAT, 3 * sizeof(c_float), 3, 6 * sizeof(c_float))
        shaderProgram.enableAttributeArray(0)
        shaderProgram.enableAttributeArray(1)
        cls.vao.release()

    def __init__(self, name, scene = None, material = None, translation = QVector3D(), rotation = QVector3D(), scale = QVector3D(1.0, 1.0, 1.0)):
        super().__init__(name, scene, material, translation, rotation, scale)
    
    def draw(self, shaderProgram, glFunctions, camera = None):
        self.__class__.vao.bind()
        shaderProgram.bind()

        #calculate view
        if not camera:
            camera = self.scene.getCamera()
        view = camera.getViewMatrix()
        projection = camera.getProjectionMatrix()

        shaderProgram.setUniformValue("model", self.model)
        shaderProgram.setUniformValue("view", view)
        shaderProgram.setUniformValue("projection", projection)
        shaderProgram.setUniformValue("inColor", self.material.getEditorColor())

        glFunctions.glDrawArrays(GL.GL_TRIANGLES, 0, self.__class__.vertices.size / 2)

        self.__class__.vao.release()
        shaderProgram.release()
    
    def area(self):
        return np.pi * self.scaleVec.x() * self.scaleVec.z()
예제 #12
0
class Sphere(TransformableObject):

    vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
    ebo = QOpenGLBuffer(QOpenGLBuffer.IndexBuffer)
    vao = QOpenGLVertexArrayObject()

    @classmethod
    def initGL(cls, shaderProgram):
        cls.vbo.create()
        cls.vao.create()
        cls.ebo.create()
        cls.vbo.bind()

        vertices = []
        elements = []

        cls.createCircleArrays(50, vertices, elements)

        cls.vertices = np.array(vertices, dtype=c_float)
        cls.elements = np.array(elements, dtype=c_ushort)

        cls.vbo.allocate(cls.vertices.tobytes(),
                         cls.vertices.size * sizeof(c_float))

        cls.vao.bind()
        cls.ebo.bind()
        cls.ebo.allocate(cls.elements.tobytes(),
                         cls.elements.size * sizeof(c_ushort))
        shaderProgram.setAttributeBuffer(0, GL.GL_FLOAT, 0, 3,
                                         3 * sizeof(c_float))
        shaderProgram.setAttributeBuffer(1, GL.GL_FLOAT, 0, 3,
                                         3 * sizeof(c_float))
        shaderProgram.enableAttributeArray(0)
        shaderProgram.enableAttributeArray(1)
        cls.vao.release()
        cls.ebo.release()

    @classmethod
    def createCircleArrays(cls, phiSubdivisions, vertices, elements):
        phiSubdivisions -= phiSubdivisions % 2
        vertices[0:3] = 0.0, 1.0, 0.0
        delta = 360.0 / phiSubdivisions

        for th in range(1, phiSubdivisions // 2):
            for ph in range(0, phiSubdivisions):
                v = cls.sphericalToCartesian(th * delta, -ph * delta)
                vertices[len(vertices):] = v.x(), v.y(), v.z()

        vertices[len(vertices):] = 0.0, -1.0, 0.0

        offset = 1
        for colIdx in range(0, phiSubdivisions):
            nextColIdx = (colIdx + 1) % phiSubdivisions
            elements[len(elements):] = offset + colIdx, offset + nextColIdx, 0

        for row in range(1, phiSubdivisions // 2 - 1):
            rowIdx = row * phiSubdivisions + 1
            prevRowIdx = rowIdx - phiSubdivisions
            for colIdx in range(0, phiSubdivisions):
                nextColIdx = (colIdx + 1) % phiSubdivisions
                elements[len(
                    elements
                ):] = rowIdx + colIdx, rowIdx + nextColIdx, prevRowIdx + colIdx
                elements[len(
                    elements
                ):] = rowIdx + nextColIdx, prevRowIdx + nextColIdx, prevRowIdx + colIdx

        offset = 1 + (phiSubdivisions // 2 - 2) * phiSubdivisions
        for colIdx in range(0, phiSubdivisions):
            nextColIdx = (colIdx + 1) % phiSubdivisions
            elements[len(
                elements
            ):] = offset + colIdx, offset + phiSubdivisions, offset + nextColIdx

    @staticmethod
    def sphericalToCartesian(theta, phi):
        thetaRot = QMatrix4x4()
        thetaRot.rotate(theta, QVector3D(1.0, 0.0, 0.0))
        phiRot = QMatrix4x4()
        phiRot.rotate(phi, QVector3D(0.0, 1.0, 0.0))
        v = QVector3D(0.0, 1.0, 0.0)
        return (v * thetaRot) * phiRot

    def __init__(self,
                 name,
                 scene=None,
                 material=None,
                 translation=QVector3D(),
                 rotation=QVector3D(),
                 scale=QVector3D(1.0, 1.0, 1.0)):
        super().__init__(name, scene, material, translation, rotation, scale)

    def draw(self, shaderProgram, glFunctions, camera=None):
        self.__class__.vao.bind()
        shaderProgram.bind()

        #calculate view
        if not camera:
            camera = self.scene.getCamera()
        view = camera.getViewMatrix()
        projection = camera.getProjectionMatrix()

        shaderProgram.setUniformValue("model", self.model)
        shaderProgram.setUniformValue("view", view)
        shaderProgram.setUniformValue("projection", projection)
        shaderProgram.setUniformValue("inColor",
                                      self.material.getEditorColor())

        glFunctions.glDrawElements(GL.GL_TRIANGLES,
                                   self.__class__.elements.size,
                                   GL.GL_UNSIGNED_SHORT, VoidPtr(0))

        self.__class__.vao.release()
        shaderProgram.release()

    def area(self):
        return 4 * np.pi * pow(
            ((pow(self.scaleVec.x() * self.scaleVec.y(), 1.6) +
              pow(self.scaleVec.x() * self.scaleVec.z(), 1.6) +
              pow(self.scaleVec.y() * self.scaleVec.z(), 1.6)) / 3), 1 / 1.6)