static void CalculateBounds(MeshImportJob jobData) { var upperBound = new Vector3(float.MinValue, float.MinValue, float.MinValue); var lowerBound = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); var count = jobData.Vertices.Length; for (var i = 0; i < count; ++i) { var vertex = jobData.Vertices[i]; if (vertex.Position.x > upperBound.x) { upperBound.x = vertex.Position.x; } if (vertex.Position.y > upperBound.y) { upperBound.y = vertex.Position.y; } if (vertex.Position.z > upperBound.z) { upperBound.z = vertex.Position.z; } if (vertex.Position.x < lowerBound.x) { lowerBound.x = vertex.Position.x; } if (vertex.Position.y < lowerBound.y) { lowerBound.y = vertex.Position.y; } if (vertex.Position.z < lowerBound.z) { lowerBound.z = vertex.Position.z; } } jobData.MeshBounds = new Bounds((lowerBound + upperBound) * 0.5f, upperBound - lowerBound); }
static MeshImportJob ImportMesh <T>(SyncMesh syncMesh) where T : struct { var data = new MeshImportJob { SyncMesh = syncMesh }; var toggle = new IndexToggle <T>(data); var count = syncMesh.Vertices.Count; data.Vertices = new Vertex[count]; for (var i = 0; i < count; ++i) { var v = syncMesh.Vertices[i]; data.Vertices[i].Position = new Vector3(v.X, v.Y, v.Z); } count = syncMesh.Normals.Count; for (var i = 0; i < count; ++i) { var n = syncMesh.Normals[i]; data.Vertices[i].Normal = new Vector3(n.X, n.Y, n.Z); } count = syncMesh.Uvs.Count; for (var i = 0; i < count; ++i) { var u = syncMesh.Uvs[i]; data.Vertices[i].UV = new Vector2(u.X, u.Y); } var subMeshCount = syncMesh.SubMeshes.Count; var nbIndices = syncMesh.SubMeshes.Sum(x => x.Triangles.Count); toggle.InstantiateArray(nbIndices); data.SubMeshStarts = new int[syncMesh.SubMeshes.Count]; data.SubMeshLengths = new int[syncMesh.SubMeshes.Count]; var offset = 0; for (var i = 0; i < subMeshCount; ++i) { count = syncMesh.SubMeshes[i].Triangles.Count; data.SubMeshStarts[i] = offset; data.SubMeshLengths[i] = count; var index = 0; foreach (var triangleIndex in syncMesh.SubMeshes[i].Triangles) { toggle.Set(offset + index++, triangleIndex); } offset += count; } CalculateBounds(data); CalculateMeshTangents(data, toggle); return(data); }
static void CalculateMeshTangents <T>(MeshImportJob jobData, IndexToggle <T> toggle) where T : struct { // Todo: Validate that this function is yielding the same result as the internal unity function var vertices = jobData.Vertices; var triangleCount = toggle.GetLength(); var vertexCount = vertices.Length; var tan1 = new Vector3[vertexCount]; var tan2 = new Vector3[vertexCount]; for (long a = 0; a < triangleCount; a += 3) { long i1 = toggle.Get(a + 0); long i2 = toggle.Get(a + 1); long i3 = toggle.Get(a + 2); var v1 = vertices[i1].Position; var v2 = vertices[i2].Position; var v3 = vertices[i3].Position; var w1 = vertices[i1].UV; var w2 = vertices[i2].UV; var w3 = vertices[i3].UV; var x1 = v2.x - v1.x; var x2 = v3.x - v1.x; var y1 = v2.y - v1.y; var y2 = v3.y - v1.y; var z1 = v2.z - v1.z; var z2 = v3.z - v1.z; var s1 = w2.x - w1.x; var s2 = w3.x - w1.x; var t1 = w2.y - w1.y; var t2 = w3.y - w1.y; var div = s1 * t2 - s2 * t1; var r = div == 0.0f ? 0.0f : 1.0f / (s1 * t2 - s2 * t1); var sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); var tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); tan1[i1] += sdir; tan1[i2] += sdir; tan1[i3] += sdir; tan2[i1] += tdir; tan2[i2] += tdir; tan2[i3] += tdir; } for (long a = 0; a < vertexCount; ++a) { var n = vertices[a].Normal; var t = tan1[a]; Vector3.OrthoNormalize(ref n, ref t); vertices[a].Tangent.Set(t.x, t.y, t.z, Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f ? -1.0f : 1.0f); } }
public IndexToggle(MeshImportJob jobData) { m_JobData = jobData; }