Пример #1
0
        public int AddChannelAndGetSampler(int nodeIndex, GLTFAnimationTarget.AnimationProperty property)
        {
            // find channel
            var channel = channels.FirstOrDefault(x => x.target.node == nodeIndex && x.target.path == GLTFAnimationTarget.GetPathName(property));

            if (channel != null)
            {
                return(channel.sampler);
            }

            // not found. create new
            var samplerIndex = samplers.Count;
            var sampler      = new GLTFAnimationSampler();

            samplers.Add(sampler);

            channel = new GLTFAnimationChannel
            {
                sampler = samplerIndex,
                target  = new GLTFAnimationTarget
                {
                    node = nodeIndex,
                    path = GLTFAnimationTarget.GetPathName(property),
                },
            };
            channels.Add(channel);

            return(samplerIndex);
        }
Пример #2
0
        public AnimationWithSampleCurves Export(AnimationClip clip, Transform root, List <Transform> nodes)
        {
            var animation = new AnimationWithSampleCurves
            {
                animation = new GLTFAnimation(),
            };

            List <AnimationCurveData> curveDatas = new List <AnimationCurveData>();
            var bindings = AnimationUtility.GetCurveBindings(clip);

            foreach (var binding in bindings)
            {
                var property = PropertyToTarget(binding.propertyName);
                if (property == GLTFAnimationTarget.AnimationProperty.NotImplemented)
                {
                    Debug.LogWarning("Not Implemented keyframe property : " + binding.propertyName);
                    continue;
                }
                if (property == GLTFAnimationTarget.AnimationProperty.EulerRotation)
                {
                    Debug.LogWarning("Interpolation setting of AnimationClip should be Quaternion");
                    continue;
                }
                var curve = AnimationUtility.GetEditorCurve(clip, binding);

                var nodeIndex    = GetNodeIndex(root, nodes, binding.path);
                var samplerIndex = animation.animation.AddChannelAndGetSampler(nodeIndex, property);
                var elementCount = 0;
                if (property == GLTFAnimationTarget.AnimationProperty.BlendShape)
                {
                    var mesh = nodes[nodeIndex].GetComponent <SkinnedMeshRenderer>().sharedMesh;
                    elementCount = mesh.blendShapeCount;
                }
                else
                {
                    elementCount = GLTFAnimationTarget.GetElementCount(property);
                }
                Debug.Log("export animation binding ... " + nodeIndex + " == " + elementCount);

                // 同一のsamplerIndexが割り当てられているcurveDataがある場合はそれを使用し、無ければ作る
                var curveData = curveDatas.FirstOrDefault(x => x.samplerIndex == samplerIndex);
                if (curveData == null)
                {
                    curveData = new AnimationCurveData(AnimationUtility.GetKeyRightTangentMode(curve, 0), property, samplerIndex, elementCount);
                    curveDatas.Add(curveData);
                }

                // 全てのキーフレームを回収
                int   elementOffset = 0;
                float valueFactor   = 1.0f;
                if (property == GLTFAnimationTarget.AnimationProperty.BlendShape)
                {
                    var mesh           = nodes[nodeIndex].GetComponent <SkinnedMeshRenderer>().sharedMesh;
                    var blendShapeName = binding.propertyName.Replace("blendShape.", "");
                    elementOffset = mesh.GetBlendShapeIndex(blendShapeName);
                    valueFactor   = 0.01f;
                }
                else
                {
                    elementOffset = GetElementOffset(binding.propertyName);
                }

                if (elementOffset >= 0 && elementOffset < elementCount)
                {
                    for (int i = 0; i < curve.keys.Length; i++)
                    {
                        curveData.SetKeyframeData(curve.keys[i].time, curve.keys[i].value * valueFactor, elementOffset);
                    }
                }
            }

            //キー挿入
            foreach (var curve in curveDatas)
            {
                if (curve.Keyframes.Count == 0)
                {
                    continue;
                }

                curve.RecountEmptyKeyframe();

                var elementNum = curve.Keyframes.First().Values.Length;
                var values     = default(InputOutputValues);
                if (!animation.samplers.TryGetValue(curve.samplerIndex, out values))
                {
                    values        = new InputOutputValues();
                    values.input  = new float[curve.Keyframes.Count];
                    values.output = new float[curve.Keyframes.Count * elementNum];
                    animation.samplers[curve.samplerIndex] = values;
                    animation.animation.samplers[curve.samplerIndex].interpolation = curve.GetInterpolation();
                }

                int keyframeIndex = 0;
                foreach (var keyframe in curve.Keyframes)
                {
                    values.input[keyframeIndex] = keyframe.time;
                    Buffer.BlockCopy(keyframe.GetRightHandCoordinate(), 0, values.output, keyframeIndex * elementNum * sizeof(float), elementNum * sizeof(float));
                    keyframeIndex++;
                }
            }

            return(animation);
        }
Пример #3
0
        void FromGameObject(GLTFRoot gltf, GameObject go, bool useSparseAccessorForMorphTarget = false, int textureFormat = 0)
        {
            var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
            var bufferIndex = gltf.AddBuffer(bytesBuffer);

            GameObject tmpParent = null;

            if (go.transform.childCount == 0)
            {
                tmpParent = new GameObject("tmpParent");
                go.transform.SetParent(tmpParent.transform, true);
                go = tmpParent;
            }

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

                #region Materials and Textures
                materials = nodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
                var unityTextures = materials.SelectMany(x => x.GetTextures()).Where(x => x.Texture != null).Distinct().ToList();

                textureManager = new TextureExportManager(unityTextures);

                gltf.materials = materials.Select(x => _materialExporter.ExportMaterial(x, textureManager)).ToList();
                Debug.Log("image count = " + unityTextures.Count);
                for (int i = 0; i < unityTextures.Count; ++i)
                {
                    gltf.ExportTexture(bufferIndex, textureManager.GetExportTexture(i), unityTextures[i].TextureType, textureFormat);
                }
                #endregion


                #region Meshes
                var unityMeshes = nodes
                                  .Select(x => new MeshWithRenderer
                {
                    mesh       = x.GetSharedMesh(),
                    rendererer = x.GetComponent <Renderer>(),
                })
                                  .Where(x =>
                {
                    if (x.mesh == null)
                    {
                        return(false);
                    }
                    if (x.rendererer.sharedMaterials == null ||
                        x.rendererer.sharedMaterials.Length == 0)
                    {
                        return(false);
                    }

                    return(true);
                })
                                  .ToList();
                Debug.Log("unityMesher...." + unityMeshes.Count);
                _meshExporter.Export(gltf, bufferIndex, unityMeshes, materials, useSparseAccessorForMorphTarget);
                meshes = unityMeshes.Select(x => x.mesh).ToList();
                #endregion

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

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

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

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

#if UNITY_EDITOR
                #region Animations

                var clips     = new List <AnimationClip>();
                var animator  = go.GetComponent <Animator>();
                var animation = go.GetComponent <Animation>();
                if (animator != null)
                {
                    clips = _animationExporter.GetAnimationClips(animator);
                }
                else if (animation != null)
                {
                    clips = _animationExporter.GetAnimationClips(animation);
                }

                if (clips.Any())
                {
                    Debug.Log("export clips.." + clips.Count);
                    foreach (AnimationClip clip in clips)
                    {
                        var animationWithCurve = _animationExporter.Export(clip, go.transform, nodes);

                        foreach (var kv in animationWithCurve.samplers)
                        {
                            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;
                            Debug.Log(sampler.interpolation + ">>" + string.Join(",", kv.Value.output));

                            // 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 1:
                                outputAccessor.type = "SCALAR";
                                //outputAccessor.count = ;
                                break;

                            case 3:
                                outputAccessor.type   = "VEC3";
                                outputAccessor.count /= 3;
                                break;

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

                            default:
                                throw new NotImplementedException();
                            }
                        }
                        animationWithCurve.animation.name = clip.name;
                        gltf.animations.Add(animationWithCurve.animation);
                    }
                }
                #endregion
#endif
            }
            finally
            {
                if (tmpParent != null)
                {
                    tmpParent.transform.GetChild(0).SetParent(null);
                    if (Application.isPlaying)
                    {
                        GameObject.Destroy(tmpParent);
                    }
                    else
                    {
                        GameObject.DestroyImmediate(tmpParent);
                    }
                }
            }
        }