public void Mtl_LoadMtl_TwoMaterials() { // Arrange var mtlFile = new[] { "newmtl Material", "Ns 96.078431", "Ka 1.000000 1.000000 1.000000", "Kd 0.630388 0.620861 0.640000", "Ks 0.500000 0.500000 0.500000", "Ke 0.000000 0.000000 0.000000", "Tf 0.000000 0.000000 0.000000", "Ni 1.000000", "d 1.000000", "illum 2", "", "newmtl Material.001", "Ns 96.078431", "Ka 1.000000 1.000000 1.000000", "Kd 0.640000 0.026578 0.014364", "Ks 0.500000 0.500000 0.500000", "Ke 0.000000 0.000000 0.000000", "Ni 1.000000", "d 1.000000", "illum 2" }; // Act mtl.LoadMtl(mtlFile); // Assert Assert.AreEqual(2, mtl.MaterialList.Count); ObjParser.Types.Material first = mtl.MaterialList[0]; Assert.AreEqual("Material", first.Name); Assert.AreEqual(96.078431f, first.SpecularExponent); Assert.AreEqual(1.0f, first.AmbientReflectivity.r); Assert.AreEqual(1.0f, first.AmbientReflectivity.g); Assert.AreEqual(1.0f, first.AmbientReflectivity.b); Assert.AreEqual(0.630388f, first.DiffuseReflectivity.r); Assert.AreEqual(0.620861f, first.DiffuseReflectivity.g); Assert.AreEqual(0.640000f, first.DiffuseReflectivity.b); Assert.AreEqual(0.5f, first.SpecularReflectivity.r); Assert.AreEqual(0.5f, first.SpecularReflectivity.g); Assert.AreEqual(0.5f, first.SpecularReflectivity.b); Assert.AreEqual(0.0f, first.EmissiveCoefficient.r); Assert.AreEqual(0.0f, first.EmissiveCoefficient.g); Assert.AreEqual(0.0f, first.EmissiveCoefficient.b); Assert.AreEqual(0.0f, first.TransmissionFilter.r); Assert.AreEqual(0.0f, first.TransmissionFilter.g); Assert.AreEqual(0.0f, first.TransmissionFilter.b); Assert.AreEqual(1.0f, first.OpticalDensity); Assert.AreEqual(1.0f, first.Dissolve); Assert.AreEqual(2, first.IlluminationModel); ObjParser.Types.Material second = mtl.MaterialList[1]; Assert.AreEqual("Material.001", second.Name); Assert.AreEqual(96.078431f, second.SpecularExponent); }
public void OpenObj(string file) { string objFile = file.Substring(0, file.Length - 3) + "obj"; string mtlFile = file.Substring(0, file.Length - 3) + "mtl"; obj = new Obj(); obj.LoadObj(objFile); mtl = new Mtl(); mtl.LoadMtl(mtlFile); Console.WriteLine("finish."); }
public static IObject3D Load(Stream fileStream, Action <double, string> reportProgress = null, IObject3D source = null) { IObject3D root = source ?? new Object3D(); var time = Stopwatch.StartNew(); // LOAD THE MESH DATA var objFile = new Obj(); objFile.LoadObj(fileStream); IObject3D context = new Object3D(); root.Children.Add(context); var mesh = new Mesh(); context.SetMeshDirect(mesh); foreach (var vertex in objFile.VertexList) { mesh.Vertices.Add(new Vector3Float(vertex.X, vertex.Y, vertex.Z)); } foreach (var face in objFile.FaceList) { for (int i = 0; i < face.VertexIndexList.Length; i++) { if (face.VertexIndexList[i] >= objFile.TextureList.Count) { int a = 0; } } mesh.Faces.Add(face.VertexIndexList[0] - 1, face.VertexIndexList[1] - 1, face.VertexIndexList[2] - 1, mesh.Vertices); if (face.VertexIndexList.Length == 4) { // add the other side of the quad mesh.Faces.Add(face.VertexIndexList[0] - 1, face.VertexIndexList[2] - 1, face.VertexIndexList[3] - 1, mesh.Vertices); } } // load and apply any texture if (objFile.Material != "") { // TODO: have consideration for this being in a shared zip file string pathToObj = Path.GetDirectoryName(((FileStream)fileStream).Name); //Try-catch block for when objFile.Material is not found try { using (var materialsStream = File.OpenRead(Path.Combine(pathToObj, objFile.Material))) { var mtl = new Mtl(); mtl.LoadMtl(materialsStream); foreach (var material in mtl.MaterialList) { if (!string.IsNullOrEmpty(material.DiffuseTextureFileName)) { var pathToTexture = Path.Combine(pathToObj, material.DiffuseTextureFileName); if (File.Exists(pathToTexture)) { var diffuseTexture = new ImageBuffer(); // TODO: have consideration for this being in a shared zip file using (var imageStream = File.OpenRead(pathToTexture)) { if (Path.GetExtension(material.DiffuseTextureFileName).ToLower() == ".tga") { ImageTgaIO.LoadImageData(diffuseTexture, imageStream, 32); } else { ImageIO.LoadImageData(imageStream, diffuseTexture); } } if (diffuseTexture.Width > 0 && diffuseTexture.Height > 0) { int meshFace = 0; for (int objFace = 0; objFace < objFile.FaceList.Count; objFace++, meshFace++) { var face = mesh.Faces[meshFace]; var faceData = objFile.FaceList[objFace]; int textureIndex0 = faceData.TextureVertexIndexList[0] - 1; var uv0 = new Vector2Float(objFile.TextureList[textureIndex0].X, objFile.TextureList[textureIndex0].Y); int textureIndex1 = faceData.TextureVertexIndexList[1] - 1; var uv1 = new Vector2Float(objFile.TextureList[textureIndex1].X, objFile.TextureList[textureIndex1].Y); int textureIndex2 = faceData.TextureVertexIndexList[2] - 1; var uv2 = new Vector2Float(objFile.TextureList[textureIndex2].X, objFile.TextureList[textureIndex2].Y); mesh.FaceTextures.Add(meshFace, new FaceTextureData(diffuseTexture, uv0, uv1, uv2)); if (faceData.TextureVertexIndexList.Length == 4) { meshFace++; int textureIndex3 = faceData.TextureVertexIndexList[3] - 1; var uv3 = new Vector2Float(objFile.TextureList[textureIndex3].X, objFile.TextureList[textureIndex3].Y); mesh.FaceTextures.Add(meshFace, new FaceTextureData(diffuseTexture, uv0, uv2, uv3)); } } context.Color = Color.White; root.Color = Color.White; } } } } } } catch (FileNotFoundException) { // Just continue as if obj.Material == "" to show object } } time.Stop(); Debug.WriteLine(string.Format("OBJ Load in {0:0.00}s", time.Elapsed.TotalSeconds)); time.Restart(); bool hasValidMesh = root.Children.Where(item => item.Mesh.Faces.Count > 0).Any(); Debug.WriteLine("hasValidMesh: " + time.ElapsedMilliseconds); reportProgress?.Invoke(1, ""); return(hasValidMesh ? root : null); }
public static IObject3D Load(Stream fileStream, CancellationToken cancellationToken, Action <double, string> reportProgress = null, IObject3D source = null) { IObject3D root = source ?? new Object3D(); Stopwatch time = Stopwatch.StartNew(); // LOAD THE MESH DATA Obj objFile = new Obj(); objFile.LoadObj(fileStream); IObject3D context = new Object3D(); root.Children.Add(context); var mesh = new Mesh(); context.SetMeshDirect(mesh); foreach (var vertex in objFile.VertexList) { mesh.CreateVertex(vertex.X, vertex.Y, vertex.Z, CreateOption.CreateNew, SortOption.WillSortLater); } foreach (var face in objFile.FaceList) { List <int> zeroBased = new List <int>(face.VertexIndexList.Length); foreach (var index in face.VertexIndexList) { zeroBased.Add(index - 1); } mesh.CreateFace(zeroBased.ToArray(), CreateOption.CreateNew); } // load and apply any texture if (objFile.Material != "") { // TODO: have consideration for this being in a shared zip file string pathToObj = Path.GetDirectoryName(((FileStream)fileStream).Name); using (var materialsStream = File.OpenRead(Path.Combine(pathToObj, objFile.Material))) { var mtl = new Mtl(); mtl.LoadMtl(materialsStream); foreach (var material in mtl.MaterialList) { if (!string.IsNullOrEmpty(material.DiffuseTextureFileName)) { var pathToTexture = Path.Combine(pathToObj, material.DiffuseTextureFileName); if (File.Exists(pathToTexture)) { ImageBuffer diffuseTexture = new ImageBuffer(); // TODO: have consideration for this being in a shared zip file using (var ImageStream = File.OpenRead(pathToTexture)) { if (Path.GetExtension(material.DiffuseTextureFileName).ToLower() == ".tga") { ImageTgaIO.LoadImageData(diffuseTexture, ImageStream, 32); } else { AggContext.ImageIO.LoadImageData(ImageStream, diffuseTexture); } } if (diffuseTexture.Width > 0 && diffuseTexture.Height > 0) { for (int faceIndex = 0; faceIndex < objFile.FaceList.Count; faceIndex++) { var faceData = objFile.FaceList[faceIndex]; var polyFace = mesh.Faces[faceIndex]; polyFace.SetTexture(0, diffuseTexture); int edgeIndex = 0; foreach (FaceEdge faceEdge in polyFace.FaceEdges()) { int textureIndex = faceData.TextureVertexIndexList[edgeIndex] - 1; faceEdge.SetUv(0, new Vector2(objFile.TextureList[textureIndex].X, objFile.TextureList[textureIndex].Y)); edgeIndex++; } } context.Color = Color.White; root.Color = Color.White; } } } } } } time.Stop(); Debug.WriteLine(string.Format("OBJ Load in {0:0.00}s", time.Elapsed.TotalSeconds)); time.Restart(); bool hasValidMesh = root.Children.Where(item => item.Mesh.Faces.Count > 0).Any(); Debug.WriteLine("hasValidMesh: " + time.ElapsedMilliseconds); reportProgress?.Invoke(1, ""); return((hasValidMesh) ? root : null); }
public Model(string filepath) { path = filepath; name = Path.GetFileNameWithoutExtension(filepath).Replace('_', ' '); Obj tobj = new Obj(); tobj.LoadObj(filepath); Mtl tmtl = new Mtl(); tmtl.LoadMtl(Path.GetDirectoryName(filepath) + filepathSlash + tobj.Mtl); List <Vector3> Vertices = new List <Vector3>(); foreach (ObjParser.Types.Vertex v in tobj.VertexList) { Vertices.Add(new Vector3((float)v.X, (float)v.Y, (float)v.Z)); } List <Vector3> Normals = new List <Vector3>(); foreach (ObjParser.Types.Normal vn in tobj.NormalList) { Normals.Add(new Vector3((float)vn.X, (float)vn.Y, (float)vn.Z)); } List <Vector2> UVs = new List <Vector2>(); foreach (ObjParser.Types.TextureVertex vt in tobj.TextureList) { UVs.Add(new Vector2((float)vt.X, (float)vt.Y)); } foreach (ObjParser.Types.Material mat in tmtl.MaterialList) { List <int[]> faces = new List <int[]>(); List <int[]> fnmls = new List <int[]>(); List <int[]> fuvs = new List <int[]>(); int texture; Console.WriteLine("{0}: {1}", mat.DiffuseTexture, Path.IsPathRooted(mat.DiffuseTexture)); if (Path.IsPathRooted(mat.DiffuseTexture)) { texture = ContentPipe.Load_and_AddTexture(mat.DiffuseTexture); } else { texture = ContentPipe.Load_and_AddTexture(Path.GetDirectoryName(filepath) + filepathSlash + mat.DiffuseTexture); } foreach (ObjParser.Types.Face f in tobj.FaceList) { if (f.UseMtl == mat.Name) { faces.Add(f.VertexIndexList); fnmls.Add(f.NormalIndexList); fuvs.Add(f.TextureVertexIndexList); } } List <Vector3> cverts = new List <Vector3>(); List <Vector3> cnorms = new List <Vector3>(); List <Vector2> cuvs = new List <Vector2>(); foreach (Vector3 v in Vertices) { cverts.Add(v); } foreach (Vector3 n in Normals) { cnorms.Add(n); } foreach (Vector2 t in UVs) { cuvs.Add(t); } meshes.Add(new Mesh(cverts, cnorms, cuvs, faces, fnmls, fuvs, Vector3.One, texture)); } Obj tobjkcl = new Obj(); tobjkcl.LoadObj(Path.GetDirectoryName(filepath) + filepathSlash + Path.GetFileNameWithoutExtension(filepath) + "_KCL.obj"); List <Vector3> CVerts = new List <Vector3>(); foreach (ObjParser.Types.Vertex v in tobjkcl.VertexList) { CVerts.Add(new Vector3((float)v.X, (float)v.Y, (float)v.Z)); } foreach (string name in tobjkcl.objects) { Collision_Mesh.CollisionType coll; if (name == "ROAD") { coll = Collision_Mesh.CollisionType.road; } else if (name == "WALL") { coll = Collision_Mesh.CollisionType.wall; } else if (name == "OFFROAD") { coll = Collision_Mesh.CollisionType.off_road; } else if (name == "WAYOFFROAD") { coll = Collision_Mesh.CollisionType.way_off_road; } else if (name == "OUTOFBOUNDS") { coll = Collision_Mesh.CollisionType.out_of_bounds; } else if (name == "BOOST") { coll = Collision_Mesh.CollisionType.boost; } else if (name == "RAMP") { coll = Collision_Mesh.CollisionType.ramp; } else if (name == "ENGAGEGLIDER") { coll = Collision_Mesh.CollisionType.engage_glider; } else if (name == "SIDERAMP") { coll = Collision_Mesh.CollisionType.side_ramp; } else if (name == "CANNON") { coll = Collision_Mesh.CollisionType.cannon; } else if (name == "WATER") { coll = Collision_Mesh.CollisionType.water; } else if (name == "LAVA") { coll = Collision_Mesh.CollisionType.lava; } else if (name == "SPINOUT") { coll = Collision_Mesh.CollisionType.spin_out; } else if (name == "KNOCKOUT") { coll = Collision_Mesh.CollisionType.knock_out; } else { continue; } List <int[]> faces = new List <int[]>(); foreach (ObjParser.Types.Face f in tobjkcl.FaceList) { if (f.objectName == name) { faces.Add(f.VertexIndexList); } } List <Vector3> cverts = new List <Vector3>(); foreach (Vector3 v in CVerts) { cverts.Add(v); } KCLs.Add(new Collision_Mesh(cverts, faces, coll)); } CalculateBounds(); ImportAttachments(Path.GetDirectoryName(filepath) + filepathSlash + Path.GetFileNameWithoutExtension(filepath) + "_Atch.txt"); }
//public Character ProcessOBJ2(string filepath) { // ObjLoaderFactory OBJLF = new ObjLoaderFactory(); // var objl = OBJLF.Create(); // FileStream fs = new FileStream(filepath, System.IO.FileMode.Open); // var Model = objl.Load(fs); // fs.Close(); // //begin processing // Character chr = new Character { name = Path.GetFileNameWithoutExtension(filepath) }; // int MajorOffset = 0; // foreach (Group g in Model.Groups) { // Shape shape = new Shape(); // shape.rawVertices = ConvertCJCVectorsToVector3((List<Vertex>)Model.Vertices); // shape.textures.Add(Path.GetFileNameWithoutExtension(g.Material.DiffuseTextureMap)); // shape.name = g.Name; // shape.type = 1; // //we have all the vertices // //now we parse them into primitives aka faces // int VertexCount = 0; // foreach (Face face in g.Faces) { // Prim prim = new Prim(); // for (int i = 0;i < face._vertices.Count;i++) { // prim.vertices.Add(i); // VertexCount++; // } // shape.rawPrimitives.Add(prim); // } // foreach (Face face in g.Faces) { // foreach (FaceVertex fv in face._vertices) { // int v3df = (VertexCount - Math.Abs(fv.VertexIndex)) + MajorOffset; // shape.rawVertices.Add(new Vector3(Model.Vertices[v3df].X, Model.Vertices[v3df].Y, Model.Vertices[v3df].Z)); // //shape.rawVertexTextureCoords.Add(new Vector2(Model.TextureCoords[v3df].X, Model.TextureCoords[v3df].Y)); // } // } // MajorOffset += VertexCount; // chr.shapes.Add(shape); // } // return chr; //} public void ProcessOBJ(string filepath, bool imp_textures, bool imp_materials, bool imp_names, Vector3 imp_translation) { Obj obj = new Obj(); obj.LoadObj(filepath); Mtl mat = new Mtl(); mat.LoadMtl(obj.Mtl); //for (int i = 0;i < obj.FaceList.Count;i++) { // Shape shape = new Shape(); // //shape.name = obj.GroupNames[i]; // shape.rawVertices = objptoshapes(obj, obj.FaceList[i]); // importedCharacter.shapes.Add(new Shape()); //} //a note from the Obj class, when we parse in the obj file, its entirely likely that the obj will have no groups or objects //this is a problem as this is so rudimentary that we rely on them existing to build our shape DB //the parser takes care of that for us, and regardless of whether or not the .OBJ file has a group or object, //a default object and group is made to store all the data in, so...yeah... //tl;dr, Objects[0].groups[0] will always exist regardless of whats imported. int vOffset = 0; int vAccumulator = 0; for (int i = 0; i < obj.Objects.Count; i++)//for each shape... { Obj.obj o = obj.Objects[i]; Shape shape = new Shape(); shape.name = (!imp_names || o.name == null) ? "" : o.name; foreach (Vertex v in o.vertexList) { shape.rawVertices.Add(new Vector3((float)v.X, (float)v.Y, (float)v.Z)); shape.rawVertexShading.Add((v.color == null) ? System.Drawing.Color.Black : F_NGN.VColorToColor(v.color.ToArrayFloat())); } Matrix4D GTMF = new Matrix4D(); imp_translation.SetMatrix4DNegative(GTMF, imp_translation); Vector3.TransformPoints(GTMF, ref shape.rawVertices); foreach (TextureVertex t in o.textureList) { shape.rawVertexTextureCoords.Add(new Vector3((float)t.X, (float)t.Y, 0.0f)); } for (int j = 0; j < o.groups.Count; j++)//for each prim... { Obj.gf g = o.groups[j]; Prim prim = new Prim(); if (g.faces[0].VertexIndexList.Count() == 4) { prim.type = 4; } else { prim.type = 1; }; if (imp_materials) { ObjParser.Types.Material usemtl = GetUsemtl(g.materialName, mat); Material material = new Material { id = (usemtl.Opacity == 1) ? 129 : 193, RGB = usemtl.DiffuseReflectivity.ToArrayDouble().ToList() }; if (imp_textures) { material.textureName = usemtl.DiffuseMap.Split('.')[0]; } shape.AddMaterial(material); } for (int k = 0; k < g.faces.Count; k++) // for each face... (3/4 points thing this is whats actually the prim, its weird i know) { Face f = g.faces[k]; for (int l = 0; l < f.VertexIndexList.Length; l++)//for each vertex, of each face, of each primitive inside this root shape... { prim.vertices.Add((f.VertexIndexList[l] - 1) - vOffset); vAccumulator++; } } shape.rawPrimitives.Add(prim); } shape.rawVertexData = (List <Vector3>)XF.GenerateListData(1, shape.rawVertices.Count, new Vector3(0, 0, 0)); shape.type = 5; shape.type2 = 65535; importedCharacter.shapes.Add(shape); vOffset += vAccumulator; vAccumulator = 0; } //for (int i = 0;i < obj.GroupFaces.Count;i++) { // Shape shape = new Shape(); // shape.name = obj.GroupFaces[i].name; // List<int> vertices = new List<int>(); // for (int j = 0;j < obj.GroupFaces[i].faces.Count;j++) { // ObjParser.Types.Face face = obj.GroupFaces[i].faces[j]; // Prim prim = new Prim(); // prim.type = face.VertexIndexList.Count(); // for (int k = 0;k < face.VertexIndexList.Length;k++) { // int v = Math.Abs(face.VertexIndexList[k]) - 1; // prim.vertices.Add(v); // vertices.Add(v); // } // shape.rawPrimitives.Add(prim); // } // for (int j = 0;j < vertices.Count;j++) { // ObjParser.Types.Vertex vertex = obj.VertexList[vertices[j]]; // shape.rawVertices.Add(new Vector3((float)vertex.X, (float)vertex.Y, (float)vertex.Z)); // } // shape.rawVertexData = (List<Vector3>)XF.GenerateListData(1, shape.rawVertices.Count, new Vector3(0, 0, 0)); // shape.rawVertexShading = (List<System.Drawing.Color>)XF.GenerateListData(1, shape.rawVertices.Count, System.Drawing.Color.FromArgb(255, 0, 0, 0)); // shape.rawVertexTextureCoords = (List<Vector3>)XF.GenerateListData(1, shape.rawVertices.Count, new Vector3(0, 0, 0)); // shape.type = 5; // shape.type2 = 65535; // importedCharacter.shapes.Add(shape); //} }