将 QTextureMaterial 添加到自定义网格
Add a QTextureMaterial to a custom mesh
我有一个自定义网格(在搅拌机中创建),我使用以下代码将其插入到 Qt3D 中:
QMesh *mesh = new QMesh(rootEntity);
mesh->setSource(QUrl::fromLocalFile(baseUrl+"mesh.obj"));
这很好用;我可以将它添加到具有 material 和所有内容的实体中。
然后我使用从 .png
加载的纹理创建自定义 material。我使用以下代码执行此操作:
Qt3DRender::QTextureLoader *loader = new Qt3DRender::QTextureLoader(rootEntity);
Qt3DExtras::QTextureMaterial *material = new Qt3DExtras::QTextureMaterial(rootEntity);
loader->setSource(QUrl::fromLocalFile(baseUrl+"pattern.jpg"));
material->setTexture(loader);
这也很好用。当我将此 material 添加到内置 Qt 网格(例如 QPlaneMesh
或 QSphereMesh
)时,它会像人们预期的那样完美地显示在表面上。
但是 - 现在问题来了 - 如果我用上面指定的 QMesh 添加它,网格只会得到一种均匀的颜色,这似乎是图案中颜色的平均值。在这里你可以明白我的意思:两个对象具有相同的material。上面的是外插的,下面的是QPlaneMesh
.
谁能解释一下为什么会这样?有没有办法成功地将纹理添加到自定义网格?
注意:我已经对 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);
我像在 QPlaneMesh
代码中一样为 setDataGenerator
创建了仿函数。现在我怀疑分段错误是因为大小不匹配。那么如何从 QGeometry
中获取外部网格的正确宽度和高度?这里还有什么问题?
网格似乎缺少纹理坐标。当您使用文本编辑器打开文件时,您是否在某处看到了键 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
以显示所有内容。
我有一个自定义网格(在搅拌机中创建),我使用以下代码将其插入到 Qt3D 中:
QMesh *mesh = new QMesh(rootEntity);
mesh->setSource(QUrl::fromLocalFile(baseUrl+"mesh.obj"));
这很好用;我可以将它添加到具有 material 和所有内容的实体中。
然后我使用从 .png
加载的纹理创建自定义 material。我使用以下代码执行此操作:
Qt3DRender::QTextureLoader *loader = new Qt3DRender::QTextureLoader(rootEntity);
Qt3DExtras::QTextureMaterial *material = new Qt3DExtras::QTextureMaterial(rootEntity);
loader->setSource(QUrl::fromLocalFile(baseUrl+"pattern.jpg"));
material->setTexture(loader);
这也很好用。当我将此 material 添加到内置 Qt 网格(例如 QPlaneMesh
或 QSphereMesh
)时,它会像人们预期的那样完美地显示在表面上。
但是 - 现在问题来了 - 如果我用上面指定的 QMesh 添加它,网格只会得到一种均匀的颜色,这似乎是图案中颜色的平均值。在这里你可以明白我的意思:两个对象具有相同的material。上面的是外插的,下面的是QPlaneMesh
.
谁能解释一下为什么会这样?有没有办法成功地将纹理添加到自定义网格?
注意:我已经对 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);
我像在 QPlaneMesh
代码中一样为 setDataGenerator
创建了仿函数。现在我怀疑分段错误是因为大小不匹配。那么如何从 QGeometry
中获取外部网格的正确宽度和高度?这里还有什么问题?
网格似乎缺少纹理坐标。当您使用文本编辑器打开文件时,您是否在某处看到了键 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
以显示所有内容。