将QTextureMaterial添加到自定义网格

时间:2018-09-04 12:59:15

标签: qt qt3d

我有一个使用以下代码插入Qt3D的自定义网格物体(在Blender中创建):

 QMesh *mesh = new QMesh(rootEntity);
 mesh->setSource(QUrl::fromLocalFile(baseUrl+"mesh.obj"));

这很好用;我可以将其添加到具有材料和所有内容的实体中。

然后,我使用从.png加载的纹理创建自定义材质。我使用以下代码执行此操作:

Qt3DRender::QTextureLoader *loader = new Qt3DRender::QTextureLoader(rootEntity);
Qt3DExtras::QTextureMaterial *material = new Qt3DExtras::QTextureMaterial(rootEntity);
loader->setSource(QUrl::fromLocalFile(baseUrl+"pattern.jpg"));
material->setTexture(loader);

这也很好。当我将这种材料添加到内置的Qt网格(例如QPlaneMeshQSphereMesh)中时,它可以像人们期望的那样完美地显示在表面上。

但是-现在出现了问题-如果我将其与上面指定的QMesh相加,则网格只会得到一种均匀的颜色,这似乎是图案中颜色的平均值。在这里,您可以了解我的意思:两个对象都具有相同的材质。顶部插入外部,而底部插入QPlaneMesh

enter image description here

有人可以向我解释为什么会这样吗?有没有一种方法可以成功地将纹理添加到自定义网格?

注意:我已经尝试使用2D和3D网格进行此操作,并且结果相同。

注2:我也尝试过使用不同的图像,但仍然只能获得一种均匀的平均颜色。

更新:我尝试(按照答案中的建议)将纹理属性添加到导入的网格的几何体中,如下所示:

Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(rootEntity);
QMesh *mesh = new QMesh(entity);
mesh->setSource(QUrl::fromLocalFile(baseUrl+"mesh.obj"));

const int stride = (3 + 2 + 3 + 4) * sizeof(float);
QSize resolution = QSize(2,2);
const int nVerts = resolution.width() * resolution.height();
QAttribute *texCoordAttr = new QAttribute(mesh->geometry());
Qt3DRender::QBuffer *vertexBuffer = new Qt3DRender::QBuffer(mesh->geometry());
texCoordAttr->setName(QAttribute::defaultTextureCoordinate1AttributeName());
texCoordAttr->setVertexBaseType(QAttribute::Float);
texCoordAttr->setVertexSize(2);
texCoordAttr->setAttributeType(QAttribute::VertexAttribute);
texCoordAttr->setBuffer(vertexBuffer);
texCoordAttr->setByteStride(stride);
texCoordAttr->setByteOffset(3*sizeof(float));
texCoordAttr->setCount(nVerts);
vertexBuffer->setDataGenerator(QSharedPointer<PlaneVertexBufferFunctor>::create(1.0f,1.0f,resolution, false));   //these input values (width, height, resolution, mirrored) are probably the cause of the problem

mesh->geometry()->addAttribute(texCoordAttr);   //it crashes here
entity->addComponent(mesh);
entity->addComponent(transform);
entity->addComponent(material);

我像setDataGenerator代码一样为QPlaneMesh创建了仿函数。现在,我怀疑分割错误是由于尺寸不匹配造成的。那么,如何从其QGeometry获取外部网格的正确宽度和高度?还有什么可能是错的?

1 个答案:

答案 0 :(得分:0)

看来网格物体缺少纹理坐标。使用文本编辑器打开文件时,您在某处看到密钥vt吗?这些是纹理坐标。您可以阅读有关格式here的信息。

如果您仍然希望拥有obj文件,那么如果没有,则必须添加纹理坐标。最好在Blender中打开文件并使用其纹理映射器-至少对于更复杂的网格而言。猜测哪个顶点需要哪个纹理坐标确实不可行。

纹理坐标的工作方式如下: 如果您的图像为500 x 400像素,则纹理坐标(0.7,0.3)为(500 * 0.7,400 * 0.3)=(350,120),这意味着具有该纹理坐标的顶点将接收(350,120)处像素的颜色值。三角形内的值将被插值。

如果obj文件与mtl文件一起提供,则它可能已经具有纹理坐标。如果要加载此mtl文件,请使用QSceneLoader并将其添加到其父QEntity中以显示所有内容。