private void ReadData(MeshPtr _meshPtr) { int indexOffset = 0; uint vertexOffset = 0; // read the index and vertex data from the mesh for (ushort i = 0; i < _meshPtr.NumSubMeshes; i++) { SubMesh subMesh = _meshPtr.GetSubMesh(i); //index int indexOffset2 = ReadIndexData(indexOffset, vertexOffset, subMesh.indexData); _index_Submesh.Add(i, new KeyValuePair <uint, uint>((uint)indexOffset, (uint)indexOffset2)); indexOffset = indexOffset2; //vertex if (subMesh.useSharedVertices == false) { vertexOffset = ReadVertexData(vertexOffset, subMesh.vertexData); } } // add the shared vertex data if (_meshPtr.sharedVertexData != null) { vertexOffset = ReadVertexData(vertexOffset, _meshPtr.sharedVertexData); } }
private void PrepareBuffers(MeshPtr _meshPtr) { uint indexCount = 0; uint vertexCount = 0; // Add any shared vertices if (_meshPtr.sharedVertexData != null) { vertexCount = _meshPtr.sharedVertexData.vertexCount; } // Calculate the number of vertices and indices in the sub meshes for (ushort i = 0; i < _meshPtr.NumSubMeshes; i++) { SubMesh subMesh = _meshPtr.GetSubMesh(i); // we have already counted the vertices that are shared if (subMesh.useSharedVertices == false) { vertexCount += subMesh.vertexData.vertexCount; } indexCount += subMesh.indexData.indexCount; } // Allocate space for the vertices and indices _vertices = new Vector3[vertexCount]; _indices = new uint[indexCount]; _index_Submesh = new Dictionary <uint, KeyValuePair <uint, uint> >(); if (_readTextureCoordinate) { _textureCroodnitas = new Vector2[vertexCount]; } }
private bool CheckSubMeshOpType(MeshPtr mesh, RenderOperation.OperationTypes opType) { for (ushort i = 0; i < mesh.NumSubMeshes; i++) { if (mesh.GetSubMesh(i).operationType != opType) { return(false); } } return(true); }
private void ReadData() { int indexOffset = 0; uint vertexOffset = 0; // read the index and vertex data from the mesh for (ushort i = 0; i < meshPtr.NumSubMeshes; i++) { SubMesh subMesh = meshPtr.GetSubMesh(i); indexOffset = ReadIndexData(indexOffset, vertexOffset, subMesh.indexData); if (subMesh.useSharedVertices == false) { vertexOffset = ReadVertexData(vertexOffset, subMesh.vertexData); } } // add the shared vertex data if (meshPtr.sharedVertexData != null) { vertexOffset = ReadVertexData(vertexOffset, meshPtr.sharedVertexData); } }
private void Initiliase(MeshPtr meshPtr, bool autodispose_meshPtr, Vector3 scale, Quaternion qua, Vector3 pos, bool readtextcroodnitas) { this._scale = scale; //this._meshPtr = meshPtr; this.meshName = meshPtr.Name; this.opType = meshPtr.GetSubMesh(0).operationType; this._readTextureCoordinate = readtextcroodnitas; this._quaoffset = qua; this._posoffset = pos; PrepareBuffers(meshPtr); ReadData(meshPtr); if (autodispose_meshPtr) { meshPtr.Dispose(); meshPtr = null; } }
public static unsafe void GetMeshInformation(MeshPtr mesh, ref uint vertex_count, ref Vector3[] vertices, ref uint index_count, ref uint[] indices, Vector3 position, Quaternion orientation, Vector3 scale) { bool added_shared = false; uint current_offset = 0; uint shared_offset = 0; uint next_offset = 0; uint index_offset = 0; vertex_count = index_count = 0; for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); if (submesh.useSharedVertices) { if (!added_shared) { vertex_count += mesh.sharedVertexData.vertexCount; added_shared = true; } } else { vertex_count += submesh.vertexData.vertexCount; } index_count += submesh.indexData.indexCount; } vertices = new Vector3[vertex_count]; indices = new uint[index_count]; added_shared = false; for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); VertexData vertex_data = submesh.useSharedVertices ? mesh.sharedVertexData : submesh.vertexData; if (!submesh.useSharedVertices || (submesh.useSharedVertices && !added_shared)) { if (submesh.useSharedVertices) { added_shared = true; shared_offset = current_offset; } VertexElement posElem = vertex_data.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertex_data.vertexBufferBinding.GetBuffer(posElem.Source); byte* vertex = (byte*) vbuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); float* pReal; for (int j = 0; j < vertex_data.vertexCount; ++j, vertex += vbuf.VertexSize) { posElem.BaseVertexPointerToElement(vertex, &pReal); Vector3 pt = new Vector3(pReal[0], pReal[1], pReal[2]); vertices[current_offset + j] = (orientation * (pt * scale)) + position; } vbuf.Unlock(); vbuf.Dispose(); next_offset += vertex_data.vertexCount; } IndexData index_data = submesh.indexData; uint numTris = index_data.indexCount / 3; HardwareIndexBufferSharedPtr ibuf = index_data.indexBuffer; bool use32bitindexes = (ibuf.Type == HardwareIndexBuffer.IndexType.IT_32BIT); uint* pLong = (uint*) ibuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); ushort* pShort = (ushort*) pLong; uint offset = submesh.useSharedVertices ? shared_offset : current_offset; if (use32bitindexes) { for (int k = 0; k < index_data.indexCount; ++k) { indices[index_offset++] = pLong[k] + offset; } } else { for (int k = 0; k < index_data.indexCount; ++k) { indices[index_offset++] = (uint) pShort[k] + (uint) offset; } } ibuf.Unlock(); ibuf.Dispose(); current_offset = next_offset; } }
private void ReadData(MeshPtr _meshPtr) { int indexOffset = 0; uint vertexOffset = 0; // read the index and vertex data from the mesh for (ushort i = 0; i < _meshPtr.NumSubMeshes; i++) { SubMesh subMesh = _meshPtr.GetSubMesh(i); //index int indexOffset2 = ReadIndexData(indexOffset, vertexOffset, subMesh.indexData); _index_Submesh.Add(i, new KeyValuePair<uint, uint>((uint)indexOffset, (uint)indexOffset2)); indexOffset = indexOffset2; //vertex if (subMesh.useSharedVertices == false) { vertexOffset = ReadVertexData(vertexOffset, subMesh.vertexData); } } // add the shared vertex data if (_meshPtr.sharedVertexData != null) { vertexOffset = ReadVertexData(vertexOffset, _meshPtr.sharedVertexData); } }
private void PrepareBuffers(MeshPtr _meshPtr) { uint indexCount = 0; uint vertexCount = 0; // Add any shared vertices if (_meshPtr.sharedVertexData != null) vertexCount = _meshPtr.sharedVertexData.vertexCount; // Calculate the number of vertices and indices in the sub meshes for (ushort i = 0; i < _meshPtr.NumSubMeshes; i++) { SubMesh subMesh = _meshPtr.GetSubMesh(i); // we have already counted the vertices that are shared if (subMesh.useSharedVertices == false) vertexCount += subMesh.vertexData.vertexCount; indexCount += subMesh.indexData.indexCount; } // Allocate space for the vertices and indices _vertices = new Vector3[vertexCount]; _indices = new uint[indexCount]; _index_Submesh = new Dictionary<uint, KeyValuePair<uint, uint>>(); if (_readTextureCoordinate) { _textureCroodnitas = new Vector2[vertexCount]; } }
private void Initiliase(MeshPtr meshPtr, bool autodispose_meshPtr, Vector3 scale, Quaternion qua, Vector3 pos, bool readtextcroodnitas) { this._scale = scale; //this._meshPtr = meshPtr; this.meshName = meshPtr.Name; this.opType = meshPtr.GetSubMesh(0).operationType; this._readTextureCoordinate = readtextcroodnitas; this._quaoffset = qua; this._posoffset = pos; PrepareBuffers(meshPtr); ReadData(meshPtr); if (autodispose_meshPtr) { meshPtr.Dispose(); meshPtr = null; } }
// Get the mesh information for the given mesh. // Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData private static unsafe void GetMeshInformation(MeshPtr mesh, out uint vertex_count, out Vector3[] vertices, out uint index_count, out ulong[] indices, Vector3 position, Quaternion orient, Vector3 scale) { bool added_shared = false; uint current_offset = 0; uint shared_offset = 0; uint next_offset = 0; uint index_offset = 0; vertex_count = index_count = 0; // Calculate how many vertices and indices we're going to need for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); // We only need to add the shared vertices once if (submesh.useSharedVertices) { if (!added_shared) { vertex_count += mesh.sharedVertexData.vertexCount; added_shared = true; } } else { vertex_count += submesh.vertexData.vertexCount; } // Add the indices index_count += submesh.indexData.indexCount; } // Allocate space for the vertices and indices vertices = new Vector3[vertex_count]; indices = new ulong[index_count]; added_shared = false; // Run through the submeshes again, adding the data into the arrays for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); VertexData vertex_data = submesh.useSharedVertices ? mesh.sharedVertexData : submesh.vertexData; if ((!submesh.useSharedVertices) || (submesh.useSharedVertices && !added_shared)) { if (submesh.useSharedVertices) { added_shared = true; shared_offset = current_offset; } VertexElement posElem = vertex_data.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertex_data.vertexBufferBinding.GetBuffer(posElem.Source); byte *vertex = (byte *)vbuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double // as second argument. So make it float, to avoid trouble when Ogre::Real will // be comiled/typedefed as double: // Ogre::Real* pReal; float *preal; for (uint j = 0; j < vertex_data.vertexCount; ++j, vertex += vbuf.VertexSize) { posElem.BaseVertexPointerToElement(vertex, &preal); Vector3 pt = new Vector3(preal[0], preal[1], preal[2]); vertices[current_offset + j] = (orient * (pt * scale)) + position; } vbuf.Unlock(); next_offset += vertex_data.vertexCount; } IndexData index_data = submesh.indexData; uint numTris = index_data.indexCount / 3; HardwareIndexBufferSharedPtr ibuf = index_data.indexBuffer; bool use32bitindexes = (ibuf.Type == HardwareIndexBuffer.IndexType.IT_32BIT); ulong * plong = (ulong *)ibuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); ushort *pshort = (ushort *)plong; uint offset = submesh.useSharedVertices ? shared_offset : current_offset; if (use32bitindexes) { for (uint k = 0; k < numTris * 3; ++k) { indices[index_offset++] = (ulong)plong[k] + (ulong)offset; } } else { for (uint k = 0; k < numTris * 3; ++k) { indices[index_offset++] = pshort[k] + (ulong)offset; } } ibuf.Unlock(); current_offset = next_offset; } }
private bool CheckSubMeshOpType(MeshPtr mesh, RenderOperation.OperationTypes opType) { for (ushort i = 0; i < mesh.NumSubMeshes; i++) { if (mesh.GetSubMesh(i).operationType != opType) { return false; } } return true; }
// Get the mesh information for the given mesh. // Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData private static unsafe void GetMeshInformation(MeshPtr mesh, out Vector3[] vertices, out int[] indices, Vector3 position, Quaternion orient, Vector3 scale) { bool addedShared = false; int currentOffset = 0, sharedOffset = 0, nextOffset = 0, indexOffset = 0; int vertexCount = 0, indexCount = 0; // Calculate how many vertices and indices we're going to need for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); // We only need to add the shared vertices once if (submesh.useSharedVertices) { if (!addedShared) { vertexCount += (int)mesh.sharedVertexData.vertexCount; addedShared = true; } } else { vertexCount += (int)submesh.vertexData.vertexCount; } // Add the indices indexCount += (int)submesh.indexData.indexCount; } // Allocate space for the vertices and indices vertices = new Vector3[vertexCount]; indices = new int[indexCount]; addedShared = false; // Run through the submeshes again, adding the data into the arrays for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); VertexData vertexData = submesh.useSharedVertices ? mesh.sharedVertexData : submesh.vertexData; if ((!submesh.useSharedVertices) || (submesh.useSharedVertices && !addedShared)) { if (submesh.useSharedVertices) { addedShared = true; sharedOffset = currentOffset; } VertexElement posElem = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); System.Diagnostics.Debug.Assert(posElem.Type == VertexElementType.VET_FLOAT3); using (HardwareVertexBufferSharedPtr vbuf = vertexData.vertexBufferBinding.GetBuffer(posElem.Source)) { byte* vertex = (byte*)vbuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); float* preal; for (uint j = 0; j < vertexData.vertexCount; ++j, vertex += vbuf.VertexSize) { posElem.BaseVertexPointerToElement(vertex, &preal); Vector3 pt = new Vector3(preal[0], preal[1], preal[2]); vertices[currentOffset + j] = (orient * (pt * scale)) + position; } vbuf.Unlock(); } nextOffset += (int)vertexData.vertexCount; } IndexData indexData = submesh.indexData; using (HardwareIndexBufferSharedPtr ibuf = indexData.indexBuffer) { bool use32bitindexes = ibuf.Type == HardwareIndexBuffer.IndexType.IT_32BIT; int* plong = (int*)ibuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); ushort* pshort = (ushort*)plong; int offset = submesh.useSharedVertices ? sharedOffset : currentOffset; if (use32bitindexes) { for (uint k = 0; k < indexData.indexCount; ++k) { indices[indexOffset++] = plong[k] + offset; } } else { for (uint k = 0; k < indexData.indexCount; ++k) { indices[indexOffset++] = pshort[k] + offset; } } ibuf.Unlock(); } currentOffset = nextOffset; } }
// Get the mesh information for the given mesh. // Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData private static unsafe void GetMeshInformation(MeshPtr mesh, out Vector3[] vertices, out int[] indices, Vector3 position, Quaternion orient, Vector3 scale) { bool addedShared = false; int currentOffset = 0, sharedOffset = 0, nextOffset = 0, indexOffset = 0; int vertexCount = 0, indexCount = 0; // Calculate how many vertices and indices we're going to need for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); // We only need to add the shared vertices once if (submesh.useSharedVertices) { if (!addedShared) { vertexCount += (int)mesh.sharedVertexData.vertexCount; addedShared = true; } } else { vertexCount += (int)submesh.vertexData.vertexCount; } // Add the indices indexCount += (int)submesh.indexData.indexCount; } // Allocate space for the vertices and indices vertices = new Vector3[vertexCount]; indices = new int[indexCount]; addedShared = false; // Run through the submeshes again, adding the data into the arrays for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); VertexData vertexData = submesh.useSharedVertices ? mesh.sharedVertexData : submesh.vertexData; if ((!submesh.useSharedVertices) || (submesh.useSharedVertices && !addedShared)) { if (submesh.useSharedVertices) { addedShared = true; sharedOffset = currentOffset; } VertexElement posElem = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); System.Diagnostics.Debug.Assert(posElem.Type == VertexElementType.VET_FLOAT3); using (HardwareVertexBufferSharedPtr vbuf = vertexData.vertexBufferBinding.GetBuffer(posElem.Source)) { byte * vertex = (byte *)vbuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); float *preal; for (uint j = 0; j < vertexData.vertexCount; ++j, vertex += vbuf.VertexSize) { posElem.BaseVertexPointerToElement(vertex, &preal); Vector3 pt = new Vector3(preal[0], preal[1], preal[2]); vertices[currentOffset + j] = (orient * (pt * scale)) + position; } vbuf.Unlock(); } nextOffset += (int)vertexData.vertexCount; } IndexData indexData = submesh.indexData; using (HardwareIndexBufferSharedPtr ibuf = indexData.indexBuffer) { bool use32bitindexes = ibuf.Type == HardwareIndexBuffer.IndexType.IT_32BIT; int * plong = (int *)ibuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); ushort *pshort = (ushort *)plong; int offset = submesh.useSharedVertices ? sharedOffset : currentOffset; if (use32bitindexes) { for (uint k = 0; k < indexData.indexCount; ++k) { indices[indexOffset++] = plong[k] + offset; } } else { for (uint k = 0; k < indexData.indexCount; ++k) { indices[indexOffset++] = pshort[k] + offset; } } ibuf.Unlock(); } currentOffset = nextOffset; } }
public RaycastResult Raycast(Ray ray, uint queryMask) { RaycastResult rr = new RaycastResult(); RaySceneQuery raySceneQuery = this.sceneMgr.CreateRayQuery(new Ray()); raySceneQuery.SetSortByDistance(true); // check we are initialised if (raySceneQuery != null) { // create a query object raySceneQuery.Ray = ray; raySceneQuery.SetSortByDistance(true); raySceneQuery.QueryMask = queryMask; using (RaySceneQueryResult queryResult = raySceneQuery.Execute()) { // execute the query, returns a vector of hits if (queryResult.Count <= 0) { // raycast did not hit an objects bounding box this.sceneMgr.DestroyQuery(raySceneQuery); raySceneQuery.Dispose(); return(null); } // at this point we have raycast to a series of different objects bounding boxes. // we need to test these different objects to see which is the first polygon hit. // there are some minor optimizations (distance based) that mean we wont have to // check all of the objects most of the time, but the worst case scenario is that // we need to test every triangle of every object. // Ogre::Real closest_distance = -1.0f; rr.Distance = -1.0f; Vector3 closestResult = Vector3.ZERO; for (int qridx = 0; qridx < queryResult.Count; qridx++) { // stop checking if we have found a raycast hit that is closer // than all remaining entities if (rr.Distance >= 0.0f && rr.Distance < queryResult[qridx].distance) { break; } // only check this result if its a hit against an entity if (queryResult[qridx].movable != null && queryResult[qridx].movable.MovableType == "Entity") { // get the entity to check Entity entity = (Entity)queryResult[qridx].movable; // mesh data to retrieve Vector3[] vertices; int[] indices; RenderOperation.OperationTypes opType; // get the mesh information using (MeshPtr mesh = entity.GetMesh()) { opType = mesh.GetSubMesh(0).operationType; Debug.Assert(CheckSubMeshOpType(mesh, opType)); GetMeshInformation( mesh, out vertices, out indices, entity.ParentNode._getDerivedPosition(), entity.ParentNode._getDerivedOrientation(), entity.ParentNode._getDerivedScale()); } int vertexCount = vertices.Length; int indexCount = indices.Length; // test for hitting individual triangles on the mesh bool newClosestFound = false; Pair <bool, float> hit; switch (opType) { case RenderOperation.OperationTypes.OT_TRIANGLE_LIST: for (int i = 0; i < indexCount; i += 3) { hit = Mogre.Math.Intersects(ray, vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]], true, false); if (CheckDistance(rr, hit)) { newClosestFound = true; } } break; case RenderOperation.OperationTypes.OT_TRIANGLE_STRIP: for (int i = 0; i < indexCount - 2; i++) { hit = Mogre.Math.Intersects(ray, vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]], true, true); if (CheckDistance(rr, hit)) { newClosestFound = true; } } break; case RenderOperation.OperationTypes.OT_TRIANGLE_FAN: for (int i = 0; i < indexCount - 2; i++) { hit = Mogre.Math.Intersects(ray, vertices[indices[0]], vertices[indices[i + 1]], vertices[indices[i + 2]], true, true); if (CheckDistance(rr, hit)) { newClosestFound = true; } } break; default: throw new Exception("invalid operation type"); } // if we found a new closest raycast for this object, update the // closest_result before moving on to the next object. if (newClosestFound) { rr.Target = entity; closestResult = ray.GetPoint(rr.Distance); } } } this.sceneMgr.DestroyQuery(raySceneQuery); raySceneQuery.Dispose(); // return the result if (rr.Distance >= 0.0f) { // raycast success rr.Position = closestResult; return(rr); } else { return(null); } } } else { return(null); } }
public unsafe void GetSubMeshInformation(MeshPtr mesh, ref uint vertex_count, ref Mogre.Vector3[] vertices, ref uint index_count, ref UInt64[] indices, Mogre.Vector3 position, Quaternion orientation, Mogre.Vector3 scale, ushort subMeshIndex) { bool added_shared = false; uint current_offset = 0; uint shared_offset = 0; uint next_offset = 0; uint index_offset = 0; vertex_count = index_count = 0; SubMesh submesh = mesh.GetSubMesh(subMeshIndex); // We only need to add the shared vertices once if (submesh.useSharedVertices) { if (!added_shared) { vertex_count += mesh.sharedVertexData.vertexCount; added_shared = true; } } else { vertex_count += submesh.vertexData.vertexCount; } // Add the indices index_count += submesh.indexData.indexCount; // Allocate space for the vertices and indices vertices = new Mogre.Vector3[vertex_count]; indices = new UInt64[index_count]; added_shared = false; // Run through the submesh again, adding the data into the arrays VertexData vertex_data = submesh.useSharedVertices ? mesh.sharedVertexData : submesh.vertexData; if (!submesh.useSharedVertices || (submesh.useSharedVertices && !added_shared)) { if (submesh.useSharedVertices) { added_shared = true; shared_offset = current_offset; } VertexElement posElem = vertex_data.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertex_data.vertexBufferBinding.GetBuffer(posElem.Source); byte* vertex = (byte*)vbuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); float* pReal; // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double // as second argument. So make it float, to avoid trouble when Ogre::Real will // be comiled/typedefed as double: // Ogre::Real* pReal; for (int j = 0; j < vertex_data.vertexCount; ++j, vertex += vbuf.VertexSize) { posElem.BaseVertexPointerToElement(vertex, &pReal); Mogre.Vector3 pt = new Mogre.Vector3(pReal[0], pReal[1], pReal[2]); vertices[current_offset + j] = (orientation * (pt * scale)) + position; } // |!| Important: VertexBuffer Unlock() + Dispose() avoids memory corruption vbuf.Unlock(); vbuf.Dispose(); next_offset += vertex_data.vertexCount; } IndexData index_data = submesh.indexData; uint numTris = index_data.indexCount / 3; HardwareIndexBufferSharedPtr ibuf = index_data.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) bool use32bitindexes = (ibuf.Type == HardwareIndexBuffer.IndexType.IT_32BIT); uint* pLong = (uint*)ibuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); ushort* pShort = (ushort*)pLong; uint offset = submesh.useSharedVertices ? shared_offset : current_offset; if (use32bitindexes) { for (int k = 0; k < index_data.indexCount; ++k) indices[index_offset++] = (UInt64)pLong[k] + (UInt64)offset; } else { for (int k = 0; k < index_data.indexCount; ++k) indices[index_offset++] = (UInt64)pShort[k] + (UInt64)offset; } // |!| Important: IndexBuffer Unlock() + Dispose() avoids memory corruption ibuf.Unlock(); ibuf.Dispose(); current_offset = next_offset; // |!| Important: MeshPtr Dispose() avoids memory corruption mesh.Dispose(); // This dispose the MeshPtr, not the Mesh }