private void CalculateTangentArray(int vertexCount, Vertex[] vertex, Vector[] normal, Texcoord[] texcoord, int triangleCount, Face[] triangles, out Vector[] Bitangent, out Vector[] Normals, out Vector[] Tangent) { Vector3[] tan1 = new Vector3[vertexCount]; Vector3[] tan2 = new Vector3[vertexCount]; Normals = new Vector[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 Vertex v1 = vertex[i1]; Vertex v2 = vertex[i2]; Vertex v3 = vertex[i3]; //From Texture Array Copy Coordinates of Vertex's Texcoord w1 = texcoord[vt1]; Texcoord w2 = texcoord[vt2]; Texcoord w3 = texcoord[vt3]; //Make Relative to Vertex 1 //Vertex Coordinates float x1 = v2.Position.X - v1.Position.X; float x2 = v3.Position.X - v1.Position.X; float y1 = v2.Position.Y - v1.Position.Y; float y2 = v3.Position.Y - v1.Position.Y; float z1 = v2.Position.Z - v1.Position.Z; float z2 = v3.Position.Z - v1.Position.Z; //Texture Coordinates float s1 = w2.Coordinates.X - w1.Coordinates.X; float s2 = w3.Coordinates.X - w1.Coordinates.X; float t1 = w2.Coordinates.Y - w1.Coordinates.Y; float t2 = w3.Coordinates.Y - w1.Coordinates.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.Position, v2.Position, v3.Position); 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 Vector[vertexCount]; Bitangent = new Vector[vertexCount]; for (int a = 0; a < vertexCount; a++) { Vector3 n = normal[a].Components; 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] = new Vector(Vector3.Empty, Vector.VectorUsage.Tangent); Tangent[a].Components = temp; Tangent[a] = Round(Tangent[a]); // Calculate handedness float W = (Vector3.Dot(Vector3.Cross(n, t), b) < 0.0F) ? -1.0F : 1.0F; //Calculate Bitangent Bitangent[a] = new Vector(Vector3.Empty, Vector.VectorUsage.Bitangent); Bitangent[a].Components = Vector3.Multiply((Vector3.Cross(n, temp)), W); Bitangent[a] = Round(Bitangent[a]); } }
private int Compress(ref Vector vector) { int X_sign = vector.Components.X < 0 ? 1 : 0; int Y_sign = vector.Components.Y < 0 ? 1 : 0; int Z_sign = vector.Components.Z < 0 ? 1 : 0; vector.Components.X = vector.Components.X < 0 ? (1 + vector.Components.X) : vector.Components.X; vector.Components.Y = vector.Components.Y < 0 ? (1 + vector.Components.Y) : vector.Components.Y; vector.Components.Z = vector.Components.Z < 0 ? (1 + vector.Components.Z) : vector.Components.Z; int X = (int)(vector.Components.X * 0x3FF); int Y = (int)(vector.Components.Y * 0x3FF); int Z = (int)(vector.Components.Z * 0x1FF); int integer = (Z_sign << 31) | (Z << 22) | (Y_sign << 21) | (Y << 11) | (X_sign << 10) | X; return integer; }
public Vector[] ToVectorArray() { Vector[] Vectors = new Vector[RawVectorData.Length]; for (int Count = 0; Count < RawVectorData.Length; Count++) { byte xSign = (byte)((RawVectorData[Count] >> 10) & 0x1); byte ySign = (byte)((RawVectorData[Count] >> 21) & 0x1); byte zSign = (byte)((RawVectorData[Count] >> 31) & 0x1); float x = (int)((RawVectorData[Count]) & 0x3FF); x /= (float)0x3FF; float y = (float)((RawVectorData[Count] >> 11) & 0x3FF); y /= (float)0x3FF; float z = (float)((RawVectorData[Count] >> 22) & 0x1FF); z /= (float)0x1FF; z = zSign == 1 ? (z - 1) : z; y = ySign == 1 ? (y - 1) : y; x = xSign == 1 ? (x - 1) : x; Vectors[Count] = new Vector(new Vector3(x, y, z), (Vector.VectorUsage)(Count % 3)); } return Vectors; }
public VectorData(int vertexcount, Vertex[] vertices, Vector[] normals, Texcoord[] texcoords, int trianglecount, Face[] triangles) { Vector[] Tangents, Bitangents; CalculateTangentArray(vertexcount, vertices, normals, texcoords, trianglecount, triangles, out Bitangents, out normals, out Tangents); Size = (uint)(normals.Length * 3 * 4); List<int> RawData = new List<int>((int)Size); for (int Index = 0; Index < normals.Length; Index++) { RawData.Add(Compress(ref normals[Index])); RawData.Add(Compress(ref Bitangents[Index])); RawData.Add(Compress(ref Tangents[Index])); } RawVectorData = RawData.ToArray(); }
private Vector Round(Vector vector) { vector.Components.X = (float)Math.Round((double)vector.Components.X, 5); vector.Components.Y = (float)Math.Round((double)vector.Components.Y, 5); vector.Components.Z = (float)Math.Round((double)vector.Components.Z, 5); return vector; }