Exemple #1
0
        protected void SplitGeometry(VertexData vd, IndexData id, SubMeshLodGeometryLink targetGeomLink)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                if (this.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
                var use32bitIndexes = id.indexBuffer.Type == IndexType.Size32;
                var indexRemap      = new Dictionary <int, int>();
                var src             = id.indexBuffer.Lock(BufferLocking.ReadOnly);
                indexRemap.Clear();
                if (use32bitIndexes)
                {
                    var p32 = src.ToIntPointer();
                    for (var i = 0; i < id.indexCount; ++i)
                    {
                        indexRemap[p32[i]] = indexRemap.Count;
                    }
                }
                else
                {
                    var p16 = src.ToShortPointer();
                    for (var i = 0; i < id.indexCount; ++i)
                    {
                        indexRemap[p16[i]] = 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
                var newvd = targetGeomLink.vertexData;
                //IndexData newid = targetGeomLink.IndexData;
                // Update the vertex count
                newvd.vertexCount = indexRemap.Count;

                var numvbufs = vd.vertexBufferBinding.BindingCount;
                // Copy buffers from old to new
                for (short b = 0; b < numvbufs; ++b)
                {
                    // Lock old buffer
                    var oldBuf = vd.vertexBufferBinding.GetBuffer(b);
                    // Create new buffer
                    var 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)
                    var vdSrc      = oldBuf.Lock(BufferLocking.ReadOnly);
                    var pSrcBase   = vdSrc;
                    var vdDest     = newBuf.Lock(BufferLocking.Discard);
                    var pDstBase   = vdDest;
                    var vertexSize = oldBuf.VertexSize;
                    // Buffers should be the same size
                    Debug.Assert(vertexSize == newBuf.VertexSize);

                    foreach (var pair in indexRemap)
                    {
                        Debug.Assert(pair.Key < oldBuf.VertexCount);
                        Debug.Assert(pair.Value < newBuf.VertexCount);

                        var pSrc = (pSrcBase + pair.Key * vertexSize).ToBytePointer();
                        var pDst = (pDstBase + pair.Value * vertexSize).ToBytePointer();
                        for (var i = 0; i < vertexSize; i++)
                        {
                            pDst[i] = pSrc[i];
                        }
                    }
                    // unlock
                    oldBuf.Unlock();
                    newBuf.Unlock();
                }

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

                var idSrc  = id.indexBuffer.Lock(BufferLocking.ReadOnly);
                var idDest = ibuf.Lock(BufferLocking.Discard);
                if (use32bitIndexes)
                {
                    var pSrc32 = idSrc.ToIntPointer();
                    var pDst32 = idDest.ToIntPointer();
                    for (var i = 0; i < id.indexCount; ++i)
                    {
                        pDst32[i] = indexRemap[pSrc32[i]];
                    }
                }
                else
                {
                    var pSrc16 = idSrc.ToUShortPointer();
                    var pDst16 = idDest.ToUShortPointer();
                    for (var i = 0; i < id.indexCount; ++i)
                    {
                        pDst16[i] = (ushort)indexRemap[pSrc16[i]];
                    }
                }
                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
                var optGeom = new OptimisedSubMeshGeometry();
                optGeom.indexData  = targetGeomLink.indexData;
                optGeom.vertexData = targetGeomLink.vertexData;
                this.optimisedSubMeshGeometryList.Add(optGeom);
            }
        }
		/// <summary>
		///   Split some shared geometry into dedicated geometry.
		/// </summary>
		/// <param name="vd"> </param>
		/// <param name="id"> </param>
		/// <param name="targetGeomLink"> </param>
		public 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;

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

			if ( use32bitIndexes )
			{
				var p32 = id.indexBuffer.Lock( id.indexStart, id.indexCount*id.indexBuffer.IndexSize, BufferLocking.ReadOnly );
				BuildIndexRemap( p32, id.indexCount, ref indexRemap );
				id.indexBuffer.Unlock();
			}
			else
			{
				var p16 = 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.VertexDeclaration,
						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)
				var pSrcBase = oldBuf.Lock( BufferLocking.ReadOnly );
				var pDstBase = newBuf.Lock( BufferLocking.Discard );
				int vertexSize = oldBuf.VertexSize;
				// Buffers should be the same size
				Debug.Assert( vertexSize == newBuf.VertexSize );

				foreach ( var r in indexRemap )
				{
					Debug.Assert( r.Key < oldBuf.VertexCount );
					Debug.Assert( r.Value < newBuf.VertexCount );

					var pSrc = pSrcBase + r.Key*vertexSize;
					var pDst = pDstBase + r.Value*vertexSize;
					var pSrcPtr = pSrc;
					var pDstPtr = 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
			var optGeom = new OptimisedSubMeshGeometry();
			optGeom.indexData = targetGeomLink.indexData;
			optGeom.vertexData = targetGeomLink.vertexData;
			mOptimisedSubMeshGeometryList.Add( optGeom );
		}
Exemple #3
0
        /// <summary>
        ///   Split some shared geometry into dedicated geometry.
        /// </summary>
        /// <param name="vd"> </param>
        /// <param name="id"> </param>
        /// <param name="targetGeomLink"> </param>
        public 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;

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

            if (use32bitIndexes)
            {
                var p32 = id.indexBuffer.Lock(id.indexStart, id.indexCount * id.indexBuffer.IndexSize, BufferLocking.ReadOnly);
                BuildIndexRemap(p32, id.indexCount, ref indexRemap);
                id.indexBuffer.Unlock();
            }
            else
            {
                var p16 = 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.VertexDeclaration,
                        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)
                var pSrcBase   = oldBuf.Lock(BufferLocking.ReadOnly);
                var pDstBase   = newBuf.Lock(BufferLocking.Discard);
                int vertexSize = oldBuf.VertexSize;
                // Buffers should be the same size
                Debug.Assert(vertexSize == newBuf.VertexSize);

                foreach (var r in indexRemap)
                {
                    Debug.Assert(r.Key < oldBuf.VertexCount);
                    Debug.Assert(r.Value < newBuf.VertexCount);

                    var pSrc    = pSrcBase + r.Key * vertexSize;
                    var pDst    = pDstBase + r.Value * vertexSize;
                    var pSrcPtr = pSrc;
                    var pDstPtr = 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
            var optGeom = new OptimisedSubMeshGeometry();

            optGeom.indexData  = targetGeomLink.indexData;
            optGeom.vertexData = targetGeomLink.vertexData;
            mOptimisedSubMeshGeometryList.Add(optGeom);
        }
		protected void SplitGeometry( VertexData vd, IndexData id, SubMeshLodGeometryLink targetGeomLink )
		{
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				if ( this.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
				var use32bitIndexes = id.indexBuffer.Type == IndexType.Size32;
				var indexRemap = new Dictionary<int, int>();
				var src = id.indexBuffer.Lock( BufferLocking.ReadOnly );
				indexRemap.Clear();
				if ( use32bitIndexes )
				{
					var p32 = src.ToIntPointer();
					for ( var i = 0; i < id.indexCount; ++i )
					{
						indexRemap[ p32[ i ] ] = indexRemap.Count;
					}
				}
				else
				{
					var p16 = src.ToShortPointer();
					for ( var i = 0; i < id.indexCount; ++i )
					{
						indexRemap[ p16[ i ] ] = 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
				var newvd = targetGeomLink.vertexData;
				//IndexData newid = targetGeomLink.IndexData;
				// Update the vertex count
				newvd.vertexCount = indexRemap.Count;

				var numvbufs = vd.vertexBufferBinding.BindingCount;
				// Copy buffers from old to new
				for ( short b = 0; b < numvbufs; ++b )
				{
					// Lock old buffer
					var oldBuf = vd.vertexBufferBinding.GetBuffer( b );
					// Create new buffer
					var 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)
					var vdSrc = oldBuf.Lock( BufferLocking.ReadOnly );
					var pSrcBase = vdSrc;
					var vdDest = newBuf.Lock( BufferLocking.Discard );
					var pDstBase = vdDest;
					var vertexSize = oldBuf.VertexSize;
					// Buffers should be the same size
					Debug.Assert( vertexSize == newBuf.VertexSize );

					foreach ( var pair in indexRemap )
					{
						Debug.Assert( pair.Key < oldBuf.VertexCount );
						Debug.Assert( pair.Value < newBuf.VertexCount );

						var pSrc = ( pSrcBase + pair.Key*vertexSize ).ToBytePointer();
						var pDst = ( pDstBase + pair.Value*vertexSize ).ToBytePointer();
						for ( var i = 0; i < vertexSize; i++ )
						{
							pDst[ i ] = pSrc[ i ];
						}
					}
					// unlock
					oldBuf.Unlock();
					newBuf.Unlock();
				}

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

				var idSrc = id.indexBuffer.Lock( BufferLocking.ReadOnly );
				var idDest = ibuf.Lock( BufferLocking.Discard );
				if ( use32bitIndexes )
				{
					var pSrc32 = idSrc.ToIntPointer();
					var pDst32 = idDest.ToIntPointer();
					for ( var i = 0; i < id.indexCount; ++i )
					{
						pDst32[ i ] = indexRemap[ pSrc32[ i ] ];
					}
				}
				else
				{
					var pSrc16 = idSrc.ToUShortPointer();
					var pDst16 = idDest.ToUShortPointer();
					for ( var i = 0; i < id.indexCount; ++i )
					{
						pDst16[ i ] = (ushort)indexRemap[ pSrc16[ i ] ];
					}
				}
				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
				var optGeom = new OptimisedSubMeshGeometry();
				optGeom.indexData = targetGeomLink.indexData;
				optGeom.vertexData = targetGeomLink.vertexData;
				this.optimisedSubMeshGeometryList.Add( optGeom );
			}
		}
        protected unsafe void SplitGeometry(VertexData vd, IndexData id, SubMeshLodGeometryLink targetGeomLink)
        {
            log.Info("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 (ushort b = 0; b < numvbufs; ++b)
            {
                // Lock old buffer
                HardwareVertexBuffer oldBuf = vd.vertexBufferBinding.GetBuffer(b);
                // Create new buffer
                HardwareVertexBuffer newBuf =
                    HardwareBufferManager.Instance.CreateVertexBuffer(oldBuf.VertexSize, 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);
        }
Exemple #6
0
        protected unsafe void SplitGeometry(VertexData vd, IndexData id, SubMeshLodGeometryLink targetGeomLink)
        {
            log.Info("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 (ushort b = 0; b < numvbufs; ++b)
            {
                // Lock old buffer
                HardwareVertexBuffer oldBuf = vd.vertexBufferBinding.GetBuffer(b);
                // Create new buffer
                HardwareVertexBuffer newBuf =
                    HardwareBufferManager.Instance.CreateVertexBuffer(oldBuf.VertexSize, 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);
        }