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

SplitGeometry() protected method

protected SplitGeometry ( VertexData vd, IndexData id, Axiom.Core.SubMeshLodGeometryLink targetGeomLink ) : void
vd Axiom.Graphics.VertexData
id Axiom.Graphics.IndexData
targetGeomLink Axiom.Core.SubMeshLodGeometryLink
return void
		protected unsafe void SplitGeometry( VertexData vd, IndexData id, SubMeshLodGeometryLink targetGeomLink )
		{
			if ( logLevel <= 1 )
				LogManager.Instance.Write( "StaticGeometry.SplitGeometry called" );
			// 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;
			Dictionary<int, int> indexRemap = new Dictionary<int, int>();
			IntPtr src = id.indexBuffer.Lock( BufferLocking.ReadOnly );
			indexRemap.Clear();
			if ( use32bitIndexes )
			{
				int* p32 = (int*)src.ToPointer();
				for ( int i = 0; i < id.indexCount; ++i )
					indexRemap[ *p32++ ] = indexRemap.Count;
			}
			else
			{
				short* p16 = (short*)src.ToPointer();
				for ( int i = 0; i < id.indexCount; ++i )
					indexRemap[ *p16++ ] = indexRemap.Count;
			}
			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 ( short b = 0; b < numvbufs; ++b )
			{
				// Lock old buffer
				HardwareVertexBuffer oldBuf = vd.vertexBufferBinding.GetBuffer( b );
				// Create new buffer
				HardwareVertexBuffer newBuf =
					HardwareBufferManager.Instance.CreateVertexBuffer( oldBuf.VertexDeclaration, indexRemap.Count, BufferUsage.Static );
				// rebind
				newvd.vertexBufferBinding.SetBinding( 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)
				IntPtr vdSrc = oldBuf.Lock( BufferLocking.ReadOnly );
				byte* pSrcBase = (byte*)vdSrc.ToPointer();
				IntPtr vdDest = newBuf.Lock( BufferLocking.Discard );
				byte* pDstBase = (byte*)vdDest.ToPointer();
				int vertexSize = oldBuf.VertexSize;
				// Buffers should be the same size
				Debug.Assert( vertexSize == newBuf.VertexSize );

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

					byte* pSrc = pSrcBase + pair.Key * vertexSize;
					byte* pDst = pDstBase + pair.Value * vertexSize;
					for ( int i = 0; i < vertexSize; i++ )
						*pDst++ = *pSrc++;
				}
				// unlock
				oldBuf.Unlock();
				newBuf.Unlock();
			}

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

			IntPtr idSrc = id.indexBuffer.Lock( BufferLocking.ReadOnly );
			IntPtr idDest = ibuf.Lock( BufferLocking.Discard );
			if ( use32bitIndexes )
			{
				int* pSrc32 = (int*)idSrc.ToPointer();
				int* pDst32 = (int*)idDest.ToPointer();
				for ( int i = 0; i < id.indexCount; ++i )
					*pDst32++ = (int)indexRemap[ *pSrc32++ ];
			}
			else
			{
				ushort* pSrc16 = (ushort*)idSrc.ToPointer();
				ushort* pDst16 = (ushort*)idDest.ToPointer();
				for ( int i = 0; i < id.indexCount; ++i )
					*pDst16++ = (ushort)indexRemap[ *pSrc16++ ];
			}
			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;
			optimisedSubMeshGeometryList.Add( optGeom );
		}