Добавить QTextureMaterial в пользовательскую сетку - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть пользовательская сетка (созданная в Blender), которую я вставляю в Qt3D, используя следующий код:

 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 (например, QPlaneMesh или QSphereMesh), он отлично отображается на поверхности, как и следовало ожидать.

Однако - теперь возникает проблема - если я добавлю его с 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 голосов
/ 04 сентября 2018

Похоже, что в сетке отсутствуют текстурные координаты. Когда вы открываете файл в текстовом редакторе, вы видите где-нибудь ключ vt? Это координаты текстуры. Вы можете прочитать о формате здесь .

Если вы все еще хотите получить файл obj, который у вас есть, вы должны добавить текстурные координаты, если у него их нет. Вероятно, лучше всего открыть файл в Blender и использовать его текстурный маппер - по крайней мере, для более сложных сеток. Догадаться, какой вершине нужна какая координата текстуры, на самом деле невозможно.

Текстурные координаты работают следующим образом: Если у вас есть изображение, скажем, 500 на 400 пикселей, координата текстуры (0,7, 0,3) равна (500 * 0,7, 400 * 0,3) = (350, 120), что означает, что вершина, имеющая эту координату текстуры, получит значение цвета пикселя при (350, 120). Значения внутри треугольника будут интерполированы.

Если ваш obj-файл идет вместе с mtl-файлом, то он, вероятно, уже имеет текстурные координаты. Если вы хотите загрузить этот файл mtl, используйте QSceneLoader и добавьте его в родительский файл QEntity, чтобы отобразить все.

...