Ogre3D: работа с вертексным буфером
Ура :) Я научился таки работать с вертексным буфером в этом самам огре.
Как было просто в голом опенглы. Так просто, что даже вспомнить не хочется. :-D
Теперь же нам надо сделать что-то вроде этого
void TutorialApplication::createScene(void)
{
/* Зачем дополнительно создавать submesh пока не понял */
Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual("CustomMesh", "General");
Ogre::SubMesh *subMesh = mesh->createSubMesh();
/* Подготавливаем структуру для трех вершин (треугольник у нас) */
mesh->sharedVertexData = new Ogre::VertexData;
mesh->sharedVertexData->vertexCount = 3;
/* Получаем ссылку на дескриптор буфера (описывает структуру) */
Ogre::VertexDeclaration *decl = mesh->sharedVertexData->vertexDeclaration;
size_t offset = 0;
/* первый элемент буфера - это сама вершина (ее координаты) */
decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
/* вторая часть буфера - нормаль вершины */
decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
/* Третья часть - это цвет вершины */
decl->addElement(0, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
/* Генерируем вертексный буфер по описанию, которое выше */
Ogre::HardwareVertexBufferSharedPtr vertexBuffer = Ogre::HardwareBufferManager::getSingleton().
createVertexBuffer(offset, mesh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC);
// подготавливаем цвета
// можно писать цвета руками и использовать не Ogre::VET_COLOUR, а VET_FLOAT3|4 (4 - это если альфаканал нужен)
Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
Ogre::uint32 red, green, blue;
rs->convertColourValue(Ogre::ColourValue(1,0,0,1), &red);
rs->convertColourValue(Ogre::ColourValue(0,1,0,1), &green);
rs->convertColourValue(Ogre::ColourValue(0,0,1,1), &blue);
const float sqrt13 = 0.577350269f; /* sqrt(1/3) - это для нормалей */
/* блокируем буфер на запись и берем указатель на него */
float *pVertex = static_cast<float *>(vertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
// Заполняем буфер
*pVertex++ = 0.0f; *pVertex++ = 1.0f; *pVertex++ = 0.0f; // вершина
*pVertex++ = -sqrt13; *pVertex++ = sqrt13; *pVertex++ = -sqrt13; // нормаль
*(*(Ogre::uint32**)&pVertex)++ = red; //цвета
*pVertex++ = -1.0f; *pVertex++ = -1.0f; *pVertex++ = 0.0f; // вершина
*pVertex++ = sqrt13; *pVertex++ = sqrt13; *pVertex++ = -sqrt13; // нормаль
*(*(Ogre::uint32**)&pVertex)++ = green; // цвета
*pVertex++ = 1.0f; *pVertex++ = -1.0f; *pVertex++ = 0.0f; // вершина
*pVertex++ = -sqrt13; *pVertex++ = -sqrt13; *pVertex++ = -sqrt13; // нормаль
*(*(Ogre::uint32**)&pVertex)++ = blue; // цвета
/* разблокируем */
vertexBuffer->unlock();
/* Создаем буфер для индексов */
Ogre::HardwareIndexBufferSharedPtr indexBuffer = Ogre::HardwareBufferManager::getSingleton().
createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, mesh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC);
/* Получаем блокировку на запись и пишем индексы в буфер */
uint16_t *indices = static_cast<uint16_t *>(indexBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL));
/* Задаем нужный индексы вершин, которые будет треугольник представлять */
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
/* записали - разблокировали */
indexBuffer->unlock();
/* Теперь надо прицепить к нашей геометрии созданный буфер */
mesh->sharedVertexData->vertexBufferBinding->setBinding(0, vertexBuffer);
subMesh->useSharedVertices = true;
subMesh->indexData->indexBuffer = indexBuffer;
subMesh->indexData->indexCount = mesh->sharedVertexData->vertexCount;
subMesh->indexData->indexStart = 0;
/* Если не объявить рамку, то огр не сможет правильно обсчитать сетку
* и она будет видна лишь в корневой ноде (если ее туда прицепить),
* а в дочерних - не будет.
* Для этого можно зачитать http://www.ogre3d.org/forums/viewtopic.php?f=2&t=60200
*/
mesh->_setBounds(Ogre::AxisAlignedBox(-1, -1, -1, 1, 1, 1));
/* нарисовали - грузим */
mesh->load();
/*
* А теперь нужно задефайнить материал.
* Если этого не сделать, то новоиспеченный триангл будет выглядеть белым,
* а не многоцветным как задумано выше
*/
Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("Test/ColourTest", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
material->getTechnique(0)->getPass(0)->setVertexColourTracking(Ogre::TVC_AMBIENT);
/* Создаем ноду на базе того, что накодили выше. */
Ogre::Entity *entity = mSceneMgr->createEntity("CustomEntity", "CustomMesh", "General");
entity->setMaterialName("Test/ColourTest", "General");
Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(entity);
mCamera->lookAt(Ogre::Vector3(0, 0, 0));
mCamera->setPosition(Ogre::Vector3(0, 10, 50));
}
- https://grahamedgecombe.com/blog/custom-meshes-in-ogre3d
- http://www.ogre3d.org/forums/viewtopic.php?f=2&t=60200
- http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Generating+A+Mesh
Категории: JFF