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) - это для нормалей \*/

    /\* блокируем буфер на запись и берем указатель на него \*/  
&nbsp;&nbsp;&nbsp; float \*pVertex = static\_cast\<float \*\>(vertexBuffer-\>lock(Ogre::HardwareBuffer::HBL\_DISCARD));

&nbsp;&nbsp;&nbsp; // Заполняем буфер  
&nbsp;&nbsp;&nbsp; \*pVertex++ = 0.0f; \*pVertex++ = 1.0f; \*pVertex++ = 0.0f; // вершина  
&nbsp;&nbsp;&nbsp; \*pVertex++ = -sqrt13; \*pVertex++ = sqrt13; \*pVertex++ = -sqrt13; // нормаль  
&nbsp;&nbsp;&nbsp; \*(\*(Ogre::uint32\*\*)&pVertex)++ = red;&nbsp;&nbsp; //цвета  
&nbsp;&nbsp;&nbsp; \*pVertex++ = -1.0f; \*pVertex++ = -1.0f; \*pVertex++ = 0.0f; // вершина  
&nbsp;&nbsp;&nbsp; \*pVertex++ = sqrt13; \*pVertex++ = sqrt13; \*pVertex++ = -sqrt13; // нормаль  
&nbsp;&nbsp;&nbsp; \*(\*(Ogre::uint32\*\*)&pVertex)++ = green; // цвета  
&nbsp;&nbsp;&nbsp; \*pVertex++ = 1.0f; \*pVertex++ = -1.0f; \*pVertex++ = 0.0f; // вершина  
&nbsp;&nbsp;&nbsp; \*pVertex++ = -sqrt13; \*pVertex++ = -sqrt13; \*pVertex++ = -sqrt13; // нормаль  
&nbsp;&nbsp;&nbsp; \*(\*(Ogre::uint32\*\*)&pVertex)++ = blue;&nbsp; // цвета

&nbsp;&nbsp;&nbsp; /\* разблокируем \*/  
&nbsp;&nbsp;&nbsp; vertexBuffer-\>unlock();

&nbsp;&nbsp;&nbsp; /\* Создаем буфер для индексов \*/  
&nbsp;&nbsp;&nbsp; Ogre::HardwareIndexBufferSharedPtr indexBuffer = Ogre::HardwareBufferManager::getSingleton().  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; createIndexBuffer(Ogre::HardwareIndexBuffer::IT\_16BIT, mesh-\>sharedVertexData-\>vertexCount, Ogre::HardwareBuffer::HBU\_STATIC);

&nbsp;&nbsp;&nbsp; /\* Получаем блокировку на запись и пишем индексы в буфер \*/  
&nbsp;&nbsp;&nbsp; uint16\_t \*indices = static\_cast\<uint16\_t \*\>(indexBuffer-\>lock(Ogre::HardwareBuffer::HBL\_NORMAL));

&nbsp;&nbsp;&nbsp; /\* Задаем нужный индексы вершин, которые будет треугольник представлять \*/  
&nbsp;&nbsp;&nbsp; indices[0] = 0;  
&nbsp;&nbsp;&nbsp; indices[1] = 1;  
&nbsp;&nbsp;&nbsp; indices[2] = 2;

&nbsp;&nbsp;&nbsp; /\* записали - разблокировали \*/  
&nbsp;&nbsp;&nbsp; indexBuffer-\>unlock();

&nbsp;&nbsp;&nbsp; /\* Теперь надо прицепить к нашей геометрии созданный буфер \*/  
&nbsp;&nbsp;&nbsp; mesh-\>sharedVertexData-\>vertexBufferBinding-\>setBinding(0, vertexBuffer);  
&nbsp;&nbsp;&nbsp; subMesh-\>useSharedVertices = true;  
&nbsp;&nbsp;&nbsp; subMesh-\>indexData-\>indexBuffer = indexBuffer;  
&nbsp;&nbsp;&nbsp; subMesh-\>indexData-\>indexCount = mesh-\>sharedVertexData-\>vertexCount;  
&nbsp;&nbsp;&nbsp; subMesh-\>indexData-\>indexStart = 0;

&nbsp;&nbsp;&nbsp; /\* Если не объявить рамку, то огр не сможет правильно обсчитать сетку  
&nbsp;&nbsp;&nbsp;&nbsp; \* и она будет видна лишь в корневой ноде (если ее туда прицепить),  
&nbsp;&nbsp;&nbsp;&nbsp; \* а в дочерних - не будет.  
&nbsp;&nbsp;&nbsp;&nbsp; \* Для этого можно зачитать http://www.ogre3d.org/forums/viewtopic.php?f=2&t=60200  
&nbsp;&nbsp;&nbsp;&nbsp; \*/  
&nbsp;&nbsp;&nbsp; mesh-\>\_setBounds(Ogre::AxisAlignedBox(-1, -1, -1, 1, 1, 1));

&nbsp;&nbsp;&nbsp; /\* нарисовали - грузим \*/  
&nbsp;&nbsp;&nbsp; mesh-\>load();

&nbsp;&nbsp;&nbsp; /\*  
&nbsp;&nbsp;&nbsp;&nbsp; \* А теперь нужно задефайнить материал.  
&nbsp;&nbsp;&nbsp;&nbsp; \* Если этого не сделать, то новоиспеченный триангл будет выглядеть белым,  
&nbsp;&nbsp;&nbsp;&nbsp; \* а не многоцветным как задумано выше  
&nbsp;&nbsp;&nbsp;&nbsp; \*/  
&nbsp;&nbsp;&nbsp; Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("Test/ColourTest", Ogre::ResourceGroupManager::DEFAULT\_RESOURCE\_GROUP\_NAME);  
&nbsp;&nbsp;&nbsp; material-\>getTechnique(0)-\>getPass(0)-\>setVertexColourTracking(Ogre::TVC\_AMBIENT);

&nbsp;&nbsp;&nbsp; /\* Создаем ноду на базе того, что накодили выше. \*/  
&nbsp;&nbsp;&nbsp; Ogre::Entity \*entity = mSceneMgr-\>createEntity("CustomEntity", "CustomMesh", "General");  
&nbsp;&nbsp;&nbsp; entity-\>setMaterialName("Test/ColourTest", "General");  
&nbsp;&nbsp;&nbsp; Ogre::SceneNode \*node = mSceneMgr-\>getRootSceneNode()-\>createChildSceneNode();  
&nbsp;&nbsp;&nbsp; node-\>attachObject(entity);

&nbsp;&nbsp;&nbsp; mCamera-\>lookAt(Ogre::Vector3(0, 0, 0));  
&nbsp;&nbsp;&nbsp; mCamera-\>setPosition(Ogre::Vector3(0, 10, 50));  
}

 

Ogre3D - использование вертексного буфераЧего почитать: