bool TryGetMeshInfo(GameObject root, Renderer renderer, out MeshExportInfo info) { info = default; if (root == null) { info.Summary = ""; return(false); } if (renderer == null) { info.Summary = "no Renderer"; return(false); } info.Renderer = renderer; if (renderer is SkinnedMeshRenderer smr) { info.Skinned = true; info.Mesh = smr.sharedMesh; info.IsRendererActive = smr.EnableForExport(); } else if (renderer is MeshRenderer mr) { var filter = mr.GetComponent <MeshFilter>(); if (filter != null) { info.Mesh = filter.sharedMesh; } info.IsRendererActive = mr.EnableForExport(); } else { info.Summary = "no Mesh"; return(false); } info.VertexColor = MeshExportInfo.DetectVertexColor(info.Mesh, info.Renderer.sharedMaterials); var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(renderer.transform, root.transform); CalcMeshSize(ref info, relativePath); return(true); }
static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex, MeshWithRenderer unityMesh, List <Material> unityMaterials) { var mesh = unityMesh.Mesh; var materials = unityMesh.Renderer.sharedMaterials; var positions = mesh.vertices.Select(y => y.ReverseZ()).ToArray(); var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER); gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray(); gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray(); var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.normals.Select(y => y.normalized.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); #if GLTF_EXPORT_TANGENTS var tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); #endif var uvAccessorIndex0 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER); var uvAccessorIndex1 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv2.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER); var colorAccessorIndex = -1; var vColorState = MeshExportInfo.DetectVertexColor(mesh, materials); if (vColorState == MeshExportInfo.VertexColorState.ExistsAndIsUsed || // VColor使っている vColorState == MeshExportInfo.VertexColorState.ExistsAndMixed // VColorを使っているところと使っていないところが混在(とりあえずExportする) ) { // UniUnlit で Multiply 設定になっている colorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors, glBufferTarget.ARRAY_BUFFER); } var boneweights = mesh.boneWeights; var weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new UShort4( (ushort)unityMesh.GetJointIndex(y.boneIndex0), (ushort)unityMesh.GetJointIndex(y.boneIndex1), (ushort)unityMesh.GetJointIndex(y.boneIndex2), (ushort)unityMesh.GetJointIndex(y.boneIndex3)) ).ToArray(), glBufferTarget.ARRAY_BUFFER); var attributes = new glTFAttributes { POSITION = positionAccessorIndex, }; if (normalAccessorIndex != -1) { attributes.NORMAL = normalAccessorIndex; } #if GLTF_EXPORT_TANGENTS if (tangentAccessorIndex != -1) { attributes.TANGENT = tangentAccessorIndex; } #endif if (uvAccessorIndex0 != -1) { attributes.TEXCOORD_0 = uvAccessorIndex0; } if (uvAccessorIndex1 != -1) { attributes.TEXCOORD_1 = uvAccessorIndex1; } if (colorAccessorIndex != -1) { attributes.COLOR_0 = colorAccessorIndex; } if (weightAccessorIndex != -1) { attributes.WEIGHTS_0 = weightAccessorIndex; } if (jointsAccessorIndex != -1) { attributes.JOINTS_0 = jointsAccessorIndex; } var gltfMesh = new glTFMesh(mesh.name); var indices = new List <uint>(); for (int j = 0; j < mesh.subMeshCount; ++j) { indices.Clear(); var triangles = mesh.GetIndices(j); if (triangles.Length == 0) { // https://github.com/vrm-c/UniVRM/issues/664 continue; } for (int i = 0; i < triangles.Length; i += 3) { var i0 = triangles[i]; var i1 = triangles[i + 1]; var i2 = triangles[i + 2]; // flip triangle indices.Add((uint)i2); indices.Add((uint)i1); indices.Add((uint)i0); } var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices.ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER); if (indicesAccessorIndex < 0) { // https://github.com/vrm-c/UniVRM/issues/664 throw new Exception(); } if (j >= materials.Length) { Debug.LogWarningFormat("{0}.materials is not enough", unityMesh.Renderer.name); break; } gltfMesh.primitives.Add(new glTFPrimitives { attributes = attributes, indices = indicesAccessorIndex, mode = 4, // triangles ? material = unityMaterials.IndexOf(materials[j]) }); } return(gltfMesh); }
static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex, string rendererName, Mesh mesh, Material[] materials, List <Material> unityMaterials) { var positions = mesh.vertices.Select(y => y.ReverseZ()).ToArray(); var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER); gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray(); gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray(); var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.normals.Select(y => y.normalized.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); #if GLTF_EXPORT_TANGENTS var tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER); #endif var uvAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER); var colorAccessorIndex = -1; var vColorState = MeshExportInfo.DetectVertexColor(mesh, materials); if (vColorState == MeshExportInfo.VertexColorState.ExistsAndIsUsed || // VColor使っている vColorState == MeshExportInfo.VertexColorState.ExistsAndMixed // VColorを使っているところと使っていないところが混在(とりあえずExportする) ) { // UniUnlit で Multiply 設定になっている colorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors, glBufferTarget.ARRAY_BUFFER); } var boneweights = mesh.boneWeights; var weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new UShort4((ushort)y.boneIndex0, (ushort)y.boneIndex1, (ushort)y.boneIndex2, (ushort)y.boneIndex3)).ToArray(), glBufferTarget.ARRAY_BUFFER); var attributes = new glTFAttributes { POSITION = positionAccessorIndex, }; if (normalAccessorIndex != -1) { attributes.NORMAL = normalAccessorIndex; } #if GLTF_EXPORT_TANGENTS if (tangentAccessorIndex != -1) { attributes.TANGENT = tangentAccessorIndex; } #endif if (uvAccessorIndex != -1) { attributes.TEXCOORD_0 = uvAccessorIndex; } if (colorAccessorIndex != -1) { attributes.COLOR_0 = colorAccessorIndex; } if (weightAccessorIndex != -1) { attributes.WEIGHTS_0 = weightAccessorIndex; } if (jointsAccessorIndex != -1) { attributes.JOINTS_0 = jointsAccessorIndex; } var gltfMesh = new glTFMesh(mesh.name); for (int j = 0; j < mesh.subMeshCount; ++j) { var indices = TriangleUtil.FlipTriangle(mesh.GetIndices(j)).Select(y => (uint)y).ToArray(); var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices, glBufferTarget.ELEMENT_ARRAY_BUFFER); if (j >= materials.Length) { Debug.LogWarningFormat("{0}.materials is not enough", rendererName); break; } gltfMesh.primitives.Add(new glTFPrimitives { attributes = attributes, indices = indicesAccessorIndex, mode = 4, // triangles ? material = unityMaterials.IndexOf(materials[j]) }); } return(gltfMesh); }