protected virtual void BuildMeshAttributes(MeshPrimitive primitive, int meshID, int primitiveIndex) { if (_assetCache.MeshCache[meshID][primitiveIndex].MeshAttributes.Count == 0) { Dictionary <string, AttributeAccessor> attributeAccessors = new Dictionary <string, AttributeAccessor>(primitive.Attributes.Count + 1); foreach (var attributePair in primitive.Attributes) { AttributeAccessor AttributeAccessor = new AttributeAccessor() { AccessorId = attributePair.Value, Buffer = _assetCache.BufferCache[attributePair.Value.Value.BufferView.Value.Buffer.Id] }; attributeAccessors[attributePair.Key] = AttributeAccessor; } if (primitive.Indices != null) { AttributeAccessor indexBuilder = new AttributeAccessor() { AccessorId = primitive.Indices, Buffer = _assetCache.BufferCache[primitive.Indices.Value.BufferView.Value.Buffer.Id] }; attributeAccessors[SemanticProperties.INDICES] = indexBuilder; } GLTFHelpers.BuildMeshAttributes(ref attributeAccessors); // Flip vectors and triangles to the Unity coordinate system. if (attributeAccessors.ContainsKey(SemanticProperties.POSITION)) { NumericArray resultArray = attributeAccessors[SemanticProperties.POSITION].AccessorContent; resultArray.AsVertices = GLTFUnityHelpers.FlipVectorArrayHandedness(resultArray.AsVertices); attributeAccessors[SemanticProperties.POSITION].AccessorContent = resultArray; } if (attributeAccessors.ContainsKey(SemanticProperties.INDICES)) { NumericArray resultArray = attributeAccessors[SemanticProperties.INDICES].AccessorContent; resultArray.AsTriangles = GLTFUnityHelpers.FlipFaces(resultArray.AsTriangles); attributeAccessors[SemanticProperties.INDICES].AccessorContent = resultArray; } if (attributeAccessors.ContainsKey(SemanticProperties.NORMAL)) { NumericArray resultArray = attributeAccessors[SemanticProperties.NORMAL].AccessorContent; resultArray.AsNormals = GLTFUnityHelpers.FlipVectorArrayHandedness(resultArray.AsNormals); attributeAccessors[SemanticProperties.NORMAL].AccessorContent = resultArray; } // TexCoord goes from 0 to 3 to match GLTFHelpers.BuildMeshAttributes for (int i = 0; i < 4; i++) { if (attributeAccessors.ContainsKey(SemanticProperties.TexCoord(i))) { NumericArray resultArray = attributeAccessors[SemanticProperties.TexCoord(i)].AccessorContent; resultArray.AsTexcoords = GLTFUnityHelpers.FlipTexCoordArrayV(resultArray.AsTexcoords); attributeAccessors[SemanticProperties.TexCoord(i)].AccessorContent = resultArray; } } if (attributeAccessors.ContainsKey(SemanticProperties.TANGENT)) { NumericArray resultArray = attributeAccessors[SemanticProperties.TANGENT].AccessorContent; resultArray.AsTangents = GLTFUnityHelpers.FlipVectorArrayHandedness(resultArray.AsTangents); attributeAccessors[SemanticProperties.TANGENT].AccessorContent = resultArray; } _assetCache.MeshCache[meshID][primitiveIndex].MeshAttributes = attributeAccessors; } }
// a mesh *might* decode to multiple prims if there are submeshes private MeshPrimitive[] ExportPrimitive(GameObject gameObject) { var filter = gameObject.GetComponent <MeshFilter>(); var meshObj = filter.sharedMesh; var renderer = gameObject.GetComponent <MeshRenderer>(); var materialsObj = renderer.sharedMaterials; var prims = new MeshPrimitive[meshObj.subMeshCount]; // don't export any more accessors if this mesh is already exported MeshPrimitive[] primVariations; if (_meshToPrims.TryGetValue(meshObj, out primVariations) && meshObj.subMeshCount == primVariations.Length) { for (var i = 0; i < primVariations.Length; i++) { prims[i] = new MeshPrimitive(primVariations[i], _root) { Material = ExportMaterial(materialsObj[i]) }; } return(prims); } AccessorId aPosition = null, aNormal = null, aTangent = null, aTexcoord0 = null, aTexcoord1 = null, aColor0 = null; aPosition = ExportAccessor(GLTFUnityHelpers.FlipVectorArrayHandedness(meshObj.vertices)); if (meshObj.normals.Length != 0) { aNormal = ExportAccessor(GLTFUnityHelpers.FlipVectorArrayHandedness(meshObj.normals)); } if (meshObj.tangents.Length != 0) { aTangent = ExportAccessor(GLTFUnityHelpers.FlipVectorArrayHandedness(meshObj.tangents)); } if (meshObj.uv.Length != 0) { aTexcoord0 = ExportAccessor(GLTFUnityHelpers.FlipTexCoordArrayV(meshObj.uv)); } if (meshObj.uv2.Length != 0) { aTexcoord1 = ExportAccessor(GLTFUnityHelpers.FlipTexCoordArrayV(meshObj.uv2)); } if (meshObj.colors.Length != 0) { aColor0 = ExportAccessor(meshObj.colors); } MaterialId lastMaterialId = null; for (var submesh = 0; submesh < meshObj.subMeshCount; submesh++) { var primitive = new MeshPrimitive(); var triangles = meshObj.GetTriangles(submesh); primitive.Indices = ExportAccessor(GLTFUnityHelpers.FlipFaces(triangles), true); primitive.Attributes = new Dictionary <string, AccessorId>(); primitive.Attributes.Add(SemanticProperties.POSITION, aPosition); if (aNormal != null) { primitive.Attributes.Add(SemanticProperties.NORMAL, aNormal); } if (aTangent != null) { primitive.Attributes.Add(SemanticProperties.TANGENT, aTangent); } if (aTexcoord0 != null) { primitive.Attributes.Add(SemanticProperties.TexCoord(0), aTexcoord0); } if (aTexcoord1 != null) { primitive.Attributes.Add(SemanticProperties.TexCoord(1), aTexcoord1); } if (aColor0 != null) { primitive.Attributes.Add(SemanticProperties.Color(0), aColor0); } if (submesh < materialsObj.Length) { primitive.Material = ExportMaterial(materialsObj[submesh]); lastMaterialId = primitive.Material; } else { primitive.Material = lastMaterialId; } prims[submesh] = primitive; } _meshToPrims[meshObj] = prims; return(prims); }