/// <summary> /// Parses the mesh data from the current data segment. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> protected void ParseMeshData(DataReader3DS dataSegment) { string name = dataSegment.GetString(); // mesh object name DataReader3DS subSegment = dataSegment.GetNextSubSegment(); // working subsegment this.currentMeshData = new MeshData3DS(); this.currentMeshData.Name = name; while (subSegment != null) { switch (subSegment.Tag) { case 0x4100: // Current subsegment contains the polygonal information this.ParsePolygonalData(subSegment); break; default: // Ignore all other subsegment types break; } subSegment = dataSegment.GetNextSubSegment(); } while (this.meshDataStore.ContainsKey(this.currentMeshData.Name)) { this.currentMeshData.Name += "X"; } this.meshDataStore.Add(this.currentMeshData.Name, this.currentMeshData); }
/// <summary> /// Parses the face-specific polygonal data from the current data segment. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> protected void ParseFaceData(DataReader3DS dataSegment) { int i; // counter DataReader3DS subSegment; // will be used to read other subsegments (do not initialize yet) this.currentMeshData.Faces = new MeshData3DS.FaceData3DS[dataSegment.GetUShort()]; // Read face data for (i = 0; i < this.currentMeshData.Faces.Length; i++) { this.currentMeshData.Faces[i].Vertex1 = dataSegment.GetUShort(); this.currentMeshData.Faces[i].Vertex2 = dataSegment.GetUShort(); this.currentMeshData.Faces[i].Vertex3 = dataSegment.GetUShort(); this.currentMeshData.Faces[i].Flags = dataSegment.GetUShort(); } // Read other subsegments subSegment = dataSegment.GetNextSubSegment(); while (subSegment != null) { switch (subSegment.Tag) { case 0x4130: // Name of material used this.currentMeshData.MaterialUsed = subSegment.GetString(); break; } subSegment = dataSegment.GetNextSubSegment(); } }
/// <summary> /// Moves to the next subsegment of data in the data stream. /// </summary> /// <returns>Returns the next subsegment of data in the data stream.</returns> public DataReader3DS GetNextSubSegment() { if (this.currentSegment.BaseStream.Position > 3700000) { Debug.WriteLine("Breaking..."); } if ((ulong)this.currentSegment.BaseStream.Position < (this.size - HeaderSize)) { if (this.currentSubSegment != null) { this.currentSegment.BaseStream.Position += (long)this.currentSubSegment.Size; this.currentSubSegment = null; } //currentSubSegment = new DataReader3DS(sourceData, // (int)currentSegment.BaseStream.Position, // (int)(currentSegment.BaseStream.Length - currentSegment.BaseStream.Position)); if ((this.currentSegment.BaseStream.Length - this.currentSegment.BaseStream.Position) > 0) { this.currentSubSegment = new DataReader3DS(this.sourceData, (int) (this.myStreamOffset + (ulong)this.currentSegment.BaseStream.Position), (int) (this.currentSegment.BaseStream.Length - this.currentSegment.BaseStream.Position)); } } else { this.currentSubSegment = null; } return(this.currentSubSegment); }
protected ushort tag; //specifies what is contained in the data subsegment #endregion #region Constructor(s) /// <summary> /// Creates a DataReader3DS object. /// </summary> /// <param name="inputData">Contains array of data bytes.</param> public DataReader3DS(byte[] inputData) { this.sourceData = inputData; this.myStreamOffset = 0; this.sourceStream = new MemoryStream(this.sourceData); this.dataReader = new BinaryReader(this.sourceStream); this.tag = this.dataReader.ReadUInt16(); this.size = (ulong)this.dataReader.ReadInt32(); this.currentSubSegment = null; this.currentSegment = this.dataReader; }
protected ushort tag; //specifies what is contained in the data subsegment #endregion Fields #region Constructors /// <summary> /// Creates a DataReader3DS object. /// </summary> /// <param name="inputData">Contains array of data bytes.</param> public DataReader3DS(byte[] inputData) { this.sourceData = inputData; this.myStreamOffset = 0; this.sourceStream = new MemoryStream(this.sourceData); this.dataReader = new BinaryReader(this.sourceStream); this.tag = this.dataReader.ReadUInt16(); this.size = (ulong)this.dataReader.ReadInt32(); this.currentSubSegment = null; this.currentSegment = this.dataReader; }
/// <summary> /// Internal constructor that creates a DataReader3DS object. /// </summary> /// <param name="inputData">Contains array of data bytes.</param> /// <param name="startingPoint">Specified starting location.</param> /// <param name="length">Specified length.</param> protected DataReader3DS(byte[] inputData, int startingPoint, int length) { this.sourceData = inputData; this.myStreamOffset = (ulong)startingPoint; this.sourceStream = new MemoryStream(this.sourceData, startingPoint, length); this.dataReader = new BinaryReader(this.sourceStream); this.tag = this.dataReader.ReadUInt16(); this.size = (ulong)this.dataReader.ReadInt32(); this.currentSubSegment = null; this.currentSegment = this.dataReader; }
/// <summary> /// Parses the polygonal data from the current data segment. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> protected void ParsePolygonalData(DataReader3DS dataSegment) { int i; // counter DataReader3DS subSegment = dataSegment.GetNextSubSegment(); // working data subsegment while (subSegment != null) { switch (subSegment.Tag) { case 0x4110: // Subsegment contains vertex information this.currentMeshData.Vertices = new Point3D[subSegment.GetUShort()]; for (i = 0; i < this.currentMeshData.Vertices.Length; i++) { this.currentMeshData.Vertices[i].X = subSegment.GetFloat(); this.currentMeshData.Vertices[i].Y = subSegment.GetFloat(); this.currentMeshData.Vertices[i].Z = subSegment.GetFloat(); } break; case 0x4160: // Subsegment contains translation matrix info (ignore for now) break; case 0x4120: // Subsegment contains face information this.ParseFaceData(subSegment); break; case 0x4140: // Subsegment contains texture mapping information this.currentMeshData.TextureCoordinates = new Point2D[subSegment.GetUShort()]; //HACK: This is because the above array allocation doesn't automatically //HACK: create each element. for (i = 0; i < this.currentMeshData.TextureCoordinates.Length; i++) { this.currentMeshData.TextureCoordinates[i] = new Point2D(); } //HACK: End hack. if (this.currentMeshData.TextureCoordinates.Length != this.currentMeshData.Vertices.Length) { Console.WriteLine("WARNING: Possible errors in texture coordinate mapping!"); } for (i = 0; i < this.currentMeshData.TextureCoordinates.Length; i++) { this.currentMeshData.TextureCoordinates[i].X = subSegment.GetFloat(); this.currentMeshData.TextureCoordinates[i].Y = subSegment.GetFloat(); } break; } subSegment = dataSegment.GetNextSubSegment(); } // Also use face data to calculate vertex normals this.CalculateVertexNormals(); }
public void Load() { DataReader3DS dataSubSegment = null; //Validate that the 3DS file is good if ((this.dataReader != null) && (this.dataReader.Tag == 0x4D4D)) { dataSubSegment = this.dataReader.GetNextSubSegment(); } else { throw new FileLoadException("3DS file is either corrupted or otherwise not recognizable."); } // Check to see what kind of data is contained in the current data subsegment while (dataSubSegment != null) { // Check the tag to see what sort of data is in this subsegment (or "chunk") switch (dataSubSegment.Tag) { case 0x0002: // Subsegment contains 3DS version ushort version3DS = dataSubSegment.GetUShort(); //This is the 3DS version this.version = version3DS.ToString(); break; case 0x3D3D: // Subsegment contains 3DS data this.ParseData(dataSubSegment); break; } dataSubSegment = this.dataReader.GetNextSubSegment(); } //// Attempt to write mesh data to the .mesh.xml file //if (meshDataStore.Count > 0) { // try { // WriteMeshFile(meshFileName); // } catch (Exception anyException) { // System.Console.WriteLine("Error writing mesh XML file. See below for error..."); // System.Console.WriteLine(anyException.Message); // } //} //// Attempt to write material data to the .material file //if (materialDataStore.Count > 0) { // try { // WriteMaterialFile(materialFileName); // } catch (Exception anyException) { // System.Console.WriteLine("Error writing material file. See below for error..."); // System.Console.WriteLine(anyException.Message); // } //} }
public Loader3DSModel(String filePath) { if (filePath != null && File.Exists(filePath)) { this.filePath = filePath; this.stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); BinaryReader byteExtractor = new BinaryReader(this.stream); this.dataReader = new DataReader3DS(byteExtractor.ReadBytes((int) this.stream.Length)); this.meshDataStore = new Hashtable(); this.materialDataStore = new Hashtable(); this.currentMeshData = null; this.currentMaterialData = null; } else { throw new FileNotFoundException(); } }
/// <summary> /// Parses the texture weight from the current data segment. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> protected void ParseTextureWeight(DataReader3DS dataSegment) { switch (dataSegment.Tag) { case 0x0030: // Percentage is in short format this.currentMaterialData.textureWeight = ((float)dataSegment.GetUShort()) / (float)100.0; break; case 0x0031: // Percentage is in float format this.currentMaterialData.textureWeight = dataSegment.GetFloat(); break; default: // There should be no other formats, but if there are then we ignore break; } }
public Loader3DSModel(String filePath) { if (filePath != null && File.Exists(filePath)) { this.filePath = filePath; this.stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); BinaryReader byteExtractor = new BinaryReader(this.stream); this.dataReader = new DataReader3DS(byteExtractor.ReadBytes((int)this.stream.Length)); this.meshDataStore = new Hashtable(); this.materialDataStore = new Hashtable(); this.currentMeshData = null; this.currentMaterialData = null; } else { throw new FileNotFoundException(); } }
/// <summary> /// Parses the 3DS data stream into mesh and material information. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> protected void ParseData(DataReader3DS dataSegment) { DataReader3DS subSegment = dataSegment.GetNextSubSegment(); while (subSegment != null) { switch (subSegment.Tag) { case 0xafff: // Current subsegment holds material data this.ParseMaterialData(subSegment); break; case 0x4000: // Current subsegment holds mesh data this.ParseMeshData(subSegment); break; } subSegment = dataSegment.GetNextSubSegment(); } }
/// <summary> /// Parses the material data from the current data segment. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> protected void ParseMaterialData(DataReader3DS dataSegment) { DataReader3DS subSegment = dataSegment.GetNextSubSegment(); this.currentMaterialData = new MaterialData3DS(); while (subSegment != null) { switch (subSegment.Tag) { case 0xa000: // Subsegment holds material name this.currentMaterialData.name = subSegment.GetString(); Console.WriteLine("Material is named: " + this.currentMaterialData.name); break; case 0xa010: // Subsegment holds ambient color this.currentMaterialData.ambient = this.ParseColorData(subSegment.GetNextSubSegment()); break; case 0xa020: // Subsegment holds diffuse color (this is iffy...) this.currentMaterialData.diffuse = this.ParseColorData(subSegment.GetNextSubSegment()); break; case 0xa200: // Subsegment holds texture map info this.ParseTextureWeight(subSegment.GetNextSubSegment()); this.currentMaterialData.textureName = subSegment.GetNextSubSegment().GetString(); break; default: // Ignore all other subsegment types break; } subSegment = dataSegment.GetNextSubSegment(); } // Store newly created material in data store and change name if another exists with its name while (this.materialDataStore.ContainsKey(this.currentMaterialData.name)) { this.currentMaterialData.name += "X"; } this.materialDataStore.Add(this.currentMaterialData.name, this.currentMaterialData); }
/// <summary> /// Parses color data from the current data segment. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> /// <returns> /// Returns the color that was parsed. /// </returns> protected RGBColor ParseColorData(DataReader3DS dataSegment) { RGBColor result = RGBColor.Black; switch (dataSegment.Tag) { case 0x0010: // Color is in float format result.R = dataSegment.GetFloat(); result.G = dataSegment.GetFloat(); result.B = dataSegment.GetFloat(); break; case 0x0011: // Color is in byte format result.R = dataSegment.GetByte() / 255.0f; result.G = dataSegment.GetByte() / 255.0f; result.B = dataSegment.GetByte() / 255.0f; break; default: // If there are any other formats, then we ignore them break; } return(result); }
/// <summary> /// Parses the texture weight from the current data segment. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> protected void ParseTextureWeight(DataReader3DS dataSegment) { switch (dataSegment.Tag) { case 0x0030: // Percentage is in short format this.currentMaterialData.textureWeight = ((float) dataSegment.GetUShort()) / (float) 100.0; break; case 0x0031: // Percentage is in float format this.currentMaterialData.textureWeight = dataSegment.GetFloat(); break; default: // There should be no other formats, but if there are then we ignore break; } }
/// <summary> /// Parses color data from the current data segment. /// </summary> /// <param name="dataSegment"> /// Contains the data to be parsed. /// </param> /// <returns> /// Returns the color that was parsed. /// </returns> protected RGBColor ParseColorData(DataReader3DS dataSegment) { RGBColor result = RGBColor.Black; switch (dataSegment.Tag) { case 0x0010: // Color is in float format result.R = dataSegment.GetFloat(); result.G = dataSegment.GetFloat(); result.B = dataSegment.GetFloat(); break; case 0x0011: // Color is in byte format result.R = dataSegment.GetByte() / 255.0f; result.G = dataSegment.GetByte() / 255.0f; result.B = dataSegment.GetByte() / 255.0f; break; default: // If there are any other formats, then we ignore them break; } return result; }
/// <summary> /// Moves to the next subsegment of data in the data stream. /// </summary> /// <returns>Returns the next subsegment of data in the data stream.</returns> public DataReader3DS GetNextSubSegment() { if(this.currentSegment.BaseStream.Position > 3700000){ Debug.WriteLine("Breaking..."); } if((ulong)this.currentSegment.BaseStream.Position < (this.size - HeaderSize)){ if(this.currentSubSegment != null){ this.currentSegment.BaseStream.Position += (long)this.currentSubSegment.Size; this.currentSubSegment = null; } //currentSubSegment = new DataReader3DS(sourceData, // (int)currentSegment.BaseStream.Position, // (int)(currentSegment.BaseStream.Length - currentSegment.BaseStream.Position)); if((this.currentSegment.BaseStream.Length - this.currentSegment.BaseStream.Position) > 0){ this.currentSubSegment = new DataReader3DS(this.sourceData, (int) (this.myStreamOffset + (ulong)this.currentSegment.BaseStream.Position), (int) (this.currentSegment.BaseStream.Length - this.currentSegment.BaseStream.Position)); } } else{ this.currentSubSegment = null; } return this.currentSubSegment; }