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(); } } }
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 ); } }
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; }
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); }