Axiom.Core.InstancedGeometry.SplitGeometry C# (CSharp) Method

SplitGeometry() public method

Split some shared geometry into dedicated geometry.
public SplitGeometry ( VertexData vd, IndexData id, Axiom.Core.SubMeshLodGeometryLink &targetGeomLink ) : void
vd Axiom.Graphics.VertexData
id Axiom.Graphics.IndexData
targetGeomLink Axiom.Core.SubMeshLodGeometryLink
return void
		public unsafe void SplitGeometry( VertexData vd, IndexData id, ref SubMeshLodGeometryLink targetGeomLink )
		{
			// Firstly we need to scan to see how many vertices are being used
			// and while we're at it, build the remap we can use later
			bool use32bitIndexes = id.indexBuffer.Type == IndexType.Size32;
			ushort* p16;
			uint* p32;

			Dictionary<int, int> indexRemap = new Dictionary<int, int>();

			if ( use32bitIndexes )
			{
				p32 = (uint*)id.indexBuffer.Lock(
					id.indexStart,
					id.indexCount * id.indexBuffer.IndexSize,
					BufferLocking.ReadOnly );
				BuildIndexRemap( p32, id.indexCount, ref indexRemap );
				id.indexBuffer.Unlock();
			}
			else
			{
				p16 = (ushort*)id.indexBuffer.Lock(
					id.indexStart,
					id.indexCount * id.indexBuffer.IndexSize,
					BufferLocking.ReadOnly );
				BuildIndexRemap( p16, id.indexCount, ref indexRemap );
				id.indexBuffer.Unlock();
			}

			if ( indexRemap.Count == vd.vertexCount )
			{
				// ha, complete usage after all
				targetGeomLink.vertexData = vd;
				targetGeomLink.indexData = id;
				return;
			}

			// Create the new vertex data records
			targetGeomLink.vertexData = vd.Clone( false );
			// Convenience
			VertexData newvd = targetGeomLink.vertexData;
			//IndexData* newid = targetGeomLink->indexData;
			// Update the vertex count
			newvd.vertexCount = indexRemap.Count;

			int numvbufs = vd.vertexBufferBinding.BindingCount;

			// Copy buffers from old to new
			for ( int b = 0; b < numvbufs; ++b )
			{
				// Lock old buffer
				HardwareVertexBuffer oldBuf = vd.vertexBufferBinding.GetBuffer( (short)b );
				// Create new buffer
				HardwareVertexBuffer newBuf =
					HardwareBufferManager.Instance.CreateVertexBuffer(
						oldBuf.VertexSize,
						indexRemap.Count,
						BufferUsage.Static );
				// rebind
				newvd.vertexBufferBinding.SetBinding( (short)b, newBuf );

				// Copy all the elements of the buffer across, by iterating over
				// the IndexRemap which describes how to move the old vertices
				// to the new ones. By nature of the map the remap is in order of
				// indexes in the old buffer, but note that we're not guaranteed to
				// address every vertex (which is kinda why we're here)
				byte* pSrcBase = (byte*)oldBuf.Lock( BufferLocking.ReadOnly );
				byte* pDstBase = (byte*)newBuf.Lock( BufferLocking.Discard );
				int vertexSize = oldBuf.VertexSize;
				// Buffers should be the same size
				Debug.Assert( vertexSize == newBuf.VertexSize );

				foreach ( KeyValuePair<int, int> r in indexRemap )
				{
					Debug.Assert( r.Key < oldBuf.VertexCount );
					Debug.Assert( r.Value < newBuf.VertexCount );

					void* pSrc = pSrcBase + r.Key * vertexSize;
					void* pDst = pDstBase + r.Value * vertexSize;
					IntPtr pSrcPtr = new IntPtr( pSrc );
					IntPtr pDstPtr = new IntPtr( pDst );
					Memory.Copy( pDstPtr, pSrcPtr, vertexSize );
				}
				// unlock
				oldBuf.Unlock();
				newBuf.Unlock();

			}

			// Now create a new index buffer
			HardwareIndexBuffer ibuf = HardwareBufferManager.Instance.CreateIndexBuffer(
					id.indexBuffer.Type, id.indexCount, BufferUsage.Static );

			if ( use32bitIndexes )
			{
				uint* pSrc32, pDst32;
				pSrc32 = (uint*)id.indexBuffer.Lock(
					id.indexStart, id.indexCount * id.indexBuffer.IndexSize, BufferLocking.ReadOnly );
				pDst32 = (uint*)ibuf.Lock( BufferLocking.Discard );
				RemapIndexes( pSrc32, pDst32, ref indexRemap, id.indexCount );
				id.indexBuffer.Unlock();
				ibuf.Unlock();
			}
			else
			{
				ushort* pSrc16, pDst16;
				pSrc16 = (ushort*)id.indexBuffer.Lock(
					id.indexStart, id.indexCount * id.indexBuffer.IndexSize, BufferLocking.ReadOnly );
				pDst16 = (ushort*)ibuf.Lock( BufferLocking.Discard );
				RemapIndexes( pSrc16, pDst16, ref indexRemap, id.indexCount );
				id.indexBuffer.Unlock();
				ibuf.Unlock();
			}

			targetGeomLink.indexData = new IndexData();
			targetGeomLink.indexData.indexStart = 0;
			targetGeomLink.indexData.indexCount = id.indexCount;
			targetGeomLink.indexData.indexBuffer = ibuf;

			// Store optimised geometry for deallocation later
			OptimisedSubMeshGeometry optGeom = new OptimisedSubMeshGeometry();
			optGeom.indexData = targetGeomLink.indexData;
			optGeom.vertexData = targetGeomLink.vertexData;
			mOptimisedSubMeshGeometryList.Add( optGeom );
		}