Ogre3D: работа с вертексным буфером
04 Nov 2014
Ура :) Я научился таки работать с вертексным буфером в этом самам огре.
Как было просто в голом опенглы. Так просто, что даже вспомнить не хочется. :-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