diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs index 7f6f774f7..e223014e7 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs @@ -1,83 +1,57 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; using UnityEngine; namespace UniGLTF { public class MeshContext { - [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)] - struct Float4 + private readonly List _positions = new List(); + private readonly List _normals = new List(); + [Obsolete] private readonly List _tangents = new List(); + private readonly List _uv = new List(); + private readonly List _uv2 = new List(); + private readonly List _colors = new List(); + private readonly List _boneWeights = new List(); + private readonly List _subMeshes = new List(); + private readonly List _materialIndices = new List(); + private readonly List _blendShapes = new List(); + + public IReadOnlyList Positions => _positions; + public IReadOnlyList Normals => _normals; + + [Obsolete] public IReadOnlyList Tangetns => _tangents; + + public IReadOnlyList UV => _uv; + + public IReadOnlyList UV2 => _uv2; + public IReadOnlyList Colors => _colors; + + public IReadOnlyList BoneWeights => _boneWeights; + + public IReadOnlyList SubMeshes => _subMeshes; + + public IReadOnlyList MaterialIndices => _materialIndices; + + public IReadOnlyList BlendShapes => _blendShapes; + + public string Name { get; } + + private BlendShape GetOrCreateBlendShape(int i) { - public float x; - public float y; - public float z; - public float w; - - public Float4 One() + if (i < _blendShapes.Count && _blendShapes[i] != null) { - var sum = x + y + z + w; - var f = 1.0f / sum; - return new Float4 - { - x = x * f, - y = y * f, - z = z * f, - w = w * f, - }; - } - } - - string m_name; - public string name => m_name; - - readonly List m_positions = new List(); - public List Positions => m_positions; - - readonly List m_normals = new List(); - public List Normals => m_normals; - - [Obsolete] - readonly List m_tangents = new List(); - [Obsolete] - public List Tangetns => m_tangents; - - readonly List m_uv = new List(); - public List UV => m_uv; - - readonly List m_uv2 = new List(); - public List UV2 => m_uv2; - - readonly List m_colors = new List(); - public List Colors => m_colors; - - readonly List m_boneWeights = new List(); - public List BoneWeights => m_boneWeights; - - readonly List m_subMeshes = new List(); - public List SubMeshes => m_subMeshes; - - readonly List m_materialIndices = new List(); - public List MaterialIndices => m_materialIndices; - - readonly List m_blendShapes = new List(); - public List BlendShapes => m_blendShapes; - BlendShape GetOrCreateBlendShape(int i) - { - if (i < m_blendShapes.Count && m_blendShapes[i] != null) - { - return m_blendShapes[i]; + return _blendShapes[i]; } - while (m_blendShapes.Count <= i) + while (_blendShapes.Count <= i) { - m_blendShapes.Add(null); + _blendShapes.Add(null); } var blendShape = new BlendShape(i.ToString()); - m_blendShapes[i] = blendShape; + _blendShapes[i] = blendShape; return blendShape; } @@ -85,9 +59,10 @@ namespace UniGLTF { if (string.IsNullOrEmpty(name)) { - name = string.Format("UniGLTF import#{0}", meshIndex); + name = $"UniGLTF import#{meshIndex}"; } - m_name = name; + + this.Name = name; } /// @@ -96,25 +71,27 @@ namespace UniGLTF /// /// /// - static void FillZero(IList list, int fillLength) + private static void FillZero(ICollection list, int fillLength) { if (list.Count > fillLength) { throw new Exception("Impossible"); } + while (list.Count < fillLength) { list.Add(default); } } - public static BoneWeight NormalizeBoneWeight(BoneWeight src) + private static BoneWeight NormalizeBoneWeight(BoneWeight src) { var sum = src.weight0 + src.weight1 + src.weight2 + src.weight3; if (sum == 0) { return src; } + var f = 1.0f / sum; src.weight0 *= f; src.weight1 *= f; @@ -136,13 +113,13 @@ namespace UniGLTF { foreach (var prim in gltfMesh.primitives) { - var indexOffset = m_positions.Count; + var indexOffset = _positions.Count; var indexBuffer = prim.indices; // position は必ずある var positions = data.GetArrayFromAccessor(prim.attributes.POSITION); - m_positions.AddRange(positions.Select(inverter.InvertVector3)); - var fillLength = m_positions.Count; + _positions.AddRange(positions.Select(inverter.InvertVector3)); + var fillLength = _positions.Count; // normal if (prim.attributes.NORMAL != -1) @@ -152,8 +129,9 @@ namespace UniGLTF { throw new Exception("different length"); } - m_normals.AddRange(normals.Select(inverter.InvertVector3)); - FillZero(m_normals, fillLength); + + _normals.AddRange(normals.Select(inverter.InvertVector3)); + FillZero(_normals, fillLength); } // uv @@ -164,18 +142,19 @@ namespace UniGLTF { throw new Exception("different length"); } + if (data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16)) { #pragma warning disable 0612 // backward compatibility - m_uv.AddRange(uvs.Select(x => x.ReverseY())); - FillZero(m_uv, fillLength); + _uv.AddRange(uvs.Select(x => x.ReverseY())); + FillZero(_uv, fillLength); #pragma warning restore 0612 } else { - m_uv.AddRange(uvs.Select(x => x.ReverseUV())); - FillZero(m_uv, fillLength); + _uv.AddRange(uvs.Select(x => x.ReverseUV())); + FillZero(_uv, fillLength); } } @@ -187,8 +166,9 @@ namespace UniGLTF { throw new Exception("different length"); } - m_uv2.AddRange(uvs.Select(x => x.ReverseUV())); - FillZero(m_uv2, fillLength); + + _uv2.AddRange(uvs.Select(x => x.ReverseUV())); + FillZero(_uv2, fillLength); } // color @@ -199,8 +179,9 @@ namespace UniGLTF { throw new Exception("different length"); } - m_colors.AddRange(colors); - FillZero(m_colors, fillLength); + + _colors.AddRange(colors); + FillZero(_colors, fillLength); } // skin @@ -212,11 +193,13 @@ namespace UniGLTF { throw new Exception("different length"); } + if (weightsLength != positions.Length) { throw new Exception("different length"); } - for (int j = 0; j < jointsLength; ++j) + + for (var j = 0; j < jointsLength; ++j) { var bw = new BoneWeight(); @@ -237,15 +220,16 @@ namespace UniGLTF bw = NormalizeBoneWeight(bw); - m_boneWeights.Add(bw); + _boneWeights.Add(bw); } - FillZero(m_boneWeights, fillLength); + + FillZero(_boneWeights, fillLength); } // blendshape if (prim.targets != null && prim.targets.Count > 0) { - for (int i = 0; i < prim.targets.Count; ++i) + for (var i = 0; i < prim.targets.Count; ++i) { var primTarget = prim.targets[i]; var blendShape = GetOrCreateBlendShape(i); @@ -256,9 +240,11 @@ namespace UniGLTF { throw new Exception("different length"); } + blendShape.Positions.AddRange(array.Select(inverter.InvertVector3).ToArray()); FillZero(blendShape.Positions, fillLength); } + if (primTarget.NORMAL != -1) { var array = data.GetArrayFromAccessor(primTarget.NORMAL); @@ -266,9 +252,11 @@ namespace UniGLTF { throw new Exception("different length"); } + blendShape.Normals.AddRange(array.Select(inverter.InvertVector3).ToArray()); FillZero(blendShape.Normals, fillLength); } + if (primTarget.TANGENT != -1) { var array = data.GetArrayFromAccessor(primTarget.TANGENT); @@ -276,6 +264,7 @@ namespace UniGLTF { throw new Exception("different length"); } + blendShape.Tangents.AddRange(array.Select(inverter.InvertVector3).ToArray()); FillZero(blendShape.Tangents, fillLength); } @@ -285,17 +274,18 @@ namespace UniGLTF var indices = (indexBuffer >= 0) ? data.GetIndices(indexBuffer) - : TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray() // without index array + : TriangleUtil.FlipTriangle(Enumerable.Range(0, _positions.Count)) + .ToArray() // without index array ; - for (int i = 0; i < indices.Length; ++i) + for (var i = 0; i < indices.Length; ++i) { indices[i] += indexOffset; } - m_subMeshes.Add(indices); + _subMeshes.Add(indices); // material - m_materialIndices.Add(prim.material); + _materialIndices.Add(prim.material); } } @@ -312,12 +302,14 @@ namespace UniGLTF { // 同じVertexBufferを共有しているので先頭のモノを使う var prim = gltfMesh.primitives.First(); - m_positions.AddRange(data.GetArrayFromAccessor(prim.attributes.POSITION).SelectInplace(inverter.InvertVector3)); + _positions.AddRange(data.GetArrayFromAccessor(prim.attributes.POSITION) + .SelectInplace(inverter.InvertVector3)); // normal if (prim.attributes.NORMAL != -1) { - m_normals.AddRange(data.GetArrayFromAccessor(prim.attributes.NORMAL).SelectInplace(inverter.InvertVector3)); + _normals.AddRange(data.GetArrayFromAccessor(prim.attributes.NORMAL) + .SelectInplace(inverter.InvertVector3)); } #if false @@ -335,42 +327,48 @@ namespace UniGLTF { #pragma warning disable 0612 // backward compatibility - m_uv.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY())); + _uv.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_0) + .SelectInplace(x => x.ReverseY())); #pragma warning restore 0612 } else { - m_uv.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV())); + _uv.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_0) + .SelectInplace(x => x.ReverseUV())); } } // uv2 if (prim.attributes.TEXCOORD_1 != -1) { - m_uv2.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_1).SelectInplace(x => x.ReverseUV())); + _uv2.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_1) + .SelectInplace(x => x.ReverseUV())); } // color if (prim.attributes.COLOR_0 != -1) { - if (data.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 3) + switch (data.GLTF.accessors[prim.attributes.COLOR_0].TypeCount) { - var vec3Color = data.GetArrayFromAccessor(prim.attributes.COLOR_0); - m_colors.AddRange(new Color[vec3Color.Length]); - - for (int i = 0; i < vec3Color.Length; i++) + case 3: { - Vector3 color = vec3Color[i]; - m_colors[i] = new Color(color.x, color.y, color.z); + var vec3Color = data.GetArrayFromAccessor(prim.attributes.COLOR_0); + _colors.AddRange(new Color[vec3Color.Length]); + + for (var i = 0; i < vec3Color.Length; i++) + { + var color = vec3Color[i]; + _colors[i] = new Color(color.x, color.y, color.z); + } + + break; } - } - else if (data.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 4) - { - m_colors.AddRange(data.GetArrayFromAccessor(prim.attributes.COLOR_0)); - } - else - { - throw new NotImplementedException(string.Format("unknown color type {0}", data.GLTF.accessors[prim.attributes.COLOR_0].type)); + case 4: + _colors.AddRange(data.GetArrayFromAccessor(prim.attributes.COLOR_0)); + break; + default: + throw new NotImplementedException( + $"unknown color type {data.GLTF.accessors[prim.attributes.COLOR_0].type}"); } } @@ -380,7 +378,7 @@ namespace UniGLTF var (joints0, jointsLength) = JointsAccessor.GetAccessor(data, prim.attributes.JOINTS_0); var (weights0, weightsLength) = WeightsAccessor.GetAccessor(data, prim.attributes.WEIGHTS_0); - for (int j = 0; j < jointsLength; ++j) + for (var j = 0; j < jointsLength; ++j) { var bw = new BoneWeight(); @@ -401,30 +399,32 @@ namespace UniGLTF bw = NormalizeBoneWeight(bw); - m_boneWeights.Add(bw); + _boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { - m_blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape(i.ToString()))); + _blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape(i.ToString()))); for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; - var blendShape = m_blendShapes[i]; + var blendShape = _blendShapes[i]; if (primTarget.POSITION != -1) { blendShape.Positions.Assign( data.GetArrayFromAccessor(primTarget.POSITION), inverter.InvertVector3); } + if (primTarget.NORMAL != -1) { blendShape.Normals.Assign( data.GetArrayFromAccessor(primTarget.NORMAL), inverter.InvertVector3); } + if (primTarget.TANGENT != -1) { blendShape.Tangents.Assign( @@ -438,41 +438,41 @@ namespace UniGLTF { if (prim.indices == -1) { - m_subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray()); + _subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, _positions.Count)).ToArray()); } else { var indices = data.GetIndices(prim.indices); - m_subMeshes.Add(indices); + _subMeshes.Add(indices); } // material - m_materialIndices.Add(prim.material); + _materialIndices.Add(prim.material); } } public void RenameBlendShape(glTFMesh gltfMesh) { - if (gltf_mesh_extras_targetNames.TryGet(gltfMesh, out List targetNames)) + if (!gltf_mesh_extras_targetNames.TryGet(gltfMesh, out var targetNames)) return; + for (var i = 0; i < BlendShapes.Count; i++) { - for (var i = 0; i < BlendShapes.Count; i++) + if (i >= targetNames.Count) { - if (i >= targetNames.Count) - { - Debug.LogWarning($"invalid primitive.extras.targetNames length"); - break; - } - BlendShapes[i].Name = targetNames[i]; + Debug.LogWarning($"invalid primitive.extras.targetNames length"); + break; } + + BlendShapes[i].Name = targetNames[i]; } } - static void Truncate(List list, int maxIndex) + private static void Truncate(List list, int maxIndex) { if (list == null) { return; } + var count = maxIndex + 1; if (list.Count > count) { @@ -481,6 +481,15 @@ namespace UniGLTF } } + public void AddDefaultMaterial() + { + if (!_materialIndices.Any()) + { + // add default material + _materialIndices.Add(0); + } + } + // // https://github.com/vrm-c/UniVRM/issues/610 // @@ -488,17 +497,17 @@ namespace UniGLTF // public void DropUnusedVertices() { - var maxIndex = m_subMeshes.SelectMany(x => x).Max(); - Truncate(m_positions, maxIndex); - Truncate(m_normals, maxIndex); - Truncate(m_uv, maxIndex); - Truncate(m_uv2, maxIndex); - Truncate(m_colors, maxIndex); - Truncate(m_boneWeights, maxIndex); -#if false + var maxIndex = _subMeshes.SelectMany(x => x).Max(); + Truncate(_positions, maxIndex); + Truncate(_normals, maxIndex); + Truncate(_uv, maxIndex); + Truncate(_uv2, maxIndex); + Truncate(_colors, maxIndex); + Truncate(_boneWeights, maxIndex); +#if false Truncate(m_tangents, maxIndex); #endif - foreach (var blendshape in m_blendShapes) + foreach (var blendshape in _blendShapes) { Truncate(blendshape.Positions, maxIndex); Truncate(blendshape.Normals, maxIndex); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs index be4350524..8b9727eec 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs @@ -9,9 +9,9 @@ namespace UniGLTF { public class MeshImporter { - const float FRAME_WEIGHT = 100.0f; + private const float FrameWeight = 100.0f; - static bool HasSharedVertexBuffer(glTFMesh gltfMesh) + private static bool HasSharedVertexBuffer(glTFMesh gltfMesh) { glTFAttributes lastAttributes = null; var sharedAttributes = true; @@ -25,6 +25,7 @@ namespace UniGLTF lastAttributes = prim.attributes; } + return sharedAttributes; } @@ -49,25 +50,23 @@ namespace UniGLTF return meshContext; } - static (Mesh, bool) _BuildMesh(MeshContext meshContext) + private static (Mesh, bool) _BuildMesh(MeshContext meshContext) { - if (!meshContext.MaterialIndices.Any()) - { - // add default material - meshContext.MaterialIndices.Add(0); - } + meshContext.AddDefaultMaterial(); //Debug.Log(prims.ToJson()); - var mesh = new Mesh(); - mesh.name = meshContext.name; + var mesh = new Mesh + { + name = meshContext.Name + }; - if (meshContext.Positions.Count > UInt16.MaxValue) + if (meshContext.Positions.Count > ushort.MaxValue) { mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; } mesh.vertices = meshContext.Positions.ToArray(); - bool recalculateNormals = false; + var recalculateNormals = false; if (meshContext.Normals != null && meshContext.Normals.Count > 0) { mesh.normals = meshContext.Normals.ToArray(); @@ -81,12 +80,13 @@ namespace UniGLTF { mesh.uv = meshContext.UV.ToArray(); } + if (meshContext.UV2.Count == mesh.vertexCount) { mesh.uv2 = meshContext.UV2.ToArray(); } - bool recalculateTangents = true; + var recalculateTangents = true; #if UNIGLTF_IMPORT_TANGENTS if (meshContext.Tangents.Length > 0) { @@ -99,12 +99,14 @@ namespace UniGLTF { mesh.colors = meshContext.Colors.ToArray(); } + if (meshContext.BoneWeights.Count > 0) { mesh.boneWeights = meshContext.BoneWeights.ToArray(); } + mesh.subMeshCount = meshContext.SubMeshes.Count; - for (int i = 0; i < meshContext.SubMeshes.Count; ++i) + for (var i = 0; i < meshContext.SubMeshes.Count; ++i) { mesh.SetTriangles(meshContext.SubMeshes[i], i); } @@ -117,7 +119,8 @@ namespace UniGLTF return (mesh, recalculateTangents); } - static async Task BuildBlendShapeAsync(IAwaitCaller awaitCaller, Mesh mesh, MeshContext meshContext, BlendShape blendShape, Vector3[] emptyVertices) + private static async Task BuildBlendShapeAsync(IAwaitCaller awaitCaller, Mesh mesh, BlendShape blendShape, + Vector3[] emptyVertices) { Vector3[] positions = null; Vector3[] normals = null; @@ -132,31 +135,35 @@ namespace UniGLTF { if (blendShape.Positions.Count == mesh.vertexCount) { - mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT, + mesh.AddBlendShapeFrame(blendShape.Name, FrameWeight, blendShape.Positions.ToArray(), normals.Length == mesh.vertexCount && normals.Length == positions.Length ? normals : null, null - ); + ); } else { - Debug.LogWarningFormat("May be partial primitive has blendShape. Require separate mesh or extend blend shape, but not implemented: {0}", blendShape.Name); + Debug.LogWarningFormat( + "May be partial primitive has blendShape. Require separate mesh or extend blend shape, but not implemented: {0}", + blendShape.Name); } } else { // Debug.LogFormat("empty blendshape: {0}.{1}", mesh.name, blendShape.Name); // add empty blend shape for keep blend shape index - mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT, + mesh.AddBlendShapeFrame(blendShape.Name, FrameWeight, emptyVertices, null, null - ); + ); } + Profiler.EndSample(); } - public static async Task BuildMeshAsync(IAwaitCaller awaitCaller, Func ctx, MeshContext meshContext) + public static async Task BuildMeshAsync(IAwaitCaller awaitCaller, Func ctx, + MeshContext meshContext) { Profiler.BeginSample("MeshImporter._BuildMesh"); var (mesh, recalculateTangents) = _BuildMesh(meshContext); @@ -182,7 +189,7 @@ namespace UniGLTF var emptyVertices = new Vector3[mesh.vertexCount]; foreach (var blendShape in meshContext.BlendShapes) { - await BuildBlendShapeAsync(awaitCaller, mesh, meshContext, blendShape, emptyVertices); + await BuildBlendShapeAsync(awaitCaller, mesh, blendShape, emptyVertices); } } @@ -193,4 +200,4 @@ namespace UniGLTF return result; } } -} +} \ No newline at end of file