예제 #1
0
        static AnimationWithSampleCurves ExportAnimation(AnimationClip clip, Transform root, List <Transform> nodes)
        {
            var animation = new AnimationWithSampleCurves
            {
                Animation = new glTFAnimation(),
            };

            foreach (var binding in AnimationUtility.GetCurveBindings(clip))
            {
                var curve = AnimationUtility.GetEditorCurve(clip, binding);

                var nodeIndex = GetNodeIndex(root, nodes, binding.path);
                var target    = PropertyToTarget(binding.propertyName);
                if (target == glTFAnimationTarget.NOT_IMPLEMENTED)
                {
                    continue;
                }
                var samplerIndex = animation.Animation.AddChannelAndGetSampler(nodeIndex, target);
                var sampler      = animation.Animation.samplers[samplerIndex];

                var keys         = curve.keys;
                var elementCount = glTFAnimationTarget.GetElementCount(target);
                var values       = default(InputOutputValues);
                if (!animation.SamplerMap.TryGetValue(samplerIndex, out values))
                {
                    values        = new InputOutputValues();
                    values.Input  = new float[keys.Length];
                    values.Output = new float[keys.Length * elementCount];
                    animation.SamplerMap[samplerIndex] = values;
                }

                var j = GetElementOffset(binding.propertyName);
                for (int i = 0; i < keys.Length; ++i, j += elementCount)
                {
                    values.Input[i] = keys[i].time;
                    if (binding.propertyName == "m_LocalPosition.z" ||
                        binding.propertyName == "m_LocalRotation.z" ||
                        binding.propertyName == "m_LocalRotation.w")
                    {
                        values.Output[j] = -keys[i].value;
                    }
                    else
                    {
                        values.Output[j] = keys[i].value;
                    }
                }
            }

            return(animation);
        }
예제 #2
0
        public static void WriteAnimationWithSampleCurves(glTF gltf, AnimationWithSampleCurves animationWithCurve, string animationName, int bufferIndex)
        {
            foreach (var kv in animationWithCurve.SamplerMap)
            {
                var sampler = animationWithCurve.Animation.samplers[kv.Key];

                float min = float.PositiveInfinity;
                float max = float.NegativeInfinity;
                foreach (float value in kv.Value.Input)
                {
                    if (value < min)
                    {
                        min = value;
                    }
                    if (value > max)
                    {
                        max = value;
                    }
                }

                var inputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(
                    bufferIndex,
                    kv.Value.Input,
                    glBufferTarget.NONE,
                    new float[] { min },
                    new float[] { max });
                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 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 = animationName;
            gltf.animations.Add(animationWithCurve.Animation);
        }
예제 #3
0
        public static AnimationWithSampleCurves Export(AnimationClip clip, Transform root, List <Transform> nodes)
        {
            var animation = new AnimationWithSampleCurves
            {
                Animation = new glTFAnimation(),
            };

#if UNITY_5_6_OR_NEWER
            List <AnimationCurveData> curveDatum = new List <AnimationCurveData>();

            foreach (var binding in AnimationUtility.GetCurveBindings(clip))
            {
                var curve = AnimationUtility.GetEditorCurve(clip, binding);

                var property = AnimationExporter.PropertyToTarget(binding.propertyName);
                if (property == glTFAnimationTarget.AnimationProperties.NotImplemented)
                {
                    Debug.LogWarning("Not Implemented keyframe property : " + binding.propertyName);
                    continue;
                }
                if (property == glTFAnimationTarget.AnimationProperties.EulerRotation)
                {
                    Debug.LogWarning("Interpolation setting of AnimationClip should be Quaternion");
                    continue;
                }

                var nodeIndex    = GetNodeIndex(root, nodes, binding.path);
                var samplerIndex = animation.Animation.AddChannelAndGetSampler(nodeIndex, property);
                var elementCount = 0;
                if (property == glTFAnimationTarget.AnimationProperties.BlendShape)
                {
                    var mesh = nodes[nodeIndex].GetComponent <SkinnedMeshRenderer>().sharedMesh;
                    elementCount = mesh.blendShapeCount;
                }
                else
                {
                    elementCount = glTFAnimationTarget.GetElementCount(property);
                }

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

                // 全てのキーフレームを回収
                int   elementOffset = 0;
                float valueFactor   = 1.0f;
                if (property == glTFAnimationTarget.AnimationProperties.BlendShape)
                {
                    var mesh           = nodes[nodeIndex].GetComponent <SkinnedMeshRenderer>().sharedMesh;
                    var blendShapeName = binding.propertyName.Replace("blendShape.", "");
                    elementOffset = mesh.GetBlendShapeIndex(blendShapeName);
                    valueFactor   = 0.01f;
                }
                else
                {
                    elementOffset = AnimationExporter.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 curveDatum)
            {
                if (curve.Keyframes.Count == 0)
                {
                    continue;
                }

                curve.RecountEmptyKeyframe();

                var elementNum = curve.Keyframes.First().Values.Length;
                var values     = default(InputOutputValues);
                if (!animation.SamplerMap.TryGetValue(curve.SamplerIndex, out values))
                {
                    values        = new InputOutputValues();
                    values.Input  = new float[curve.Keyframes.Count];
                    values.Output = new float[curve.Keyframes.Count * elementNum];
                    animation.SamplerMap[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++;
                }
            }
#endif

            return(animation);
        }