private void ProcessLine(string line, string folderPath) { string[] parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length > 0) { switch (parts[0]) { case "mtllib": Material = ProcessMaterial(parts[1], folderPath); break; case "v": Vector3 vertex = ProcessVertex(parts); Vertices.Add(vertex); break; case "vt": Vector2 texCoord = ProcessTextureCoordinate(parts); TexCoords.Add(texCoord); break; case "vn": Vector3 normal = ProcessVertex(parts); Normals.Add(normal); break; case "f": ObjFace face = ProcessFace(parts); Faces.Add(face); break; } } }
public void BuildFacesFromData() { List <ObjFace> faces = new List <ObjFace>(); for (int i = 0; i < Positions.Count; i += 3) { ObjFace face = new ObjFace(); bool hasTexCoords = TexCoords.Count > 0; bool hasNormal = Normals.Count > 0; face.Positions = new int[3]; for (int j = 0; j < 3; j++) { face.Positions[j] = i + 1; } if (hasTexCoords) { face.TexCoords = new int[3]; for (int j = 0; j < 3; j++) { face.TexCoords[j] = i + 1; } } if (hasNormal) { face.Normals = new int[3]; for (int j = 0; j < 3; j++) { face.Normals[j] = i + 1; } } } }
private static Dictionary <string, List <ObjFace> > ReadObjects(BinaryReader b, int num) { var d = new Dictionary <string, List <ObjFace> >(); for (var i = 0; i < num; i++) { var faces = new List <ObjFace>(); var objectName = b.ReadNtString(); var numFaces = b.ReadInt32(); for (var j = 0; j < numFaces; j++) { var face = new ObjFace(); var material = (FaceMaterial)b.ReadByte(); var numVerts = b.ReadInt32(); face.MaterialName = GetMaterialName(material); for (var k = 0; k < numVerts; k++) { var v = b.Read7BitEncodedInt(); var n = b.Read7BitEncodedInt(); var t = b.Read7BitEncodedInt(); face.Vertices.Add(new ObjTriplet(v + 1, t + 1, n + 1)); } faces.Add(face); } d[objectName] = faces; } return(d); }
public void BuildFacesFromData() { List<ObjFace> faces = new List<ObjFace>(); for (int i = 0; i < Positions.Count; i += 3) { ObjFace face = new ObjFace(); bool hasTexCoords = TexCoords.Count > 0; bool hasNormal = Normals.Count > 0; face.Positions = new int[3]; for (int j = 0; j < 3; j++) face.Positions[j] = i + 1; if (hasTexCoords) { face.TexCoords = new int[3]; for (int j = 0; j < 3; j++) face.TexCoords[j] = i + 1; } if (hasNormal) { face.Normals = new int[3]; for (int j = 0; j < 3; j++) face.Normals[j] = i + 1; } } }
private void GetObjFace(ObjFace face, ObjItem objModel, ref List <float> vertexPositions, ref List <float> vertexNormals, ref List <float> vertexTextureCoordinates, ref List <float> vertexBoneWeights, ref List <float> vertexBoneIndices, ref List <uint> indeces) { if (face.Count == 3) { for (var i = 0; i < face.Count; i++) { var faceVertex = face[i]; ObjLoader.AppendObjTriangle(objModel, faceVertex, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); } SetFaceTriangleIndex(face, objModel); } else if (face.Count == 4) { var faceVertex0 = face[0]; var faceVertex1 = face[1]; var faceVertex2 = face[2]; var faceVertex3 = face[3]; ObjLoader.AppendObjTriangle(objModel, faceVertex0, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex1, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex2, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex2, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex3, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex0, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); SetFaceTriangleIndex(face, objModel); } }
private void SaveObj(string directory, string filename, params string[] meshnames) { var obj = new ObjFile(); var referenced_materials = new List <PortableMaterial>(); foreach (var name in meshnames) { var pmesh = meshes[name]; for (int i = 0; i < pmesh.triangles.Count; i++) { var triangle = pmesh.triangles[i]; var face = new ObjFace(); face.ObjectName = name; foreach (var vertex in triangle.vertices) { obj.Vertices.Add(vertex.position); obj.VertexNormals.Add(vertex.normal); obj.TextureVertices.Add(vertex.uv); var index = obj.Vertices.Count; face.Vertices.Add(new ObjTriplet(index, index, index)); } face.MaterialName = triangle.material.name; obj.Faces.Add(face); referenced_materials.Add(triangle.material); } } var mtl = new ObjMaterialFile(); var materials = referenced_materials.Distinct(); foreach (var m in materials) { var material = new ObjMaterial(m.name); material.DiffuseColor = new ObjMaterialColor(m.colour.x, m.colour.y, m.colour.z); if (m.texture != null) { material.DiffuseMap = new ObjMaterialMap(m.texture.filename); } material.IsAntiAliasingEnabled = false; mtl.Materials.Add(material); } mtl.WriteTo(directory + Path.DirectorySeparatorChar + filename + ".mtl"); obj.MaterialLibraries.Add(filename + ".mtl"); obj.WriteTo(directory + Path.DirectorySeparatorChar + filename + ".obj"); }
private void SetFaceTriangleIndex(ObjFace face, ObjItem objModel) { if (objModel.ObjExport != null && face.ObjExportIndex > -1) { objModel.ObjExport.Faces[face.ObjExportIndex].TriangleIndex0 = LastTriangleIndex++; if (face.Count == 4) { objModel.ObjExport.Faces[face.ObjExportIndex].TriangleIndex1 = LastTriangleIndex++; } } }
public void Element_Face_Valid() { var obj = new ObjFile(); obj.Groups.Add(new ObjGroup("b")); obj.Vertices.Add(new ObjVertex(0, 0, 0)); obj.Vertices.Add(new ObjVertex(0, 0, 0)); obj.Vertices.Add(new ObjVertex(0, 0, 0)); obj.Vertices.Add(new ObjVertex(0, 0, 0)); obj.Vertices.Add(new ObjVertex(0, 0, 0)); obj.Vertices.Add(new ObjVertex(0, 0, 0)); var face = new ObjFace(); face.Vertices.Add(new ObjTriplet(2, 0, 0)); face.Vertices.Add(new ObjTriplet(3, 0, 0)); face.Vertices.Add(new ObjTriplet(4, 0, 0)); face.Vertices.Add(new ObjTriplet(5, 0, 0)); face.Vertices.Add(new ObjTriplet(6, 0, 0)); obj.Faces.Add(face); obj.Groups[0].Faces.Add(face); face.ObjectName = "a"; face.LevelOfDetail = 2; face.MapName = "c"; face.MaterialName = "d"; face.SmoothingGroupNumber = 10; face.IsBevelInterpolationEnabled = true; face.IsColorInterpolationEnabled = true; face.IsDissolveInterpolationEnabled = true; string text = WriteObj(obj); string expected = @"v 0.000000 0.000000 0.000000 v 0.000000 0.000000 0.000000 v 0.000000 0.000000 0.000000 v 0.000000 0.000000 0.000000 v 0.000000 0.000000 0.000000 v 0.000000 0.000000 0.000000 g b o a lod 2 usemap c usemtl d s 10 bevel on c_interp on d_interp on f 2 3 4 5 6 "; AssertExtensions.TextEqual(expected, text); }
private Face CreateFace(Map map, List <Vector3> points, ObjFace objFace) { var verts = objFace.Vertices.Select(x => points[x]).ToList(); var f = new Face(map.NumberGenerator.Next("Face")) { Plane = new Plane(verts[2], verts[1], verts[0]) }; verts.Reverse(); f.Vertices.AddRange(verts); return(f); }
private void ParseFace(string[] data) { int length = data.Length - 1; var face = new ObjFace(3); currentFaceGroup.Faces.Add(face); for (int i = 0; i < length; i++) { string[] parts = data[i + 1].Split('/'); var vert = new ObjFaceVertex(); vert.VertexIndex = ParseIndex(parts, 0); if (parts.Length > 1 && !string.IsNullOrEmpty(parts[1])) { vert.UVIndex = ParseIndex(parts, 1); } if (parts.Length > 2 && !string.IsNullOrEmpty(parts[2])) { vert.NormalIndex = ParseIndex(parts, 2); } if (i < 3) { face.Vertices[i] = vert; } else { // polygon > 3 vertices -> triangulate: add new face for every additional polygon var newFace = new ObjFace(3); newFace.Vertices[0] = face.Vertices[0]; newFace.Vertices[1] = face.Vertices[2]; newFace.Vertices[2] = vert; face = newFace; currentFaceGroup.Faces.Add(face); } } }
private static void WriteObj(Int32Rect[][] tiles, BitmapSource[][][] imagedata, ConvertOptions options) { var positions = new Dictionary <Vector3, int>(); var normals = new Dictionary <Vector3, int>(); var uvs = new Dictionary <Vector2, int>(); var normal = new Vector3(0, 0, 1); var xcount = (options.ImageWidth.Value + options.TileWidth - 1) / options.TileWidth; var ycount = (options.ImageHeight.Value + options.TileHeight - 1) / options.TileHeight; var folder = Path.GetDirectoryName(options.InputFileName); var filename = Path.GetFileNameWithoutExtension(options.InputFileName); var mtl = new ObjMaterialFile(); var obj = new ObjFile(); obj.MaterialLibraries.Add($"{filename}.mtl"); for (var y = 0; y < ycount; y++) { for (var x = 0; x < xcount; x++) { var tile = tiles[y][x]; var texture = imagedata[0][y][x]; var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(texture)); var matname = $"{filename}_{y:D3}_{x:D3}"; using (var outfile = File.Open(Path.Combine(folder, $"{matname}.png"), FileMode.Create, FileAccess.Write, FileShare.None)) { encoder.Save(outfile); } var material = new ObjMaterial(matname); material.DiffuseMap = new ObjMaterialMap($"{matname}.png"); mtl.Materials.Add(material); var face = new ObjFace(); face.MaterialName = matname; face.Vertices.Add(new ObjTriplet( positions.AddUniqueIndex(new Vector3(tile.X, -(tile.Y), 0)), uvs.AddUniqueIndex(new Vector2(0, (float)tile.Height / texture.PixelHeight)), normals.AddUniqueIndex(normal) )); face.Vertices.Add(new ObjTriplet( positions.AddUniqueIndex(new Vector3(tile.X + tile.Width, -(tile.Y), 0)), uvs.AddUniqueIndex(new Vector2((float)tile.Width / texture.PixelWidth, (float)tile.Height / texture.PixelHeight)), normals.AddUniqueIndex(normal) )); face.Vertices.Add(new ObjTriplet( positions.AddUniqueIndex(new Vector3(tile.X + tile.Width, -(tile.Y + tile.Height), 0)), uvs.AddUniqueIndex(new Vector2((float)tile.Width / texture.PixelWidth, 0)), normals.AddUniqueIndex(normal) )); face.Vertices.Add(new ObjTriplet( positions.AddUniqueIndex(new Vector3(tile.X, -(tile.Y + tile.Height), 0)), uvs.AddUniqueIndex(new Vector2(0, 0)), normals.AddUniqueIndex(normal) )); obj.Faces.Add(face); } } (from x in positions orderby x.Value select x.Key).ToList().ForEach(x => obj.Vertices.Add(x.ToObjVertex())); (from x in normals orderby x.Value select x.Key).ToList().ForEach(x => obj.VertexNormals.Add(x.ToObjVector3())); (from x in uvs orderby x.Value select x.Key).ToList().ForEach(x => obj.TextureVertices.Add(x.ToObjVector3())); mtl.WriteTo(Path.Combine(folder, $"{filename}.mtl")); obj.WriteTo(Path.Combine(folder, $"{filename}.obj")); }
private void ParseObj(Stream stream) { ObjMesh currentMesh = null; ObjPolygon currentPolygon = null; using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { List <Vector3> Positions = new List <Vector3>(); List <Vector2> TexCoords = new List <Vector2>(); List <Vector3> Normals = new List <Vector3>(); var enusculture = new CultureInfo("en-US"); string currentMaterial = null; while (!reader.EndOfStream) { string line = reader.ReadLine(); line = line.Replace(",", "."); // Ignore empty lines and comments. if (String.IsNullOrWhiteSpace(line) || line.StartsWith("#")) { continue; } string[] args = line.Split(_argSeparators, StringSplitOptions.RemoveEmptyEntries); if (args.Length == 1) { continue; } switch (args[0]) { case "o": case "g": currentMesh = new ObjMesh(args.Length > 1 ? args[1] : $"Mesh{Meshes.Count}"); Meshes.Add(currentMesh); continue; case "v": Positions.Add(new Vector3( Single.Parse(args[1], enusculture), Single.Parse(args[2], enusculture), Single.Parse(args[3], enusculture))); continue; case "vt": TexCoords.Add(new Vector2( Single.Parse(args[1], enusculture), Single.Parse(args[2], enusculture))); continue; case "vn": Normals.Add(new Vector3( Single.Parse(args[1], enusculture), Single.Parse(args[2], enusculture), Single.Parse(args[3], enusculture))); continue; case "f": // Only support triangles for now. if (args.Length != 4) { throw new Exception("Obj must be trianglulated!"); } int[] indices = new int[3 * 2]; //3 faces, position and normal indices if (!currentMesh.Polygons.ContainsKey(currentMaterial)) { currentPolygon = new ObjPolygon(currentMaterial); currentMesh.Polygons.Add(currentMaterial, currentPolygon); } ObjFace face = new ObjFace() { Vertices = new ObjVertex[3] }; for (int i = 0; i < 3; i++) { string[] vertexArgs = args[i + 1].Split(_vertexSeparators, StringSplitOptions.None); int positionIndex = Int32.Parse(vertexArgs[0]) - 1; face.Vertices[i].Position = Positions[positionIndex]; currentPolygon.Indices.Add(positionIndex); if (float.IsNaN(face.Vertices[i].Position.X) || float.IsNaN(face.Vertices[i].Position.Y) || float.IsNaN(face.Vertices[i].Position.Z)) { face.Vertices = null; break; } if (vertexArgs.Length > 1 && vertexArgs[1] != String.Empty) { face.Vertices[i].TexCoord = TexCoords[Int32.Parse(vertexArgs[1]) - 1]; } if (vertexArgs.Length > 2 && vertexArgs[2] != String.Empty) { face.Vertices[i].Normal = Normals[Int32.Parse(vertexArgs[2]) - 1]; } } currentPolygon.Faces.Add(face); continue; case "usemtl": { if (args.Length < 2) { continue; } currentMaterial = args[1]; continue; } } } } }
public ObjFace(ObjFace face) { Vertices = face.Vertices; }
private static ObjFace ParceFace(string line) { var vertices = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var face = new ObjFace(); foreach (var vertexString in vertices) { var faceVertex = ParseFaceVertex(vertexString); face.AddVertex(faceVertex); } return face; }
private void SetFaceTriangleIndex(ObjFace face, ObjItem objModel) { if (objModel.ObjExport != null && face.ObjExportIndex > -1) { objModel.ObjExport.Faces[face.ObjExportIndex].TriangleIndex0 = LastTriangleIndex++; if (face.Count == 4) objModel.ObjExport.Faces[face.ObjExportIndex].TriangleIndex1 = LastTriangleIndex++; } }
private void GetObjFace(ObjFace face, ObjItem objModel, ref List<float> vertexPositions, ref List<float> vertexNormals, ref List<float> vertexTextureCoordinates, ref List<float> vertexBoneWeights, ref List<float> vertexBoneIndices, ref List<uint> indeces) { if (face.Count == 3) { for (var i = 0; i < face.Count; i++) { var faceVertex = face[i]; ObjLoader.AppendObjTriangle(objModel, faceVertex, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); } SetFaceTriangleIndex(face, objModel); } else if (face.Count == 4) { var faceVertex0 = face[0]; var faceVertex1 = face[1]; var faceVertex2 = face[2]; var faceVertex3 = face[3]; ObjLoader.AppendObjTriangle(objModel, faceVertex0, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex1, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex2, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex2, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex3, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); ObjLoader.AppendObjTriangle(objModel, faceVertex0, ref vertexPositions, ref vertexNormals, ref vertexTextureCoordinates, ref vertexBoneWeights, ref vertexBoneIndices, ref indeces); SetFaceTriangleIndex(face, objModel); } }
private Face CreateFace(DataStructures.MapObjects.Map map, List<Coordinate> points, ObjFace objFace) { var verts = objFace.Vertices.Select(x => points[x]).ToList(); var f = new Face(map.IDGenerator.GetNextFaceID()); f.Plane = new Plane(verts[2], verts[1], verts[0]); f.Vertices.AddRange(verts.Select(x => new Vertex(x, f)).Reverse()); f.UpdateBoundingBox(); return f; }
private void loadModel(string fileName) { treeView1.Nodes.Clear(); m = new WavefrontOBJ(); m.loadObjModel(fileName); TreeNode nodeObjects = new TreeNode("Objects (" + m.getNumObjects() + ")"); for (int i = 0; i < m.getNumObjects(); i++) { ObjObject o = m.getObject(i); TreeNode nodeObject = new TreeNode("Object " + i + " - \"" + o.getName() + "\""); // object name TreeNode nodeObjectName = new TreeNode("Name"); TreeNode nodeObjectNameValue = new TreeNode(o.getName()); nodeObjectNameValue.Tag = o; nodeObjectName.Nodes.Add(nodeObjectNameValue); nodeObject.Nodes.Add(nodeObjectName); // first face TreeNode nodeObjectFirstFace = new TreeNode("First face"); TreeNode nodeObjectFirstFaceValue = new TreeNode(o.getFirstFace().ToString()); nodeObjectFirstFace.Nodes.Add(nodeObjectFirstFaceValue); nodeObject.Nodes.Add(nodeObjectFirstFace); // face count TreeNode nodeObjectNumFaces = new TreeNode("Faces count"); TreeNode nodeObjectNumFacesValue = new TreeNode(o.getNumFaces().ToString()); nodeObjectNumFaces.Nodes.Add(nodeObjectNumFacesValue); nodeObject.Nodes.Add(nodeObjectNumFaces); nodeObjects.Nodes.Add(nodeObject); } treeView1.Nodes.Add(nodeObjects); TreeNode nodeGroups = new TreeNode("Groups (" + m.getNumGroups() + ")"); for (int i = 0; i < m.getNumGroups(); i++) { ObjGroup o = m.getGroup(i); TreeNode nodeGroup = new TreeNode("Group " + i + " - \"" + o.getName() + "\""); // object name TreeNode nodeGroupName = new TreeNode("Name"); TreeNode nodeGroupNameValue = new TreeNode(o.getName()); nodeGroupNameValue.Tag = o; nodeGroupName.Nodes.Add(nodeGroupNameValue); nodeGroup.Nodes.Add(nodeGroupName); // first face TreeNode nodeGroupFirstFace = new TreeNode("First face"); TreeNode nodeGroupFirstFaceValue = new TreeNode(o.getFirstFace().ToString()); nodeGroupFirstFace.Nodes.Add(nodeGroupFirstFaceValue); nodeGroup.Nodes.Add(nodeGroupFirstFace); // face count TreeNode nodeGroupNumFaces = new TreeNode("Faces count"); TreeNode nodeGroupNumFacesValue = new TreeNode(o.getNumFaces().ToString()); nodeGroupNumFaces.Nodes.Add(nodeGroupNumFacesValue); nodeGroup.Nodes.Add(nodeGroupNumFaces); nodeGroups.Nodes.Add(nodeGroup); } treeView1.Nodes.Add(nodeGroups); TreeNode nodeFaces = new TreeNode("Faces (" + m.getNumFaces() + ")"); for (int i = 0; i < m.getNumFaces(); i++) { ObjFace f = m.getFace(i); TreeNode nodeFace = new TreeNode("Face " + i); // number of vertices /*TreeNode nodeFaceNumFaceVerts = new TreeNode("FaceVerts count"); * TreeNode nodeFaceNumFaceVertsValue = new TreeNode(f.getNumVerts().ToString()); * nodeFaceNumFaceVerts.Nodes.Add(nodeFaceNumFaceVertsValue); * nodeFace.Nodes.Add(nodeFaceNumFaceVerts);*/ // vertices TreeNode nodeFaceFaceVerts = new TreeNode("FaceVerts (" + f.getNumVerts() + ")"); for (int j = 0; j < f.getNumVerts(); j++) { TreeNode nodeFaceFaceVert = new TreeNode("FaceVert " + j + " (abs " + (j + f.getFirstVert()) + ")"); nodeFaceFaceVerts.Nodes.Add(nodeFaceFaceVert); } nodeFace.Nodes.Add(nodeFaceFaceVerts); nodeFaces.Nodes.Add(nodeFace); } treeView1.Nodes.Add(nodeFaces); TreeNode nodePositions = new TreeNode("XYZs (" + m.getNumXYZs() + ")"); for (int i = 0; i < m.getNumXYZs(); i++) { TreeNode nodePosition = new TreeNode("XYZ " + i); TreeNode nodePositionValue = new TreeNode(m.getXYZ(i).ToString()); nodePosition.Nodes.Add(nodePositionValue); nodePositions.Nodes.Add(nodePosition); } treeView1.Nodes.Add(nodePositions); if (m.getNumTexCoords() > 0) { TreeNode nodeTexCoords = new TreeNode("TexCoords (" + m.getNumTexCoords() + ")"); for (int i = 0; i < m.getNumTexCoords(); i++) { TreeNode nodeTexCoord = new TreeNode("TexCoord " + i); TreeNode nodeTexCoordValue = new TreeNode(m.getTexCoord(i).ToString()); nodeTexCoord.Nodes.Add(nodeTexCoordValue); nodeTexCoords.Nodes.Add(nodeTexCoord); } treeView1.Nodes.Add(nodeTexCoords); } ; if (m.getNumNormals() > 0) { TreeNode nodeNormals = new TreeNode("Normals (" + m.getNumNormals() + ")"); for (int i = 0; i < m.getNumNormals(); i++) { TreeNode nodeNormal = new TreeNode("Normal " + i); TreeNode nodeNormalValue = new TreeNode(m.getNormal(i).ToString()); nodeNormal.Nodes.Add(nodeNormalValue); nodeNormals.Nodes.Add(nodeNormal); } treeView1.Nodes.Add(nodeNormals); } }
public static GameObject LoadOBJFile(string FilePath, List <Texture2D> LoadedTextures) { string meshName = Path.GetFileNameWithoutExtension(FilePath); bool hasNormals = false; //OBJ LISTS List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); //UMESH LISTS List <Vector3> uvertices = new List <Vector3>(); List <Vector3> unormals = new List <Vector3>(); List <Vector2> uuvs = new List <Vector2>(); //MESH CONSTRUCTION List <string> materialNames = new List <string>(); List <string> objectNames = new List <string>(); Dictionary <string, int> hashtable = new Dictionary <string, int>(); List <ObjFace> faceList = new List <ObjFace>(); string cmaterial = ""; string cmesh = "default"; //CACHE Material[] materialCache = null; //save this info for later FileInfo OBJFileInfo = new FileInfo(FilePath); foreach (string ln in File.ReadAllLines(FilePath)) { if (ln.Length > 0 && ln[0] != '#') { string l = ln.Trim().Replace(" ", " "); string[] cmps = l.Split(' '); string data = l.Remove(0, l.IndexOf(' ') + 1); if (cmps[0] == "mtllib") { //load cache string pth = OBJGetFilePath(data, OBJFileInfo.Directory.FullName + Path.DirectorySeparatorChar, meshName); if (pth != null) { materialCache = LoadMTLFile(pth, LoadedTextures); } } else if ((cmps[0] == "g" || cmps[0] == "o") && SplitByMaterial == false) { cmesh = data; if (!objectNames.Contains(cmesh)) { objectNames.Add(cmesh); } } else if (cmps[0] == "usemtl") { cmaterial = data; if (!materialNames.Contains(cmaterial)) { materialNames.Add(cmaterial); } if (SplitByMaterial) { if (!objectNames.Contains(cmaterial)) { objectNames.Add(cmaterial); } } } else if (cmps[0] == "v") { //VERTEX vertices.Add(ParseVectorFromCMPS(cmps)); } else if (cmps[0] == "vn") { //VERTEX NORMAL normals.Add(ParseVectorFromCMPS(cmps)); } else if (cmps[0] == "vt") { //VERTEX UV uvs.Add(ParseVectorFromCMPS(cmps)); } else if (cmps[0] == "f") { int[] indexes = new int[cmps.Length - 1]; for (int i = 1; i < cmps.Length; i++) { string felement = cmps[i]; int vertexIndex = -1; int normalIndex = -1; int uvIndex = -1; if (felement.Contains("//")) { //doubleslash, no UVS. string[] elementComps = felement.Split('/'); vertexIndex = int.Parse(elementComps[0]) - 1; normalIndex = int.Parse(elementComps[2]) - 1; } else if (felement.Split('/').Length == 3) { //contains everything string[] elementComps = felement.Split('/'); vertexIndex = int.Parse(elementComps[0]) - 1; uvIndex = int.Parse(elementComps[1]) - 1; normalIndex = int.Parse(elementComps[2]) - 1; } else if (!felement.Contains("/")) { //just vertex inedx vertexIndex = int.Parse(felement) - 1; } else { //vertex and uv string[] elementComps = felement.Split('/'); vertexIndex = int.Parse(elementComps[0]) - 1; uvIndex = int.Parse(elementComps[1]) - 1; } string hashEntry = vertexIndex + "|" + normalIndex + "|" + uvIndex; if (hashtable.ContainsKey(hashEntry)) { indexes[i - 1] = hashtable[hashEntry]; } else { //create a new hash entry indexes[i - 1] = hashtable.Count; hashtable[hashEntry] = hashtable.Count; uvertices.Add(vertices[vertexIndex]); if (normalIndex < 0 || (normalIndex > (normals.Count - 1))) { unormals.Add(Vector3.zero); } else { hasNormals = true; unormals.Add(normals[normalIndex]); } if (uvIndex < 0 || (uvIndex > (uvs.Count - 1))) { uuvs.Add(Vector2.zero); } else { uuvs.Add(uvs[uvIndex]); } } } if (indexes.Length < 5 && indexes.Length >= 3) { ObjFace f1 = new ObjFace(); f1.MaterialName = cmaterial; f1.Indexes = new int[] { indexes[0], indexes[1], indexes[2] }; f1.MeshName = (SplitByMaterial) ? cmaterial : cmesh; faceList.Add(f1); if (indexes.Length > 3) { ObjFace f2 = new ObjFace(); f2.MaterialName = cmaterial; f2.MeshName = (SplitByMaterial) ? cmaterial : cmesh; f2.Indexes = new int[] { indexes[2], indexes[3], indexes[0] }; faceList.Add(f2); } } } } } if (objectNames.Count == 0) { objectNames.Add("default"); } //build objects GameObject parentObject = new GameObject(meshName); foreach (string obj in objectNames) { GameObject subObject = new GameObject(obj); subObject.transform.parent = parentObject.transform; subObject.transform.localScale = new Vector3(-1, 1, 1); //IIRC I did this to correct for some rotation issues? TODO review this //Create mesh Mesh m = new Mesh(); m.name = obj; //LISTS FOR REORDERING List <Vector3> processedVertices = new List <Vector3>(); List <Vector3> processedNormals = new List <Vector3>(); List <Vector2> processedUVs = new List <Vector2>(); List <int[]> processedIndexes = new List <int[]>(); Dictionary <int, int> remapTable = new Dictionary <int, int>(); //POPULATE MESH List <string> meshMaterialNames = new List <string>(); List <ObjFace> ofaces = faceList.FindAll(x => x.MeshName == obj); foreach (string mn in materialNames) { ObjFace[] faces = ofaces.FindAll(x => x.MaterialName == mn).ToArray(); if (faces.Length > 0) { int[] indexes = new int[0]; foreach (ObjFace f in faces) { int l = indexes.Length; Array.Resize(ref indexes, l + f.Indexes.Length); Array.Copy(f.Indexes, 0, indexes, l, f.Indexes.Length); } meshMaterialNames.Add(mn); if (m.subMeshCount != meshMaterialNames.Count) { m.subMeshCount = meshMaterialNames.Count; } for (int i = 0; i < indexes.Length; i++) { int idx = indexes[i]; //build remap table if (remapTable.ContainsKey(idx)) { //ezpz indexes[i] = remapTable[idx]; } else { processedVertices.Add(uvertices[idx]); processedNormals.Add(unormals[idx]); processedUVs.Add(uuvs[idx]); remapTable[idx] = processedVertices.Count - 1; indexes[i] = remapTable[idx]; } } processedIndexes.Add(indexes); } else { } } //apply stuff m.vertices = processedVertices.ToArray(); m.normals = processedNormals.ToArray(); m.uv = processedUVs.ToArray(); for (int i = 0; i < processedIndexes.Count; i++) { m.SetTriangles(processedIndexes[i], i); } if (!hasNormals) { m.RecalculateNormals(); } m.RecalculateBounds(); ; MeshFilter mf = subObject.AddComponent <MeshFilter>(); MeshRenderer mr = subObject.AddComponent <MeshRenderer>(); Material[] processedMaterials = new Material[meshMaterialNames.Count]; for (int i = 0; i < meshMaterialNames.Count; i++) { if (materialCache == null) { processedMaterials[i] = new Material(Shader.Find("Standard (Specular setup)")); } else { Material mfn = Array.Find(materialCache, x => x.name == meshMaterialNames[i]);; if (mfn == null) { processedMaterials[i] = new Material(Shader.Find("Standard (Specular setup)")); } else { processedMaterials[i] = mfn; } } processedMaterials[i].name = meshMaterialNames[i]; } mr.materials = processedMaterials; mr.enabled = true; mr.useLightProbes = false; mf.mesh = m; } return(parentObject); }
private Face CreateFace(DataStructures.MapObjects.Map map, List <Coordinate> points, ObjFace objFace) { var verts = objFace.Vertices.Select(x => points[x]).ToList(); var f = new Face(map.IDGenerator.GetNextFaceID()); f.Plane = new Plane(verts[2], verts[1], verts[0]); f.Vertices.AddRange(verts.Select(x => new Vertex(x, f)).Reverse()); f.UpdateBoundingBox(); return(f); }
static void Main(string[] args) { void ShowInfo() { AdvConsole.WriteLine(ConsoleColor.Cyan, "PlaneBorder\n" + "by Zach Combs\n" + "\n" + "<sourceOBJ> <destOBJ> <borderWidth> <borderHeight>\n" + " Maps textures for a VVVVVV Circuit style track.\n" + " sourceOBJ The source OBJ file\n" + " destOBj The destination OBJ file\n" + " borderWidth The width of borders\n" + " borderHeight The height of borders"); } void WriteError(string s) { AdvConsole.WriteLine(ConsoleColor.Red, "ERROR: " + s); } Rect2d[] CalculateVerticesOfRect(float width, float height, float cornerwidth, float cornerheight) { //coords[0] = topleft corner //coords[1] = topright corner //coords[2] = bottomleft corner //coords[3] = bottomright corner //coords[4] = left side //coords[5] = right side //coords[6] = bottom side //coords[7] = top side //coords[8] = center Rect2d[] coords = new Rect2d[9]; Rect2d corner_topleft = new Rect2d(); Rect2d corner_topright = new Rect2d(); Rect2d corner_bottomleft = new Rect2d(); Rect2d corner_bottomright = new Rect2d(); Rect2d side_left = new Rect2d(); Rect2d side_right = new Rect2d(); Rect2d side_bottom = new Rect2d(); Rect2d side_top = new Rect2d(); Rect2d center = new Rect2d(); ObjVector2 in_topleft = new ObjVector2(); ObjVector2 in_bottomright = new ObjVector2(); if (width < (cornerwidth * 2)) { in_topleft.X = width / 2; } else { in_topleft.X = cornerwidth; } if (height < (cornerheight * 2)) { in_topleft.Y = height / 2; } else { in_topleft.Y = cornerheight; } if (width < (cornerwidth * 2)) { in_bottomright.X = width / 2; } else { in_bottomright.X = width - cornerwidth; } if (height < (cornerheight * 2)) { in_bottomright.Y = height / 2; } else { in_bottomright.Y = height - cornerheight; } corner_topleft = new Rect2d( new ObjVector2(0, 0), new ObjVector2(in_topleft.X, in_topleft.Y)); corner_topright = new Rect2d( new ObjVector2(in_bottomright.X, 0), new ObjVector2(width, in_topleft.Y)); corner_bottomleft = new Rect2d( new ObjVector2(0, in_bottomright.Y), new ObjVector2(in_topleft.X, height)); corner_bottomright = new Rect2d( new ObjVector2(in_bottomright.X, in_bottomright.Y), new ObjVector2(width, height)); side_left = new Rect2d( new ObjVector2(0, in_topleft.Y), new ObjVector2(in_topleft.X, in_bottomright.Y)); side_right = new Rect2d( new ObjVector2(in_bottomright.X, in_topleft.Y), new ObjVector2(width, in_bottomright.Y)); side_bottom = new Rect2d( new ObjVector2(in_topleft.X, in_bottomright.Y), new ObjVector2(in_bottomright.X, height)); side_top = new Rect2d( new ObjVector2(in_topleft.X, 0), new ObjVector2(in_bottomright.X, in_topleft.Y)); center = new Rect2d( new ObjVector2(in_topleft.X, in_topleft.Y), new ObjVector2(in_bottomright.X, in_bottomright.Y)); coords[0] = corner_topleft; coords[1] = corner_topright; coords[2] = corner_bottomleft; coords[3] = corner_bottomright; coords[4] = side_left; coords[5] = side_right; coords[6] = side_bottom; coords[7] = side_top; coords[8] = center; return(coords); } Rect2d[] CalculateTexCoordsOfRect(float width, float height, float cornerwidth, float cornerheight) { //coords[0] = topleft corner //coords[1] = topright corner //coords[2] = bottomleft corner //coords[3] = bottomright corner //coords[4] = left side //coords[5] = right side //coords[6] = bottom side //coords[7] = top side //coords[8] = center Rect2d[] coords = new Rect2d[9]; coords[0] = new Rect2d( new ObjVector2(0.125F, 0F), new ObjVector2(0.25F, 0.5F)); coords[1] = new Rect2d( new ObjVector2(0.25F, 0F), new ObjVector2(0.375F, 0.5F)); coords[2] = new Rect2d( new ObjVector2(0.125F, 0.5F), new ObjVector2(0.25F, 1F)); coords[3] = new Rect2d( new ObjVector2(0.25F, 0.5F), new ObjVector2(0.375F, 1F)); float in_width = ((width < (cornerwidth * 2)) ? 0f : (width - (cornerwidth * 2))); float in_height = ((height < (cornerheight * 2)) ? 0f : (height - (cornerheight * 2))); float uv_in_width = ((in_width == 0) ? 0f : ( ((in_width / (cornerwidth * 2)) < 0.5f) ? 0.5f : ((float)Math2.Round(in_width / (cornerwidth * 2), 0.5, Math2.RoundTechnique.ToNearest)) )); float uv_in_height = ((in_height == 0) ? 0f : ( ((in_height / (cornerheight * 2)) < 0.5f) ? 0.5f : ((float)Math2.Round(in_height / (cornerheight * 2), 0.5, Math2.RoundTechnique.ToNearest)) )); Rect2d side_left = new Rect2d( new ObjVector2(0.375F, 0F), new ObjVector2(0.5F, uv_in_height)); Rect2d side_right = new Rect2d( new ObjVector2(0.5F, 0F), new ObjVector2(0.625F, uv_in_height)); Rect2d side_bottom = new Rect2d( new ObjVector2(0.625F, 0F), new ObjVector2(0.75F, uv_in_width));//This will be rotated counter-clockwise Rect2d side_top = new Rect2d( new ObjVector2(0.75F, 0F), new ObjVector2(0.875F, uv_in_width));//This will be rotated counter-clockwise Rect2d center = new Rect2d( new ObjVector2(0F, 0F), new ObjVector2(uv_in_width, uv_in_height)); coords[4] = side_left; coords[5] = side_right; coords[6] = side_bottom; coords[7] = side_top; coords[8] = center; return(coords); } bool IsARectangle(ObjVector2 v1, ObjVector2 v2, ObjVector2 v3, ObjVector2 v4, out ObjVector2[] outpoints, out int[] oldindexes, out bool isclockwise) { //Returns whether or not v1, v2, v3, v4 make a rectangle //The vertices need to be in the order of building a rectangle //If v1, v2, v3, v4 make a rectangle, it makes an array of the vertices where the top-left vertex is first //The order of the vertices in the array depends on whether or not the rectangle the built clockwise or counter-clockwise int topleft = -1; float mincoordx = Math.Min(Math.Min(v1.X, v2.X), Math.Min(v3.X, v4.X)); float mincoordy = Math.Min(Math.Min(v1.Y, v2.Y), Math.Min(v3.Y, v4.Y)); if (v1.X == mincoordx & v1.Y == mincoordy) { topleft = 0; } if (v2.X == mincoordx & v2.Y == mincoordy) { topleft = 1; } if (v3.X == mincoordx & v3.Y == mincoordy) { topleft = 2; } if (v4.X == mincoordx & v4.Y == mincoordy) { topleft = 3; } if (topleft == -1) { outpoints = null; oldindexes = null; isclockwise = false; return(false); } else { ObjVector2 newv1 = null; ObjVector2 newv2 = null; ObjVector2 newv3 = null; ObjVector2 newv4 = null; int oldind1 = -1; int oldind2 = -1; int oldind3 = -1; int oldind4 = -1; if (topleft == 0) { newv1 = new ObjVector2(v1.X, v1.Y); newv2 = new ObjVector2(v2.X, v2.Y); newv3 = new ObjVector2(v3.X, v3.Y); newv4 = new ObjVector2(v4.X, v4.Y); oldind1 = 0; oldind2 = 1; oldind3 = 2; oldind4 = 3; } else if (topleft == 1) { newv1 = new ObjVector2(v2.X, v2.Y); newv2 = new ObjVector2(v3.X, v3.Y); newv3 = new ObjVector2(v4.X, v4.Y); newv4 = new ObjVector2(v1.X, v1.Y); oldind1 = 1; oldind2 = 2; oldind3 = 3; oldind4 = 0; } else if (topleft == 2) { newv1 = new ObjVector2(v3.X, v3.Y); newv2 = new ObjVector2(v4.X, v4.Y); newv3 = new ObjVector2(v1.X, v1.Y); newv4 = new ObjVector2(v2.X, v2.Y); oldind1 = 2; oldind2 = 3; oldind3 = 0; oldind4 = 1; } else if (topleft == 3) { newv1 = new ObjVector2(v4.X, v4.Y); newv2 = new ObjVector2(v1.X, v1.Y); newv3 = new ObjVector2(v2.X, v2.Y); newv4 = new ObjVector2(v3.X, v3.Y); oldind1 = 3; oldind2 = 0; oldind3 = 1; oldind4 = 2; } bool isrectccw = (newv1.X == newv2.X & newv2.Y == newv3.Y & newv3.X == newv4.X & newv4.Y == newv1.Y); bool isrectcw = (newv1.Y == newv2.Y & newv2.X == newv3.X & newv3.Y == newv4.Y & newv4.X == newv1.X); if (isrectccw | isrectcw) { outpoints = new ObjVector2[4]; outpoints[0] = newv1; outpoints[1] = newv2; outpoints[2] = newv3; outpoints[3] = newv4; oldindexes = new int[4]; oldindexes[0] = oldind1; oldindexes[1] = oldind2; oldindexes[2] = oldind3; oldindexes[3] = oldind4; isclockwise = isrectcw; return(true); } else { outpoints = null; oldindexes = null; isclockwise = false; return(false); } } } double PointDirection(ObjVector2 pnt1, ObjVector2 pnt2) { double xxx = pnt2.X - pnt1.X; double yyy = pnt2.Y - pnt1.Y; if (xxx == 0) { if (yyy < 0) { return(Math.PI * 1.5D); } else { return(Math.PI * 0.5D); } } else if (xxx < 0) { return(Math.Atan(yyy / xxx) + Math.PI); } else { return(Math.Atan(yyy / xxx)); } } const int reqargs = 4; if (args == null) { ShowInfo(); return; } if (args.Length == 0) { ShowInfo(); return; } if (args.Length < reqargs) { WriteError( "You must specify source obj, dest obj, corner width, and corner height" ); return; } string file_source = args[0]; string file_dest = args[1]; float corner_width = 0f; //borderWidth float corner_height = 0f; //borderHeight if (!File.Exists(file_source)) { WriteError(String.Format( "\"{0}\" does not exist" , file_source)); return; } if (File.Exists(file_dest)) { WriteError(String.Format( "\"{0}\" already exists" , file_dest)); return; } if (!float.TryParse(args[2], out corner_width)) { WriteError(String.Format( "\"{0}\" is not valid" , args[2])); return; } if (!float.TryParse(args[3], out corner_height)) { WriteError(String.Format( "\"{0}\" is not valid" , args[3])); return; } try { Obj obj = new Obj(); obj.Load(file_source, ObjLoadMode.IgnoreGroups, false); ObjGroup group = obj.Groups.Groups[0]; ObjGroup newgroup = new ObjGroup(); int AddVertex(ObjVector3 vertex) { int index = -1; int n = 0; while (n < newgroup.Vertexes.Count & index == -1) { ObjVector3 vector = newgroup.Vertexes.Item(n); if ( vertex.X == vector.X & vertex.Y == vector.Y & vertex.Z == vector.Z) { index = n; } n += 1; } if (index == -1) { index = newgroup.Vertexes.Count; newgroup.Vertexes.Add(vertex); } return(index); } void AddRectangle( ObjVector3 topleftpos, int coordplane, Rect2d[] Vertices, Rect2d[] TexCoords) { //coordplane==0: +X+Z plane //coordplane==1: -X+Z plane //coordplane==2: +X-Y plane //coordplane==3: -X-Y plane //coordplane==4: +Z-Y plane //coordplane==5: -Z-Y plane ObjVector3 DeterminePosition(float vx, float vy) { ObjVector3 vector = new ObjVector3( topleftpos.X, topleftpos.Y, topleftpos.Z); if (coordplane == 0) { vector.X += vx; vector.Z += vy; } else if (coordplane == 1) { vector.X += -vx; vector.Z += vy; } else if (coordplane == 2) { vector.X += vx; vector.Y += -vy; } else if (coordplane == 3) { vector.X += -vx; vector.Y += -vy; } else if (coordplane == 4) { vector.Z += vx; vector.Y += -vy; } else if (coordplane == 5) { vector.Z += -vx; vector.Y += -vy; } return(vector); } ObjFacePoint NewFacePoint(int v, int vt) { ObjFacePoint facepoint = new ObjFacePoint(); facepoint.Vertex_Index = v; facepoint.TexCoord_Index = vt; return(facepoint); } for (int n = 0; n < Math.Min( Vertices.Length, TexCoords.Length ); n += 1) { Rect2d rect_v = Vertices[n]; Rect2d rect_tc = TexCoords[n]; if ( (rect_v.Pos_TopLeft.X != rect_v.Pos_BottomRight.X) & (rect_v.Pos_TopLeft.Y != rect_v.Pos_BottomRight.Y) ) { ObjVector2 newtexcoord_tl = new ObjVector2( rect_tc.Pos_TopLeft.X, rect_tc.Pos_TopLeft.Y); ObjVector2 newtexcoord_tr = new ObjVector2( rect_tc.Pos_BottomRight.X, rect_tc.Pos_TopLeft.Y); ObjVector2 newtexcoord_bl = new ObjVector2( rect_tc.Pos_TopLeft.X, rect_tc.Pos_BottomRight.Y); ObjVector2 newtexcoord_br = new ObjVector2( rect_tc.Pos_BottomRight.X, rect_tc.Pos_BottomRight.Y); if (n == 6 | n == 7) { //These are the top/bottom rectangles newtexcoord_tl.X = rect_tc.Pos_BottomRight.X; newtexcoord_tl.Y = rect_tc.Pos_TopLeft.Y; newtexcoord_tr.X = rect_tc.Pos_BottomRight.X; newtexcoord_tr.Y = rect_tc.Pos_BottomRight.Y; newtexcoord_bl.X = rect_tc.Pos_TopLeft.X; newtexcoord_bl.Y = rect_tc.Pos_TopLeft.Y; newtexcoord_br.X = rect_tc.Pos_TopLeft.X; newtexcoord_br.Y = rect_tc.Pos_BottomRight.Y; } ObjVector3 newvertex_tl = DeterminePosition( rect_v.Pos_TopLeft.X, rect_v.Pos_TopLeft.Y); ObjVector3 newvertex_tr = DeterminePosition( rect_v.Pos_BottomRight.X, rect_v.Pos_TopLeft.Y); ObjVector3 newvertex_bl = DeterminePosition( rect_v.Pos_TopLeft.X, rect_v.Pos_BottomRight.Y); ObjVector3 newvertex_br = DeterminePosition( rect_v.Pos_BottomRight.X, rect_v.Pos_BottomRight.Y); int v_index_tl = AddVertex(newvertex_tl); int v_index_tr = AddVertex(newvertex_tr); int v_index_bl = AddVertex(newvertex_bl); int v_index_br = AddVertex(newvertex_br); int tc_index_tl = newgroup.TexCoords.Count; newgroup.TexCoords.Add(newtexcoord_tl); int tc_index_tr = newgroup.TexCoords.Count; newgroup.TexCoords.Add(newtexcoord_tr); int tc_index_bl = newgroup.TexCoords.Count; newgroup.TexCoords.Add(newtexcoord_bl); int tc_index_br = newgroup.TexCoords.Count; newgroup.TexCoords.Add(newtexcoord_br); ObjFace newface = new ObjFace(); newface.UsesNormals = false; newface.UsesTexCoords = true; newface.Points.Add(NewFacePoint( v_index_tl, tc_index_tl )); newface.Points.Add(NewFacePoint( v_index_bl, tc_index_bl )); newface.Points.Add(NewFacePoint( v_index_br, tc_index_br )); newface.Points.Add(NewFacePoint( v_index_tr, tc_index_tr )); newgroup.Faces.Add(newface); } } } #region Create rectangles //Create rectangles //Create vertices and textures AdvConsole.WriteLine(ConsoleColor.Green, "Creating rectangles" ); for (int n = 0; n < group.Faces.Count; n += 1) { ObjFace face = group.Faces.Item(n); ObjFacePointCollection points = face.Points; List <ObjVector3> vertexes = new List <ObjVector3>(); for (int m = 0; m < points.Count; m += 1) { int prev = m - 1; if (prev < 0) { prev = points.Count - 1; } int next = m + 1; if (next >= points.Count) { next = 0; } int index = points.Item(m).Vertex_Index; int index_p = points.Item(prev).Vertex_Index; int index_n = points.Item(next).Vertex_Index; ObjVector3 vertex = group.Vertexes.Item(index); ObjVector3 vertex_p = group.Vertexes.Item(index_p); ObjVector3 vertex_n = group.Vertexes.Item(index_n); bool xsame = (vertex.X == vertex_p.X & vertex.X == vertex_n.X); bool ysame = (vertex.Y == vertex_p.Y & vertex.Y == vertex_n.Y); bool zsame = (vertex.Z == vertex_p.Z & vertex.Z == vertex_n.Z); if (!((xsame & zsame) | (xsame & ysame) | (zsame & ysame))) { vertexes.Add(vertex); } } if (vertexes.Count == 4) { ObjVector3 v1 = vertexes[0]; ObjVector3 v2 = vertexes[1]; ObjVector3 v3 = vertexes[2]; ObjVector3 v4 = vertexes[3]; bool isonx = (v1.X == v2.X & v2.X == v3.X & v3.X == v4.X); bool isony = (v1.Y == v2.Y & v2.Y == v3.Y & v3.Y == v4.Y); bool isonz = (v1.Z == v2.Z & v2.Z == v3.Z & v3.Z == v4.Z); if (isonx | isony | isonz) { //coordplane==0: +X+Z plane //coordplane==1: -X+Z plane //coordplane==2: +X-Y plane //coordplane==3: -X-Y plane //coordplane==4: +Z-Y plane //coordplane==5: -Z-Y plane int coordplane; bool isclockwise; ObjVector2[] rectpoints; int[] oldindexes; int axis = -1; //0=X; 1=Y; 2=Z; if (isonx) { axis = 0; } if (isony) { axis = 1; } if (isonz) { axis = 2; } ObjVector2 v1_2 = null; ObjVector2 v2_2 = null; ObjVector2 v3_2 = null; ObjVector2 v4_2 = null; if (axis == 0) { v1_2 = new ObjVector2( v1.Z, -v1.Y ); v2_2 = new ObjVector2( v2.Z, -v2.Y ); v3_2 = new ObjVector2( v3.Z, -v3.Y ); v4_2 = new ObjVector2( v4.Z, -v4.Y ); } if (axis == 1) { v1_2 = new ObjVector2( v1.X, v1.Z ); v2_2 = new ObjVector2( v2.X, v2.Z ); v3_2 = new ObjVector2( v3.X, v3.Z ); v4_2 = new ObjVector2( v4.X, v4.Z ); } if (axis == 2) { v1_2 = new ObjVector2( v1.X, -v1.Y ); v2_2 = new ObjVector2( v2.X, -v2.Y ); v3_2 = new ObjVector2( v3.X, -v3.Y ); v4_2 = new ObjVector2( v4.X, -v4.Y ); } if (IsARectangle(v1_2, v2_2, v3_2, v4_2, out rectpoints, out oldindexes, out isclockwise)) { float width; float height; int topleftindex; if (isclockwise) { ObjVector2 tl = rectpoints[1]; ObjVector2 br = rectpoints[3]; topleftindex = oldindexes[1]; width = -(br.X - tl.X); height = br.Y - tl.Y; } else { ObjVector2 tl = rectpoints[0]; ObjVector2 br = rectpoints[2]; topleftindex = oldindexes[0]; width = br.X - tl.X; height = br.Y - tl.Y; } Rect2d[] rects_v = CalculateVerticesOfRect( width, height, corner_width, corner_height ); Rect2d[] rects_vt = CalculateTexCoordsOfRect( width, height, corner_width, corner_height ); if (axis == 1 & !isclockwise) { coordplane = 0; } else if (axis == 1 & isclockwise) { coordplane = 1; } else if (axis == 2 & !isclockwise) { coordplane = 2; } else if (axis == 2 & isclockwise) { coordplane = 3; } else if (axis == 0 & !isclockwise) { coordplane = 4; } else { coordplane = 5; } AddRectangle(vertexes[topleftindex], coordplane, rects_v, rects_vt); } } } } #endregion #region Finalize faces AdvConsole.Write(ConsoleColor.Green, "Finalizing faces " ); int cursorleft = Console.CursorLeft; int cursortop = Console.CursorTop; for (int n = 0; n <= newgroup.Faces.Count; n += 1) { Console.CursorLeft = cursorleft; Console.CursorTop = cursortop; AdvConsole.WriteLine(ConsoleColor.Green, "({0}/{1})" , n, newgroup.Faces.Count); if (n < newgroup.Faces.Count) { int index = newgroup.Faces.Count - 1 - n; ObjFace face = newgroup.Faces.Item(index); ObjFacePointCollection newpoints = new ObjFacePointCollection(); for (int m = 0; m < 4; m += 1) { int next = m + 1; if (next >= 4) { next = 0; } ObjFacePoint pnt = face.Points.Item(m); ObjFacePoint pnt_next = face.Points.Item(next); int ind = pnt.Vertex_Index; int ind_next = pnt_next.Vertex_Index; int ind_t = pnt.TexCoord_Index; int ind_t_next = pnt_next.TexCoord_Index; ObjVector3 v = newgroup.Vertexes.Item(ind); ObjVector3 v_next = newgroup.Vertexes.Item(ind_next); ObjVector2 vt = newgroup.TexCoords.Item(ind_t); ObjVector2 vt_next = newgroup.TexCoords.Item(ind_t_next); double distanceapart = Math.Sqrt( Math.Pow(v_next.X - v.X, 2) + Math.Pow(v_next.Y - v.Y, 2) + Math.Pow(v_next.Z - v.Z, 2) ); double t_distanceapart = Math.Sqrt( Math.Pow(vt_next.X - vt.X, 2) + Math.Pow(vt_next.Y - vt.Y, 2) ); double t_direction = PointDirection( vt, vt_next ); int axis = -1;//0=X different; 1=Y different; 2=Z different if (v.Y == v_next.Y & v.Z == v_next.Z) { axis = 0; } if (v.X == v_next.X & v.Z == v_next.Z) { axis = 1; } if (v.X == v_next.X & v.Y == v_next.Y) { axis = 2; } ObjFacePoint point_first = new ObjFacePoint(); point_first.Vertex_Index = ind; point_first.TexCoord_Index = ind_t; newpoints.Add(point_first); Dictionary <int, float> newinpoints = new Dictionary <int, float>();//int=vertex index float val; float val_next; if (axis == 0) { val = v.X; val_next = v_next.X; } else if (axis == 1) { val = v.Y; val_next = v_next.Y; } else { val = v.Z; val_next = v_next.Z; } for (int o = 0; o < newgroup.Vertexes.Count; o += 1) { if (o != ind & o != ind_next) { ObjVector3 vector = newgroup.Vertexes.Item(o); if ( (axis == 0 & vector.Y == v.Y & vector.Z == v.Z & vector.X > Math.Min(val, val_next) & vector.X < Math.Max(val, val_next)) | (axis == 1 & vector.X == v.X & vector.Z == v.Z & vector.Y > Math.Min(val, val_next) & vector.Y < Math.Max(val, val_next)) | (axis == 2 & vector.X == v.X & vector.Y == v.Y & vector.Z > Math.Min(val, val_next) & vector.Z < Math.Max(val, val_next)) ) { float val_in; if (axis == 0) { val_in = vector.X; } else if (axis == 1) { val_in = vector.Y; } else { val_in = vector.Z; } newinpoints.Add(o, val_in); } } } int[] nip_keys = newinpoints.Keys.ToArray(); float[] nip_values = newinpoints.Values.ToArray(); Array.Sort(nip_values, nip_keys); if (val > val_next) { Array.Reverse(nip_keys); Array.Reverse(nip_values); } for (int o = 0; o < nip_keys.Length; o += 1) { int nip_key = nip_keys[o]; ObjVector3 inpnt = newgroup.Vertexes.Item(nip_key); double fromstrt2pnt = Math.Sqrt( Math.Pow(inpnt.X - v.X, 2) + Math.Pow(inpnt.Y - v.Y, 2) + Math.Pow(inpnt.Z - v.Z, 2) ); double xx = vt.X + Math.Cos(t_direction) * (fromstrt2pnt / distanceapart) * t_distanceapart; double yy = vt.Y + Math.Sin(t_direction) * (fromstrt2pnt / distanceapart) * t_distanceapart; int tind = newgroup.TexCoords.Count; newgroup.TexCoords.Add( new ObjVector2((float)xx, (float)yy)); ObjFacePoint point_in = new ObjFacePoint(); point_in.Vertex_Index = nip_key; point_in.TexCoord_Index = tind; newpoints.Add(point_in); } } face.Points = newpoints; } } #endregion #region Save OBJ AdvConsole.WriteLine(ConsoleColor.Green, "Saving OBJ" ); string DetermineMTLSaveName() { string filewithoutext = Path.GetDirectoryName( Path.GetFullPath(file_source)) + Path.GetFileNameWithoutExtension( file_source); string mtlfilename = filewithoutext + ".mtl"; int i = 0; while (File.Exists(mtlfilename)) { mtlfilename = filewithoutext + i.ToString() + ".mtl"; i += 1; } return(mtlfilename); } Obj newobj = new Obj(); newobj.Groups.Add("newgroup", newgroup); newobj.Save(file_dest, DetermineMTLSaveName()); #endregion } catch (Exception ex) { WriteError("Could not complete program\n" + ex.Message); } }
private ObjFace ProcessFace(string[] data) { ObjFace face = new ObjFace(); for (int i = 0; i < 3; i++) { string[] faceData = data[i + 1].Split(new[] { '/' }); // Ensure we've allocated arrays for this type of data. if (faceData.Length >= 1) // Position only { if (face.Positions == null) { face.Positions = new int[3]; } } if (faceData.Length >= 2 && faceData[1] != "") // Potentially no Texcoord { if (face.TexCoords == null) { face.TexCoords = new int[3]; } } if (faceData.Length >= 3) // Position + Normal, Potentially no Texcoord { if (face.Normals == null) { face.Normals = new int[3]; } } if (faceData.Length >= 1) { int posIndex; bool bHasPos = int.TryParse(faceData[0], out posIndex); if (bHasPos) { face.Positions[i] = posIndex - 1; } } if (faceData.Length >= 2) { int texCoordIndex; bool bHasTexcoord = int.TryParse(faceData[1], out texCoordIndex); if (bHasTexcoord) { face.TexCoords[i] = texCoordIndex - 1; } } if (faceData.Length >= 3) { int normalIndex; bool bHasNormal = int.TryParse(faceData[2], out normalIndex); if (bHasNormal) { face.Normals[i] = normalIndex - 1; } } } return(face); }
private static void ParseFace(ObjContext objContext, string[] token) { if (objContext == null) { throw new ArgumentNullException("objContext"); } if (token == null) { throw new ArgumentNullException("token"); } if (token.Length < 3) { throw new ArgumentException("wrong array length", "token"); } if (objContext.Groups.Count == 0) { throw new InvalidOperationException("no group"); } ObjGroup objGroup = objContext.Groups[objContext.Groups.Count - 1]; if (objGroup.Geometries.Count == 0) { throw new InvalidOperationException("no geometry"); } ObjGeometry objGeometry = objGroup.Geometries[objGroup.Geometries.Count - 1]; ObjFace objFace = new ObjFace(); foreach (string values in token) { string[] indices = Regex.Split(values, "/"); int[] indicesValues = Array.ConvertAll(indices, delegate(string item) { if (String.IsNullOrEmpty(item) == false) { return(Int32.Parse(item, NumberFormatInfo.InvariantInfo)); } else { return(Int32.MinValue); } }); int indexVertex = indicesValues[0]; int indexNormal = indicesValues[2]; int indexTexCoord = indicesValues[1]; ObjFaceCoord objFaceCoord = new ObjFaceCoord(); // Position if (indexVertex < 0) { indexVertex = objContext.Vertices.Count + indexVertex + 1; } objFaceCoord.VertexIndex = indexVertex - 1; // Normal (optional) if (indexNormal != Int32.MinValue) { if (indexNormal < 0) { indexNormal = objContext.Normals.Count + indexNormal + 1; } objFaceCoord.NormalIndex = indexNormal - 1; } // Tex coord (optional) if (indexTexCoord != Int32.MinValue) { if (indexTexCoord < 0) { indexTexCoord = objContext.TextureCoords.Count + indexTexCoord + 1; } objFaceCoord.TexCoordIndex = indexTexCoord - 1; } objFace.Coords.Add(objFaceCoord); } objGeometry.Faces.Add(objFace); }
private Mesh GetMesh(ObjModel model) { Mesh m = new Mesh { name = Name }; int count = FaceList.Count * 3; List <Vector3> verticesList = new List <Vector3>(); List <Vector3> normalList = new List <Vector3>(); List <Vector2> uvList = new List <Vector2>(); bool hasNormal = false; List <int[]> triangleList = new List <int[]>(); //用于保存顶点索引(全局) 与当前mesh中 顶点的索引 Dictionary <string, int> indexDict = new Dictionary <string, int>(); //按照材质去找面 foreach (string matName in MatsList) { List <ObjFace> faces = FaceList.FindAll((ObjFace o) => { if (o.MatName == matName) { return(true); } return(false); }); int[] triangles = new int[faces.Count * 3]; int idx = 0; // for (int i = 0; i < faces.Count; i++) { ObjFace face = faces[i]; string[] f = face.FaceStr; for (int j = 0; j < f.Length; j++) { string[] indexs = f[j].Split('/'); int vIndex = int.Parse(indexs[0]); int nIndex = -1; int uIndex = -1; if (indexs.Length > 2 && indexs[2] != "") { nIndex = int.Parse(indexs[2]); hasNormal = true; } //法线索引 if (indexs.Length > 1 && indexs[1] != "") { uIndex = int.Parse(indexs[1]); } string key = vIndex + "|" + uIndex + "|" + nIndex; if (indexDict.ContainsKey(key)) { triangles[idx] = indexDict[key]; } else { triangles[idx] = verticesList.Count; indexDict[key] = verticesList.Count; verticesList.Add(model.VertexList[vIndex - 1]); normalList.Add(nIndex == -1 ? Vector3.zero : model.NormalList[nIndex - 1]); uvList.Add(uIndex == -1 ? Vector2.zero : model.UVList[uIndex - 1]); } idx++; } } triangleList.Add(triangles); } m.vertices = verticesList.ToArray(); m.normals = normalList.ToArray(); m.uv = uvList.ToArray(); m.subMeshCount = triangleList.Count; for (int i = 0; i < triangleList.Count; i++) { m.SetTriangles(triangleList[i], i); } if (!hasNormal) { m.RecalculateNormals(); } m.RecalculateBounds(); return(m); }
public void AddFace(ObjFace face) { _faces.Add(face); }
/// <summary> /// 解析obj文件 /// </summary> /// <param name="objPath"></param> /// <returns></returns> public static ObjModel ParseObj(string objContent, string objName = "obj") { if (string.IsNullOrEmpty(objContent)) { return(null); } ObjModel model = new ObjModel(objName); string matName = "Standard"; string[] allLines = objContent.Split('\n'); //将文本化后的obj文件内容按行分割 foreach (string line in allLines) { if (string.IsNullOrEmpty(line) || line[0] == '#' || string.IsNullOrEmpty(line)) { continue; } //去掉多余的空格 有的中间会是2个空格 string temp = line.Trim().Replace(" ", " "); string[] chars = temp.Split(' '); if (chars.Length <= 1) { continue; } //移除第一个空格前的字符 如 v f vt vn string data = temp.Remove(0, temp.IndexOf(' ') + 1); //根据第一个字符来判断数据的类型 switch (chars[0]) { case "mtllib": model.MtlName = data; break; //处理顶点 case "v": model.VertexList.Add(StringToVector3(chars)); break; //处理法线 case "vn": model.NormalList.Add(StringToVector3(chars)); break; //处理UV case "vt": model.UVList.Add(StringToVector3(chars)); break; case "g": case "o": model.AddObjPart(data); break; //使用的材质球名字 case "usemtl": matName = data; break; //处理面 case "f": if (model.LastPart == null) { continue; } //3个点 if (chars.Length >= 4) { string[] faceStr = new string[] { chars[1], chars[2], chars[3] }; ObjFace face = new ObjFace(matName, faceStr); model.LastPart.FaceList.Add(face); } //4个点 相当于2个面 if (chars.Length >= 5) { string[] faceStr = new string[] { chars[3], chars[4], chars[1] }; ObjFace face = new ObjFace(matName, faceStr); model.LastPart.FaceList.Add(face); } if (model.LastPart.MatsList.Contains(matName) == false) { model.LastPart.MatsList.Add(matName); } break; } } return(model); }
private ObjFace ProcessFace(string[] data) { ObjFace face = new ObjFace(); for (int i = 0; i < 3; i++) { string[] faceData = data[i + 1].Split(new[] { '/' }); // Ensure we've allocated arrays for this type of data. if (faceData.Length >= 1) // Position only if (face.Positions == null) face.Positions = new int[3]; if (faceData.Length >= 2 && faceData[1] != "") // Potentially no Texcoord if (face.TexCoords == null) face.TexCoords = new int[3]; if (faceData.Length >= 3) // Position + Normal, Potentially no Texcoord if (face.Normals == null) face.Normals = new int[3]; if (faceData.Length >= 1) { int posIndex; bool bHasPos = int.TryParse(faceData[0], out posIndex); if (bHasPos) face.Positions[i] = posIndex - 1; } if (faceData.Length >= 2) { int texCoordIndex; bool bHasTexcoord = int.TryParse(faceData[1], out texCoordIndex); if (bHasTexcoord) face.TexCoords[i] = texCoordIndex - 1; } if (faceData.Length >= 3) { int normalIndex; bool bHasNormal = int.TryParse(faceData[2], out normalIndex); if (bHasNormal) face.Normals[i] = normalIndex - 1; } } return face; }
// Read the obj file. private void ReadObjFile(string dir, string objfile) { char[] whitespace = { ' ', '\t' }; List <string> unknown = new List <string>(); // The current smoothing group. int smoothingGroup = 0; // The current material name. string curMatName = ""; // Read the file. using (StreamReader file = new System.IO.StreamReader(dir + objfile)) { while (!file.EndOfStream) { // Read the next line. string line = CleanLine(file.ReadLine()); if (line.Length == 0) { continue; } string[] fields = line.Split(whitespace, StringSplitOptions.RemoveEmptyEntries); switch (fields[0]) { case "o": // Object model. case "g": // Group. // Only create a new one if the current one isn't empty. if ((NewObjectModel == null) || (NewObjectModel.Faces.Count > 0)) { NewObjectModel = new ObjModel(); AllObjectModels.Add(NewObjectModel); } NewObjectModel.MaterialName = curMatName; if (fields.Length > 1) { NewObjectModel.Name = fields[1]; } smoothingGroup = 0; break; case "v": // Vertex. double x = double.Parse(fields[1]); double y = double.Parse(fields[2]); double z = double.Parse(fields[3]); AllVertices.Add(new Point3D(x, y, z)); break; case "vt": // Texture coordinates. double u = double.Parse(fields[1]); double v = double.Parse(fields[2]); AllTextureCoordinates.Add(new Point(u, v)); break; case "vn": // Normal. double nx = double.Parse(fields[1]); double ny = double.Parse(fields[2]); double nz = double.Parse(fields[3]); AllNormals.Add(new Vector3D(nx, ny, nz)); break; case "f": // Face. ObjFace face = new ObjFace( AllVertices, AllNormals, AllTextureCoordinates, line); face.SmoothingGroup = smoothingGroup; NewObjectModel.Faces.Add(face); NewObjectModel.MaterialName = curMatName; break; case "s": // Smoothing. if (fields.Length == 0) { smoothingGroup = 0; } else if (fields[1] == "off") { smoothingGroup = 0; } else if (fields[1] == "on") { smoothingGroup = 1; } else if (!int.TryParse(fields[1], out smoothingGroup)) { smoothingGroup = 0; } break; case "usemtl": // Material. if (fields.Length > 1) { curMatName = fields[1]; } break; case "mtllib": // Material file. string mtlfile = line.Substring(6).Trim(); ReadMtlFile(dir, mtlfile); break; default: if (!unknown.Contains(fields[0])) { unknown.Add(fields[0]); } break; } } } // If the final model is empty, remove it. if (AllObjectModels[AllObjectModels.Count - 1].Faces.Count == 0) { AllObjectModels.RemoveAt(AllObjectModels.Count - 1); } // List unknown tokens. if (unknown.Count > 0) { Console.WriteLine("Unknown obj tokens:"); foreach (string token in unknown) { Console.WriteLine(" " + token); } } }
public ObjFile Import(string modelPath) { try { buffer = File.ReadAllBytes(modelPath); } catch { Console.WriteLine("Could not find model: " + modelPath); return(null); } int[][] sections = ParseFile(); Dictionary <int, object[]> parsedSections = new Dictionary <int, object[]>(); foreach (int[] section in sections) { switch (section[1]) { case AnimationDataTag: //Debug.Log("animation data"); parsedSections[section[2]] = ParseAnimationData(section[0] + 12, section[3], section[2]); break; case AuthorTag: //Debug.Log("author tag"); parsedSections[section[2]] = ParseAuthor(section[0] + 12, section[3], section[2]); break; case MaterialGroupTag: //Debug.Log("material group tag"); parsedSections[section[2]] = ParseMaterialGroup(section[0] + 12, section[3], section[2]); break; case MaterialTag: //Debug.Log("material tag"); parsedSections[section[2]] = ParseMaterial(section[0] + 12, section[3], section[2]); break; case Object3DTag: //Debug.Log("object3d tag"); parsedSections[section[2]] = ParseObject3D(section[0] + 12, section[3], section[2]); break; case ModelDataTag: //Debug.Log("model data tag"); parsedSections[section[2]] = ParseModelData(section[0] + 12, section[3], section[2]); break; case GeometryTag: //Debug.Log("geometry tag"); parsedSections[section[2]] = ParseGeometry(section[0] + 12, section[3], section[2]); break; case TopologyTag: //Debug.Log("topology tag"); parsedSections[section[2]] = ParseTopology(section[0] + 12, section[3], section[2]); break; case TopologyIpTag: //Debug.Log("topologyIP tag"); parsedSections[section[2]] = ParseTopologyIp(section[0] + 12, section[3], section[2]); break; } if ((uint)section[1] == PassthroughTag) { parsedSections[section[2]] = ParsePassthroughGp(section[0] + 12, section[3], section[2]); } } ObjFile obj = new ObjFile(); foreach (int[] section in sections) { if (section[1] == ModelDataTag) { object[] modelData = parsedSections[section[2]]; if ((int)modelData[3] == 6) { continue; } string modelId = "model-" + ((object[])modelData[2])[1]; object[] geometry = parsedSections[(int)parsedSections[(int)modelData[4]][2]]; object[] topology = parsedSections[(int)parsedSections[(int)modelData[4]][3]]; List <short[]> faces = (List <short[]>)topology[4]; List <float[]> vertices = (List <float[]>)geometry[6]; List <float[]> uvs = (List <float[]>)geometry[7]; List <float[]> normals = (List <float[]>)geometry[8]; float[] position = (float[])((object[])modelData[2])[5]; foreach (short[] face in faces) { ObjFace objFace = new ObjFace(); objFace.Vertices.Add(new ObjTriplet(face[0] + 1, face[0] + 1, face[0] + 1)); objFace.Vertices.Add(new ObjTriplet(face[1] + 1, face[1] + 1, face[1] + 1)); objFace.Vertices.Add(new ObjTriplet(face[2] + 1, face[2] + 1, face[2] + 1)); obj.Faces.Add(objFace); } foreach (float[] vertex in vertices) { obj.Vertices.Add(new ObjVertex(vertex[0] + position[0], vertex[1] + position[1], vertex[2] + position[2])); } foreach (float[] uv in uvs) { obj.TextureVertices.Add(new ObjVector3(uv[0], -uv[1], 0)); } foreach (float[] normal in normals) { obj.VertexNormals.Add(new ObjVector3(normal[0], normal[1], normal[2])); } } } return(obj); }