private void CalculateTangentArray( int vertexCount, Vector3[] vertex, Vector3[] normal, Vector2[] texcoord, int triangleCount, Face[] triangles, out Vector3[] Bitangent, out Vector3[] Tangent) { Vector3[] tan1 = new Vector3[vertexCount]; Vector3[] tan2 = new Vector3[vertexCount]; //Normals = new Vector3[vertexCount]; for (int a = 0; a < triangleCount; a++) { //Store Vertex Index's int i1 = triangles[a].VertexIndices[0]; int i2 = triangles[a].VertexIndices[1]; int i3 = triangles[a].VertexIndices[2]; int n1 = triangles[a].NormalIndices[0]; int n2 = triangles[a].NormalIndices[1]; int n3 = triangles[a].NormalIndices[2]; int vt1 = triangles[a].TexcoordIndices[0]; int vt2 = triangles[a].TexcoordIndices[1]; int vt3 = triangles[a].TexcoordIndices[2]; //From Vertex Array Copy Coordinates of Vertex's Vector3 v1 = vertex[i1]; Vector3 v2 = vertex[i2]; Vector3 v3 = vertex[i3]; //From Texture Array Copy Coordinates of Vertex's Vector2 w1 = texcoord[vt1]; Vector2 w2 = texcoord[vt2]; Vector2 w3 = texcoord[vt3]; //Make Relative to Vertex 1 //Vertex Coordinates float x1 = v2.X - v1.X; float x2 = v3.X - v1.X; float y1 = v2.Y - v1.Y; float y2 = v3.Y - v1.Y; float z1 = v2.Z - v1.Z; float z2 = v3.Z - v1.Z; //Texture Coordinates float s1 = w2.X - w1.X; float s2 = w3.X - w1.X; float t1 = w2.Y - w1.Y; float t2 = w3.Y - w1.Y; float r = 1.0F / (s1 * t2 - s2 * t1); Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); AngleFucker AF = new AngleFucker(v1, v2, v3); tan1[i1] += Vector3.Multiply(sdir, AF.Get_v1_Angle()); tan1[i2] += Vector3.Multiply(sdir, AF.Get_v2_Angle()); tan1[i3] += Vector3.Multiply(sdir, AF.Get_v3_Angle()); tan2[i1] += Vector3.Multiply(tdir, AF.Get_v1_Angle()); tan2[i2] += Vector3.Multiply(tdir, AF.Get_v2_Angle()); tan2[i3] += Vector3.Multiply(tdir, AF.Get_v3_Angle()); } Tangent = new Vector3[vertexCount]; Bitangent = new Vector3[vertexCount]; for (int a = 0; a < vertexCount; a++) { Vector3 n = normal[a]; //Normals[a] = Round(normal[a]); Vector3 b = tan2[a]; Vector3 t = tan1[a]; // Gram-Schmidt orthogonalize Vector3 temp = Vector3.Subtract(t, Vector3.Multiply(n, Vector3.Dot(n, t))); temp.Normalize(); Tangent[a] = Round(temp); // Calculate handedness float W = (Vector3.Dot(Vector3.Cross(n, t), b) < 0.0F) ? -1.0F : 1.0F; //Calculate Bitangent Bitangent[a] = Vector3.Multiply((Vector3.Cross(n, temp)), W); Bitangent[a] = Round(Bitangent[a]); } }
public WavefrontObject(Stream stream) { //I'm very very sorry :{ //For everything that follows... StreamReader sr = new StreamReader(stream); string s = sr.ReadToEnd(); sr.Close(); string[] Lines = s.Split(new string[] { "\r\n", "\n\r", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries); s = ""; 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) VertexCount++; else { float x = float.Parse(components[1]); float y = float.Parse(components[2]); float z = float.Parse(components[3]); Vertices.Add(new Vector3(x, y, z)); } break; case "vt": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) TexcoordCount++; else { float u = float.Parse(components[1]); float v = float.Parse(components[2]); Texcoords.Add(new Vector2(u, v)); } break; case "vn": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) NormalCount++; else { float x = float.Parse(components[1]); float y = float.Parse(components[2]); float z = float.Parse(components[3]); Normals.Add(new Vector3(x, y, z)); } break; case "f": t = Lines[i].Trim(); components = t.Split(new string[] { " ", "/" }, StringSplitOptions.RemoveEmptyEntries); if (Scan) FaceCount++; else { Face temp = new Face(components); temp.MaterialID = Material; temp.GroupID = Group; Faces.Add(temp); } break; //case "l": // t = Lines[i].Trim(); // if (Scan) // LineCount++; // else // { // Line temp = new Line(t); // Lines.Add(temp); // } // break; case "g": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) GroupCount++; else { if (!(components.Length == 1) && !Groups.ContainsKey(components[1])) { Groups.Add(components[1], Groups.Count); Group = Groups[components[1]]; } else if (!(components.Length == 1)) Group = Groups[components[1]]; } break; case "usemtl": t = Lines[i].Trim(); components = t.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (Scan) MaterialCount++; else { if (!Materials.ContainsKey(components[1])) Materials.Add(components[1], Materials.Count); Material = Materials[components[1]]; } break; default: break; } } if (Scan) { Initialize(); Scan = false; } } }
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; }