public MeshPrimitiveAttributes BuildMeshAttributes(Dictionary <Buffer, byte[]> bufferCache) { var attributes = new MeshPrimitiveAttributes(); if (Attributes.ContainsKey(SemanticProperties.POSITION)) { var accessor = Attributes[SemanticProperties.POSITION].Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; attributes.Vertices = accessor.AsVector3Array(bufferData); } if (Indices != null) { var accessor = Indices.Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; var unflippedTriangles = accessor.AsIntArray(bufferData); var triangles = new int[unflippedTriangles.Length]; for (int i = 0; i < unflippedTriangles.Length; i += 3) { triangles[i + 2] = unflippedTriangles[i]; triangles[i + 1] = unflippedTriangles[i + 1]; triangles[i] = unflippedTriangles[i + 2]; } attributes.Triangles = triangles; } else { var triangles = new int[attributes.Vertices.Length]; for (int i = 0; i < triangles.Length; i += 3) { triangles[i + 2] = i; triangles[i + 1] = i + 1; triangles[i] = i + 2; } attributes.Triangles = triangles; } if (Attributes.ContainsKey(SemanticProperties.NORMAL)) { var accessor = Attributes[SemanticProperties.NORMAL].Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; attributes.Normals = accessor.AsVector3Array(bufferData); } if (Attributes.ContainsKey(SemanticProperties.TexCoord(0))) { var accessor = Attributes[SemanticProperties.TexCoord(0)].Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; attributes.Uv = accessor.AsVector2Array(bufferData); } if (Attributes.ContainsKey(SemanticProperties.TexCoord(1))) { var accessor = Attributes[SemanticProperties.TexCoord(1)].Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; attributes.Uv2 = accessor.AsVector2Array(bufferData); } if (Attributes.ContainsKey(SemanticProperties.TexCoord(2))) { var accessor = Attributes[SemanticProperties.TexCoord(2)].Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; attributes.Uv3 = accessor.AsVector2Array(bufferData); } if (Attributes.ContainsKey(SemanticProperties.TexCoord(3))) { var accessor = Attributes[SemanticProperties.TexCoord(3)].Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; attributes.Uv4 = accessor.AsVector2Array(bufferData); } if (Attributes.ContainsKey(SemanticProperties.Color(0))) { var accessor = Attributes[SemanticProperties.Color(0)].Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; attributes.Colors = accessor.AsColorArray(bufferData); } if (Attributes.ContainsKey(SemanticProperties.TANGENT)) { var accessor = Attributes[SemanticProperties.TANGENT].Value; var bufferData = bufferCache[accessor.BufferView.Value.Buffer.Value]; attributes.Tangents = accessor.AsVector4Array(bufferData); } return(attributes); }
// Taken from: http://answers.unity3d.com/comments/190515/view.html // Official support for Mesh.RecalculateTangents should be coming in 5.6 // https://feedback.unity3d.com/suggestions/recalculatetangents private MeshPrimitiveAttributes CalculateAndSetTangents(MeshPrimitiveAttributes attributes) { var triangleCount = attributes.Triangles.Length; var vertexCount = attributes.Vertices.Length; var tan1 = new Vector3[vertexCount]; var tan2 = new Vector3[vertexCount]; attributes.Tangents = new Vector4[vertexCount]; for (long a = 0; a < triangleCount; a += 3) { long i1 = attributes.Triangles[a + 0]; long i2 = attributes.Triangles[a + 1]; long i3 = attributes.Triangles[a + 2]; var v1 = attributes.Vertices[i1]; var v2 = attributes.Vertices[i2]; var v3 = attributes.Vertices[i3]; var w1 = attributes.Uv[i1]; var w2 = attributes.Uv[i2]; var w3 = attributes.Uv[i3]; 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 r = 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 = attributes.Normals[a]; var t = tan1[a]; Vector3.OrthoNormalize(ref n, ref t); attributes.Tangents[a].x = t.x; attributes.Tangents[a].y = t.y; attributes.Tangents[a].z = t.z; attributes.Tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f; } return(attributes); }