protected void WriteMeshLodManual( BinaryWriter writer, MeshLodUsage usage )
		{
			var start_offset = writer.Seek( 0, SeekOrigin.Current );
			WriteChunk( writer, MeshChunkID.MeshLODManual, 0 );

			WriteString( writer, usage.ManualName );

			var end_offset = writer.Seek( 0, SeekOrigin.Current );
			writer.Seek( (int)start_offset, SeekOrigin.Begin );
			WriteChunk( writer, MeshChunkID.MeshLODManual, (int)( end_offset - start_offset ) );
			writer.Seek( (int)end_offset, SeekOrigin.Begin );
		}
		protected override void ReadMeshLodInfo( BinaryReader reader )
		{
			MeshChunkID chunkId;

			// number of lod levels
			var lodLevelCount = ReadShort( reader );

			// load manual?
			mesh.IsLodManual = ReadBool( reader );

			// preallocate submesh lod face data if not manual
			if ( !mesh.IsLodManual )
			{
				for ( var i = 0; i < mesh.SubMeshCount; i++ )
				{
					var sub = mesh.GetSubMesh( i );

					// TODO: Create typed collection and implement resize
					for ( var j = 1; j < lodLevelCount; j++ )
					{
						sub.lodFaceList.Add( null );
					}
					//sub.lodFaceList.Resize(mesh.lodCount - 1);
				}
			}

			// Loop from 1 rather than 0 (full detail index is not in file)
			for ( var i = 1; i < lodLevelCount; i++ )
			{
				chunkId = ReadChunk( reader );

				if ( chunkId != MeshChunkID.MeshLODUsage )
				{
					throw new AxiomException( "Missing MeshLodUsage chunk in mesh '{0}'", mesh.Name );
				}

				// camera depth
				var usage = new MeshLodUsage();
				usage.Value = ReadFloat( reader );
				usage.UserValue = Utility.Sqrt( usage.Value );

				if ( mesh.IsLodManual )
				{
					ReadMeshLodUsageManual( reader, i, ref usage );
				}
				else
				{
					ReadMeshLodUsageGenerated( reader, i, ref usage );
				}

				// push lod usage onto the mesh lod list
				mesh.MeshLodUsageList.Add( usage );
			}
			Debug.Assert( mesh.LodLevelCount == lodLevelCount );
		}
		protected void WriteMeshLodUsage( BinaryWriter writer, MeshLodUsage usage, int usageIndex )
		{
			var start_offset = writer.Seek( 0, SeekOrigin.Current );
			WriteChunk( writer, MeshChunkID.MeshLODUsage, 0 );

			if ( this.mesh.IsLodManual )
			{
				WriteMeshLodManual( writer, usage );
			}
			else
			{
				for ( var i = 0; i < this.mesh.SubMeshCount; ++i )
				{
					var subMesh = this.mesh.GetSubMesh( i );
					WriteMeshLodGenerated( writer, subMesh, usageIndex );
				}
			}

			var end_offset = writer.Seek( 0, SeekOrigin.Current );
			writer.Seek( (int)start_offset, SeekOrigin.Begin );
			WriteChunk( writer, MeshChunkID.MeshLODUsage, (int)( end_offset - start_offset ) );
			writer.Seek( (int)end_offset, SeekOrigin.Begin );
		}
		protected virtual void ReadMeshLodUsageManual( BinaryReader reader, int lodNum, ref MeshLodUsage usage )
		{
			var chunkId = ReadChunk( reader );

			if ( chunkId != MeshChunkID.MeshLODManual )
			{
				throw new AxiomException( "Missing MeshLODManual chunk in '{0}'.", this.mesh.Name );
			}

			usage.ManualName = ReadString( reader );

			// clearing the reference just in case
			usage.ManualMesh = null;
		}
		protected virtual void ReadMeshLodUsageGenerated( BinaryReader reader, int lodNum, ref MeshLodUsage usage )
		{
			usage.ManualName = "";
			usage.ManualMesh = null;

			// get one set of detail per submesh
			MeshChunkID chunkId;

			for ( var i = 0; i < this.mesh.SubMeshCount; i++ )
			{
				chunkId = ReadChunk( reader );

				if ( chunkId != MeshChunkID.MeshLODGenerated )
				{
					throw new AxiomException( "Missing MeshLodGenerated chunk in '{0}'", this.mesh.Name );
				}

				// get the current submesh
				var sm = this.mesh.GetSubMesh( i );

				// drop another index data object into the list
				var indexData = new IndexData();
				sm.lodFaceList[ lodNum - 1 ] = indexData;

				// number of indices
				indexData.indexCount = ReadInt( reader );

				var is32bit = ReadBool( reader );

				// create an appropriate index buffer and stuff in the data
				if ( is32bit )
				{
					indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size32, indexData.indexCount,
					                                                                          this.mesh.IndexBufferUsage,
					                                                                          this.mesh.UseIndexShadowBuffer );

					// lock the buffer
					var data = indexData.indexBuffer.Lock( BufferLocking.Discard );

					// stuff the data into the index buffer
					ReadInts( reader, indexData.indexCount, data );

					// unlock the index buffer
					indexData.indexBuffer.Unlock();
				}
				else
				{
					indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, indexData.indexCount,
					                                                                          this.mesh.IndexBufferUsage,
					                                                                          this.mesh.UseIndexShadowBuffer );

					// lock the buffer
					var data = indexData.indexBuffer.Lock( BufferLocking.Discard );

					// stuff the data into the index buffer
					ReadShorts( reader, indexData.indexCount, data );

					// unlock the index buffer
					indexData.indexBuffer.Unlock();
				}
			}
		}
Beispiel #6
0
		public Mesh( ResourceManager parent, string name, ResourceHandle handle, string group, bool isManual,
		             IManualResourceLoader loader )
			: base( parent, name, handle, group, isManual, loader )
		{
			// This will be set to false by serializers 1.3 and above
			this._autoBuildEdgeLists = true;

			// default to static write only for speed
			this._vertexBufferUsage = BufferUsage.StaticWriteOnly;
			this._indexBufferUsage = BufferUsage.StaticWriteOnly;

			// default to having shadow buffers
			this._useVertexShadowBuffer = true;
			this._useIndexShadowBuffer = true;

			// Initialize to default strategy
			this._lodStrategy = LodStrategyManager.Instance.DefaultStrategy;

			// Init first (manual) lod
			var lod = new MeshLodUsage();
			lod.UserValue = float.NaN; // User value not used for base lod level
			lod.Value = this._lodStrategy.BaseValue;
			lod.EdgeData = null;
			lod.ManualMesh = null;
			this.meshLodUsageList.Add( lod );


			// always use software blending for now
			this.useSoftwareBlending = true;

			SkeletonName = "";
		}
		protected virtual void ReadMeshLodInfo( BinaryReader reader )
		{
			// Read the strategy to be used for this mesh
			var strategyName = ReadString( reader );
			var strategy = LodStrategyManager.Instance.GetStrategy( strategyName );
			this.mesh.LodStrategy = strategy;

			// number of lod levels
			var lodLevelCount = ReadShort( reader );
			// bool manual;  (true for manual alternate meshes, false for generated)
			this.mesh.IsLodManual = ReadBool( reader ); //readBools(stream, &(pMesh->mIsLodManual), 1);

			// Preallocate submesh lod face data if not manual
			if ( !this.mesh.IsLodManual )
			{
				for ( ushort i = 0; i < this.mesh.SubMeshCount; ++i )
				{
					var sm = this.mesh.GetSubMesh( i );

					// TODO: Create typed collection and implement resize
					for ( var j = 1; j < lodLevelCount; j++ )
					{
						sm.lodFaceList.Add( null );
					}
				}

				MeshChunkID chunkId;
				// Loop from 1 rather than 0 (full detail index is not in file)
				for ( var i = 1; i < lodLevelCount; i++ )
				{
					chunkId = ReadChunk( reader );

					if ( chunkId != MeshChunkID.MeshLODUsage )
					{
						throw new AxiomException( "Missing MeshLODUsage stream in '{0}'.", this.mesh.Name );
					}

					// Read depth
					var usage = new MeshLodUsage();
					usage.Value = ReadFloat( reader );
					usage.UserValue = Utility.Sqrt( usage.Value );

					if ( this.mesh.IsLodManual )
					{
						ReadMeshLodUsageManual( reader, i, ref usage );
					}
					else //(!pMesh->isLodManual)
					{
						ReadMeshLodUsageGenerated( reader, i, ref usage );
					}
					usage.EdgeData = null;

					// Save usage
					this.mesh.MeshLodUsageList.Add( usage );
				}
				Debug.Assert( this.mesh.LodLevelCount == lodLevelCount );
			}
		}
Beispiel #8
0
		public void RemoveLodLevels()
		{
			if ( !IsLodManual )
			{
				foreach ( var subMesh in this._subMeshList )
				{
					subMesh.RemoveLodLevels();
				}
			}

			FreeEdgeList();
			this.meshLodUsageList.Clear();
			var lod = new MeshLodUsage();
			lod.UserValue = float.NaN;
			lod.Value = this._lodStrategy.BaseValue;
			lod.EdgeData = null;
			lod.ManualMesh = null;
			this.meshLodUsageList.Add( lod );
			this._isLodManual = false;
		}
Beispiel #9
0
		public void GenerateLodLevels( LodValueList lodValues, ProgressiveMesh.VertexReductionQuota reductionMethod,
		                               Real reductionValue )
		{
			RemoveLodLevels();

			LogManager.Instance.Write( "Generating {0} lower LODs for mesh {1}.", lodValues.Count, Name );

			foreach ( var subMesh in this._subMeshList )
			{
				// check if triangles are present
				if ( subMesh.IndexData.indexCount > 0 )
				{
					// Set up data for reduction
					var vertexData = subMesh.useSharedVertices ? this._sharedVertexData : subMesh.vertexData;

					var pm = new ProgressiveMesh( vertexData, subMesh.indexData );
					pm.Build( (ushort)lodValues.Count, subMesh.lodFaceList, reductionMethod, reductionValue );
				}
				else
				{
					// create empty index data for each lod
					for ( var i = 0; i < lodValues.Count; ++i )
					{
						subMesh.LodFaceList.Add( new IndexData() );
					}
				}
			}

			// Iterate over the lods and record usage
			foreach ( var value in lodValues )
			{
				// Record usage
				var lod = new MeshLodUsage();
				lod.UserValue = value;
				lod.Value = this._lodStrategy.TransformUserValue( value );
				lod.EdgeData = null;
				lod.ManualMesh = null;
				this.meshLodUsageList.Add( lod );
			}
		}
        private static void SetupManualLodLevels( string srcDir, string dstDir, string name,
                                                 List<LodEntry> lodEntries )
        {
            string dir = string.Empty;
            string path = string.Empty;
            SplitPath( ref dir, ref path, name );
            if( srcDir == string.Empty )
                srcDir = dir;
            if( dstDir == string.Empty )
                dstDir = dir;
            name = path;
            // get the resource data from MeshManager
            string extension = Path.GetExtension( name ).ToLower();

            Mesh mesh = ReadMesh( srcDir, dstDir, name );
            if( mesh.LodLevelCount > 1 )
            {
                log.Warn( "Mesh already contains level of detail information" );
                mesh.RemoveLodLevels();
            }
            List<MeshLodUsage> manualLodList = new List<MeshLodUsage>();
            foreach( LodEntry lodEntry in lodEntries )
            {
                Mesh lodMesh = ReadMesh( dstDir, dstDir, lodEntry.meshFile );
                MeshLodUsage lodUsage = new MeshLodUsage();
                lodUsage.fromSquaredDepth = lodEntry.distance * lodEntry.distance;
                lodUsage.manualMesh = lodMesh;
                lodUsage.manualName = lodMesh.Name;
                manualLodList.Add( lodUsage );
            }
            mesh.AddManualLodEntries( manualLodList );

            MeshSerializer meshWriter = new MeshSerializer();
            meshWriter.ExportMesh( mesh, dstDir + name );
        }
        protected virtual void ReadMeshLodInfo(BinaryMemoryReader reader)
        {
            MeshChunkID chunkId;

            // number of lod levels
            mesh.numLods = ReadShort(reader);

            // load manual?
            mesh.isLodManual = ReadBool(reader);

            // preallocate submesh lod face data if not manual
            if(!mesh.isLodManual) {
                for(int i = 0; i < mesh.SubMeshCount; i++) {
                    SubMesh sub = mesh.GetSubMesh(i);

                    // TODO: Create typed collection and implement resize
                    for(int j = 1; j < mesh.numLods; j++) {
                        sub.lodFaceList.Add(null);
                    }
                    //sub.lodFaceList.Resize(mesh.numLods - 1);
                }
            }

            // Loop from 1 rather than 0 (full detail index is not in file)
            for(int i = 1; i < mesh.numLods; i++) {
                chunkId = ReadChunk(reader);

                if(chunkId != MeshChunkID.MeshLODUsage) {
                    throw new AxiomException("Missing MeshLodUsage chunk in mesh '{0}'", mesh.Name);
                }

                // camera depth
                MeshLodUsage usage = new MeshLodUsage();
                usage.fromSquaredDepth = ReadFloat(reader);

                if(mesh.isLodManual) {
                    ReadMeshLodUsageManual(reader, i, ref usage);
                }
                else {
                    ReadMeshLodUsageGenerated(reader, i, ref usage);
                }

                // push lod usage onto the mesh lod list
                mesh.lodUsageList.Add(usage);
            }
        }
        protected void WriteMeshLodUsage(BinaryWriter writer, MeshLodUsage usage, int usageIndex)
        {
            long start_offset = writer.Seek(0, SeekOrigin.Current);
            WriteChunk(writer, MeshChunkID.MeshLODUsage, 0);

            WriteFloat(writer, usage.fromSquaredDepth);

            if (mesh.IsLodManual)
                WriteMeshLodManual(writer, usage);
            else {
                for (int i = 0; i < mesh.SubMeshCount; ++i) {
                    SubMesh subMesh = mesh.GetSubMesh(i);
                    WriteMeshLodGenerated(writer, subMesh, usageIndex);
                }
            }

            long end_offset = writer.Seek(0, SeekOrigin.Current);
            writer.Seek((int)start_offset, SeekOrigin.Begin);
            WriteChunk(writer, MeshChunkID.MeshLODUsage, (int)(end_offset - start_offset));
            writer.Seek((int)end_offset, SeekOrigin.Begin);
        }