From 1abd5331c4ac07f8893184b224acb5ada6e5625d Mon Sep 17 00:00:00 2001 From: notargs Date: Thu, 11 Nov 2021 13:00:06 +0900 Subject: [PATCH] =?UTF-8?q?=E9=A0=82=E7=82=B9=E3=81=AE=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E3=81=ABMeshAPI=20v2=E3=82=92=E5=88=A9=E7=94=A8=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/IO/ImporterContext.cs | 6 +- .../Runtime/UniGLTF/IO/MeshIO/MeshContext.cs | 401 ++++++------------ .../Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs | 59 +-- .../Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs | 64 +++ .../UniGLTF/IO/MeshIO/MeshVertex.cs.meta | 3 + .../UniGLTF/IO/MeshIO/PrimitiveExtensions.cs | 119 ++++++ .../IO/MeshIO/PrimitiveExtensions.cs.meta | 3 + 7 files changed, 337 insertions(+), 318 deletions(-) create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs.meta create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index eeb82f652..dd368215e 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -177,9 +177,9 @@ namespace UniGLTF var index = i; using (MeasureTime("ReadMesh")) { - var x = await awaitCaller.Run(() => meshImporter.ReadMesh(Data, index, inverter)); - var y = await BuildMeshAsync(awaitCaller, MeasureTime, x, index); - Meshes.Add(y); + var meshContext = await awaitCaller.Run(() => meshImporter.ReadMesh(Data, index, inverter)); + var meshWithMaterials = await BuildMeshAsync(awaitCaller, MeasureTime, meshContext, index); + Meshes.Add(meshWithMaterials); } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs index e223014e7..68b7cfeac 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs @@ -1,43 +1,38 @@ using System; using System.Collections.Generic; using System.Linq; +using Unity.Collections; using UnityEngine; namespace UniGLTF { - public class MeshContext + internal class MeshContext { - 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 _vertices = 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 bool HasNormal { get; private set; } = true; + public string Name { get; } + /// + /// 頂点情報をMeshに対して送る + /// + /// + public void UploadMeshVertices(Mesh mesh) + { + mesh.SetVertexBufferParams(_vertices.Count, MeshVertex.GetVertexAttributeDescriptor()); + mesh.SetVertexBufferData(_vertices, 0, 0, _vertices.Count); + } + private BlendShape GetOrCreateBlendShape(int i) { if (i < _blendShapes.Count && _blendShapes[i] != null) @@ -62,41 +57,23 @@ namespace UniGLTF name = $"UniGLTF import#{meshIndex}"; } - this.Name = name; + Name = name; } - /// - /// Fill list with 0s with the specified length - /// - /// - /// - /// - private static void FillZero(ICollection list, int fillLength) + private static (float x, float y, float z, float w) NormalizeBoneWeight( + (float x, float y, float z, float w) src) { - if (list.Count > fillLength) - { - throw new Exception("Impossible"); - } - - while (list.Count < fillLength) - { - list.Add(default); - } - } - - private static BoneWeight NormalizeBoneWeight(BoneWeight src) - { - var sum = src.weight0 + src.weight1 + src.weight2 + src.weight3; + var sum = src.x + src.y + src.z + src.w; if (sum == 0) { return src; } var f = 1.0f / sum; - src.weight0 *= f; - src.weight1 *= f; - src.weight2 *= f; - src.weight3 *= f; + src.x *= f; + src.y *= f; + src.z *= f; + src.w *= f; return src; } @@ -111,127 +88,72 @@ namespace UniGLTF /// public void ImportMeshIndependentVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter) { - foreach (var prim in gltfMesh.primitives) + foreach (var primitives in gltfMesh.primitives) { - var indexOffset = _positions.Count; - var indexBuffer = prim.indices; + var indexOffset = _vertices.Count; + var indexBuffer = primitives.indices; // position は必ずある - var positions = data.GetArrayFromAccessor(prim.attributes.POSITION); - _positions.AddRange(positions.Select(inverter.InvertVector3)); - var fillLength = _positions.Count; + var positions = primitives.GetPositions(data); + var normals = primitives.GetNormals(data, positions.Length); + var texCoords0 = primitives.GetTexCoords0(data, positions.Length); + var texCoords1 = primitives.GetTexCoords1(data, positions.Length); + var colors = primitives.GetColors(data, positions.Length); + var jointsGetter = primitives.GetJoints(data, positions.Length); + var weightsGetter = primitives.GetWeights(data, positions.Length); - // normal - if (prim.attributes.NORMAL != -1) + CheckAttributeUsages(primitives); + + for (var i = 0; i < positions.Length; ++i) { - var normals = data.GetArrayFromAccessor(prim.attributes.NORMAL); - if (normals.Length != positions.Length) - { - throw new Exception("different length"); - } + var position = inverter.InvertVector3(positions[i]); + var normal = normals != null ? inverter.InvertVector3(normals[i]) : Vector3.zero; - _normals.AddRange(normals.Select(inverter.InvertVector3)); - FillZero(_normals, fillLength); - } - - // uv - if (prim.attributes.TEXCOORD_0 != -1) - { - var uvs = data.GetArrayFromAccessor(prim.attributes.TEXCOORD_0); - if (uvs.Length != positions.Length) - { - throw new Exception("different length"); - } - - if (data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16)) + var texCoord0 = Vector2.zero; + if (texCoords0 != null) { + if (data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16)) + { #pragma warning disable 0612 - // backward compatibility - _uv.AddRange(uvs.Select(x => x.ReverseY())); - FillZero(_uv, fillLength); + // backward compatibility + texCoord0 = texCoords0[i].ReverseY(); #pragma warning restore 0612 - } - else - { - _uv.AddRange(uvs.Select(x => x.ReverseUV())); - FillZero(_uv, fillLength); - } - } - - // uv2 - if (prim.attributes.TEXCOORD_1 != -1) - { - var uvs = data.GetArrayFromAccessor(prim.attributes.TEXCOORD_1); - if (uvs.Length != positions.Length) - { - throw new Exception("different length"); + } + else + { + texCoord0 = texCoords0[i].ReverseUV(); + } } - _uv2.AddRange(uvs.Select(x => x.ReverseUV())); - FillZero(_uv2, fillLength); - } + var texCoord1 = texCoords1 != null ? texCoords1[i].ReverseUV() : Vector2.zero; + var joints = jointsGetter?.Invoke(i) ?? (0, 0, 0, 0); + var weights = weightsGetter != null ? NormalizeBoneWeight(weightsGetter(i)) : (0, 0, 0, 0); - // color - if (prim.attributes.COLOR_0 != -1) - { - var colors = data.GetArrayFromAccessor(prim.attributes.COLOR_0); - if (colors.Length != positions.Length) - { - throw new Exception("different length"); - } - - _colors.AddRange(colors); - FillZero(_colors, fillLength); - } - - // skin - if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) - { - var (joints0, jointsLength) = JointsAccessor.GetAccessor(data, prim.attributes.JOINTS_0); - var (weights0, weightsLength) = WeightsAccessor.GetAccessor(data, prim.attributes.WEIGHTS_0); - if (jointsLength != positions.Length) - { - throw new Exception("different length"); - } - - if (weightsLength != positions.Length) - { - throw new Exception("different length"); - } - - for (var j = 0; j < jointsLength; ++j) - { - var bw = new BoneWeight(); - - var joints = joints0(j); - var weights = weights0(j); - - bw.boneIndex0 = joints.x; - bw.weight0 = weights.x; - - bw.boneIndex1 = joints.y; - bw.weight1 = weights.y; - - bw.boneIndex2 = joints.z; - bw.weight2 = weights.z; - - bw.boneIndex3 = joints.w; - bw.weight3 = weights.w; - - bw = NormalizeBoneWeight(bw); - - _boneWeights.Add(bw); - } - - FillZero(_boneWeights, fillLength); + var color = colors[i]; + _vertices.Add( + new MeshVertex( + position, + normal, + texCoord0, + texCoord1, + color, + joints.x, + joints.y, + joints.z, + joints.w, + weights.x, + weights.y, + weights.z, + weights.w + )); } // blendshape - if (prim.targets != null && prim.targets.Count > 0) + if (primitives.targets != null && primitives.targets.Count > 0) { - for (var i = 0; i < prim.targets.Count; ++i) + for (var i = 0; i < primitives.targets.Count; ++i) { - var primTarget = prim.targets[i]; + var primTarget = primitives.targets[i]; var blendShape = GetOrCreateBlendShape(i); if (primTarget.POSITION != -1) { @@ -242,7 +164,6 @@ namespace UniGLTF } blendShape.Positions.AddRange(array.Select(inverter.InvertVector3).ToArray()); - FillZero(blendShape.Positions, fillLength); } if (primTarget.NORMAL != -1) @@ -254,7 +175,6 @@ namespace UniGLTF } blendShape.Normals.AddRange(array.Select(inverter.InvertVector3).ToArray()); - FillZero(blendShape.Normals, fillLength); } if (primTarget.TANGENT != -1) @@ -266,7 +186,6 @@ namespace UniGLTF } blendShape.Tangents.AddRange(array.Select(inverter.InvertVector3).ToArray()); - FillZero(blendShape.Tangents, fillLength); } } } @@ -274,7 +193,7 @@ namespace UniGLTF var indices = (indexBuffer >= 0) ? data.GetIndices(indexBuffer) - : TriangleUtil.FlipTriangle(Enumerable.Range(0, _positions.Count)) + : TriangleUtil.FlipTriangle(Enumerable.Range(0, _vertices.Count)) .ToArray() // without index array ; for (var i = 0; i < indices.Length; ++i) @@ -285,10 +204,19 @@ namespace UniGLTF _subMeshes.Add(indices); // material - _materialIndices.Add(prim.material); + _materialIndices.Add(primitives.material); } } + /// + /// 各種頂点属性が使われているかどうかをチェックし、使われていなかったらフラグを切る + /// MEMO: O(1)で検知する手段がありそう + /// + private void CheckAttributeUsages(glTFPrimitives primitives) + { + if (!primitives.HasNormal()) HasNormal = false; + } + /// /// /// 各primitiveが同じ attribute を共有している場合専用のローダー。 @@ -301,116 +229,67 @@ namespace UniGLTF { { // 同じVertexBufferを共有しているので先頭のモノを使う - var prim = gltfMesh.primitives.First(); - _positions.AddRange(data.GetArrayFromAccessor(prim.attributes.POSITION) - .SelectInplace(inverter.InvertVector3)); + var primitives = gltfMesh.primitives.First(); - // normal - if (prim.attributes.NORMAL != -1) + var positions = primitives.GetPositions(data); + var normals = primitives.GetNormals(data, positions.Length); + var texCoords0 = primitives.GetTexCoords0(data, positions.Length); + var texCoords1 = primitives.GetTexCoords1(data, positions.Length); + var colors = primitives.GetColors(data, positions.Length); + var jointsGetter = primitives.GetJoints(data, positions.Length); + var weightsGetter = primitives.GetWeights(data, positions.Length); + + CheckAttributeUsages(primitives); + + for (var i = 0; i < positions.Length; ++i) { - _normals.AddRange(data.GetArrayFromAccessor(prim.attributes.NORMAL) - .SelectInplace(inverter.InvertVector3)); - } - -#if false - // tangent - if (prim.attributes.TANGENT != -1) + var position = inverter.InvertVector3(positions[i]); + var normal = normals != null ? inverter.InvertVector3(normals[i]) : Vector3.zero; + var texCoord0 = Vector2.zero; + if (texCoords0 != null) { - tangents.AddRange(gltf.GetArrayFromAccessor(prim.attributes.TANGENT).SelectInplace(inverter.InvertVector4)); - } -#endif - - // uv - if (prim.attributes.TEXCOORD_0 != -1) - { - if (data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16)) - { -#pragma warning disable 0612 - // backward compatibility - _uv.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_0) - .SelectInplace(x => x.ReverseY())); -#pragma warning restore 0612 - } - else - { - _uv.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_0) - .SelectInplace(x => x.ReverseUV())); - } - } - - // uv2 - if (prim.attributes.TEXCOORD_1 != -1) - { - _uv2.AddRange(data.GetArrayFromAccessor(prim.attributes.TEXCOORD_1) - .SelectInplace(x => x.ReverseUV())); - } - - // color - if (prim.attributes.COLOR_0 != -1) - { - switch (data.GLTF.accessors[prim.attributes.COLOR_0].TypeCount) - { - case 3: + if (data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16)) { - 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; +#pragma warning disable 0612 + texCoord0 = texCoords0[i].ReverseY(); +#pragma warning restore 0612 + } + else + { + texCoord0 = texCoords0[i].ReverseUV(); } - 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}"); } - } - // skin - if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) - { - var (joints0, jointsLength) = JointsAccessor.GetAccessor(data, prim.attributes.JOINTS_0); - var (weights0, weightsLength) = WeightsAccessor.GetAccessor(data, prim.attributes.WEIGHTS_0); + var texCoord1 = texCoords1 != null ? texCoords1[i].ReverseUV() : Vector2.zero; + var color = colors != null ? colors[i] : Color.black; + var joints = jointsGetter?.Invoke(i) ?? (0, 0, 0, 0); + var weights = weightsGetter != null ? NormalizeBoneWeight(weightsGetter(i)) : (0, 0, 0, 0); - for (var j = 0; j < jointsLength; ++j) - { - var bw = new BoneWeight(); - - var joints = joints0(j); - var weights = weights0(j); - - bw.boneIndex0 = joints.x; - bw.weight0 = weights.x; - - bw.boneIndex1 = joints.y; - bw.weight1 = weights.y; - - bw.boneIndex2 = joints.z; - bw.weight2 = weights.z; - - bw.boneIndex3 = joints.w; - bw.weight3 = weights.w; - - bw = NormalizeBoneWeight(bw); - - _boneWeights.Add(bw); - } + _vertices.Add(new MeshVertex( + position, + normal, + texCoord0, + texCoord1, + color, + joints.x, + joints.y, + joints.z, + joints.w, + weights.x, + weights.y, + weights.z, + weights.w + )); } // blendshape - if (prim.targets != null && prim.targets.Count > 0) + if (primitives.targets != null && primitives.targets.Count > 0) { - _blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape(i.ToString()))); - for (int i = 0; i < prim.targets.Count; ++i) + _blendShapes.AddRange(primitives.targets.Select((x, i) => new BlendShape(i.ToString()))); + for (int i = 0; i < primitives.targets.Count; ++i) { //var name = string.Format("target{0}", i++); - var primTarget = prim.targets[i]; + var primTarget = primitives.targets[i]; var blendShape = _blendShapes[i]; if (primTarget.POSITION != -1) @@ -434,20 +313,20 @@ namespace UniGLTF } } - foreach (var prim in gltfMesh.primitives) + foreach (var primitive in gltfMesh.primitives) { - if (prim.indices == -1) + if (primitive.indices == -1) { - _subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, _positions.Count)).ToArray()); + _subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, _vertices.Count)).ToArray()); } else { - var indices = data.GetIndices(prim.indices); + var indices = data.GetIndices(primitive.indices); _subMeshes.Add(indices); } // material - _materialIndices.Add(prim.material); + _materialIndices.Add(primitive.material); } } @@ -498,15 +377,7 @@ namespace UniGLTF public void DropUnusedVertices() { 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 + Truncate(_vertices, maxIndex); foreach (var blendshape in _blendShapes) { Truncate(blendshape.Positions, maxIndex); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs index 8b9727eec..9cd55f0a5 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs @@ -29,7 +29,7 @@ namespace UniGLTF return sharedAttributes; } - public MeshContext ReadMesh(GltfData data, int meshIndex, IAxisInverter inverter) + internal MeshContext ReadMesh(GltfData data, int meshIndex, IAxisInverter inverter) { var gltfMesh = data.GLTF.meshes[meshIndex]; @@ -50,7 +50,7 @@ namespace UniGLTF return meshContext; } - private static (Mesh, bool) _BuildMesh(MeshContext meshContext) + private static (Mesh, bool) BuildMesh(MeshContext meshContext) { meshContext.AddDefaultMaterial(); @@ -60,50 +60,7 @@ namespace UniGLTF name = meshContext.Name }; - if (meshContext.Positions.Count > ushort.MaxValue) - { - mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; - } - - mesh.vertices = meshContext.Positions.ToArray(); - var recalculateNormals = false; - if (meshContext.Normals != null && meshContext.Normals.Count > 0) - { - mesh.normals = meshContext.Normals.ToArray(); - } - else - { - recalculateNormals = true; - } - - if (meshContext.UV.Count == mesh.vertexCount) - { - mesh.uv = meshContext.UV.ToArray(); - } - - if (meshContext.UV2.Count == mesh.vertexCount) - { - mesh.uv2 = meshContext.UV2.ToArray(); - } - - var recalculateTangents = true; -#if UNIGLTF_IMPORT_TANGENTS - if (meshContext.Tangents.Length > 0) - { - mesh.tangents = meshContext.Tangents.ToArray(); - recalculateTangents = false; - } -#endif - - if (meshContext.Colors.Count == mesh.vertexCount) - { - mesh.colors = meshContext.Colors.ToArray(); - } - - if (meshContext.BoneWeights.Count > 0) - { - mesh.boneWeights = meshContext.BoneWeights.ToArray(); - } + meshContext.UploadMeshVertices(mesh); mesh.subMeshCount = meshContext.SubMeshes.Count; for (var i = 0; i < meshContext.SubMeshes.Count; ++i) @@ -111,12 +68,12 @@ namespace UniGLTF mesh.SetTriangles(meshContext.SubMeshes[i], i); } - if (recalculateNormals) + if (!meshContext.HasNormal) { mesh.RecalculateNormals(); } - return (mesh, recalculateTangents); + return (mesh, true); } private static async Task BuildBlendShapeAsync(IAwaitCaller awaitCaller, Mesh mesh, BlendShape blendShape, @@ -162,11 +119,13 @@ namespace UniGLTF Profiler.EndSample(); } - public static async Task BuildMeshAsync(IAwaitCaller awaitCaller, Func ctx, + internal static async Task BuildMeshAsync( + IAwaitCaller awaitCaller, + Func ctx, MeshContext meshContext) { Profiler.BeginSample("MeshImporter._BuildMesh"); - var (mesh, recalculateTangents) = _BuildMesh(meshContext); + var (mesh, recalculateTangents) = BuildMesh(meshContext); Profiler.EndSample(); if (recalculateTangents) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs new file mode 100644 index 000000000..cbb846974 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs @@ -0,0 +1,64 @@ +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Rendering; + +namespace UniGLTF +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public readonly struct MeshVertex + { + public readonly Vector3 Position; + public readonly Vector3 Normal; + public readonly Color Color; + public readonly Vector2 Uv; + public readonly Vector2 Uv2; + public readonly float BoneWeight0; + public readonly float BoneWeight1; + public readonly float BoneWeight2; + public readonly float BoneWeight3; + public readonly ushort BoneIndex0; + public readonly ushort BoneIndex1; + public readonly ushort BoneIndex2; + public readonly ushort BoneIndex3; + + public MeshVertex( + Vector3 position, + Vector3 normal, + Vector2 uv, + Vector2 uv2, + Color color, + ushort boneIndex0, + ushort boneIndex1, + ushort boneIndex2, + ushort boneIndex3, + float boneWeight0, + float boneWeight1, + float boneWeight2, + float boneWeight3) + { + Position = position; + Normal = normal; + Uv = uv; + Uv2 = uv2; + Color = color; + BoneIndex0 = boneIndex0; + BoneIndex1 = boneIndex1; + BoneIndex2 = boneIndex2; + BoneIndex3 = boneIndex3; + BoneWeight0 = boneWeight0; + BoneWeight1 = boneWeight1; + BoneWeight2 = boneWeight2; + BoneWeight3 = boneWeight3; + } + + public static VertexAttributeDescriptor[] GetVertexAttributeDescriptor() => new[] { + new VertexAttributeDescriptor(VertexAttribute.Position), + new VertexAttributeDescriptor(VertexAttribute.Normal), + new VertexAttributeDescriptor(VertexAttribute.Color, dimension: 4), + new VertexAttributeDescriptor(VertexAttribute.TexCoord0, dimension: 2), + new VertexAttributeDescriptor(VertexAttribute.TexCoord1, dimension: 2), + new VertexAttributeDescriptor(VertexAttribute.BlendWeight, dimension: 4), + new VertexAttributeDescriptor(VertexAttribute.BlendIndices, VertexAttributeFormat.UInt16, 4), + }; + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs.meta new file mode 100644 index 000000000..8190c9154 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0d540d8e32d54e7089a72156edb7ad80 +timeCreated: 1636526648 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs new file mode 100644 index 000000000..7e0f9fd08 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs @@ -0,0 +1,119 @@ +using System; +using UnityEngine; + +namespace UniGLTF +{ + internal static class PrimitiveExtensions + { + public static bool HasNormal(this glTFPrimitives primitives) => primitives.attributes.NORMAL != -1; + public static bool HasTexCoord0(this glTFPrimitives primitives) => primitives.attributes.TEXCOORD_0 != -1; + public static bool HasTexCoord1(this glTFPrimitives primitives) => primitives.attributes.TEXCOORD_1 != -1; + public static bool HasSkin(this glTFPrimitives primitives) => primitives.attributes.JOINTS_0 != -1 && primitives.attributes.WEIGHTS_0 != -1; + public static bool HasColor(this glTFPrimitives primitives) => primitives.attributes.COLOR_0 != -1; + + public static Vector3[] GetPositions(this glTFPrimitives primitives, GltfData data) + { + return data.GetArrayFromAccessor(primitives.attributes.POSITION); + } + + public static Vector3[] GetNormals(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + if (!HasNormal(primitives)) return null; + var result = data.GetArrayFromAccessor(primitives.attributes.NORMAL); + if (result.Length != positionsLength) + { + throw new Exception("different length"); + } + + return result; + } + + public static Vector2[] GetTexCoords0(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + if (!HasTexCoord0(primitives)) return null; + var result = data.GetArrayFromAccessor(primitives.attributes.TEXCOORD_0); + if (result.Length != positionsLength) + { + throw new Exception("different length"); + } + + return result; + } + + public static Vector2[] GetTexCoords1(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + if (!HasTexCoord1(primitives)) return null; + var result = data.GetArrayFromAccessor(primitives.attributes.TEXCOORD_1); + if (result.Length != positionsLength) + { + throw new Exception("different length"); + } + + return result; + } + + public static Color[] GetColors(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + if (!HasColor(primitives)) return null; + + switch (data.GLTF.accessors[primitives.attributes.COLOR_0].TypeCount) + { + case 3: + { + var vec3Color = data.GetArrayFromAccessor(primitives.attributes.COLOR_0); + if (vec3Color.Length != positionsLength) + { + throw new Exception("different length"); + } + var colors = new Color[vec3Color.Length]; + + for (var index = 0; index < vec3Color.Length; index++) + { + var color = vec3Color[index]; + colors[index] = new Color(color.x, color.y, color.z); + } + + return colors; + } + case 4: + var result = data.GetArrayFromAccessor(primitives.attributes.COLOR_0); + if (result.Length != positionsLength) + { + throw new Exception("different length"); + } + + return result; + default: + throw new NotImplementedException( + $"unknown color type {data.GLTF.accessors[primitives.attributes.COLOR_0].type}"); + } + } + + public static JointsAccessor.Getter GetJoints(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + // skin + if (!HasSkin(primitives)) return null; + var (getter, length) = JointsAccessor.GetAccessor(data, primitives.attributes.JOINTS_0); + if (length != positionsLength) + { + throw new Exception("different length"); + } + + return getter; + + } + + public static WeightsAccessor.Getter GetWeights(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + // skin + if (!HasSkin(primitives)) return null; + var (getter, length) = WeightsAccessor.GetAccessor(data, primitives.attributes.WEIGHTS_0); + if (length != positionsLength) + { + throw new Exception("different length"); + } + + return getter; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs.meta new file mode 100644 index 000000000..bb9ad2215 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 867e7d22991044cd921d5479269142f2 +timeCreated: 1636536120 \ No newline at end of file