This demo code shows how to read out data from vertex buffer and index buffer of a ManualObject.
It was written in C# (for Mogre), but should be easy to port to C++. If anybody do so, please publish the C++ code on this wiki page.
The interesting code is in section DATA GRABBING. The code before and behind is just for testing and displaying.
Don't forget the unsafe declaration to avoid compiler errors.
To convert the (local) vertex positions to world positions, look to the code comments and apply the conversion.
Written by user Beauty in 2011 and tested with Ogre/Mogre 1.7.
For questions or bug reports use this forum topic.
Copy to clipboard
public static unsafe void test_GetManualObjectRawData(SceneManager smgr) { //-- CREATE TEST OBJECT -- ManualObject manOb = smgr.CreateManualObject("manob_test_" + Guid.NewGuid()); manOb.Begin("Core/NodeMaterial", RenderOperation.OperationTypes.OT_POINT_LIST); manOb.Position(new Vector3(0, 0, 0)); manOb.Position(new Vector3(1, 1, 1)); manOb.End(); manOb.Begin("Core/NodeMaterial", RenderOperation.OperationTypes.OT_LINE_LIST); manOb.Position(new Vector3(2, 2, 2)); manOb.Position(new Vector3(3, 3, 3)); manOb.End(); manOb.Begin("Core/NodeMaterial", RenderOperation.OperationTypes.OT_LINE_STRIP); manOb.Position(new Vector3(11, 11, 11)); manOb.Position(new Vector3(22, 22, 22)); manOb.Position(new Vector3(33, 33, 33)); manOb.Index(2); manOb.Index(1); manOb.Index(0); manOb.Index(2); manOb.End(); // storage lists for test output List<Vector3> posList = new List<Vector3>(); List<UInt64> indexList = new List<UInt64>(); //-- DATA GRABBING -- RenderOperation moData = new RenderOperation(); // access to vertex and index buffer // loop for each section for (UInt32 i = 0; i < manOb.NumSections; i++) { manOb.GetSection(i).GetRenderOperation(moData); //-- read vertex data -- VertexElement posEl = moData.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); HardwareVertexBufferSharedPtr vBuff = moData.vertexData.vertexBufferBinding.GetBuffer(posEl.Source); byte* pVertex = (byte*)vBuff.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); float* pReal; for (Int32 j = 0; j < moData.vertexData.vertexCount; j++) { posEl.BaseVertexPointerToElement(pVertex, &pReal); Vector3 vertexPos = new Vector3(pReal[0], pReal[1], pReal[2]); // CONVERSION TO WORLD POSITIONS: // Grabb world properties of parent SceneNode // by _getDerivedPosition() / _getDerivedOrientation() / _getDerivedScale() // and apply this calculation: // vertexPos = (orientation * (vertexPos * scale)) + position; posList.Add(vertexPos); pVertex += vBuff.VertexSize; } vBuff.Unlock(); //-- read index data -- if (moData.useIndexes) { HardwareIndexBufferSharedPtr iBuff = moData.indexData.indexBuffer; // UNPORTED line of C++ code (because ibuf.IsNull() doesn't exist in C#) // if( ibuf.isNull() ) continue // need to check if index buffer is valid (which will be not if the mesh doesn't have triangles like a pointcloud) uint* pLong = (uint*)iBuff.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); ushort* pShort = (ushort*)pLong; for (int k = 0; k < moData.indexData.indexCount; k++) { UInt64 index; if (iBuff.Type == HardwareIndexBuffer.IndexType.IT_32BIT) // if 32bit indexes index = (UInt64)pLong[k]; else index = (UInt64)pShort[k]; indexList.Add(index); } iBuff.Unlock(); } // if //-- read vertex data by index order -- // Note: This block is independent from the previous blocks if (moData.useIndexes) { //VertexElement posEl = moData.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); //HardwareVertexBufferSharedPtr vBuff = moData.vertexData.vertexBufferBinding.GetBuffer(posEl.Source); //byte* pVertex = (byte*)vBuff.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); //float* pReal; byte* pStartVertex = pVertex; HardwareIndexBufferSharedPtr iBuff = moData.indexData.indexBuffer; // UNPORTED line of C++ code (because ibuf.IsNull() doesn't exist in C#) // if( ibuf.isNull() ) continue // need to check if index buffer is valid (which will be not if the mesh doesn't have triangles like a pointcloud) uint* pLong = (uint*)iBuff.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); ushort* pShort = (ushort*)pLong; for (int k = 0; k < moData.indexData.indexCount; k++) { UInt64 index; if (iBuff.Type == HardwareIndexBuffer.IndexType.IT_32BIT) // if 32bit indexes index = (UInt64)pLong[k]; else index = (UInt64)pShort[k]; pVertex = pStartVertex + (vBuff.VertexSize * index); posEl.BaseVertexPointerToElement(pVertex, &pReal); Vector3 vertexPos = new Vector3(pReal[0], pReal[1], pReal[2]); posByIndexList.Add(vertexPos); } iBuff.Unlock(); vBuff.Unlock(); } // if //-- TEST OUTPUT -- Console.WriteLine("--- new section of ManualObject ---"); Console.WriteLine("Render operation type: " + moData.operationType); foreach(Vector3 vertexPos in posList) Console.WriteLine("Vertex position: " + vertexPos); foreach (UInt64 ind in indexList) Console.WriteLine("Index: " + ind); foreach (Vector3 vertexPos in posByIndexList) Console.WriteLine("Vertex by index: " + vertexPos); if (indexList.Count == 0) Console.WriteLine("No indexes"); posList.Clear(); indexList.Clear(); posByIndexList.Clear(); } // for each section Console.WriteLine("\n"); }