void ProcessMaterialChunk(ThreeDSChunk chunk) { string name = string.Empty; Material m = new Material(); while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((Groups)child.ID) { case Groups.C_MATNAME: name = ProcessString(child); Console.WriteLine("Material: {0}", name); break; case Groups.C_MATAMBIENT: m.Ambient = ProcessColorChunk(child); break; case Groups.C_MATDIFFUSE: m.Diffuse = ProcessColorChunk(child); break; case Groups.C_MATSPECULAR: m.Specular = ProcessColorChunk(child); break; case Groups.C_MATSHININESS: m.Shininess = ProcessPercentageChunk(child); //Console.WriteLine ( "SHININESS: {0}", m.Shininess ); break; case Groups.C_MAT_TRANSPARENCY: m.Trans = 100 - ProcessPercentageChunk(child); break; case Groups.C_MATMAP: ProcessPercentageChunk(child); //SkipChunk ( child ); ProcessTexMapChunk(child, m); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; } materials.Add(name, m); }
Entity ProcessObjectChunk(ThreeDSChunk chunk, Entity e) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(this, reader); #if LOG_CHUNKS Logger.Log("ProcessObjectChunk: chunk = {0:X}, len = {1}", child.ID, chunk.Length); #endif switch (child.ID) { case Groups.C_OBJECT_MESH: ProcessObjectChunk(child, e); break; case Groups.C_OBJECT_VERTICES: e.vertices = ReadVertices(child); break; case Groups.C_OBJECT_FACES: e.triangles = ReadTriangles(child); #if LOG_FACES Logger.Log("Object Faces: {0}", e.indices.Length); #endif if (child.BytesRead < child.Length) { ProcessFaceChunk(child, e); } break; case Groups.C_OBJECT_UV: int cnt = reader.ReadUInt16(); child.BytesRead += 2; //Console.WriteLine ( " TexCoords: {0}", cnt ); e.texcoords = new TexCoord [cnt]; for (int ii = 0; ii < cnt; ii++) { e.texcoords [ii] = new TexCoord(reader.ReadSingle(), reader.ReadSingle()); } child.BytesRead += (cnt * (4 * 2)); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; child.SkipToEnd(reader); //Console.WriteLine ( " ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } return(e); }
Vector[] ReadVertices(ThreeDSChunk chunk) { ushort numVerts = reader.ReadUInt16(); chunk.BytesRead += 2; //Console.WriteLine ( " Vertices: {0}", numVerts ); Vector[] verts = new Vector[numVerts]; for (int ii = 0; ii < numVerts; ii++) { float f1 = reader.ReadSingle(); float f2 = reader.ReadSingle(); float f3 = reader.ReadSingle(); verts[ii] = new Vector(f1, f3, -f2); //Console.WriteLine ( verts [ii] ); } //Console.WriteLine ( "{0} {1}", verts.Length * ( 3 * 4 ), chunk.Length - chunk.BytesRead ); chunk.BytesRead += verts.Length * (3 * 4); //chunk.BytesRead = (int) chunk.Length; //SkipChunk ( chunk ); return(verts); }
void SkipChunk(ThreeDSChunk chunk) { int length = (int)chunk.Length - chunk.BytesRead; reader.ReadBytes(length); chunk.BytesRead += length; }
float[] ProcessColorChunk(ThreeDSChunk chunk) { ThreeDSChunk child = new ThreeDSChunk(this, reader); float red = 1.0f; float green = 1.0f; float blue = 1.0f; switch (child.ID) { // Each color component is represented by a single-precision floating point number. case Groups.C_COLOR_F: red = reader.ReadSingle(); green = reader.ReadSingle(); blue = reader.ReadSingle(); break; // Each color component is represented by a byte. case Groups.C_COLOR_24: red = (float)reader.ReadByte() / 255.0f; green = (float)reader.ReadByte() / 255.0f; blue = (float)reader.ReadByte() / 255.0f; break; } // Logger.Log("ProcessColorChunk: color = ({0},{1},{2}) len = {3}", red, green, blue, child.Length); chunk.BytesRead += (int)child.Length; child.SkipToEnd(reader); return(new float[] { red, green, blue }); }
void ProcessChunk(ThreeDSChunk chunk) { // process chunks until there are none left while (chunk.BytesRead < chunk.Length) { // grab a chunk ThreeDSChunk child = new ThreeDSChunk(reader); // process based on ID switch ((Groups)child.ID) { case Groups.C_VERSION: version = reader.ReadInt32(); child.BytesRead += 4; break; case Groups.C_OBJECTINFO: // not sure whats up with this chunk //SkipChunk ( obj_chunk ); //child.BytesRead += obj_chunk.BytesRead; //ProcessChunk ( child ); // blender 3ds export (others?) uses this // in the hierarchy of objects and materials // so lets process the next (child) chunk break; case Groups.C_MATERIAL: ProcessMaterialChunk(child); break; case Groups.C_OBJECT: // string name = ProcessString(child); Entity e = ProcessObjectChunk(child); e.CalculateNormals(); model.Entities.Add(e); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; //Console.WriteLine ( "ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } }
Entity ProcessFaceChunk(ThreeDSChunk chunk, Entity e) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(this, reader); #if LOG_CHUNKS Logger.Log("ProcessFaceChunk: chunk = {0:X}, len = {1}", child.ID, chunk.Length); #endif switch (child.ID) { case Groups.C_OBJECT_MATERIAL: string materialName = ProcessString(child); #if LOG_FACES Logger.Log("Uses Material: {0}", materialName); #endif Material material = null; if (materials.TryGetValue(materialName, out material)) { e.material = material; } #if LOG_MATERIAL else { Logger.Log(" Warning: Material '{0}' not found. ", materialName); } #endif //Console.WriteLine(" Warning: Material '{0}' not found. ", name2); //throw new Exception ( "Material not found!" ); int nfaces = reader.ReadUInt16(); child.BytesRead += 2; #if LOG_FACES Logger.Log("ProcessFaceChunk: {0} material faces", nfaces); #endif for (int i = 0; i < nfaces; i++) { int faceIndex = reader.ReadUInt16(); e.triangles[faceIndex].material = (material ?? Triangle.defaultMaterial); child.BytesRead += 2; } SkipChunk(child); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; child.SkipToEnd(reader); //Console.WriteLine ( " ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } return(e); }
void ProcessChunk(ThreeDSChunk chunk) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((Groups)child.ID) { case Groups.C_VERSION: int version = reader.ReadInt32(); child.BytesRead += 4; Console.WriteLine("3DS File Version: {0}", version); break; case Groups.C_OBJECTINFO: ThreeDSChunk obj_chunk = new ThreeDSChunk(reader); // not sure whats up with this chunk SkipChunk(obj_chunk); child.BytesRead += obj_chunk.BytesRead; ProcessChunk(child); break; case Groups.C_MATERIAL: ProcessMaterialChunk(child); //SkipChunk ( child ); break; case Groups.C_OBJECT: //SkipChunk ( child ); string name = ProcessString(child); Console.WriteLine("OBJECT NAME: {0}", name); Object3d e = ProcessObjectChunk(child); //e.CalculateNormals(); e.Update(); models.Add(e); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; //Console.WriteLine ( "ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } }
float[] ProcessColorChunk(ThreeDSChunk chunk) { ThreeDSChunk child = new ThreeDSChunk(reader); float[] c = new float[] { (float)reader.ReadByte() / 256, (float)reader.ReadByte() / 256, (float)reader.ReadByte() / 256 }; //Console.WriteLine ( "R {0} G {1} B {2}", c.R, c.B, c.G ); chunk.BytesRead += (int)child.Length; return(c); }
int ProcessPercentageChunk(ThreeDSChunk chunk) { ThreeDSChunk child = new ThreeDSChunk(reader); int per = reader.ReadUInt16(); child.BytesRead += 2; chunk.BytesRead += child.BytesRead; return(per); }
void ProcessMaterialChunk(ThreeDSChunk chunk) { string name = string.Empty; ThreeDSMaterial m = new ThreeDSMaterial(); while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((ThreeDSChunkType)child.ID) { case ThreeDSChunkType.MaterialName: name = ProcessString(child); Console.WriteLine("Material: {0}", name); break; case ThreeDSChunkType.AmbientColor: m.Ambient = ProcessColorChunk(child); break; case ThreeDSChunkType.DiffuseColor: m.Diffuse = ProcessColorChunk(child); break; case ThreeDSChunkType.SpecularColor: m.Specular = ProcessColorChunk(child); break; case ThreeDSChunkType.C_MATSHININESS: m.Shininess = ProcessPercentageChunk(child); //Console.WriteLine ( "SHININESS: {0}", m.Shininess ); break; case ThreeDSChunkType.TextureMap: ProcessPercentageChunk(child); //SkipChunk ( child ); ProcessTexMapChunk(child, m); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; } materials.Add(name, m); }
void ProcessChunk(ThreeDSChunk chunk) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((ThreeDSChunkType)child.ID) { case ThreeDSChunkType.CVersion: int version = reader.ReadInt32(); child.BytesRead += 4; Console.WriteLine("3DS File Version: {0}", version); break; case ThreeDSChunkType._3DEditorChunk: ThreeDSChunk obj_chunk = new ThreeDSChunk(reader); // not sure whats up with this chunk SkipChunk(obj_chunk); child.BytesRead += obj_chunk.BytesRead; ProcessChunk(child); break; case ThreeDSChunkType.EditorMaterial: ProcessMaterialChunk(child); //SkipChunk ( child ); break; case ThreeDSChunkType.ObjectBlock: //SkipChunk ( child ); string name = ProcessString(child); Console.WriteLine("OBJECT NAME: {0}", name); ThreeDSMesh e = ProcessObjectChunk(child); e.CalculateNormals(); model.Entities.Add(e); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; //Console.WriteLine ( "ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } }
Vector[] ReadVertices(ThreeDSChunk chunk) { ushort numVerts = reader.ReadUInt16(); chunk.BytesRead += 2; Console.WriteLine(" Vertices: {0}", numVerts); Vector[] verts = new Vector[numVerts]; for (int ii = 0; ii < verts.Length; ii++) { float f1 = reader.ReadSingle(); float f2 = reader.ReadSingle(); float f3 = reader.ReadSingle(); Vector v = new Vector(f1, f3, -f2); // track the boundaries of this model if (v.X > maxX) { maxX = v.X; } if (v.Y > maxY) { maxY = v.Y; } if (v.Z > maxZ) { maxZ = v.Z; } if (v.X < minX) { minX = v.X; } if (v.Y < minY) { minY = v.Y; } if (v.Z < minZ) { minZ = v.Z; } verts[ii] = v; //Console.WriteLine ( verts [ii] ); } //Console.WriteLine ( "{0} {1}", verts.Length * ( 3 * 4 ), chunk.Length - chunk.BytesRead ); chunk.BytesRead += verts.Length * (3 * 4); //chunk.BytesRead = (int) chunk.Length; //SkipChunk ( chunk ); return(verts); }
/// <summary> /// Constructor /// </summary> /// <param name="file_name"> /// A <see cref="System.String"/>. The path to the 3ds file /// </param> public ThreeDSFile(string file_name) { if (string.IsNullOrEmpty(file_name)) { throw new ArgumentNullException("file_name"); } if (!File.Exists(file_name)) { throw new ArgumentException("3ds file could not be found", "file_name"); } // 3ds models can use additional files which are expected in the same directory base_dir = new FileInfo(file_name).DirectoryName + "/"; maxX = maxY = maxZ = double.MinValue; minX = minY = minZ = double.MaxValue; FileStream file = null; try { // create a binary stream from this file file = new FileStream(file_name, FileMode.Open, FileAccess.Read); reader = new BinaryReader(file); reader.BaseStream.Seek(0, SeekOrigin.Begin); // 3ds files are in chunks // read the first one ThreeDSChunk chunk = new ThreeDSChunk(reader); if (chunk.ID != (short)Groups.C_PRIMARY) { throw new FormatException("Not a proper 3DS file."); } // recursively process chunks ProcessChunk(chunk); } finally { // close up everything if (reader != null) { reader.Close(); } if (file != null) { file.Close(); } } }
public void LoadModel(Stream stream) { Contract.Requires(stream != null); /* * if (string.IsNullOrEmpty(file_name)) * { * throw new ArgumentNullException("file_name"); * } * * if (!File.Exists(file_name)) * { * throw new ArgumentException("3ds file could not be found", "file_name"); * } * * // 3ds models can use additional files which are expected in the same directory * base_dir = new FileInfo ( file_name ).DirectoryName + "/"; */ // FileStream file = null; try { // create a binary stream from this file // file = new FileStream(file_name, FileMode.Open, FileAccess.Read); // reader = new BinaryReader ( file ); reader = new BinaryReader(stream); // reader.BaseStream.Seek (0, SeekOrigin.Begin); // 3ds files are in chunks // read the first one ThreeDSChunk chunk = new ThreeDSChunk(this, reader); #if LOG_CHUNKS Logger.Log("ThreeDSFile: first chunk = {0:X}, len = {1}", chunk.ID, chunk.Length); #endif if (chunk.ID != Groups.C_PRIMARY) { throw new FormatException("Not a proper 3DS file."); } // Don't skip to the end of this chunk, as it contains the entire file/model. // recursively process chunks ProcessChunk(chunk); } finally { // close up everything // if (reader != null) reader.Close (); // if (file != null) file.Close (); } }
void ProcessTexMapChunk(ThreeDSChunk chunk, Material m) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((Groups)child.ID) { case Groups.C_MATMAPFILE: string name = ProcessString(child); Console.WriteLine(" Texture File: {0}", name); /* * Bitmap bmp; * try * { * bmp = new Bitmap(base_dir + name); * } * catch (Exception e) * { * // couldn't find the file * Console.WriteLine(" ERROR: could not load file '{0}'", base_dir + name); * break; * } * * // Flip image (needed so texture are the correct way around!) * bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); * * System.Drawing.Imaging.BitmapData imgData = bmp.LockBits(new Rectangle(new Point(0, 0), bmp.Size), * System.Drawing.Imaging.ImageLockMode.ReadOnly, * System.Drawing.Imaging.PixelFormat.Format32bppArgb); * // System.Drawing.Imaging.PixelFormat.Format24bppRgb ); * * m.BindTexture(imgData.Width, imgData.Height, imgData.Scan0); * * bmp.UnlockBits(imgData); * bmp.Dispose(); */ break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; } }
void SkipChunk(ThreeDSChunk chunk) { int length = (int)chunk.Length - chunk.BytesRead; #if LOG_CHUNKS Logger.Log("SkipChunk: len = {0}, bytesRead = {1}", chunk.Length, chunk.BytesRead); #endif reader.BaseStream.Seek(length, SeekOrigin.Current); // reader.ReadBytes(length); chunk.BytesRead += length; // ModelLoadProgressEvent(this, new ProgressChangedEventArgs(reader.BaseStream.Position * 100.0 / reader.BaseStream.Length)); }
void SkipChunk(ThreeDSChunk chunk, int maxSkip = -1) { int length = (int)chunk.Length - chunk.BytesRead; if (maxSkip != -1) { if (length > maxSkip)//Something wrong about 3ds file may happen here. { length = maxSkip; } } //reader.ReadBytes(length); reader.BaseStream.Position += length; chunk.BytesRead += length; }
Triangle[] ReadIndices(ThreeDSChunk chunk) { ushort numIdcs = reader.ReadUInt16(); chunk.BytesRead += 2; Console.WriteLine(" Indices: {0}", numIdcs); Triangle[] idcs = new Triangle[numIdcs]; for (int ii = 0; ii < idcs.Length; ii++) { idcs[ii] = new Triangle(reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16()); // flags reader.ReadUInt16(); } chunk.BytesRead += (2 * 4) * idcs.Length; return(idcs); }
string ProcessString(ThreeDSChunk chunk) { StringBuilder sb = new StringBuilder(); byte b = reader.ReadByte(); int idx = 0; while (b != 0) { sb.Append((char)b); b = reader.ReadByte(); idx++; } chunk.BytesRead += idx + 1; return(sb.ToString()); }
public ThreeDSFile(string file_name) { base_dir = new FileInfo(file_name).DirectoryName + "/"; FileStream file; file = new FileStream(file_name, FileMode.Open, FileAccess.Read); reader = new BinaryReader(file); reader.BaseStream.Seek(0, SeekOrigin.Begin); ThreeDSChunk chunk = new ThreeDSChunk(reader); if (chunk.ID != (short)Groups.C_PRIMARY) throw new ApplicationException("Not a proper 3DS file."); ProcessChunk(chunk); reader.Close(); file.Close(); }
ArrayList ReadVertices(ThreeDSChunk chunk) { ushort numVerts = reader.ReadUInt16(); chunk.BytesRead += 2; Console.WriteLine(" Vertices: {0}", numVerts); ArrayList lst = new ArrayList(); for (int ii = 0; ii < numVerts; ii++) { float f1 = reader.ReadSingle(); float f2 = reader.ReadSingle(); float f3 = reader.ReadSingle(); Point3d pnt = new Point3d(f1, f2, f3, 1.0); lst.Add(pnt); } chunk.BytesRead += lst.Count * (3 * 4); return(lst); }
public ThreeDSFile(string file_name) { base_dir = new FileInfo(file_name).DirectoryName + "/"; FileStream file; file = new FileStream(file_name, FileMode.Open, FileAccess.Read); reader = new BinaryReader(file); reader.BaseStream.Seek(0, SeekOrigin.Begin); ThreeDSChunk chunk = new ThreeDSChunk(reader); if (chunk.ID != (short)Groups.C_PRIMARY) { throw new ApplicationException("Not a proper 3DS file."); } ProcessChunk(chunk); reader.Close(); file.Close(); }
void ProcessTexMapChunk(ThreeDSChunk chunk, Material m) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((Groups)child.ID) { case Groups.C_MATMAPFILE: string name = ProcessString(child); Console.WriteLine(" Texture File: {0}", name); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; } }
Triangle[] ReadTriangles(ThreeDSChunk chunk) { ushort numTris = reader.ReadUInt16(); chunk.BytesRead += 2; //Console.WriteLine ( " Triangles: {0}", numTris ); Triangle[] tris = new Triangle[numTris]; for (int ii = 0; ii < numTris; ii++) { tris [ii] = new Triangle(reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16()); //Console.WriteLine ( idcs [ii] ); // flags reader.ReadUInt16(); } chunk.BytesRead += (2 * 4) * tris.Length; //Console.WriteLine ( "b {0} l {1}", chunk.BytesRead, chunk.Length); //chunk.BytesRead = (int) chunk.Length; //SkipChunk ( chunk ); return(tris); }
void ProcessMaterialChunk(ThreeDSChunk chunk) { string name = string.Empty; Material m = new Material(); while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(this, reader); #if LOG_CHUNKS Logger.Log("ProcessMaterialChunk: chunk = {0:X}, len = {1}", child.ID, chunk.Length); #endif switch (child.ID) { case Groups.C_MATNAME: name = ProcessString(child); #if LOG_MATERIAL Logger.Log("Material name: {0}", name); #endif break; case Groups.C_MATAMBIENT: m.Ambient = ProcessColorChunk(child); #if LOG_MATERIAL Logger.Log("Material ambient color: ({0},{1},{2})", m.Ambient[0], m.Ambient[1], m.Ambient[2]); #endif break; case Groups.C_MATDIFFUSE: m.Diffuse = ProcessColorChunk(child); #if LOG_MATERIAL Logger.Log("Material diffuse color: ({0},{1},{2})", m.Diffuse[0], m.Diffuse[1], m.Diffuse[2]); #endif break; case Groups.C_MATSPECULAR: m.Specular = ProcessColorChunk(child); #if LOG_MATERIAL Logger.Log("Material specular color: ({0},{1},{2})", m.Specular[0], m.Specular[1], m.Specular[2]); #endif break; case Groups.C_MATSHININESS: m.Shininess = ProcessPercentageChunk(child); #if LOG_MATERIAL Logger.Log("Material shininess: {0}", m.Shininess); #endif break; case Groups.C_MATMAP: ProcessPercentageChunk(child); ProcessTexMapChunk(child, m); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; child.SkipToEnd(reader); } // Don't add materials with duplicate names if (!materials.ContainsKey(name)) { materials.Add(name, m); } }
Object3d ProcessObjectChunk(ThreeDSChunk chunk, Object3d e) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((Groups)child.ID) { case Groups.C_OBJECT_MESH: ProcessObjectChunk(child, e); break; case Groups.C_OBJECT_VERTICES: //e.vertices = ReadVertices(child); e.m_lstpoints = ReadVertices(child); break; case Groups.C_OBJECT_FACES: //e.indices = Triangle []tris = ReadIndices(child); foreach (Triangle t in tris) { Polygon p = new Polygon(); p.m_points = new Point3d[3]; p.m_points[0] = (Point3d)e.m_lstpoints[t.vertex1]; p.m_points[1] = (Point3d)e.m_lstpoints[t.vertex2]; p.m_points[2] = (Point3d)e.m_lstpoints[t.vertex3]; e.m_lstpolys.Add(p); } e.Update(); if (child.BytesRead < child.Length) ProcessObjectChunk(child, e); break; case Groups.C_OBJECT_MATERIAL: string name2 = ProcessString(child); Console.WriteLine(" Uses Material: {0}", name2); Material mat; if (materials.TryGetValue(name2, out mat)) e.material = mat; else Console.WriteLine(" Warning: Material '{0}' not found. ", name2); SkipChunk(child); break; case Groups.C_OBJECT_UV: int cnt = reader.ReadUInt16(); child.BytesRead += 2; Console.WriteLine(" TexCoords: {0}", cnt); //e.texcoords = new TexCoord[cnt]; //TexCoord tc = new TexCoord(); for (int ii = 0; ii < cnt; ii++) { //should add this to a list somewhere TexCoord tc = new TexCoord(reader.ReadSingle(), reader.ReadSingle()); } child.BytesRead += (cnt * (4 * 2)); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; //Console.WriteLine ( " ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } return e; }
Object3d ProcessObjectChunk(ThreeDSChunk chunk, Object3d e) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((Groups)child.ID) { case Groups.C_OBJECT_MESH: ProcessObjectChunk(child, e); break; case Groups.C_OBJECT_VERTICES: //e.vertices = ReadVertices(child); e.m_lstpoints = ReadVertices(child); break; case Groups.C_OBJECT_FACES: //e.indices = Triangle [] tris = ReadIndices(child); foreach (Triangle t in tris) { Polygon p = new Polygon(); p.m_points = new Point3d[3]; p.m_points[0] = (Point3d)e.m_lstpoints[t.vertex1]; p.m_points[1] = (Point3d)e.m_lstpoints[t.vertex2]; p.m_points[2] = (Point3d)e.m_lstpoints[t.vertex3]; e.m_lstpolys.Add(p); } e.Update(); if (child.BytesRead < child.Length) { ProcessObjectChunk(child, e); } break; case Groups.C_OBJECT_MATERIAL: string name2 = ProcessString(child); Console.WriteLine(" Uses Material: {0}", name2); Material mat; if (materials.TryGetValue(name2, out mat)) { e.material = mat; } else { Console.WriteLine(" Warning: Material '{0}' not found. ", name2); } SkipChunk(child); break; case Groups.C_OBJECT_UV: int cnt = reader.ReadUInt16(); child.BytesRead += 2; Console.WriteLine(" TexCoords: {0}", cnt); //e.texcoords = new TexCoord[cnt]; //TexCoord tc = new TexCoord(); for (int ii = 0; ii < cnt; ii++) { //should add this to a list somewhere TexCoord tc = new TexCoord(reader.ReadSingle(), reader.ReadSingle()); } child.BytesRead += (cnt * (4 * 2)); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; //Console.WriteLine ( " ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } return(e); }
void ProcessTexMapChunk(ThreeDSChunk chunk, Material m) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((Groups)child.ID) { case Groups.C_MATMAPFILE: string name = ProcessString(child); Console.WriteLine(" Texture File: {0}", name); /* Bitmap bmp; try { bmp = new Bitmap(base_dir + name); } catch (Exception e) { // couldn't find the file Console.WriteLine(" ERROR: could not load file '{0}'", base_dir + name); break; } // Flip image (needed so texture are the correct way around!) bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); System.Drawing.Imaging.BitmapData imgData = bmp.LockBits(new Rectangle(new Point(0, 0), bmp.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); // System.Drawing.Imaging.PixelFormat.Format24bppRgb ); m.BindTexture(imgData.Width, imgData.Height, imgData.Scan0); bmp.UnlockBits(imgData); bmp.Dispose(); */ break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; } }
/// <summary> /// Constructor /// </summary> /// <param name="file_name"> /// A <see cref="System.String"/>. The path to the 3ds file /// </param> public ThreeDSFile( string file_name ) { if (string.IsNullOrEmpty(file_name)) { throw new ArgumentNullException("file_name"); } if (!File.Exists(file_name)) { throw new ArgumentException("3ds file could not be found", "file_name"); } // 3ds models can use additional files which are expected in the same directory base_dir = new FileInfo ( file_name ).DirectoryName + "/"; maxX = maxY = maxZ = double.MinValue; minX = minY = minZ = double.MaxValue; FileStream file = null; try { // create a binary stream from this file file = new FileStream(file_name, FileMode.Open, FileAccess.Read); reader = new BinaryReader ( file ); reader.BaseStream.Seek (0, SeekOrigin.Begin); // 3ds files are in chunks // read the first one ThreeDSChunk chunk = new ThreeDSChunk ( reader ); if ( chunk.ID != (short) Groups.C_PRIMARY ) { throw new FormatException ( "Not a proper 3DS file." ); } // recursively process chunks ProcessChunk ( chunk ); } finally { // close up everything if (reader != null) reader.Close (); if (file != null) file.Close (); } }
Vector[] ReadVertices( ThreeDSChunk chunk ) { ushort numVerts = reader.ReadUInt16 (); chunk.BytesRead += 2; Console.WriteLine ( " Vertices: {0}", numVerts ); Vector[] verts = new Vector[numVerts]; for ( int ii=0; ii < verts.Length ; ii++ ) { float f1 = reader.ReadSingle(); float f2 = reader.ReadSingle(); float f3 = reader.ReadSingle(); Vector v = new Vector ( f1, f3, -f2 ); // track the boundaries of this model if (v.X > maxX) maxX = v.X; if (v.Y > maxY) maxY = v.Y; if (v.Z > maxZ) maxZ = v.Z; if (v.X < minX) minX = v.X; if (v.Y < minY) minY = v.Y; if (v.Z < minZ) minZ = v.Z; verts[ii] = v; //Console.WriteLine ( verts [ii] ); } //Console.WriteLine ( "{0} {1}", verts.Length * ( 3 * 4 ), chunk.Length - chunk.BytesRead ); chunk.BytesRead += verts.Length * ( 3 * 4 ) ; //chunk.BytesRead = (int) chunk.Length; //SkipChunk ( chunk ); return verts; }
void ProcessChunk(ThreeDSChunk chunk) { // process chunks until there are none left while (chunk.BytesRead < chunk.Length) { // grab a chunk ThreeDSChunk child = new ThreeDSChunk(this, reader); #if LOG_CHUNKS Logger.Log("ProcessChunk: chunk = {0:X}, len = {1}", child.ID, chunk.Length); #endif // process based on ID switch (child.ID) { case Groups.C_VERSION: version = reader.ReadInt32(); child.BytesRead += 4; break; case Groups.C_OBJECTINFO: ThreeDSChunk obj_chunk = new ThreeDSChunk(this, reader); // not sure whats up with this chunk SkipChunk(obj_chunk); child.BytesRead += obj_chunk.BytesRead; ProcessChunk(child); break; case Groups.C_MATERIAL: ProcessMaterialChunk(child); break; case Groups.C_OBJECT: // string name = ProcessString(child); Entity e = ProcessObjectChunk(child); if (e.vertices != null && e.triangles != null) { e.CalculateNormals(); model.Entities.Add(e); } break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; // Don't skip to the end of certain chunks, as they contain the entire file/model. if (child.ID != Groups.C_VERSION) { // Skip to the end of this chunk. child.SkipToEnd(reader); } //Console.WriteLine ( "ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } }
Vector[] ReadVertices(ThreeDSChunk chunk) { ushort numVerts = reader.ReadUInt16(); chunk.BytesRead += 2; Console.WriteLine(" Vertices: {0}", numVerts); Vector[] verts = new Vector[numVerts]; for (int ii = 0; ii < verts.Length; ii++) { float f1 = reader.ReadSingle(); float f2 = reader.ReadSingle(); float f3 = reader.ReadSingle(); verts[ii] = new Vector(f1, f3, -f2); //Console.WriteLine ( verts [ii] ); } //Console.WriteLine ( "{0} {1}", verts.Length * ( 3 * 4 ), chunk.Length - chunk.BytesRead ); chunk.BytesRead += verts.Length * (3 * 4); //chunk.BytesRead = (int) chunk.Length; //SkipChunk ( chunk ); return verts; }
Entity ProcessObjectChunk(ThreeDSChunk chunk) { return(ProcessObjectChunk(chunk, new Entity())); }
void ProcessTexMapChunk( ThreeDSChunk chunk, Material m ) { while ( chunk.BytesRead < chunk.Length ) { ThreeDSChunk child = new ThreeDSChunk ( reader ); switch ((Groups) child.ID) { case Groups.C_MATMAPFILE: string name = ProcessString ( child ); //Console.WriteLine ( " Texture File: {0}", name ); // use System.Drawing to try and load this image //FileStream fStream; Bitmap bmp; try { //fStream = new FileStream(base_dir + name, FileMode.Open, FileAccess.Read); bmp = new Bitmap ( base_dir + name ); } catch ( Exception ex ) { // couldn't find the file Console.WriteLine ( " ERROR: could not load file '{0}': {1}", base_dir + name, ex.Message ); break; } // Flip image (needed so texture is the correct way around!) bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); System.Drawing.Imaging.BitmapData imgData = bmp.LockBits ( new Rectangle(new Point(0, 0), bmp.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); // System.Drawing.Imaging.PixelFormat.Format24bppRgb ); m.BindTexture ( imgData.Width, imgData.Height, imgData.Scan0 ); bmp.UnlockBits(imgData); bmp.Dispose(); /* BinaryReader br = new BinaryReader(fStream); br.ReadBytes ( 14 ); // skip file header uint offset = br.ReadUInt32 ( ); //br.ReadBytes ( 4 ); // skip image header uint biWidth = br.ReadUInt32 (); uint biHeight = br.ReadUInt32 (); Console.WriteLine ( "w {0} h {1}", biWidth, biHeight ); br.ReadBytes ( (int) offset - 12 ); // skip rest of image header byte[,,] tex = new byte [ biHeight , biWidth , 4 ]; for ( int ii=0 ; ii < biHeight ; ii++ ) { for ( int jj=0 ; jj < biWidth ; jj++ ) { tex [ ii, jj, 0 ] = br.ReadByte(); tex [ ii, jj, 1 ] = br.ReadByte(); tex [ ii, jj, 2 ] = br.ReadByte(); tex [ ii, jj, 3 ] = 255; //Console.Write ( ii + " " ); } } br.Close(); fStream.Close(); m.BindTexture ( (int) biWidth, (int) biHeight, tex ); */ break; default: SkipChunk ( child ); break; } chunk.BytesRead += child.BytesRead; } }
void ProcessChunk( ThreeDSChunk chunk ) { // process chunks until there are none left while ( chunk.BytesRead < chunk.Length ) { // grab a chunk ThreeDSChunk child = new ThreeDSChunk ( reader ); // process based on ID switch ((Groups) child.ID) { case Groups.C_VERSION: version = reader.ReadInt32 (); child.BytesRead += 4; break; case Groups.C_OBJECTINFO: // not sure whats up with this chunk //SkipChunk ( obj_chunk ); //child.BytesRead += obj_chunk.BytesRead; //ProcessChunk ( child ); // blender 3ds export (others?) uses this // in the hierarchy of objects and materials // so lets process the next (child) chunk break; case Groups.C_MATERIAL: ProcessMaterialChunk ( child ); break; case Groups.C_OBJECT: // string name = ProcessString ( child ); Entity e = ProcessObjectChunk ( child ); e.CalculateNormals (); model.Entities.Add ( e ); break; default: SkipChunk ( child ); break; } chunk.BytesRead += child.BytesRead; //Console.WriteLine ( "ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } }
Triangle[] ReadIndices( ThreeDSChunk chunk ) { ushort numIdcs = reader.ReadUInt16 (); chunk.BytesRead += 2; Console.WriteLine ( " Indices: {0}", numIdcs ); Triangle[] idcs = new Triangle[numIdcs]; for ( int ii=0; ii < idcs.Length ; ii++ ) { idcs [ii] = new Triangle ( reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16() ); //Console.WriteLine ( idcs [ii] ); // flags reader.ReadUInt16 (); } chunk.BytesRead += ( 2 * 4 ) * idcs.Length; //Console.WriteLine ( "b {0} l {1}", chunk.BytesRead, chunk.Length); //chunk.BytesRead = (int) chunk.Length; //SkipChunk ( chunk ); return idcs; }
float[] ProcessColorChunk( ThreeDSChunk chunk ) { ThreeDSChunk child = new ThreeDSChunk ( reader ); float[] c = new float[] { (float) reader.ReadByte() / 256 , (float) reader.ReadByte() / 256 , (float) reader.ReadByte() / 256 }; //Console.WriteLine ( "R {0} G {1} B {2}", c.R, c.B, c.G ); chunk.BytesRead += (int) child.Length; return c; }
void SkipChunk( ThreeDSChunk chunk ) { int length = (int) chunk.Length - chunk.BytesRead; reader.ReadBytes ( length ); chunk.BytesRead += length; }
ArrayList ReadVertices(ThreeDSChunk chunk) { ushort numVerts = reader.ReadUInt16(); chunk.BytesRead += 2; Console.WriteLine(" Vertices: {0}", numVerts); ArrayList lst = new ArrayList(); for (int ii = 0; ii < numVerts; ii++) { float f1 = reader.ReadSingle(); float f2 = reader.ReadSingle(); float f3 = reader.ReadSingle(); Point3d pnt = new Point3d(f1,f2,f3,1.0); lst.Add(pnt); } chunk.BytesRead += lst.Count * (3 * 4); return lst; }
ThreeDSMesh ProcessObjectChunk(ThreeDSChunk chunk, ThreeDSMesh e) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(reader); switch ((ThreeDSChunkType)child.ID) { case ThreeDSChunkType.TriangularMesh: ProcessObjectChunk(child, e); break; case ThreeDSChunkType.VerticesList: e.vertices = ReadVertices(child); break; case ThreeDSChunkType.FacesDescription: e.indices = ReadIndices(child); if (child.BytesRead < child.Length) ProcessObjectChunk(child, e); break; case ThreeDSChunkType.FacesMaterial: string name2 = ProcessString(child); Console.WriteLine(" Uses Material: {0}", name2); ThreeDSMaterial mat; if (materials.TryGetValue(name2, out mat)) e.material = mat; else Console.WriteLine(" Warning: Material '{0}' not found. ", name2); //throw new Exception ( "Material not found!" ); /* int nfaces = reader.ReadUInt16 (); child.BytesRead += 2; Console.WriteLine ( nfaces ); for ( int ii=0; ii< nfaces+2; ii++) { Console.Write ( reader.ReadUInt16 () + " " ); child.BytesRead += 2; } */ SkipChunk(child); break; case ThreeDSChunkType.MappingCoordinatesList: int cnt = reader.ReadUInt16(); child.BytesRead += 2; Console.WriteLine(" TexCoords: {0}", cnt); e.texcoords = new TexCoord[cnt]; for (int ii = 0; ii < cnt; ii++) e.texcoords[ii] = new TexCoord(reader.ReadSingle(), reader.ReadSingle()); child.BytesRead += (cnt * (4 * 2)); break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; //Console.WriteLine ( " ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } return e; }
Object3d ProcessObjectChunk(ThreeDSChunk chunk) { return ProcessObjectChunk(chunk, new Object3d()); }
ThreeDSMesh ProcessObjectChunk(ThreeDSChunk chunk) { return ProcessObjectChunk(chunk, new ThreeDSMesh()); }
Entity ProcessObjectChunk( ThreeDSChunk chunk, Entity e ) { while ( chunk.BytesRead < chunk.Length ) { ThreeDSChunk child = new ThreeDSChunk ( reader ); switch ((Groups) child.ID) { case Groups.C_OBJECT_MESH: ProcessObjectChunk ( child , e ); break; case Groups.C_OBJECT_VERTICES: e.vertices = ReadVertices ( child ); break; case Groups.C_OBJECT_FACES: e.indices = ReadIndices ( child ); if ( child.BytesRead < child.Length ) ProcessObjectChunk ( child, e ); break; case Groups.C_OBJECT_MATERIAL: string name2 = ProcessString ( child ); Console.WriteLine ( " Uses Material: {0}", name2 ); Material mat; if ( materials.TryGetValue ( name2, out mat ) ) { //e.material = mat; MaterialFaces m = new MaterialFaces(); m.Material = mat; int nfaces = reader.ReadUInt16 (); child.BytesRead += 2; //Console.WriteLine ( nfaces ); m.Faces = new UInt16[nfaces]; for ( int ii=0; ii<nfaces; ii++) { //Console.Write ( reader.ReadUInt16 () + " " ); m.Faces[ii] = reader.ReadUInt16 (); child.BytesRead += 2; } e.MaterialFaces.Add(m); } else { Console.WriteLine ( " Warning: Material '{0}' not found. ", name2 ); //throw new Exception ( "Material not found!" ); SkipChunk ( child ); } break; case Groups.C_OBJECT_UV: int cnt = reader.ReadUInt16 (); child.BytesRead += 2; Console.WriteLine ( " TexCoords: {0}", cnt ); e.texcoords = new TexCoord [ cnt ]; for ( int ii=0; ii<cnt; ii++ ) e.texcoords [ii] = new TexCoord ( reader.ReadSingle (), reader.ReadSingle () ); child.BytesRead += ( cnt * ( 4 * 2 ) ); break; default: SkipChunk ( child ); break; } chunk.BytesRead += child.BytesRead; //Console.WriteLine ( " ID: {0} Length: {1} Read: {2}", chunk.ID.ToString("x"), chunk.Length , chunk.BytesRead ); } return e; }
Object3d ProcessObjectChunk(ThreeDSChunk chunk) { return(ProcessObjectChunk(chunk, new Object3d())); }
int ProcessPercentageChunk( ThreeDSChunk chunk ) { ThreeDSChunk child = new ThreeDSChunk ( reader ); int per = reader.ReadUInt16 (); child.BytesRead += 2; chunk.BytesRead += child.BytesRead; return per; }
string ProcessString( ThreeDSChunk chunk ) { StringBuilder sb = new StringBuilder (); byte b = reader.ReadByte (); int idx = 0; while ( b != 0 ) { sb.Append ( (char) b); b = reader.ReadByte (); idx++; } chunk.BytesRead += idx+1; return sb.ToString(); }
void ProcessMaterialChunk( ThreeDSChunk chunk ) { string name = string.Empty; Material m = new Material (); while ( chunk.BytesRead < chunk.Length ) { ThreeDSChunk child = new ThreeDSChunk ( reader ); switch ((Groups) child.ID) { case Groups.C_MATNAME: name = ProcessString ( child ); break; case Groups.C_MATAMBIENT: m.Ambient = ProcessColorChunk ( child ); break; case Groups.C_MATDIFFUSE: m.Diffuse = ProcessColorChunk ( child ); break; case Groups.C_MATSPECULAR: m.Specular = ProcessColorChunk ( child ); break; case Groups.C_MATSHININESS: m.Shininess = ProcessPercentageChunk ( child ); break; case Groups.C_MATMAP: ProcessPercentageChunk ( child ); ProcessTexMapChunk ( child , m ); break; default: SkipChunk ( child ); break; } chunk.BytesRead += child.BytesRead; } materials.Add ( name, m ); }
void ProcessTexMapChunk(ThreeDSChunk chunk, Material m) { while (chunk.BytesRead < chunk.Length) { ThreeDSChunk child = new ThreeDSChunk(this, reader); switch (child.ID) { case Groups.C_MATMAPFILE: string name = ProcessString(child); #if LOG_MATERIAL Logger.Log("Material texture map: {0}", name); #endif //Console.WriteLine ( " Texture File: {0}", name ); // use System.Drawing to try and load this image /* * //FileStream fStream; * Bitmap bmp; * try * { * //fStream = new FileStream(base_dir + name, FileMode.Open, FileAccess.Read); * bmp = new Bitmap ( base_dir + name ); * } * catch ( Exception ex ) * { * // couldn't find the file * Console.WriteLine ( " ERROR: could not load file '{0}': {1}", base_dir + name, ex.Message ); * break; * } * * // Flip image (needed so texture is the correct way around!) * bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); * * System.Drawing.Imaging.BitmapData imgData = bmp.LockBits ( new Rectangle(new Point(0, 0), bmp.Size), * System.Drawing.Imaging.ImageLockMode.ReadOnly, * System.Drawing.Imaging.PixelFormat.Format32bppArgb); * // System.Drawing.Imaging.PixelFormat.Format24bppRgb ); * * m.BindTexture ( imgData.Width, imgData.Height, imgData.Scan0 ); * * bmp.UnlockBits(imgData); * bmp.Dispose(); */ /* * BinaryReader br = new BinaryReader(fStream); * * br.ReadBytes ( 14 ); // skip file header * * uint offset = br.ReadUInt32 ( ); * //br.ReadBytes ( 4 ); // skip image header * uint biWidth = br.ReadUInt32 (); * uint biHeight = br.ReadUInt32 (); * Console.WriteLine ( "w {0} h {1}", biWidth, biHeight ); * br.ReadBytes ( (int) offset - 12 ); // skip rest of image header * * byte[,,] tex = new byte [ biHeight , biWidth , 4 ]; * * for ( int ii=0 ; ii < biHeight ; ii++ ) * { * for ( int jj=0 ; jj < biWidth ; jj++ ) * { * tex [ ii, jj, 0 ] = br.ReadByte(); * tex [ ii, jj, 1 ] = br.ReadByte(); * tex [ ii, jj, 2 ] = br.ReadByte(); * tex [ ii, jj, 3 ] = 255; * //Console.Write ( ii + " " ); * } * } * * br.Close(); * fStream.Close(); * m.BindTexture ( (int) biWidth, (int) biHeight, tex ); */ break; default: SkipChunk(child); break; } chunk.BytesRead += child.BytesRead; child.SkipToEnd(reader); } }
Entity ProcessObjectChunk( ThreeDSChunk chunk ) { return ProcessObjectChunk ( chunk, new Entity() ); }