Search code examples
3dpyqttexturesqt3d

Texture (QTexture2D) from image file applied to Qt3D mesh appears as plain gray - Python


I am trying to apply a texture from a jpg file to a mesh (.obj file). Both files originate from a 3D scanner and can be open in 3D tools, showing correctly.

How can I get a Qt3D mesh object to properly show in a viewer with a texture which originates from a file?

I create a mesh and load the data from the .obj file. I create a texture object and load the data from the .jpg file. I then create a material object and associate the texture to it. The object then shows as plain gray in the visualizer. Here is the code snippet. I also set a QPointLight (code below).

# Root entity.
self.rootEntity = QEntity()

# obj
filepath1 = "some_3D_file.obj"
texture_filepath1 = "some_image_file.jpg"

mesh_entity = QEntity(self.rootEntity)
mesh_object = Qt3DRender.QMesh()
mesh_object.setSource(QtCore.QUrl.fromLocalFile(filepath1))
mesh_entity.addComponent(mesh_object)

# Create texture
mesh_texture_image = Qt3DRender.QTextureImage(self.rootEntity)
mesh_texture_image.setSource(QtCore.QUrl.fromLocalFile(texture_filepath1))
mesh_texture_2D = Qt3DRender.QTexture2D(self.rootEntity)
mesh_texture_2D.addTextureImage(mesh_texture_image)

# Create material
mesh_material = QDiffuseSpecularMaterial(self.rootEntity)
mesh_material.setNormal(mesh_texture_2D)
mesh_material.setDiffuse(QColor(255, 255, 255, 0))
mesh_material.setSpecular(QColor(55, 55, 55, 0))

mesh_entity.addComponent(mesh_material)

Here is the code for the light source:

        # Light
        light_entity = QEntity(self.rootEntity)
        light = Qt3DRender.QPointLight(light_entity)
        light.setConstantAttenuation(0)
        light_entity.addComponent(light)
        light_transform = QTransform()
        light_transform.setTranslation(QVector3D(0, 100, 200))
        light_entity.addComponent(light_transform)

I tried various combinations of setting normal, diffuse, and specular, with either the loaded texture and/or plain QColor values with no luck of showing the texture image. It seems setNormal does not do much whatever I do with it. Attributing a Qcolor to setDiffuse results in the object showing the corresponding color in the viewer (as expected).

As a side question, why is there so few results when I search for Qt3D information/issues/code exmaples? I would have expected a large community using the module. Is everyone using some other 3D renderer/visualizer module that I am not aware of?

Thanks for your help.


Solution

  • I think the confusion comes from the type of texture that you have and how to use it with the right Qt3D material.

    I'm going to assume that your texture has colors in it and it doesn't really represent a normal map. If that's the case, then you need to use a QDiffuseMapMaterial instead:

    mesh_material = QDiffuseMapMaterial(self.rootEntity)
    mesh_material.setDiffuse(mesh_texture_2D)
    mesh_material.setAmbient(QColor(55, 55, 55, 0))
    

    And make sure to add a light source to the scene!