/// <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()); }
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}"); } }
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); }
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}"); } }
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); }
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(); }
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); }
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); }
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); }
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}"); } }
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}"); } }
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); }
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); }
public static bool HasTexCoord0(this glTFPrimitives primitives) => primitives.attributes.TEXCOORD_0 != -1;
public static bool HasNormal(this glTFPrimitives primitives) => primitives.attributes.NORMAL != -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;