public override Scene ImportFile(FileStream fileStream, string fileName) { Scene3ds scene3ds = new Scene3ds(fileStream, null, Scene3ds.DECODE_ALL); Scene result = new Scene(); // Compute normals for our scene computeNormals(scene3ds, result); Material defaultMaterial = new Material { Name = "Default", FileName = fileName, DiffuseColor = ColorsRgbF.Gray, SpecularColor = ColorsRgbF.White, Shininess = 64 }; for (int i = 0; i < scene3ds.Materials.Count(); ++i) { Material3ds material3ds = scene3ds.Materials.ElementAt(i); Material material = new Material { Name = material3ds.name(), FileName = fileName, DiffuseColor = material3ds.diffuse().ToColorRgbF(), AmbientColor = material3ds.ambient().ToColorRgbF(), SpecularColor = material3ds.specular().ToColorRgbF(), Transparency = material3ds.transparency() }; if (material3ds.DiffuseTexture != null) { material.DiffuseTextureName = Path.Combine(Path.GetDirectoryName(fileName), material3ds.DiffuseTexture.MapName); } if ((int)material3ds._shininess != 0) { material.Shininess = (int)material3ds._shininess; } result.Materials.Add(material); } for (int i = 0; i < scene3ds.Meshes.Count(); ++i) { Mesh3ds mesh3ds = scene3ds.Meshes.ElementAt(i); Mesh resultMesh = result.Meshes[i]; //resultMesh.Material = defaultMaterial; // TODO: Is this right? if (mesh3ds.faceMats() == 0) { resultMesh.Material = defaultMaterial; for (int fi = 0; fi < mesh3ds.faces(); ++fi) { Face3ds f = mesh3ds.face(fi); resultMesh.Indices.Add(f.P0); resultMesh.Indices.Add(f.P1); resultMesh.Indices.Add(f.P2); } } else { // TODO: Split by face materials so that each mesh only has one material. Debug.Assert(mesh3ds.faceMats() == 1); for (int fm = 0; fm < mesh3ds.faceMats(); ++fm) { // Get current material's face. FaceMat3ds fmat = mesh3ds.faceMat(fm); Material material = result.Materials[fmat.material()]; resultMesh.Material = material; for (int fi = 0; fi < fmat.faces(); ++fi) { int idx = fmat.face(fi); Face3ds f = mesh3ds.face(idx); resultMesh.Indices.Add(f.P0); resultMesh.Indices.Add(f.P1); resultMesh.Indices.Add(f.P2); } } } } return(result); }
private void read_FACE_ARRAY(Mesh3ds mes, int chunk_len) { long chunk_end = filePos() + chunk_len; int faces = ReadUnsignedShort(); mes.mFace = new Face3ds[faces]; for (int n = 0; n < faces; n++) { int p0 = ReadUnsignedShort(); int p1 = ReadUnsignedShort(); int p2 = ReadUnsignedShort(); int flags = ReadUnsignedShort(); mes.mFace[n] = new Face3ds(p0, p1, p2, flags); } if (mDecode != null) { mDecode.enter(); mDecode.println("Faces: " + faces); for (int i = 0; i < faces; i++) { mDecode.println(" " + Utils3ds.intToString(i, 4) + ": " + mes.mFace[i]); } } while (filePos() < chunk_end) { Head head = read_HEAD(); switch (head.id) { case CHUNK_MSH_MAT_GROUP: read_MSH_MAT_GROUP(mes); break; case CHUNK_SMOOTH_GROUP: read_SMOOTH_GROUP(mes, head.length - 6); break; default: SkipChunk(head.length - 6); break; } } if (mDecode != null) { mDecode.leave(); } }
// // Compute scene vertex normals // public void computeNormals(Scene3ds scene, Scene result) { Point3D vcenter = Point3D.Zero; float vcounter = 0.0f; for (int i = 0; i < scene.Meshes.Count(); i++) { Mesh3ds m = scene.Meshes.ElementAt(i); // Alloc memory Mesh mesh = new Mesh { Name = m.Name }; result.Meshes.Add(mesh); //mesh._numTexCoords = 0; Vector3D[] tmpFaceNormals = new Vector3D[m.faces()]; // Compute face normals for (int fi = 0; fi < m.faces(); fi++) { Face3ds f = m.face(fi); Vertex3ds p0 = m.vertex(f.P0); Vertex3ds p1 = m.vertex(f.P1); Vertex3ds p2 = m.vertex(f.P2); /*// Compute face middle point * mesh.faceMiddlePoint[fi] = new PVector(); * mesh.faceMiddlePoint[fi].x = (p0.X + p1.X + p2.X) / 3.0f; * mesh.faceMiddlePoint[fi].y = (p0.Y + p1.Y + p2.Y) / 3.0f; * mesh.faceMiddlePoint[fi].z = (p0.Z + p1.Z + p2.Z) / 3.0f;*/ Point3D v0 = new Point3D(p0.X, p0.Y, p0.Z); Point3D v1 = new Point3D(p1.X, p1.Y, p1.Z); Point3D v2 = new Point3D(p2.X, p2.Y, p2.Z); Vector3D e0 = v1 - v0; Vector3D e1 = v2 - v0; //mesh.faceNormals[fi] = e1.cross(e0); // save a copy of the unnormalized face normal. used for average vertex normals tmpFaceNormals[fi] = Vector3D.Cross(e1, e0); // normalize face normal //mesh.faceNormals[fi].normalize(); } // // Compute vertex normals.Take average from adjacent face normals.find coplanar faces or get weighted normals. // One could also use the smooth groups from 3ds to compute normals, we'll see about that. // //PVector v = new PVector(); TexCoord3ds tc = new TexCoord3ds(0, 0); for (int vi = 0; vi < m.vertices(); vi++) { Vertex3ds p = m.vertex(vi); vcenter += new Point3D(p.X, p.Y, p.Z); vcounter++; if (m.texCoords() > 0) { tc = m.texCoord(vi); } Vector3D n = Vector3D.Zero; float num = 0; for (int fi = 0; fi < m.faces(); fi++) { Face3ds f = m.face(fi); // Vertex3ds p0 = m.vertex(f.P0); // Vertex3ds p1 = m.vertex(f.P1); // Vertex3ds p2 = m.vertex(f.P2); if (vi == f.P0 || vi == f.P1 || vi == f.P2) { num++; n += tmpFaceNormals[fi]; //mesh.faceNormals[fi] ); } } if (num > 0) { n *= 1.0f / (float)num; } n.Normalize(); mesh.Normals.Add(n); if (FLIPYZ) { Vector3D tmp = mesh.Normals[vi]; mesh.Normals[vi] = new Vector3D(tmp.X, -tmp.Z, tmp.Y); } // Save vertex data if (FLIPYZ) { mesh.Positions.Add(new Point3D(p.X, -p.Z, p.Y)); } else { mesh.Positions.Add(new Point3D(p.X, p.Y, p.Z)); } // Save texcoord data //mesh._numTexCoords = m.texCoords(); if (m.texCoords() > 0) { if (FLIPV) { mesh.TextureCoordinates.Add(new Point3D(tc.U, 1.0f - tc.V, 0)); } else { mesh.TextureCoordinates.Add(new Point3D(tc.U, tc.V, 0)); } } } } if (vcounter > 0.0) { vcenter /= vcounter; } }
// Add mesh at end of mesh array void addMesh(Mesh3ds m) { _meshes.Add(m); }
private void read_SMOOTH_GROUP(Mesh3ds mes, int chunk_len) { int entrys = chunk_len / 4; mes.mSmoothGroup = new int[entrys]; for (int n = 0; n < entrys; n++) { mes.mSmoothGroup[n] = ReadInt(); } if (mDecode != null) { mDecode.enter(); mDecode.println("Entrys: " + entrys); for (int i = 0; i < entrys; i++) { mDecode.println(Utils3ds.intToString(i, 4) + ": " + Utils3ds.intToBinString(mes.mSmoothGroup[i], 32)); } mDecode.leave(); } if (entrys != mes.faces()) { throw new Exception3ds("SMOOTH_GROUP entrys != faces. File is probably corrupt!"); } }
private void read_N_TRI_OBJECT(string name, int chunk_len) { long chunk_end = filePos() + chunk_len; Mesh3ds mes = new Mesh3ds(); mes.Name = name; addMesh(mes); if (mDecode != null) { mDecode.enter(); } while (filePos() < chunk_end) { Head head = read_HEAD(); switch (head.id) { case CHUNK_POINT_ARRAY: mes.mVertex = read_POINT_ARRAY(); break; case CHUNK_TEX_VERTS: mes.mTexCoord = read_TEX_VERTS(); break; case CHUNK_MESH_TEXTURE_INFO: read_MESH_TEXTURE_INFO(mes); break; case CHUNK_MESH_MATRIX: readMatrix(mes.mLocalSystem); break; case CHUNK_FACE_ARRAY: read_FACE_ARRAY(mes, head.length - 6); break; default: SkipChunk(head.length - 6); break; } } if (mDecode != null) { mDecode.leave(); } }
private void read_MSH_MAT_GROUP(Mesh3ds mes) { string name = ReadName(); FaceMat3ds fm = new FaceMat3ds(); mes.addFaceMat(fm); for (int i = 0; i < Materials.Count(); i++) { if (Materials.ElementAt(i).name().Equals(name) == true) { fm.mMatIndex = i; break; } } int indexes = ReadUnsignedShort(); fm.mFaceIndex = new int[indexes]; for (int n = 0; n < indexes; n++) { fm.mFaceIndex[n] = ReadUnsignedShort(); } if (mDecode != null) { mDecode.enter(); mDecode.println("Faces: " + indexes); for (int t = 0; t < indexes; t++) { mDecode.println(" face: " + fm.mFaceIndex[t]); } mDecode.leave(); } }
private void read_MESH_TEXTURE_INFO(Mesh3ds mes) { mes.TextureMappingMode = (TextureMappingMode3ds) ReadUnsignedShort(); mes.mTexUTile = ReadFloat(); mes.mTexVTile = ReadFloat(); if (mDecode != null) { mDecode.enter(); string type = ""; switch (mes.TextureMappingMode) { case TextureMappingMode3ds.PlanarMap: type = "PLANAR"; break; case TextureMappingMode3ds.CylindricalMap: type = "CYLINDRICAL"; break; case TextureMappingMode3ds.SphericalMap: type = "SPHERICAL"; break; default: type = "" + mes.TextureMappingMode; break; } mDecode.println("Texture mapping type: " + type); mDecode.println("Texture U tiling: " + Utils3ds.floatToString(mes.mTexUTile, 9)); mDecode.println("Texture V tiling: " + Utils3ds.floatToString(mes.mTexVTile, 9)); } SkipBytes(4 * 4 + (3 * 4 + 3) * 4); if (mDecode != null) { mDecode.leave(); } }