public void ImportWavefrontObject(WavefrontObject Wavefront, CompressionBounds boundingBox) { List<D3DVertex> temp = new List<D3DVertex>(Wavefront.FaceCount * 3); for (int Material = 0; Material < Wavefront.MaterialCount; Material++) { int[] FaceIndices = Wavefront.GetFaceIndicesUsingMaterialID(Material); for (int Face = 0; Face < FaceIndices.Length; Face++) { for (int Component = 0; Component < 3; Component++) { D3DVertex d3DVertex = new D3DVertex(); d3DVertex.Position = Wavefront.Vertices[Wavefront.Faces[FaceIndices[Face]].VertexIndices[Component]]; d3DVertex.Texture = Wavefront.Texcoords[Wavefront.Faces[FaceIndices[Face]].TexcoordIndices[Component]]; d3DVertex.Normal = Wavefront.Normals[Wavefront.Faces[FaceIndices[Face]].NormalIndices[Component]]; temp.Add(d3DVertex); } } } //Hashtable D3DVertexHashtable = new Hashtable(Wavefront.FaceCount * 3); List<short> tempIndices = new List<short>(Wavefront.FaceCount * 3); List<D3DVertex> D3DVertexList = new List<D3DVertex>(Wavefront.FaceCount * 3); short IndiceIndex = 0; for (int Index = 0; Index < temp.Count; Index++) { D3DVertex d3DVertex = temp[Index]; if (!D3DVertexList.Contains(d3DVertex)) { //D3DVertexHashtable.Add(d3DVertex, d3DVertex); D3DVertexList.Add(d3DVertex); tempIndices.Add(IndiceIndex); IndiceIndex++; } else { tempIndices.Add((short)D3DVertexList.IndexOf(d3DVertex)); } } this.Indices = tempIndices.ToArray(); D3DVertex[] D3DVertices = D3DVertexList.ToArray(); RenderDevice Device = new RenderDevice(); Device.InitializeDevice(); Microsoft.DirectX.Direct3D.Mesh mesh = new Microsoft.DirectX.Direct3D.Mesh(Wavefront.FaceCount, D3DVertices.Length, MeshFlags.SystemMemory, D3DVertex.Format, Device.Device); List<int> newAttributes = new List<int>(Wavefront.FaceCount); foreach (Face f in Wavefront.Faces) { newAttributes.Add(f.MaterialID); } mesh.LockAttributeBuffer(LockFlags.None); mesh.UnlockAttributeBuffer(newAttributes.ToArray()); mesh.SetIndexBufferData(Indices.ToArray(), LockFlags.None); mesh.SetVertexBufferData(D3DVertices.ToArray(), LockFlags.None); int[] adj = new int[Wavefront.FaceCount * 3]; mesh.GenerateAdjacency(0.005F, adj); mesh.OptimizeInPlace(MeshFlags.OptimizeAttributeSort, adj); IndexBuffer iBuffer = mesh.IndexBuffer; short[] D3DIndices; int IndiceCount; short[][] MaterialFaceIndices = new short[Wavefront.MaterialCount][]; for (int Material = 0; Material < Wavefront.MaterialCount; Material++) { iBuffer = Microsoft.DirectX.Direct3D.Mesh.ConvertMeshSubsetToSingleStrip(mesh, Material, MeshFlags.SystemMemory, out IndiceCount); GraphicsStream graphics = iBuffer.Lock(0, 0, LockFlags.None); unsafe { short* IndiceArray = (short*)graphics.InternalData.ToPointer(); D3DIndices = new short[IndiceCount]; for (int Index = 0; Index < IndiceCount; Index++) { D3DIndices[Index] = IndiceArray[Index]; } } MaterialFaceIndices[Material] = D3DIndices; } List<short> newIndices = new List<short>(); Groups = new Group[MaterialFaceIndices.Length]; for (int i = 0; i < MaterialFaceIndices.Length; i++) { Groups[i] = new Group(); Groups[i].IndiceStart = (short)newIndices.Count; Groups[i].IndiceCount = (short)MaterialFaceIndices[i].Length; Groups[i].ShaderIndex = (short)i; newIndices.AddRange(MaterialFaceIndices[i]); } this.Indices = newIndices.ToArray(); this._Vertices = new Vector3[D3DVertices.Length]; this.Texcoords = new Vector2[D3DVertices.Length]; this.Normals = new Vector3[D3DVertices.Length]; for (int i = 0; i < D3DVertices.Length; i++) { _Vertices[i] = D3DVertices[i].Position; Texcoords[i] = D3DVertices[i].Texture; Normals[i] = D3DVertices[i].Normal; } CalculateTangentArray(_Vertices.Length, _Vertices, Normals, Texcoords, mesh.NumberFaces, Wavefront.Faces.ToArray(), out Bitangents, out Tangents); mesh.Dispose(); }
public static void CreateWavefrontOBJFile(WavefrontObject wavefront, string filename) { FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read); StreamWriter sw = new StreamWriter(fs); sw.NewLine = "\r\n"; if (wavefront.VertexCount > 0) foreach (Vector3 v in wavefront.Vertices) { sw.WriteLine("v " + Math.Round((double)v.X, 5, MidpointRounding.ToEven).ToString() + " " + Math.Round((double)v.Y, 5, MidpointRounding.ToEven).ToString() + " " + Math.Round((double)v.Z, 5, MidpointRounding.ToEven).ToString()); } sw.WriteLine("# " + wavefront.VertexCount.ToString() + " Vertices"); sw.WriteLine(); if (wavefront.TexcoordCount > 0) foreach (Vector2 vt in wavefront.Texcoords) { sw.WriteLine("vt " + Math.Round((double)vt.X, 5, MidpointRounding.ToEven).ToString() + " " + Math.Round((double)vt.Y, 5, MidpointRounding.ToEven).ToString()); } sw.WriteLine("# " + wavefront.TexcoordCount.ToString() + " Texcoords"); sw.WriteLine(); if (wavefront.NormalCount > 0) foreach (Vector3 vn in wavefront.Normals) { sw.WriteLine("vn " + Math.Round((double)vn.X, 5, MidpointRounding.ToEven).ToString() + " " + Math.Round((double)vn.Y, 5, MidpointRounding.ToEven).ToString() + " " + Math.Round((double)vn.Z, 5, MidpointRounding.ToEven).ToString()); } sw.WriteLine("# " + wavefront.NormalCount.ToString() + " Normals"); sw.WriteLine(); if (wavefront.FaceCount > 0) { Dictionary<int, string> MaterialNames; MaterialNames = wavefront.Materials.ToDictionary(x => x.Value, x => x.Key); int[] Faces; string curMat = ""; string newMat; Face temp; for (int Group = 0; Group < wavefront.GroupCount; Group++) { Faces = wavefront.GetFaceIndicesUsingGroupID(Group); for (int Face = 0; Face < Faces.Length; Face++) { temp = wavefront.Faces[Faces[Face]]; newMat = MaterialNames[temp.MaterialID]; if (curMat != newMat) { curMat = newMat; sw.WriteLine("usemtl " + curMat); } sw.WriteLine("f " + temp.ToString()); } sw.WriteLine("# " + Faces.Length.ToString() + " Faces"); sw.WriteLine(); curMat = ""; } } sw.Dispose(); fs.Dispose(); }
public void ExportWavefrontObject(Shader[] shaders) { WavefrontObject wfo = new WavefrontObject(); wfo.Vertices = new List<Vector3>( _Vertices); wfo.VertexCount = _Vertices.Length; wfo.Texcoords = new List<Vector2>(Texcoords); wfo.TexcoordCount = Texcoords.Length; wfo.Normals = new List<Vector3>(Normals); wfo.NormalCount = Normals.Length; wfo.Materials = new Dictionary<string, int>(); for (int i = 0; i < shaders.Length; i++) wfo.Materials.Add("Default_" + i.ToString(), i); wfo.GroupCount = Groups.Length; List<Face> FaceArray = new List<Face>(Indices.Length); for (int i = 0; i < Groups.Length; i++) { int Start = Groups[i].IndiceStart; int End = Groups[i].IndiceStart + Groups[i].IndiceCount - 2; bool Winding = true; for (int x = Start; x < End; x++) { Face Temp = new Face( Indices[x], Indices[x + 1], Indices[x + 2], Indices[x], Indices[x + 1], Indices[x + 2], Indices[x], Indices[x + 1], Indices[x + 2] ); Temp.MaterialID = Groups[i].ShaderIndex; Temp.GroupID = i; if (!Temp.IsDegenerate) { FaceArray.Add(Temp); if (Winding == false) { short y = Temp.VertexIndices[1]; short z = Temp.VertexIndices[2]; Temp.VertexIndices[1] = z; Temp.VertexIndices[2] = y; y = Temp.TexcoordIndices[1]; z = Temp.TexcoordIndices[2]; Temp.TexcoordIndices[1] = z; Temp.TexcoordIndices[2] = y; y = Temp.NormalIndices[1]; z = Temp.NormalIndices[2]; Temp.NormalIndices[1] = z; Temp.NormalIndices[2] = y; Winding = true; } else { Winding = false; } } else { if (Winding == false) { Winding = true; } else { Winding = false; } } } } FaceArray.TrimExcess(); wfo.Faces = FaceArray; wfo.FaceCount = FaceArray.Count; Wavefront.CreateWavefrontOBJFile(wfo, "O:\\test.obj"); }
public static WavefrontObject ParseWavefrontOBJFile(string filename) { StreamReader sr = new StreamReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); string s = sr.ReadToEnd(); sr.Close(); string[] Lines = s.Split(new string[] { "\r\n", "\n\r", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries); s = ""; WavefrontObject Wavefront = new WavefrontObject(); int Material = -1; int Group = -1; string Line; string[] components; string t; string last; int Length; bool Scan = true; for (int Pass = 0; Pass < 2; Pass++) { for (int i = 0; i < Lines.Length; i++) { Line = Lines[i].Trim(); Length = Line.IndexOf(" "); if (Length > 0) Line = Line.Substring(0, Length); last = s; switch (Line) { case "v": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) Wavefront.VertexCount++; else { float x = float.Parse(components[1]); float y = float.Parse(components[2]); float z = float.Parse(components[3]); Wavefront.Vertices.Add(new Vector3(x, y, z)); } break; case "vt": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) Wavefront.TexcoordCount++; else { float u = float.Parse(components[1]); float v = float.Parse(components[2]); Wavefront.Texcoords.Add(new Vector2(u, v)); } break; case "vn": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) Wavefront.NormalCount++; else { float x = float.Parse(components[1]); float y = float.Parse(components[2]); float z = float.Parse(components[3]); Wavefront.Normals.Add(new Vector3(x, y, z)); } break; case "f": t = Lines[i].Trim(); components = t.Split(new string[] { " ", "/" }, StringSplitOptions.RemoveEmptyEntries); if (Scan) Wavefront.FaceCount++; else { Face temp = new Face(components); temp.MaterialID = Material; temp.GroupID = Group; Wavefront.Faces.Add(temp); } break; case "l": t = Lines[i].Trim(); if (Scan) Wavefront.LineCount++; else { Line temp = new Line(t); Wavefront.Lines.Add(temp); } break; case "g": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) Wavefront.GroupCount++; else { if (!(components.Length == 1) && !Wavefront.Groups.ContainsKey(components[1])) { Wavefront.Groups.Add(components[1], Wavefront.Groups.Count); Group = Wavefront.Groups[components[1]]; } else if (!(components.Length == 1)) Group = Wavefront.Groups[components[1]]; } break; case "usemtl": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) Wavefront.MaterialCount++; else { if (!Wavefront.Materials.ContainsKey(components[1])) Wavefront.Materials.Add(components[1], Wavefront.Materials.Count); Material = Wavefront.Materials[components[1]]; } break; default: break; } } if (Scan) { Wavefront.Initialize(); Scan = false; } } return Wavefront; }