/// <summary> /// Recalculates the normals based on vertex positions. /// </summary> public void CalculateNormals() { if (Vertices.Count < 3) { return; } Vector3[] normals = new Vector3[Vertices.Count]; for (int i = 0; i < normals.Length; i++) { normals[i] = new Vector3(0, 0, 0); } List <uint> f = Faces; for (int i = 0; i < f.Count; i += 3) { STVertex v1 = Vertices[(int)f[i]]; STVertex v2 = Vertices[(int)f[i + 1]]; STVertex v3 = Vertices[(int)f[i + 2]]; Vector3 nrm = CalculateNormal(v1, v2, v3); normals[f[i + 0]] += nrm * (nrm.Length / 2); normals[f[i + 1]] += nrm * (nrm.Length / 2); normals[f[i + 2]] += nrm * (nrm.Length / 2); } for (int i = 0; i < normals.Length; i++) { Vertices[i].Normal = normals[i].Normalized(); } }
public float DistanceTo(STVertex vertex) { float deltaX = vertex.Position.X - Position.X; float deltaY = vertex.Position.Y - Position.Y; float deltaZ = vertex.Position.Z - Position.Z; return((float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ)); }
private Vector3 CalculateNormal(STVertex v1, STVertex v2, STVertex v3) { Vector3 U = v2.Position - v1.Position; Vector3 V = v3.Position - v1.Position; // Don't normalize here, so surface area can be calculated. return(Vector3.Cross(U, V)); }
public STVertex(STVertex vertex) { Position = vertex.Position; Normal = vertex.Normal; TexCoords = vertex.TexCoords; Colors = vertex.Colors; Tangent = vertex.Tangent; Bitangent = vertex.Bitangent; BoneWeights = vertex.BoneWeights; BoneIndices = vertex.BoneIndices; BoneNames = vertex.BoneNames; }
private void ApplyTanBitanArray(Vector3[] tanArray, Vector3[] bitanArray) { if (Vertices.Count < 3) { return; } for (int i = 0; i < Vertices.Count; i++) { STVertex v = Vertices[i]; Vector3 newTan = tanArray[i]; Vector3 newBitan = bitanArray[i]; // The tangent and bitangent should be orthogonal to the normal. // Bitangents are not calculated with a cross product to prevent flipped shading with mirrored normal maps. v.Tangent = new Vector4(Vector3.Normalize(newTan - v.Normal * Vector3.Dot(v.Normal, newTan)), 1); v.Bitangent = new Vector4(Vector3.Normalize(newBitan - v.Normal * Vector3.Dot(v.Normal, newBitan)), 1); v.Bitangent *= -1; } }
private void CalculateTanBitanArrays(List <uint> faces, Vector3[] tanArray, Vector3[] bitanArray, int uvSet = 0) { if (Vertices.Count < 3 || faces.Count <= 0) { return; } for (int i = 0; i < faces.Count; i += 3) { STVertex v1 = Vertices[(int)faces[i]]; STVertex v2 = Vertices[(int)faces[i + 1]]; STVertex v3 = Vertices[(int)faces[i + 2]]; 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; float s1, s2, t1, t2; s1 = v2.TexCoords[uvSet].X - v1.TexCoords[uvSet].X; s2 = v3.TexCoords[uvSet].X - v1.TexCoords[uvSet].X; t1 = v2.TexCoords[uvSet].Y - v1.TexCoords[uvSet].Y; t2 = v3.TexCoords[uvSet].Y - v1.TexCoords[uvSet].Y; float div = (s1 * t2 - s2 * t1); float r = 1.0f / div; // Fix +/- infinity from division by 0. if (r == float.PositiveInfinity || r == float.NegativeInfinity) { r = 1.0f; } float sX = t2 * x1 - t1 * x2; float sY = t2 * y1 - t1 * y2; float sZ = t2 * z1 - t1 * z2; Vector3 s = new Vector3(sX, sY, sZ) * r; float tX = s1 * x2 - s2 * x1; float tY = s1 * y2 - s2 * y1; float tZ = s1 * z2 - s2 * z1; Vector3 t = new Vector3(tX, tY, tZ) * r; // Prevents black tangents or bitangents due to having vertices with the same UV coordinates. float delta = 0.00075f; bool sameU, sameV; sameU = (Math.Abs(v1.TexCoords[uvSet].X - v2.TexCoords[uvSet].X) < delta) && (Math.Abs(v2.TexCoords[uvSet].X - v3.TexCoords[uvSet].X) < delta); sameV = (Math.Abs(v1.TexCoords[uvSet].Y - v2.TexCoords[uvSet].Y) < delta) && (Math.Abs(v2.TexCoords[uvSet].Y - v3.TexCoords[uvSet].Y) < delta); if (sameU || sameV) { // Let's pick some arbitrary tangent vectors. s = new Vector3(1, 0, 0); t = new Vector3(0, 1, 0); } // Average tangents and bitangents. tanArray[faces[i]] += s; tanArray[faces[i + 1]] += s; tanArray[faces[i + 2]] += s; bitanArray[faces[i]] += t; bitanArray[faces[i + 1]] += t; bitanArray[faces[i + 2]] += t; } }