Inheritance: IJsonSerializable
Beispiel #1
0
 /// <summary>
 /// 各種頂点属性が使われているかどうかをチェックし、使われていなかったらフラグを切る
 /// MEMO: O(1)で検知する手段がありそう
 /// </summary>
 private void CheckAttributeUsages(glTFPrimitives primitives)
 {
     if (!primitives.HasNormal())
     {
         HasNormal = false;
     }
 }
        public static string ToJson(this glTFPrimitives self)
        {
            var f = new JsonFormatter();

            GltfSerializer.Serialize_gltf_meshes__primitives_ITEM(f, self);
            return(f.ToString());
        }
Beispiel #3
0
        public static NativeArray <Vector3> GetPositions(this glTFPrimitives primitives, GltfData data)
        {
            var accessor = data.GLTF.accessors[primitives.attributes.POSITION];

            if (accessor.type != "VEC3")
            {
                throw new ArgumentException($"unknown POSITION type: {accessor.componentType}:{accessor.type}");
            }

            if (accessor.componentType == glComponentType.FLOAT)
            {
                return(data.GetArrayFromAccessor <Vector3>(primitives.attributes.POSITION));
            }
            else if (accessor.componentType == glComponentType.UNSIGNED_SHORT)
            {
                // KHR_mesh_quantization
                // not UShort3 for 4byte alignment !
                var src   = data.GetArrayFromAccessor <UShort4>(primitives.attributes.POSITION);
                var array = data.NativeArrayManager.CreateNativeArray <Vector3>(src.Length);
                for (int i = 0; i < src.Length; ++i)
                {
                    var v = src[i];
                    array[i] = new Vector3(v.x, v.y, v.z);
                }
                return(array);
            }
            else
            {
                throw new NotImplementedException($"unknown POSITION type: {accessor.componentType}:{accessor.type}");
            }
        }
Beispiel #4
0
        public void PrimitiveTest()
        {
            var model = new glTFPrimitives
            {
                attributes = new glTFAttributes
                {
                    POSITION = 0,
                },
                extras = new glTFPrimitives_extras
                {
                    targetNames = new List <String>
                    {
                        "aaa",
                    }
                }
            };

            var json = model.ToJson();

            Assert.AreEqual(@"{""mode"":0,""indices"":-1,""attributes"":{""POSITION"":0},""material"":0,""extras"":{""targetNames"":[""aaa""]}}", json);
            Debug.Log(json);

            var c = new JsonSchemaValidationContext("")
            {
                EnableDiagnosisForNotRequiredFields = true,
            };
            var json2 = JsonSchema.FromType <glTFPrimitives>().Serialize(model, c);

            Assert.AreEqual(@"{""mode"":0,""attributes"":{""POSITION"":0},""material"":0,""extras"":{""targetNames"":[""aaa""]}}", json2);
        }
Beispiel #5
0
        public static NativeArray <Vector3>?GetNormals(this glTFPrimitives primitives, GltfData data, int positionsLength)
        {
            if (!HasNormal(primitives))
            {
                return(null);
            }

            var accessor = data.GLTF.accessors[primitives.attributes.NORMAL];

            if (accessor.type != "VEC3")
            {
                throw new ArgumentException($"unknown NORMAL type: {accessor.componentType}:{accessor.type}");
            }

            if (accessor.componentType == glComponentType.FLOAT)
            {
                var result = data.GetArrayFromAccessor <Vector3>(primitives.attributes.NORMAL);
                if (result.Length != positionsLength)
                {
                    throw new Exception("NORMAL is different in length from POSITION");
                }
                return(result);
            }
            else if (accessor.componentType == glComponentType.BYTE)
            {
                // KHR_mesh_quantization
                // not Byte3 for 4byte alignment !
                var src   = data.GetArrayFromAccessor <SByte4>(primitives.attributes.NORMAL);
                var array = data.NativeArrayManager.CreateNativeArray <Vector3>(src.Length);
                if (accessor.normalized)
                {
                    var factor = 1.0f / 127.0f;
                    for (int i = 0; i < src.Length; ++i)
                    {
                        var v = src[i];
                        array[i] = new Vector3(
                            v.x * factor,
                            v.y * factor,
                            v.z * factor);
                    }
                }
                else
                {
                    for (int i = 0; i < src.Length; ++i)
                    {
                        var v = src[i];
                        array[i] = new Vector3(v.x, v.y, v.z);
                    }
                }
                return(array);
            }
            else
            {
                throw new NotImplementedException($"unknown NORMAL type: {accessor.componentType}:{accessor.type}");
            }
        }
Beispiel #6
0
            public glTFPrimitives ToGltfPrimitive(ExportingGltfData data, int materialIndex, IEnumerable <int> indices)
            {
                var indicesAccessorIndex  = data.ExtendBufferAndGetAccessorIndex(indices.Select(x => (uint)m_vertexIndexMap[x]).ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
                var positions             = m_positions.ToArray();
                var positionAccessorIndex = data.ExtendBufferAndGetAccessorIndex(positions, glBufferTarget.ARRAY_BUFFER);

                AccessorsBounds.UpdatePositionAccessorsBounds(data.Gltf.accessors[positionAccessorIndex], positions);

                var normals             = m_normals.ToArray();
                var normalAccessorIndex = data.ExtendBufferAndGetAccessorIndex(normals, glBufferTarget.ARRAY_BUFFER);
                var uvAccessorIndex0    = data.ExtendBufferAndGetAccessorIndex(m_uv.ToArray(), glBufferTarget.ARRAY_BUFFER);

                int?jointsAccessorIndex = default;

                if (m_joints != null)
                {
                    jointsAccessorIndex = data.ExtendBufferAndGetAccessorIndex(m_joints.ToArray(), glBufferTarget.ARRAY_BUFFER);
                }
                int?weightAccessorIndex = default;

                if (m_weights != null)
                {
                    weightAccessorIndex = data.ExtendBufferAndGetAccessorIndex(m_weights.ToArray(), glBufferTarget.ARRAY_BUFFER);
                }

                int?vertexColorIndex = default;

                if (m_color.Count == m_positions.Count)
                {
                    vertexColorIndex = data.ExtendBufferAndGetAccessorIndex(m_color.ToArray(), glBufferTarget.ARRAY_BUFFER);
                }

                var primitive = new glTFPrimitives
                {
                    indices    = indicesAccessorIndex,
                    attributes = new glTFAttributes
                    {
                        POSITION   = positionAccessorIndex,
                        NORMAL     = normalAccessorIndex,
                        TEXCOORD_0 = uvAccessorIndex0,
                        JOINTS_0   = jointsAccessorIndex.GetValueOrDefault(-1),
                        WEIGHTS_0  = weightAccessorIndex.GetValueOrDefault(-1),
                        COLOR_0    = vertexColorIndex.GetValueOrDefault(-1),
                    },
                    material = materialIndex,
                    mode     = 4,
                };

                return(primitive);
            }
Beispiel #7
0
        public static void Serialize_gltf_meshes__primitives_ITEM(JsonFormatter f, glTFPrimitives value)
        {
            f.BeginMap();


            if (true)
            {
                f.Key("mode");
                f.Value(value.mode);
            }

            if (value.indices >= 0)
            {
                f.Key("indices");
                f.Value(value.indices);
            }

            if (value.attributes != null)
            {
                f.Key("attributes");
                Serialize_gltf_meshes__primitives__attributes(f, value.attributes);
            }

            if (value.material >= 0)
            {
                f.Key("material");
                f.Value(value.material);
            }

            if (value.targets != null && value.targets.Count >= 1)
            {
                f.Key("targets");
                Serialize_gltf_meshes__primitives__targets(f, value.targets);
            }

            if (value.extras != null)
            {
                f.Key("extras");
                value.extras.Serialize(f);
            }

            if (value.extensions != null)
            {
                f.Key("extensions");
                value.extensions.Serialize(f);
            }

            f.EndMap();
        }
Beispiel #8
0
        public static NativeArray <Vector3>?GetNormals(this glTFPrimitives primitives, GltfData data, int positionsLength)
        {
            if (!HasNormal(primitives))
            {
                return(null);
            }
            var result = data.GetArrayFromAccessor <Vector3>(primitives.attributes.NORMAL);

            if (result.Length != positionsLength)
            {
                throw new Exception("different length");
            }

            return(result);
        }
Beispiel #9
0
        public static NativeArray <Vector2>?GetTexCoords1(this glTFPrimitives primitives, GltfData data, int positionsLength)
        {
            if (!HasTexCoord1(primitives))
            {
                return(null);
            }
            var result = data.GetArrayFromAccessor <Vector2>(primitives.attributes.TEXCOORD_1);

            if (result.Length != positionsLength)
            {
                throw new Exception("different length");
            }

            return(result);
        }
Beispiel #10
0
        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);
        }
        public void PrimitiveTest()
        {
            var model = new glTFPrimitives
            {
                indices    = 0,
                attributes = new glTFAttributes
                {
                    POSITION = 1,
                },
                extras = gltf_mesh_extras_targetNames.Serialize("aaa"),
            };

            var json = model.ToJson();

            Assert.AreEqual(@"{""mode"":0,""indices"":0,""attributes"":{""POSITION"":1},""material"":0,""extras"":{""targetNames"":[""aaa""]}}", json);
            Debug.Log(json);
        }
Beispiel #12
0
        public static NativeArray <Vector2>?GetTexCoords0(this glTFPrimitives primitives, GltfData data, int positionsLength)
        {
            if (!HasTexCoord0(primitives))
            {
                return(null);
            }

            var accessor = data.GLTF.accessors[primitives.attributes.TEXCOORD_0];

            if (accessor.type != "VEC2")
            {
                throw new ArgumentException($"unknown TEXCOORD_0 type: {accessor.componentType}:{accessor.type}");
            }

            if (accessor.componentType == glComponentType.FLOAT)
            {
                var result = data.GetArrayFromAccessor <Vector2>(primitives.attributes.TEXCOORD_0);
                if (result.Length != positionsLength)
                {
                    throw new Exception("different length");
                }

                return(result);
            }
            if (accessor.componentType == glComponentType.UNSIGNED_SHORT)
            {
                // KHR_mesh_quantization
                var src   = data.GetArrayFromAccessor <UShort2>(primitives.attributes.TEXCOORD_0);
                var array = data.NativeArrayManager.CreateNativeArray <Vector2>(src.Length);
                for (int i = 0; i < src.Length; ++i)
                {
                    var v = src[i];
                    array[i] = new Vector2(v.x, v.y);
                }
                return(array);
            }
            else
            {
                throw new ArgumentException($"unknown TEXCOORD_0 type: {accessor.componentType}:{accessor.type}");
            }
        }
Beispiel #13
0
        public static NativeArray <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 <Vector3>(primitives.attributes.COLOR_0);
                if (vec3Color.Length != positionsLength)
                {
                    throw new Exception("different length");
                }
                var colors = data.NativeArrayManager.CreateNativeArray <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 <Color>(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}");
            }
        }
Beispiel #14
0
            public glTFPrimitives ToGltfPrimitive(glTF gltf, int bufferIndex, int materialIndex, IEnumerable <int> indices)
            {
                var indicesAccessorIndex  = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices.Select(x => (uint)m_vertexIndexMap[x]).ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
                var positions             = m_positions.ToArray();
                var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER);
                var normals             = m_normals.ToArray();
                var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, normals, glBufferTarget.ARRAY_BUFFER);
                var uvAccessorIndex0    = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_uv.ToArray(), glBufferTarget.ARRAY_BUFFER);

                int?jointsAccessorIndex = default;

                if (m_joints != null)
                {
                    jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_joints.ToArray(), glBufferTarget.ARRAY_BUFFER);
                }
                int?weightAccessorIndex = default;

                if (m_weights != null)
                {
                    weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_weights.ToArray(), glBufferTarget.ARRAY_BUFFER);
                }

                var primitive = new glTFPrimitives
                {
                    indices    = indicesAccessorIndex,
                    attributes = new glTFAttributes
                    {
                        POSITION   = positionAccessorIndex,
                        NORMAL     = normalAccessorIndex,
                        TEXCOORD_0 = uvAccessorIndex0,
                        JOINTS_0   = jointsAccessorIndex.GetValueOrDefault(-1),
                        WEIGHTS_0  = weightAccessorIndex.GetValueOrDefault(-1),
                    },
                    material = materialIndex,
                    mode     = 4,
                };

                return(primitive);
            }
Beispiel #15
0
 public static NativeArray <Vector3> GetPositions(this glTFPrimitives primitives, GltfData data)
 {
     return(data.GetArrayFromAccessor <Vector3>(primitives.attributes.POSITION));
 }
        static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex, Mesh mesh, Material[] meshMaterials, BoneWeight[] boneWeights, int[] jointIndexMap,
                                         List <Material> exportedMaterials)
        {
            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, meshMaterials);
            if (vColorState == MeshExportInfo.VertexColorState.ExistsAndIsUsed || // VColor使っている
                vColorState == MeshExportInfo.VertexColorState.ExistsAndMixed // VColorを使っているところと使っていないところが混在(とりあえずExportする)
                )
            {
                // UniUnlit で Multiply 設定になっている
                colorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors, glBufferTarget.ARRAY_BUFFER);
            }

            var weightAccessorIndex = -1;
            var jointsAccessorIndex = -1;

            if (boneWeights != null && jointIndexMap != null)
            {
                weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneWeights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER);
                jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneWeights.Select(y =>
                                                                                                           new UShort4(
                                                                                                               (ushort)jointIndexMap[y.boneIndex0],
                                                                                                               (ushort)jointIndexMap[y.boneIndex1],
                                                                                                               (ushort)jointIndexMap[y.boneIndex2],
                                                                                                               (ushort)jointIndexMap[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 (var 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 (var 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();
                }

                var primitives = new glTFPrimitives
                {
                    attributes = attributes,
                    indices    = indicesAccessorIndex,
                    mode       = 4, // triangles ?
                };

                if (meshMaterials != null)
                {
                    primitives.material = exportedMaterials.IndexOf(meshMaterials[j]);
                }

                gltfMesh.primitives.Add(primitives);
            }
            return(gltfMesh);
        }
Beispiel #17
0
 public static bool HasTexCoord0(this glTFPrimitives primitives) => primitives.attributes.TEXCOORD_0 != -1;
Beispiel #18
0
 public static bool HasNormal(this glTFPrimitives primitives) => primitives.attributes.NORMAL != -1;
Beispiel #19
0
 public static bool HasSkin(this glTFPrimitives primitives) => primitives.attributes.JOINTS_0 != -1 && primitives.attributes.WEIGHTS_0 != -1;
Beispiel #20
0
 public static bool HasColor(this glTFPrimitives primitives) => primitives.attributes.COLOR_0 != -1;