Beispiel #1
0
        protected List <SubMeshLodGeometryLink> DetermineGeometry(SubMesh sm)
        {
            // First, determine if we've already seen this submesh before
            List <SubMeshLodGeometryLink> lodList;

            if (this.subMeshGeometryLookup.TryGetValue(sm, out lodList))
            {
                return(lodList);
            }
            // Otherwise, we have to create a new one
            lodList = new List <SubMeshLodGeometryLink>();
            this.subMeshGeometryLookup[sm] = lodList;
            var numLods = sm.Parent.IsLodManual ? 1 : sm.Parent.LodLevelCount;

            for (var lod = 0; lod < numLods; ++lod)
            {
                var geomLink = new SubMeshLodGeometryLink();
                lodList.Add(geomLink);
                var lodIndexData = lod == 0 ? sm.indexData : sm.LodFaceList[lod - 1];
                // Can use the original mesh geometry?
                if (sm.useSharedVertices)
                {
                    if (sm.Parent.SubMeshCount == 1)
                    {
                        // Ok, this is actually our own anyway
                        geomLink.vertexData = sm.Parent.SharedVertexData;
                        geomLink.indexData  = lodIndexData;
                    }
                    else
                    {
                        // We have to split it
                        SplitGeometry(sm.Parent.SharedVertexData, lodIndexData, geomLink);
                    }
                }
                else
                {
                    if (lod == 0)
                    {
                        // Ok, we can use the existing geometry; should be in full
                        // use by just this SubMesh
                        geomLink.vertexData = sm.VertexData;
                        geomLink.indexData  = sm.IndexData;
                    }
                    else
                    {
                        // We have to split it
                        SplitGeometry(sm.VertexData, lodIndexData, geomLink);
                    }
                }
                Debug.Assert(geomLink.vertexData.vertexStart == 0,
                             "Cannot use vertexStart > 0 on indexed geometry due to " +
                             "rendersystem incompatibilities - see the docs!");
            }
            return(lodList);
        }
Beispiel #2
0
            protected string GetGeometryFormatString(SubMeshLodGeometryLink geom)
            {
                // Formulate an identifying string for the geometry format
                // Must take into account the vertex declaration and the index type
                // Format is (all lines separated by '|'):
                // Index type
                // Vertex element (repeating)
                //   source
                //   semantic
                //   type
                var str = string.Format("{0}|", geom.indexData.indexBuffer.Type);

                for (var i = 0; i < geom.vertexData.vertexDeclaration.ElementCount; ++i)
                {
                    var elem = geom.vertexData.vertexDeclaration.GetElement(i);
                    str += string.Format("{0}|{0}|{1}|{2}|", elem.Source, elem.Semantic, elem.Type);
                }
                return(str);
            }
Beispiel #3
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);
            }
        }
Beispiel #4
0
			protected string GetGeometryFormatString( SubMeshLodGeometryLink geom )
			{
				// Formulate an identifying string for the geometry format
				// Must take into account the vertex declaration and the index type
				// Format is (all lines separated by '|'):
				// Index type
				// Vertex element (repeating)
				//   source
				//   semantic
				//   type
				var str = string.Format( "{0}|", geom.indexData.indexBuffer.Type );

				for ( var i = 0; i < geom.vertexData.vertexDeclaration.ElementCount; ++i )
				{
					var elem = geom.vertexData.vertexDeclaration.GetElement( i );
					str += string.Format( "{0}|{0}|{1}|{2}|", elem.Source, elem.Semantic, elem.Type );
				}
				return str;
			}
			/// Get a packed string identifying the geometry format
			//TODO
			protected String GetGeometryFormatString( SubMeshLodGeometryLink geom )
			{
				return "";
			}
		/// <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 );
		}
Beispiel #7
0
        /// <summary>
        ///   Look up or calculate the geometry data to use for this SubMesh
        /// </summary>
        /// <param name="sm"> </param>
        /// <returns> </returns>
        public List <SubMeshLodGeometryLink> DetermineGeometry(SubMesh sm)
        {
            // First, determine if we've already seen this submesh before
            if (mSubMeshGeometryLookup.ContainsKey(sm))
            {
                return(mSubMeshGeometryLookup[sm]);
            }

            // Otherwise, we have to create a new one
            var lodList = new List <SubMeshLodGeometryLink>();

            mSubMeshGeometryLookup[sm] = lodList;

            int numLods = sm.Parent.IsLodManual ? 1 : sm.Parent.LodLevelCount;

            lodList.Capacity = numLods;

            for (int lod = 0; lod < numLods; ++lod)
            {
                SubMeshLodGeometryLink geomLink = lodList[lod];
                IndexData lodIndexData;
                if (lod == 0)
                {
                    lodIndexData = sm.IndexData;
                }
                else
                {
                    lodIndexData = sm.LodFaceList[lod - 1];
                }
                // Can use the original mesh geometry?
                if (sm.useSharedVertices)
                {
                    if (sm.Parent.SubMeshCount == 1)
                    {
                        // Ok, this is actually our own anyway
                        geomLink.vertexData = sm.Parent.SharedVertexData;
                        geomLink.indexData  = lodIndexData;
                    }
                    else
                    {
                        // We have to split it
                        SplitGeometry(sm.Parent.SharedVertexData,
                                      lodIndexData, ref geomLink);
                    }
                }
                else
                {
                    if (lod == 0)
                    {
                        // Ok, we can use the existing geometry; should be in full
                        // use by just this SubMesh
                        geomLink.vertexData = sm.vertexData;
                        geomLink.indexData  = sm.indexData;
                    }
                    else
                    {
                        // We have to split it
                        SplitGeometry(sm.vertexData,
                                      lodIndexData, ref geomLink);
                    }
                }

                Debug.Assert(geomLink.vertexData.vertexStart == 0,
                             "Cannot use vertexStart > 0 on indexed geometry due to rendersystem incompatibilities - see the docs!");
            }

            return(lodList);
        }
Beispiel #8
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);
        }
Beispiel #9
0
 /// Get a packed string identifying the geometry format
 //TODO
 protected String GetGeometryFormatString(SubMeshLodGeometryLink geom)
 {
     return("");
 }
Beispiel #10
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 );
			}
		}
Beispiel #11
0
		protected List<SubMeshLodGeometryLink> DetermineGeometry( SubMesh sm )
		{
			// First, determine if we've already seen this submesh before
			List<SubMeshLodGeometryLink> lodList;
			if ( this.subMeshGeometryLookup.TryGetValue( sm, out lodList ) )
			{
				return lodList;
			}
			// Otherwise, we have to create a new one
			lodList = new List<SubMeshLodGeometryLink>();
			this.subMeshGeometryLookup[ sm ] = lodList;
			var numLods = sm.Parent.IsLodManual ? 1 : sm.Parent.LodLevelCount;
			for ( var lod = 0; lod < numLods; ++lod )
			{
				var geomLink = new SubMeshLodGeometryLink();
				lodList.Add( geomLink );
				var lodIndexData = lod == 0 ? sm.indexData : sm.LodFaceList[ lod - 1 ];
				// Can use the original mesh geometry?
				if ( sm.useSharedVertices )
				{
					if ( sm.Parent.SubMeshCount == 1 )
					{
						// Ok, this is actually our own anyway
						geomLink.vertexData = sm.Parent.SharedVertexData;
						geomLink.indexData = lodIndexData;
					}
					else
					{
						// We have to split it
						SplitGeometry( sm.Parent.SharedVertexData, lodIndexData, geomLink );
					}
				}
				else
				{
					if ( lod == 0 )
					{
						// Ok, we can use the existing geometry; should be in full
						// use by just this SubMesh
						geomLink.vertexData = sm.VertexData;
						geomLink.indexData = sm.IndexData;
					}
					else
					{
						// We have to split it
						SplitGeometry( sm.VertexData, lodIndexData, geomLink );
					}
				}
				Debug.Assert( geomLink.vertexData.vertexStart == 0,
				              "Cannot use vertexStart > 0 on indexed geometry due to " +
				              "rendersystem incompatibilities - see the docs!" );
			}
			return lodList;
		}
        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);
        }
Beispiel #13
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);
        }