Beispiel #1
0
        public int[] GetIndices(int index)
        {
            var accessor = accessors[index];
            var view     = bufferViews[accessor.bufferView];

            switch ((glComponentType)accessor.componentType)
            {
            case glComponentType.UNSIGNED_BYTE:
            {
                var indices = GetAttrib <Byte>(accessor, view);
                return(TriangleUtil.FlipTriangle(indices).ToArray());
            }

            case glComponentType.UNSIGNED_SHORT:
            {
                var indices = GetAttrib <UInt16>(accessor, view);
                return(TriangleUtil.FlipTriangle(indices).ToArray());
            }

            /*
             * case glComponentType.INT:
             * {
             *  var indices = GetAttrib<Int32>(accessor, view);
             *  return FlipTriangle(indices).ToArray();
             * }
             */

            case glComponentType.UNSIGNED_INT:
            {
                var indices = GetAttrib <UInt32>(accessor, view);
                return(TriangleUtil.FlipTriangle(indices).ToArray());
            }
            }

            throw new NotImplementedException("GetIndices: unknown componenttype: " + accessor.componentType);
        }
Beispiel #2
0
        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.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 = 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, // triangels ?
                    material   = unityMaterials.IndexOf(materials[j])
                });
            }
            return(gltfMesh);
        }
Beispiel #3
0
        // multiple submesh sharing same VertexBuffer
        private static MeshContext _ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh)
        {
            var context = new MeshContext();

            {
                var prim = gltfMesh.primitives.First();
                context.positions = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ());

                // normal
                if (prim.attributes.NORMAL != -1)
                {
                    context.normals = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ());
                }

                // tangent
                if (prim.attributes.TANGENT != -1)
                {
                    context.tangents = ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ());
                }

                // uv
                if (prim.attributes.TEXCOORD_0 != -1)
                {
                    context.uv = ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY());
                }
                else
                {
                    // for inconsistent attributes in primitives
                    context.uv = new Vector2[context.positions.Length];
                }

                // color
                if (prim.attributes.COLOR_0 != -1)
                {
                    context.colors = ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0);
                }

                // skin
                if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
                {
                    var joints0  = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4
                    var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0);
                    for (int i = 0; i < weights0.Length; ++i)
                    {
                        weights0[i] = weights0[i].One();
                    }

                    for (int j = 0; j < joints0.Length; ++j)
                    {
                        var bw = new BoneWeight();

                        bw.boneIndex0 = joints0[j].x;
                        bw.weight0    = weights0[j].x;

                        bw.boneIndex1 = joints0[j].y;
                        bw.weight1    = weights0[j].y;

                        bw.boneIndex2 = joints0[j].z;
                        bw.weight2    = weights0[j].z;

                        bw.boneIndex3 = joints0[j].w;
                        bw.weight3    = weights0[j].w;

                        context.boneWeights.Add(bw);
                    }
                }

                // blendshape
                if (prim.targets != null && prim.targets.Count > 0)
                {
                    context.blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape(
                                                                         i < prim.extras.targetNames.Count && !string.IsNullOrEmpty(prim.extras.targetNames[i])
                        ? prim.extras.targetNames[i]
                        : 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 = context.blendShapes[i];

                        if (primTarget.POSITION != -1)
                        {
                            blendShape.Positions.Assign(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION), x => x.ReverseZ());
                        }
                        if (primTarget.NORMAL != -1)
                        {
                            blendShape.Normals.Assign(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL), x => x.ReverseZ());
                        }
                        if (primTarget.TANGENT != -1)
                        {
                            blendShape.Tangents.Assign(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT), x => x.ReverseZ());
                        }
                    }
                }
            }

            foreach (var prim in gltfMesh.primitives)
            {
                if (prim.indices == -1)
                {
                    context.subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, context.positions.Length)).ToArray());
                }
                else
                {
                    var indices = ctx.GLTF.GetIndices(prim.indices);
                    context.subMeshes.Add(indices);
                }

                // material
                context.materialIndices.Add(prim.material);
            }

            return(context);
        }
Beispiel #4
0
        // multiple submMesh is not sharing a VertexBuffer.
        // each subMesh use a independent VertexBuffer.
        private static MeshContext _ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh)
        {
            //Debug.LogWarning("_ImportMeshIndependentVertexBuffer");

            var targets = gltfMesh.primitives[0].targets;

            for (int i = 1; i < gltfMesh.primitives.Count; ++i)
            {
                if (!gltfMesh.primitives[i].targets.SequenceEqual(targets))
                {
                    throw new NotImplementedException(string.Format("diffirent targets: {0} with {1}",
                                                                    gltfMesh.primitives[i],
                                                                    targets));
                }
            }

            var positions   = new List <Vector3>();
            var normals     = new List <Vector3>();
            var tangents    = new List <Vector4>();
            var uv          = new List <Vector2>();
            var colors      = new List <Color>();
            var meshContext = new MeshContext();

            foreach (var prim in gltfMesh.primitives)
            {
                var indexOffset = positions.Count;
                var indexBuffer = prim.indices;

                var positionCount = positions.Count;
                positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ()));
                positionCount = positions.Count - positionCount;

                // normal
                if (prim.attributes.NORMAL != -1)
                {
                    normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ()));
                }

                if (prim.attributes.TANGENT != -1)
                {
                    tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ()));
                }

                // uv
                if (prim.attributes.TEXCOORD_0 != -1)
                {
                    uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY()));
                }
                else
                {
                    // for inconsistent attributes in primitives
                    uv.AddRange(new Vector2[positionCount]);
                }

                // color
                if (prim.attributes.COLOR_0 != -1)
                {
                    colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0));
                }

                // skin
                if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
                {
                    var joints0  = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4
                    var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray();

                    for (int j = 0; j < joints0.Length; ++j)
                    {
                        var bw = new BoneWeight();

                        bw.boneIndex0 = joints0[j].x;
                        bw.weight0    = weights0[j].x;

                        bw.boneIndex1 = joints0[j].y;
                        bw.weight1    = weights0[j].y;

                        bw.boneIndex2 = joints0[j].z;
                        bw.weight2    = weights0[j].z;

                        bw.boneIndex3 = joints0[j].w;
                        bw.weight3    = weights0[j].w;

                        meshContext.boneWeights.Add(bw);
                    }
                }

                // blendshape
                if (prim.targets != null && prim.targets.Count > 0)
                {
                    for (int i = 0; i < prim.targets.Count; ++i)
                    {
                        //var name = string.Format("target{0}", i++);
                        var primTarget = prim.targets[i];
                        var blendShape = new BlendShape(!string.IsNullOrEmpty(prim.extras.targetNames[i])
                            ? prim.extras.targetNames[i]
                            : i.ToString())
                        ;
                        if (primTarget.POSITION != -1)
                        {
                            blendShape.Positions.AddRange(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray());
                        }
                        if (primTarget.NORMAL != -1)
                        {
                            blendShape.Normals.AddRange(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray());
                        }
                        if (primTarget.TANGENT != -1)
                        {
                            blendShape.Tangents.AddRange(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray());
                        }
                        meshContext.blendShapes.Add(blendShape);
                    }
                }

                var indices =
                    (indexBuffer >= 0)
                 ? ctx.GLTF.GetIndices(indexBuffer)
                 : TriangleUtil.FlipTriangle(Enumerable.Range(0, meshContext.positions.Length)).ToArray() // without index array
                ;
                for (int i = 0; i < indices.Length; ++i)
                {
                    indices[i] += indexOffset;
                }

                meshContext.subMeshes.Add(indices);

                // material
                meshContext.materialIndices.Add(prim.material);
            }

            meshContext.positions = positions.ToArray();
            meshContext.normals   = normals.ToArray();
            meshContext.tangents  = tangents.ToArray();
            meshContext.uv        = uv.ToArray();

            return(meshContext);
        }
Beispiel #5
0
        public static Exported FromGameObject(glTF gltf, GameObject go)
        {
            var bytesBuffer = new ArrayByteBuffer();
            var bufferIndex = gltf.AddBuffer(bytesBuffer);

            var unityNodes = go.transform.Traverse()
                             .Skip(1) // exclude root object for the symmetry with the importer
                             .ToList();

            #region Material
            var unityMaterials = unityNodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
            var unityTextures  = unityMaterials.SelectMany(x => x.GetTextures()).Where(x => x != null).Distinct().ToList();

            for (int i = 0; i < unityTextures.Count; ++i)
            {
                var texture = unityTextures[i];

                var bytesWithPath = new BytesWithPath(texture);;

                // add view
                var view      = gltf.buffers[bufferIndex].Storage.Extend(bytesWithPath.Bytes, glBufferTarget.NONE);
                var viewIndex = gltf.AddBufferView(view);

                // add image
                var imageIndex = gltf.images.Count;
                gltf.images.Add(new glTFImage
                {
                    bufferView = viewIndex,
                    mimeType   = bytesWithPath.Mime,
                });

                // add sampler
                var filter = default(glFilter);
                switch (texture.filterMode)
                {
                case FilterMode.Point:
                    filter = glFilter.NEAREST;
                    break;

                default:
                    filter = glFilter.LINEAR;
                    break;
                }
                var wrap = default(glWrap);

                switch (texture.wrapMode)
                {
                case TextureWrapMode.Clamp:
                    wrap = glWrap.CLAMP_TO_EDGE;
                    break;

                case TextureWrapMode.Repeat:
                    wrap = glWrap.REPEAT;
                    break;

#if UNITY_2017_OR_NEWER
                case TextureWrapMode.Mirror:
                    wrap = glWrap.MIRRORED_REPEAT;
                    break;
#endif

                default:
                    throw new NotImplementedException();
                }

                var samplerIndex = gltf.samplers.Count;
                gltf.samplers.Add(new glTFTextureSampler
                {
                    magFilter = filter,
                    minFilter = filter,
                    wrapS     = wrap,
                    wrapT     = wrap,
                });

                // add texture
                gltf.textures.Add(new glTFTexture
                {
                    sampler = samplerIndex,
                    source  = imageIndex,
                });
            }

            gltf.materials = unityMaterials.Select(x => ExportMaterial(x, unityTextures)).ToList();
            #endregion

            #region Meshes
            var unityMeshes = unityNodes
                              .Select(x => new MeshWithRenderer
            {
                Mesh       = x.GetSharedMesh(),
                Rendererer = x.GetComponent <Renderer>(),
            })
                              .Where(x => x.Mesh != null)
                              .ToList();
            for (int i = 0; i < unityMeshes.Count; ++i)
            {
                var x         = unityMeshes[i];
                var mesh      = x.Mesh;
                var materials = x.Rendererer.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.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                var tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                var colorAccessorIndex   = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors.Select(y => (Vector4)y).ToArray(), glBufferTarget.ARRAY_BUFFER);
                var uvAccessorIndex      = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseY()).ToArray(), 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 (tangentAccessorIndex != -1)
                {
                    attributes.TANGENT = tangentAccessorIndex;
                }
                if (colorAccessorIndex != -1)
                {
                    attributes.COLOR_0 = colorAccessorIndex;
                }
                if (uvAccessorIndex != -1)
                {
                    attributes.TEXCOORD_0 = uvAccessorIndex;
                }
                if (weightAccessorIndex != -1)
                {
                    attributes.WEIGHTS_0 = weightAccessorIndex;
                }
                if (jointsAccessorIndex != -1)
                {
                    attributes.JOINTS_0 = jointsAccessorIndex;
                }

                gltf.meshes.Add(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);

                    gltf.meshes.Last().primitives.Add(new glTFPrimitives
                    {
                        attributes = attributes,
                        indices    = indicesAccessorIndex,
                        mode       = 4,                                 // triangels ?
                        //material = unityMaterials.IndexOf(materials[j])
                        material = unityMaterials.IndexOf(materials[0]) // JIA change for Maquette image entity
                    });
                }

                if (mesh.blendShapeCount > 0)
                {
                    for (int j = 0; j < mesh.blendShapeCount; ++j)
                    {
                        var blendShapeVertices = mesh.vertices;
                        var blendShpaeNormals  = mesh.normals;
                        var blendShapeTangents = mesh.tangents.Select(y => (Vector3)y).ToArray();
                        var blendShapeColors   = mesh.colors.Select(y => (Vector4)y).ToArray();
                        var k = mesh.GetBlendShapeFrameCount(j);
                        mesh.GetBlendShapeFrameVertices(j, k - 1, blendShapeVertices, blendShpaeNormals, null);

                        var blendShapePositionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
                                                                                                   blendShapeVertices.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                        var blendShapeNormalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
                                                                                                 blendShpaeNormals.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                        var blendShapeTangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
                                                                                                  blendShapeTangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                        var blendShapeColorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
                                                                                                blendShapeColors.ToArray(), glBufferTarget.ARRAY_BUFFER);
                        //
                        // first primitive has whole blendShape
                        //
                        gltf.meshes.Last().primitives[0].targets.Add(new glTFAttributes
                        {
                            POSITION = blendShapePositionAccessorIndex,
                            NORMAL   = blendShapeNormalAccessorIndex,
                            TANGENT  = blendShapeTangentAccessorIndex,
                            COLOR_0  = blendShapeColorAccessorIndex,
                        });
                    }
                }
            }
            #endregion

            #region Skins
            var unitySkins = unityNodes
                             .Select(x => x.GetComponent <SkinnedMeshRenderer>()).Where(x => x != null)
                             .ToList();
            gltf.nodes  = unityNodes.Select(x => ExportNode(x, unityNodes, unityMeshes.Select(y => y.Mesh).ToList(), unitySkins)).ToList();
            gltf.scenes = new List <gltfScene>
            {
                new gltfScene
                {
                    nodes = go.transform.GetChildren().Select(x => unityNodes.IndexOf(x)).ToArray(),
                }
            };

            foreach (var x in unitySkins)
            {
                var matrices = x.sharedMesh.bindposes.Select(y => y.ReverseZ()).ToArray();
                var accessor = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);

                var skin = new glTFSkin
                {
                    inverseBindMatrices = accessor,
                    joints   = x.bones.Select(y => unityNodes.IndexOf(y)).ToArray(),
                    skeleton = unityNodes.IndexOf(x.rootBone),
                };
                var skinIndex = gltf.skins.Count;
                gltf.skins.Add(skin);

                foreach (var z in unityNodes.Where(y => y.Has(x)))
                {
                    var nodeIndex = unityNodes.IndexOf(z);
                    gltf.nodes[nodeIndex].skin = skinIndex;
                }
            }
            #endregion

#if UNITY_EDITOR
            #region Animations
            var animation = go.GetComponent <Animation>();
            if (animation != null)
            {
                foreach (AnimationState state in animation)
                {
                    var animationWithCurve = ExportAnimation(state.clip, go.transform, unityNodes);

                    foreach (var kv in animationWithCurve.SamplerMap)
                    {
                        var sampler = animationWithCurve.Animation.samplers[kv.Key];

                        var inputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input);
                        sampler.input = inputAccessorIndex;

                        var outputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output);
                        sampler.output = outputAccessorIndex;

                        // modify accessors
                        var outputAccessor = gltf.accessors[outputAccessorIndex];
                        var channel        = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
                        switch (glTFAnimationTarget.GetElementCount(channel.target.path))
                        {
                        case 3:
                            outputAccessor.type   = "VEC3";
                            outputAccessor.count /= 3;
                            break;

                        case 4:
                            outputAccessor.type   = "VEC4";
                            outputAccessor.count /= 4;
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }

                    gltf.animations.Add(animationWithCurve.Animation);
                }
            }
            #endregion
#endif

            // glb buffer
            gltf.buffers[bufferIndex].UpdateByteLength();

            return(new Exported
            {
                Meshes = unityMeshes,
                Nodes = unityNodes.Select(x => x.transform).ToList(),
                Materials = unityMaterials,
                Textures = unityTextures,
            });
        }
        // mesh is sharing morph targets.
        private static MeshContext _ImportMeshSharingMorphTarget(ImporterContext ctx, glTFMesh gltfMesh)
        {
            var positions   = new List <Vector3>();
            var normals     = new List <Vector3>();
            var tangents    = new List <Vector4>();
            var uv          = new List <Vector2>();
            var colors      = new List <Color>();
            var blendShapes = new List <BlendShape>();
            var meshContext = new MeshContext();

            // blendshapes
            var targetNames = gltfMesh.extras.targetNames;

            for (int i = 1; i < gltfMesh.primitives.Count; ++i)
            {
                if (gltfMesh.primitives[i].targets.Count != targetNames.Count)
                {
                    throw new FormatException(string.Format("different targets length: {0} with targetNames length.",
                                                            gltfMesh.primitives[i]));
                }
            }
            for (var i = 0; i < targetNames.Count; i++)
            {
                var blendShape = new BlendShape(!string.IsNullOrEmpty(targetNames[i]) ? targetNames[i] : i.ToString());
                blendShapes.Add(blendShape);
            }

            foreach (var prim in gltfMesh.primitives)
            {
                var indexOffset = positions.Count;
                var indexBuffer = prim.indices;

                var positionCount = positions.Count;
                positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ()));
                positionCount = positions.Count - positionCount;

                // normal
                if (prim.attributes.NORMAL != -1)
                {
                    normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ()));
                }

                if (prim.attributes.TANGENT != -1)
                {
                    tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ()));
                }

                // uv
                if (prim.attributes.TEXCOORD_0 != -1)
                {
                    if (ctx.IsGeneratedUniGLTFAndOlder(1, 16))
                    {
#pragma warning disable 0612
                        // backward compatibility
                        uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY()));
#pragma warning restore 0612
                    }
                    else
                    {
                        uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseUV()));
                    }
                }
                else
                {
                    // for inconsistent attributes in primitives
                    uv.AddRange(new Vector2[positionCount]);
                }

                // color
                if (prim.attributes.COLOR_0 != -1)
                {
                    colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0));
                }

                // skin
                if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
                {
                    var joints0  = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4
                    var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray();

                    for (int j = 0; j < joints0.Length; ++j)
                    {
                        var bw = new BoneWeight();

                        bw.boneIndex0 = joints0[j].x;
                        bw.weight0    = weights0[j].x;

                        bw.boneIndex1 = joints0[j].y;
                        bw.weight1    = weights0[j].y;

                        bw.boneIndex2 = joints0[j].z;
                        bw.weight2    = weights0[j].z;

                        bw.boneIndex3 = joints0[j].w;
                        bw.weight3    = weights0[j].w;

                        meshContext.boneWeights.Add(bw);
                    }
                }

                // blendshape
                if (prim.targets != null && prim.targets.Count > 0)
                {
                    for (int i = 0; i < prim.targets.Count; ++i)
                    {
                        var primTarget = prim.targets[i];
                        if (primTarget.POSITION != -1)
                        {
                            blendShapes[i].Positions.AddRange(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray());
                        }
                        if (primTarget.NORMAL != -1)
                        {
                            blendShapes[i].Normals.AddRange(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray());
                        }
                        if (primTarget.TANGENT != -1)
                        {
                            blendShapes[i].Tangents.AddRange(
                                ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray());
                        }
                    }
                }

                var indices =
                    (indexBuffer >= 0)
                 ? ctx.GLTF.GetIndices(indexBuffer)
                 : TriangleUtil.FlipTriangle(Enumerable.Range(0, meshContext.positions.Length)).ToArray() // without index array
                ;
                for (int i = 0; i < indices.Length; ++i)
                {
                    indices[i] += indexOffset;
                }

                meshContext.subMeshes.Add(indices);

                // material
                meshContext.materialIndices.Add(prim.material);
            }

            meshContext.positions   = positions.ToArray();
            meshContext.normals     = normals.ToArray();
            meshContext.tangents    = tangents.ToArray();
            meshContext.uv          = uv.ToArray();
            meshContext.blendShapes = blendShapes;

            return(meshContext);
        }
        static MeshWithMaterials ImportMesh(glTF gltf, int meshIndex, glTFMesh gltfMesh,
                                            List <Material> materials,
                                            GetBlendShapeName getBlendShapeName
                                            )
        {
            glTFAttributes lastAttributes   = null;
            var            sharedAttributes = true;

            foreach (var prim in gltfMesh.primitives)
            {
                if (lastAttributes != null && !prim.attributes.Equals(lastAttributes))
                {
                    sharedAttributes = false;
                    break;
                }
                lastAttributes = prim.attributes;
            }

            var positions       = new List <Vector3>();
            var normals         = new List <Vector3>();
            var tangents        = new List <Vector4>();
            var colors          = new List <Vector4>();
            var uv              = new List <Vector2>();
            var boneWeights     = new List <BoneWeight>();
            var subMeshes       = new List <int[]>();
            var materialIndices = new List <int>();

            BlendShape[] blendShapes = null;

            if (sharedAttributes)
            {
                // multiple submesh sharing same VertexBuffer
                {
                    var prim = gltfMesh.primitives.First();
                    positions.AddRange(gltf.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ()));

                    // normal
                    if (prim.attributes.NORMAL != -1)
                    {
                        normals.AddRange(gltf.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ()));
                    }

                    // tangent
                    if (prim.attributes.TANGENT != -1)
                    {
                        tangents.AddRange(gltf.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ()));
                    }

                    // vertex color
                    if (prim.attributes.COLOR_0 != -1)
                    {
                        colors.AddRange(gltf.GetArrayFromAccessor <Vector4>(prim.attributes.COLOR_0));
                    }

                    // uv
                    if (prim.attributes.TEXCOORD_0 != -1)
                    {
                        uv.AddRange(gltf.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY()));
                    }
                    else
                    {
                        // for inconsistent attributes in primitives
                        uv.AddRange(new Vector2[positions.Count]);
                    }

                    // skin
                    if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
                    {
                        var joints0  = gltf.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4
                        var weights0 = gltf.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray();

                        for (int j = 0; j < joints0.Length; ++j)
                        {
                            var bw = new BoneWeight();

                            bw.boneIndex0 = joints0[j].x;
                            bw.weight0    = weights0[j].x;

                            bw.boneIndex1 = joints0[j].y;
                            bw.weight1    = weights0[j].y;

                            bw.boneIndex2 = joints0[j].z;
                            bw.weight2    = weights0[j].z;

                            bw.boneIndex3 = joints0[j].w;
                            bw.weight3    = weights0[j].w;

                            boneWeights.Add(bw);
                        }
                    }

                    // blendshape
                    if (prim.targets != null && prim.targets.Count > 0)
                    {
                        if (blendShapes == null)
                        {
                            blendShapes = prim.targets.Select((x, i) => new BlendShape(getBlendShapeName(meshIndex, i))).ToArray();
                        }
                        for (int i = 0; i < prim.targets.Count; ++i)
                        {
                            //var name = string.Format("target{0}", i++);
                            var primTarget = prim.targets[i];
                            var blendShape = blendShapes[i];

                            if (primTarget.POSITION != -1)
                            {
                                blendShape.Positions.AddRange(
                                    gltf.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray());
                            }
                            if (primTarget.NORMAL != -1)
                            {
                                blendShape.Normals.AddRange(
                                    gltf.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray());
                            }
                            if (primTarget.TANGENT != -1)
                            {
                                blendShape.Tangents.AddRange(
                                    gltf.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray());
                            }
                        }
                    }
                }

                foreach (var prim in gltfMesh.primitives)
                {
                    var indices = gltf.GetIndices(prim.indices).Select(x => x).ToArray();
                    subMeshes.Add(indices);

                    // material
                    materialIndices.Add(prim.material);
                }
            }
            else
            {
                // multiple submMesh is not sharing a VertexBuffer.
                // each subMesh use a independent VertexBuffer.

                var targets = gltfMesh.primitives[0].targets;
                for (int i = 1; i < gltfMesh.primitives.Count; ++i)
                {
                    if (!gltfMesh.primitives[i].targets.SequenceEqual(targets))
                    {
                        throw new NotImplementedException(string.Format("diffirent targets: {0} with {1}",
                                                                        gltfMesh.primitives[i],
                                                                        targets));
                    }
                }

                foreach (var prim in gltfMesh.primitives)
                {
                    var indexOffset = positions.Count;
                    var indexBuffer = prim.indices;

                    var positionCount = positions.Count;
                    positions.AddRange(gltf.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ()));
                    positionCount = positions.Count - positionCount;

                    // normal
                    if (prim.attributes.NORMAL != -1)
                    {
                        normals.AddRange(gltf.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ()));
                    }

                    if (prim.attributes.TANGENT != -1)
                    {
                        tangents.AddRange(gltf.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ()));
                    }

                    // vertex color
                    if (prim.attributes.COLOR_0 != -1)
                    {
                        colors.AddRange(gltf.GetArrayFromAccessor <Vector4>(prim.attributes.COLOR_0));
                    }

                    // uv
                    if (prim.attributes.TEXCOORD_0 != -1)
                    {
                        uv.AddRange(gltf.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY()));
                    }
                    else
                    {
                        // for inconsistent attributes in primitives
                        uv.AddRange(new Vector2[positionCount]);
                    }

                    // skin
                    if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
                    {
                        var joints0  = gltf.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4
                        var weights0 = gltf.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray();

                        for (int j = 0; j < joints0.Length; ++j)
                        {
                            var bw = new BoneWeight();

                            bw.boneIndex0 = joints0[j].x;
                            bw.weight0    = weights0[j].x;

                            bw.boneIndex1 = joints0[j].y;
                            bw.weight1    = weights0[j].y;

                            bw.boneIndex2 = joints0[j].z;
                            bw.weight2    = weights0[j].z;

                            bw.boneIndex3 = joints0[j].w;
                            bw.weight3    = weights0[j].w;

                            boneWeights.Add(bw);
                        }
                    }

                    // blendshape
                    if (prim.targets != null && prim.targets.Count > 0)
                    {
                        if (blendShapes == null)
                        {
                            blendShapes = prim.targets.Select((x, i) => new BlendShape(i.ToString())).ToArray();
                        }
                        for (int i = 0; i < prim.targets.Count; ++i)
                        {
                            //var name = string.Format("target{0}", i++);
                            var primTarget = prim.targets[i];
                            var blendShape = blendShapes[i];

                            if (primTarget.POSITION != -1)
                            {
                                blendShape.Positions.AddRange(
                                    gltf.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray());
                            }
                            if (primTarget.NORMAL != -1)
                            {
                                blendShape.Normals.AddRange(
                                    gltf.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray());
                            }
                            if (primTarget.TANGENT != -1)
                            {
                                blendShape.Tangents.AddRange(
                                    gltf.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray());
                            }
                        }
                    }

                    var indices =
                        (indexBuffer >= 0)
                     ? gltf.GetIndices(indexBuffer).Select(x => x + indexOffset).ToArray()
                     : TriangleUtil.FlipTriangle(Enumerable.Range(0, positions.Count)).ToArray() // without index array
                    ;
                    subMeshes.Add(indices);

                    // material
                    materialIndices.Add(prim.material);
                }
            }
            if (!materialIndices.Any())
            {
                materialIndices.Add(0);
            }

            //Debug.Log(prims.ToJson());
            var mesh = new Mesh();

            mesh.name = gltfMesh.name;

            if (positions.Count > UInt16.MaxValue)
            {
#if UNITY_2017_3_OR_NEWER
                mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#else
                Debug.LogWarningFormat("vertices {0} exceed 65535. not implemented. Unity2017.3 supports large mesh", positions.Count);
#endif
            }

            mesh.vertices = positions.ToArray();
            if (normals.Any())
            {
                mesh.normals = normals.ToArray();
            }
            else
            {
                mesh.RecalculateNormals();
            }
            if (tangents.Any())
            {
                mesh.tangents = tangents.ToArray();
            }
            else
            {
                mesh.RecalculateTangents();
            }
            if (colors.Any())
            {
                mesh.colors = colors.ConvertAll(x => new Color(x.x, x.y, x.z, 1f)).ToArray();
            }
            if (uv.Any())
            {
                mesh.uv = uv.ToArray();
            }
            if (boneWeights.Any())
            {
                mesh.boneWeights = boneWeights.ToArray();
            }
            mesh.subMeshCount = subMeshes.Count;
            for (int i = 0; i < subMeshes.Count; ++i)
            {
                mesh.SetTriangles(subMeshes[i], i);
            }
            var result = new MeshWithMaterials
            {
                Mesh      = mesh,
                Materials = materialIndices.Select(x => materials[x]).ToArray()
            };

            List <Material> matList = result.Materials.ToList();
            matList.RemoveAll(x => x == null);
            result.Materials = matList.ToArray();

            if (blendShapes != null)
            {
                foreach (var blendShape in blendShapes)
                {
                    if (blendShape.Positions.Count > 0)
                    {
                        if (blendShape.Positions.Count == mesh.vertexCount)
                        {
                            mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT,
                                                    blendShape.Positions.ToArray(),
                                                    normals.Count == mesh.vertexCount ? blendShape.Normals.ToArray() : null,
                                                    null
                                                    );
                        }
                        else
                        {
                            Debug.LogWarningFormat("May be partial primitive has blendShape. Rquire separete mesh or extend blend shape, but not implemented: {0}", blendShape.Name);
                        }
                    }
                }
            }

            return(result);
        }
Beispiel #8
0
            /// <summary>
            ///
            /// 各primitiveが同じ attribute を共有している場合専用のローダー。
            ///
            /// </summary>
            /// <param name="ctx"></param>
            /// <param name="gltfMesh"></param>
            /// <returns></returns>
            public void ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh)
            {
                {
                    //  同じVertexBufferを共有しているので先頭のモノを使う
                    var prim = gltfMesh.primitives.First();
                    m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ()));

                    // normal
                    if (prim.attributes.NORMAL != -1)
                    {
                        m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ()));
                    }

#if false
                    // tangent
                    if (prim.attributes.TANGENT != -1)
                    {
                        tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ()));
                    }
#endif

                    // uv
                    if (prim.attributes.TEXCOORD_0 != -1)
                    {
                        if (ctx.IsGeneratedUniGLTFAndOlder(1, 16))
                        {
#pragma warning disable 0612
                            // backward compatibility
                            m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY()));
#pragma warning restore 0612
                        }
                        else
                        {
                            m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV()));
                        }
                    }

                    // uv2
                    if (prim.attributes.TEXCOORD_1 != -1)
                    {
                        m_uv2.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_1).SelectInplace(x => x.ReverseUV()));
                    }

                    // color
                    if (prim.attributes.COLOR_0 != -1)
                    {
                        if (ctx.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 3)
                        {
                            var vec3Color = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.COLOR_0);
                            m_colors.AddRange(new Color[vec3Color.Length]);

                            for (int i = 0; i < vec3Color.Length; i++)
                            {
                                Vector3 color = vec3Color[i];
                                m_colors[i] = new Color(color.x, color.y, color.z);
                            }
                        }
                        else if (ctx.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 4)
                        {
                            m_colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0));
                        }
                        else
                        {
                            throw new NotImplementedException(string.Format("unknown color type {0}", ctx.GLTF.accessors[prim.attributes.COLOR_0].type));
                        }
                    }

                    // skin
                    if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
                    {
                        var joints0  = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4
                        var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0);
                        for (int i = 0; i < weights0.Length; ++i)
                        {
                            weights0[i] = weights0[i].One();
                        }

                        for (int j = 0; j < joints0.Length; ++j)
                        {
                            var bw = new BoneWeight();

                            bw.boneIndex0 = joints0[j].x;
                            bw.weight0    = weights0[j].x;

                            bw.boneIndex1 = joints0[j].y;
                            bw.weight1    = weights0[j].y;

                            bw.boneIndex2 = joints0[j].z;
                            bw.weight2    = weights0[j].z;

                            bw.boneIndex3 = joints0[j].w;
                            bw.weight3    = weights0[j].w;

                            m_boneWeights.Add(bw);
                        }
                    }

                    // blendshape
                    if (prim.targets != null && prim.targets.Count > 0)
                    {
                        m_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];

                            if (primTarget.POSITION != -1)
                            {
                                blendShape.Positions.Assign(
                                    ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION), x => x.ReverseZ());
                            }
                            if (primTarget.NORMAL != -1)
                            {
                                blendShape.Normals.Assign(
                                    ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL), x => x.ReverseZ());
                            }
                            if (primTarget.TANGENT != -1)
                            {
                                blendShape.Tangents.Assign(
                                    ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT), x => x.ReverseZ());
                            }
                        }
                    }
                }

                foreach (var prim in gltfMesh.primitives)
                {
                    if (prim.indices == -1)
                    {
                        m_subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray());
                    }
                    else
                    {
                        var indices = ctx.GLTF.GetIndices(prim.indices);
                        m_subMeshes.Add(indices);
                    }

                    // material
                    m_materialIndices.Add(prim.material);
                }
            }
Beispiel #9
0
            /// <summary>
            /// 各 primitive の attribute の要素が同じでない。=> uv が有るものと無いものが混在するなど
            /// glTF 的にはありうる。
            ///
            /// primitive を独立した(Independent) Mesh として扱いこれを連結する。
            /// </summary>
            /// <param name="ctx"></param>
            /// <param name="gltfMesh"></param>
            /// <returns></returns>
            public void ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh)
            {
                foreach (var prim in gltfMesh.primitives)
                {
                    var indexOffset = m_positions.Count;
                    var indexBuffer = prim.indices;

                    // position は必ずある
                    var positionCount = m_positions.Count;
                    m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ()));
                    positionCount = m_positions.Count - positionCount;

                    // normal
                    if (prim.attributes.NORMAL != -1)
                    {
                        FillZero(m_normals);
                        m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ()));
                    }

#if false
                    if (prim.attributes.TANGENT != -1)
                    {
                        FillZero(tangetns);
                        tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ()));
                    }
#endif

                    // uv
                    if (prim.attributes.TEXCOORD_0 != -1)
                    {
                        FillZero(m_uv);
                        if (ctx.IsGeneratedUniGLTFAndOlder(1, 16))
                        {
#pragma warning disable 0612
                            // backward compatibility
                            m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY()));
#pragma warning restore 0612
                        }
                        else
                        {
                            m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseUV()));
                        }
                    }

                    // uv2
                    if (prim.attributes.TEXCOORD_1 != -1)
                    {
                        FillZero(m_uv2);
                        m_uv2.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_1).Select(x => x.ReverseUV()));
                    }

                    // color
                    if (prim.attributes.COLOR_0 != -1)
                    {
                        FillZero(m_colors);
                        m_colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0));
                    }

                    // skin
                    if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
                    {
                        FillZero(m_boneWeights);

                        var joints0  = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4
                        var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray();

                        for (int j = 0; j < joints0.Length; ++j)
                        {
                            var bw = new BoneWeight();

                            bw.boneIndex0 = joints0[j].x;
                            bw.weight0    = weights0[j].x;

                            bw.boneIndex1 = joints0[j].y;
                            bw.weight1    = weights0[j].y;

                            bw.boneIndex2 = joints0[j].z;
                            bw.weight2    = weights0[j].z;

                            bw.boneIndex3 = joints0[j].w;
                            bw.weight3    = weights0[j].w;

                            m_boneWeights.Add(bw);
                        }
                    }

                    // blendshape
                    if (prim.targets != null && prim.targets.Count > 0)
                    {
                        for (int i = 0; i < prim.targets.Count; ++i)
                        {
                            var primTarget = prim.targets[i];
                            var blendShape = new BlendShape(i.ToString());
                            if (primTarget.POSITION != -1)
                            {
                                FillZero(blendShape.Positions);
                                blendShape.Positions.AddRange(
                                    ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray());
                            }
                            if (primTarget.NORMAL != -1)
                            {
                                FillZero(blendShape.Normals);
                                blendShape.Normals.AddRange(
                                    ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray());
                            }
                            if (primTarget.TANGENT != -1)
                            {
                                FillZero(blendShape.Tangents);
                                blendShape.Tangents.AddRange(
                                    ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray());
                            }
                            m_blendShapes.Add(blendShape);
                        }
                    }

                    var indices =
                        (indexBuffer >= 0)
                     ? ctx.GLTF.GetIndices(indexBuffer)
                     : TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray() // without index array
                    ;
                    for (int i = 0; i < indices.Length; ++i)
                    {
                        indices[i] += indexOffset;
                    }

                    m_subMeshes.Add(indices);

                    // material
                    m_materialIndices.Add(prim.material);
                }
            }