Esempio n. 1
0
        private bool IsAnEmptyAnimation(BabylonAnimation babylonAnimation)
        {
            if (babylonAnimation.keys == null)
            {
                return(true);
            }
            if (babylonAnimation.keys.Length == 0)
            {
                return(true);
            }

            var defaultValue = babylonAnimation.keysFull[0];

            foreach (var animKey in babylonAnimation.keysFull)
            {
                for (int i = 0; i < animKey.values.Length; i++)
                {
                    if (!animKey.values[i].IsEqualTo(defaultValue.values[i]))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Esempio n. 2
0
        private GLTFAccessor _createAndPopulateInput(GLTF gltf, BabylonAnimation babylonAnimation)
        {
            var buffer        = GLTFBufferService.Instance.GetBuffer(gltf);
            var accessorInput = GLTFBufferService.Instance.CreateAccessor(
                gltf,
                GLTFBufferService.Instance.GetBufferViewAnimationFloatScalar(gltf, buffer),
                "accessorAnimationInput",
                GLTFAccessor.ComponentType.FLOAT,
                GLTFAccessor.TypeEnum.SCALAR
                );

            // Populate accessor
            accessorInput.min = new float[] { float.MaxValue };
            accessorInput.max = new float[] { float.MinValue };
            foreach (var babylonAnimationKey in babylonAnimation.keys)
            {
                var inputValue = babylonAnimationKey.frame / FPS_FACTOR;
                // Store values as bytes
                accessorInput.bytesList.AddRange(BitConverter.GetBytes(inputValue));
                // Update min and max values
                GLTFBufferService.UpdateMinMaxAccessor(accessorInput, inputValue);
            }
            ;
            accessorInput.count = babylonAnimation.keys.Length;
            return(accessorInput);
        }
Esempio n. 3
0
        private static bool ExportBabylonKeys(List <BabylonAnimationKey> keys, string property, List <BabylonAnimation> animations, BabylonAnimation.DataType dataType, BabylonAnimation.LoopBehavior loopBehavior)
        {
            if (keys.Count == 0)
            {
                return(false);
            }

            var end = Loader.Core.AnimRange.End;

            if (keys[keys.Count - 1].frame != end / Loader.Global.TicksPerFrame)
            {
                keys.Add(new BabylonAnimationKey()
                {
                    frame  = end / Loader.Global.TicksPerFrame,
                    values = keys[keys.Count - 1].values
                });
            }

            var babylonAnimation = new BabylonAnimation
            {
                dataType       = (int)dataType,
                name           = property + " animation",
                keys           = keys.ToArray(),
                framePerSecond = Loader.Global.FrameRate,
                loopBehavior   = (int)loopBehavior,
                property       = property
            };

            animations.Add(babylonAnimation);

            return(true);
        }
        private static void ExportAnimation(string property, List <BabylonAnimation> animations, Func <int, float[]> extractValueFunc, BabylonAnimation.DataType dataType)
        {
            var start = Loader.Core.AnimRange.Start;
            var end   = Loader.Core.AnimRange.End;

            float[] previous = null;
            var     keys     = new List <BabylonAnimationKey>();

            for (var key = start; key <= end; key += Ticks)
            {
                var current = extractValueFunc(key);


                keys.Add(new BabylonAnimationKey()
                {
                    frame  = key / Ticks,
                    values = current
                });


                previous = current;
            }
            RemoveLinearAnimationKeys(keys);
            if (keys.Count > 0)
            {
                var animationPresent = true;

                if (keys.Count == 2)
                {
                    if (keys[0].values.IsEqualTo(keys[1].values))
                    {
                        animationPresent = false;
                    }
                }

                if (animationPresent)
                {
                    if (keys[keys.Count - 1].frame != end / Ticks)
                    {
                        keys.Add(new BabylonAnimationKey()
                        {
                            frame  = end / Ticks,
                            values = keys[keys.Count - 1].values
                        });
                    }

                    var babylonAnimation = new BabylonAnimation
                    {
                        dataType       = dataType,
                        name           = property + " animation",
                        keys           = keys.ToArray(),
                        framePerSecond = Loader.Global.FrameRate,
                        loopBehavior   = BabylonAnimation.LoopBehavior.Cycle,
                        property       = property
                    };

                    animations.Add(babylonAnimation);
                }
            }
        }
Esempio n. 5
0
        private IList <BabylonAnimation> GetSubAnimations(BabylonBone babylonBone, float from, float to)
        {
            IList <BabylonAnimation> subAnimations = new List <BabylonAnimation>();

            // clone the animation
            BabylonAnimation animation = (BabylonAnimation)babylonBone.animation.Clone();

            // Select usefull keys
            var keys = animation.keysFull = animation.keysFull.FindAll(k => from <= k.frame && k.frame <= to);

            // Optimize these keys
            if (optimizeAnimations)
            {
                OptimizeAnimations(keys, true, out int keyRemovedCount);
                if (keyRemovedCount > 0)
                {
                    logger?.RaiseMessage("Optimization | Removed " + keyRemovedCount + " keys from the animation '" + animation.property + "' of '" + babylonBone.name + "'");
                }
            }
            //
            animation.keys = keys.ToArray();
            subAnimations.Add(animation);

            return(subAnimations);
        }
Esempio n. 6
0
        private IList <BabylonAnimation> GetSubAnimations(BabylonNode babylonNode, float from, float to)
        {
            IList <BabylonAnimation> subAnimations = new List <BabylonAnimation>();

            foreach (BabylonAnimation nodeAnimation in babylonNode.animations)
            {
                // clone the animation
                BabylonAnimation animation = (BabylonAnimation)nodeAnimation.Clone();

                // Select usefull keys
                var keys = animation.keysFull = animation.keysFull.FindAll(k => from <= k.frame && k.frame <= to);

                // Optimize these keys
                if (optimizeAnimations)
                {
                    OptimizeAnimations(keys, true);
                }

                //
                animation.keys = keys.ToArray();
                subAnimations.Add(animation);
            }

            return(subAnimations);
        }
Esempio n. 7
0
        private BabylonAnimation CreateMatrixAnimation(float from, float to, float[] matrix)
        {
            BabylonAnimation animation = new BabylonAnimation
            {
                name           = "_matrix animation",
                property       = "_matrix",
                dataType       = 3,
                loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                framePerSecond = Loader.Global.FrameRate,
                keysFull       = new List <BabylonAnimationKey>()
            };

            animation.keysFull.Add(new BabylonAnimationKey
            {
                frame  = (int)from,
                values = matrix
            });
            animation.keysFull.Add(new BabylonAnimationKey
            {
                frame  = (int)from,
                values = matrix
            });

            animation.keys = animation.keysFull.ToArray();

            return(animation);
        }
Esempio n. 8
0
        private BabylonAnimation CreatePositionAnimation(float from, float to, float[] position)
        {
            BabylonAnimation animation = new BabylonAnimation
            {
                name           = "position animation",
                property       = "position",
                dataType       = 1,
                loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                framePerSecond = Loader.GetFPS(),
                keysFull       = new List <BabylonAnimationKey>()
            };

            animation.keysFull.Add(new BabylonAnimationKey
            {
                frame  = (int)from,
                values = position
            });
            animation.keysFull.Add(new BabylonAnimationKey
            {
                frame  = (int)to,
                values = position
            });

            animation.keys = animation.keysFull.ToArray();

            return(animation);
        }
Esempio n. 9
0
        private BabylonAnimation ExportAnimation(string property, Func <int, float[]> extractValueFunc, BabylonAnimation.DataType dataType, bool removeLinearAnimationKeys = true, bool optimizeAnimations = false, string name = null)
        {
            var start = Loader.Core.AnimRange.Start;
            var end   = Loader.Core.AnimRange.End;

            float[] previous = null;
            var     keys     = new List <BabylonAnimationKey>();

            for (var key = start; key <= end; key += Loader.Global.TicksPerFrame)
            {
                var current = extractValueFunc(key);

                keys.Add(new BabylonAnimationKey()
                {
                    frame  = key / Loader.Global.TicksPerFrame,
                    values = current
                });

                previous = current;
            }
            var keysFull = new List <BabylonAnimationKey>(keys);

            // Optimization process always keeps first and last frames
            if (optimizeAnimations)
            {
                OptimizeAnimations(keys, removeLinearAnimationKeys, out int keyRemovedCount);
                if (keyRemovedCount > 0)
                {
                    logger?.RaiseMessage("Optimization | Removed " + keyRemovedCount + " keys from the animation '" + property + "' of '" + (name == null ? "" : name) + "'");
                }
            }

            if (IsAnimationKeysRelevant(keys))
            {
                if (keys[keys.Count - 1].frame != end / Loader.Global.TicksPerFrame)
                {
                    keys.Add(new BabylonAnimationKey()
                    {
                        frame  = end / Loader.Global.TicksPerFrame,
                        values = (float[])keys[keys.Count - 1].values.Clone()
                    });
                }

                var babylonAnimation = new BabylonAnimation
                {
                    dataType       = (int)dataType,
                    name           = property + " animation",
                    keys           = keys.ToArray(),
                    keysFull       = keysFull,
                    framePerSecond = Loader.Global.FrameRate,
                    loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                    property       = property
                };
                return(babylonAnimation);
            }
            return(null);
        }
Esempio n. 10
0
        private BabylonAnimation GetAnimationsFrameByFrameMatrix(MFnTransform mFnTransform)
        {
            int start = GetMinTime()[0];
            int end   = GetMaxTime()[0];
            BabylonAnimation animation = null;

            // get keys
            List <BabylonAnimationKey> keys = new List <BabylonAnimationKey>();

            for (int currentFrame = start; currentFrame <= end; currentFrame++)
            {
                // Set the animation key
                BabylonAnimationKey key = new BabylonAnimationKey()
                {
                    frame  = currentFrame,
                    values = GetBabylonMatrix(mFnTransform, currentFrame).m.ToArray()
                };

                keys.Add(key);
            }

            // Optimization
            OptimizeAnimations(keys, false); // Do not remove linear animation keys for bones

            // Ensure animation has at least 2 frames
            if (keys.Count > 1)
            {
                var animationPresent = true;

                // Ensure animation has at least 2 non equal frames
                if (keys.Count == 2)
                {
                    if (keys[0].values.IsEqualTo(keys[1].values))
                    {
                        animationPresent = false;
                    }
                }

                if (animationPresent)
                {
                    // Create BabylonAnimation
                    // Animations
                    animation = new BabylonAnimation()
                    {
                        name           = mFnTransform.name + "Animation", // override default animation name
                        dataType       = (int)BabylonAnimation.DataType.Matrix,
                        loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                        framePerSecond = GetFPS(),
                        keys           = keys.ToArray(),
                        property       = "_matrix"
                    };
                }
            }

            return(animation);
        }
Esempio n. 11
0
        private BabylonAnimation ExportAnimation(string property, Func <int, float[]> extractValueFunc, BabylonAnimation.DataType dataType, bool removeLinearAnimationKeys = true)
        {
            var optimizeAnimations = !Loader.Core.RootNode.GetBoolProperty("babylonjs_donotoptimizeanimations"); // reverse negation for clarity

            var start = Loader.Core.AnimRange.Start;
            var end   = Loader.Core.AnimRange.End;

            float[] previous = null;
            var     keys     = new List <BabylonAnimationKey>();

            for (var key = start; key <= end; key += Loader.Global.TicksPerFrame)
            {
                var current = extractValueFunc(key);

                keys.Add(new BabylonAnimationKey()
                {
                    frame  = key / Loader.Global.TicksPerFrame,
                    values = current
                });

                previous = current;
            }
            var keysFull = new List <BabylonAnimationKey>(keys);

            // Optimization process always keeps first and last frames
            if (optimizeAnimations)
            {
                OptimizeAnimations(keys, removeLinearAnimationKeys);
            }

            if (IsAnimationKeysRelevant(keys))
            {
                if (keys[keys.Count - 1].frame != end / Loader.Global.TicksPerFrame)
                {
                    keys.Add(new BabylonAnimationKey()
                    {
                        frame  = end / Loader.Global.TicksPerFrame,
                        values = (float[])keys[keys.Count - 1].values.Clone()
                    });
                }

                var babylonAnimation = new BabylonAnimation
                {
                    dataType       = (int)dataType,
                    name           = property + " animation",
                    keys           = keys.ToArray(),
                    keysFull       = keysFull,
                    framePerSecond = Loader.Global.FrameRate,
                    loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                    property       = property
                };
                return(babylonAnimation);
            }
            return(null);
        }
Esempio n. 12
0
        private static void ExportSkeletonAnimationClipData(Animator animator, bool autoPlay, BabylonSkeleton skeleton, Transform[] bones, BabylonMesh babylonMesh, AnimationClip clip)
        {
            var frameTime           = 1.0f / clip.frameRate;
            int animationFrameCount = (int)(clip.length * clip.frameRate);

            if (autoPlay)
            {
                babylonMesh.autoAnimate     = true;
                babylonMesh.autoAnimateFrom = 0;
                babylonMesh.autoAnimateTo   = animationFrameCount;
                babylonMesh.autoAnimateLoop = true;
            }

            foreach (var bone in skeleton.bones)
            {
                var keys      = new List <BabylonAnimationKey>();
                var transform = bones.Single(b => b.name == bone.name);

                AnimationMode.BeginSampling();
                for (var i = 0; i < animationFrameCount; i++)
                {
                    clip.SampleAnimation(animator.gameObject, i * frameTime);

                    var     local  = (transform.parent.localToWorldMatrix.inverse * transform.localToWorldMatrix);
                    float[] matrix = new[] {
                        local[0, 0], local[1, 0], local[2, 0], local[3, 0],
                        local[0, 1], local[1, 1], local[2, 1], local[3, 1],
                        local[0, 2], local[1, 2], local[2, 2], local[3, 2],
                        local[0, 3], local[1, 3], local[2, 3], local[3, 3]
                    };

                    var key = new BabylonAnimationKey
                    {
                        frame  = i,
                        values = matrix,
                    };
                    keys.Add(key);
                }
                AnimationMode.EndSampling();

                var babylonAnimation = new BabylonAnimation
                {
                    name           = bone.name + "Animation",
                    property       = "_matrix",
                    dataType       = (int)BabylonAnimation.DataType.Matrix,
                    loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = (int)clip.frameRate,
                    keys           = keys.ToArray()
                };

                bone.animation = babylonAnimation;
            }
        }
Esempio n. 13
0
 public void RemoveStaticAnimations(ref IList <BabylonAnimation> babylonAnimations)
 {
     for (int i = babylonAnimations.Count - 1; i >= 0; i--)
     {
         BabylonAnimation anim = babylonAnimations[i];
         if (IsAnEmptyAnimation(anim))
         {
             logger?.RaiseMessage("Optimization | " + anim.name + " was removed ");
             babylonAnimations.RemoveAt(i);
         }
     }
 }
Esempio n. 14
0
        private GLTFAccessor _createAndPopulateInput(GLTF gltf, BabylonAnimation babylonAnimation, int startFrame, int endFrame, bool offsetToStartAtFrameZero = true)
        {
            var buffer        = GLTFBufferService.Instance.GetBuffer(gltf);
            var accessorInput = GLTFBufferService.Instance.CreateAccessor(
                gltf,
                GLTFBufferService.Instance.GetBufferViewAnimationFloatScalar(gltf, buffer),
                "accessorAnimationInput",
                GLTFAccessor.ComponentType.FLOAT,
                GLTFAccessor.TypeEnum.SCALAR
                );

            // Populate accessor
            accessorInput.min = new float[] { float.MaxValue };
            accessorInput.max = new float[] { float.MinValue };

            int numKeys = 0;

            foreach (var babylonAnimationKey in babylonAnimation.keys)
            {
                if (babylonAnimationKey.frame < startFrame)
                {
                    continue;
                }

                if (babylonAnimationKey.frame > endFrame)
                {
                    continue;
                }

                numKeys++;
                float inputValue = babylonAnimationKey.frame;
                if (offsetToStartAtFrameZero)
                {
                    inputValue -= startFrame;
                }
                inputValue /= Loader.Global.FrameRate;
                // Store values as bytes
                accessorInput.bytesList.AddRange(BitConverter.GetBytes(inputValue));
                // Update min and max values
                GLTFBufferService.UpdateMinMaxAccessor(accessorInput, inputValue);
            }
            ;
            accessorInput.count = numKeys;

            // bail out if there are no keys
            // todo [KeyInterpolation]: bail out only when there are no keyframes at all (?) and otherwise add the appropriate (interpolated) keyframes
            if (numKeys == 0)
            {
                return(null);
            }

            return(accessorInput);
        }
Esempio n. 15
0
        /// <summary>
        /// Export the morph target influence animation.
        /// </summary>
        /// <param name="blendShapeDeformerName"></param>
        /// <param name="weightIndex"></param>
        /// <returns>A list containing all animations</returns>
        private IList <BabylonAnimation> GetAnimationsInfluence(string blendShapeDeformerName, int weightIndex)
        {
            IList <BabylonAnimation> animations = new List <BabylonAnimation>();
            BabylonAnimation         animation  = null;

            IDictionary <double, IList <double> > morphWeights = GetMorphWeightsByFrame(blendShapeDeformerName);

            // get keys
            List <BabylonAnimationKey> keys = new List <BabylonAnimationKey>();

            for (int index = 0; index < morphWeights.Count; index++)
            {
                KeyValuePair <double, IList <double> > keyValue = morphWeights.ElementAt(index);
                // Set the animation key
                BabylonAnimationKey key = new BabylonAnimationKey()
                {
                    frame  = (int)keyValue.Key,
                    values = new float[] { (float)keyValue.Value[weightIndex] }
                };

                keys.Add(key);
            }

            List <BabylonAnimationKey> keysFull = new List <BabylonAnimationKey>(keys);

            // Optimization
            OptimizeAnimations(keys, false);

            // Ensure animation has at least 2 frames
            if (IsAnimationKeysRelevant(keys))
            {
                // Animations
                animation = new BabylonAnimation()
                {
                    name           = "influence animation", // override default animation name
                    dataType       = (int)BabylonAnimation.DataType.Float,
                    loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = Loader.GetFPS(),
                    keys           = keys.ToArray(),
                    keysFull       = keysFull,
                    property       = "influence"
                };

                animations.Add(animation);
            }

            return(animations);
        }
Esempio n. 16
0
        private GLTFAccessor _createAndPopulateInput(GLTF gltf, BabylonAnimation babylonAnimation, int startFrame, int endFrame, bool offsetToStartAtFrameZero = true)
        {
            var babylonAnimationKeysInRange = babylonAnimation.keys.Where(key => key.frame >= startFrame && key.frame <= endFrame);

            if (babylonAnimationKeysInRange.Count() <= 0) // do not make empty accessors, so bail out.
            {
                return(null);
            }

            var buffer        = GLTFBufferService.Instance.GetBuffer(gltf);
            var accessorInput = GLTFBufferService.Instance.CreateAccessor(
                gltf,
                GLTFBufferService.Instance.GetBufferViewAnimationFloatScalar(gltf, buffer),
                "accessorAnimationInput",
                GLTFAccessor.ComponentType.FLOAT,
                GLTFAccessor.TypeEnum.SCALAR
                );

            // Populate accessor
            accessorInput.min = new float[] { float.MaxValue };
            accessorInput.max = new float[] { float.MinValue };

            int numKeys = 0;

            foreach (var babylonAnimationKey in babylonAnimationKeysInRange)
            {
                numKeys++;
                float inputValue = babylonAnimationKey.frame;
                if (offsetToStartAtFrameZero)
                {
                    inputValue -= startFrame;
                }
                inputValue /= babylonAnimation.framePerSecond;
                // Store values as bytes
                accessorInput.bytesList.AddRange(BitConverter.GetBytes(inputValue));
                // Update min and max values
                GLTFBufferService.UpdateMinMaxAccessor(accessorInput, inputValue);
            }
            ;
            accessorInput.count = numKeys;

            if (accessorInput.count == 0)
            {
                logger.RaiseWarning(String.Format("GLTFExporter.Animation | No input frames in GLTF Accessor for animation \"{0}\". This will cause an error in the output gltf.", babylonAnimation.name));
            }

            return(accessorInput);
        }
Esempio n. 17
0
        /// <summary>
        /// Using MEL commands, it return the babylon animation
        /// </summary>
        /// <param name="objectName">The name of the Maya object</param>
        /// <param name="mayaProperty">The attribut in Maya</param>
        /// <param name="babylonProperty">The attribut in Babylon</param>
        /// <returns>A Babylon animation that represents the Maya animation</returns>
        public BabylonAnimation GetAnimationFloat(string objectName, string mayaProperty, string babylonProperty)
        {
            // Get keyframes
            IList <double>   keyframes = GetKeyframes(objectName);
            BabylonAnimation animation = null;

            // set the key for each keyframe
            List <BabylonAnimationKey> keys = new List <BabylonAnimationKey>();

            for (int index = 0; index < keyframes.Count; index++)
            {
                double keyframe = keyframes[index];
                MGlobal.executeCommand($"getAttr -t {keyframe} {objectName}.{mayaProperty}", out double value);

                // Set the animation key
                BabylonAnimationKey key = new BabylonAnimationKey()
                {
                    frame  = (int)keyframe,
                    values = new float[] { (float)value }
                };

                keys.Add(key);
            }

            List <BabylonAnimationKey> keysFull = new List <BabylonAnimationKey>(keys);

            // Optimization
            OptimizeAnimations(keys, false);

            // Ensure animation has at least 2 frames
            if (IsAnimationKeysRelevant(keys))
            {
                // Animations
                animation = new BabylonAnimation()
                {
                    name           = $"{babylonProperty} animation", // override default animation name
                    dataType       = (int)BabylonAnimation.DataType.Float,
                    loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = Loader.GetFPS(),
                    keys           = keys.ToArray(),
                    keysFull       = keysFull,
                    property       = babylonProperty
                };
            }

            return(animation);
        }
Esempio n. 18
0
        private BabylonAnimation GetAnimationsFrameByFrameMatrix(MFnTransform mFnTransform)
        {
            int start = Loader.GetMinTime();
            int end   = Loader.GetMaxTime();
            BabylonAnimation animation = null;

            // get keys
            List <BabylonAnimationKey> keys = new List <BabylonAnimationKey>();

            for (int currentFrame = start; currentFrame <= end; currentFrame++)
            {
                // Set the animation key
                BabylonAnimationKey key = new BabylonAnimationKey()
                {
                    frame  = currentFrame,
                    values = GetBabylonMatrix(mFnTransform, currentFrame).m.ToArray()
                };

                keys.Add(key);
            }

            var keysFull = new List <BabylonAnimationKey>(keys);

            // Optimization
            OptimizeAnimations(keys, false); // Do not remove linear animation keys for bones

            // Ensure animation has at least 2 frames
            if (IsAnimationKeysRelevant(keys))
            {
                // Animations
                animation = new BabylonAnimation()
                {
                    name           = mFnTransform.name + "Animation", // override default animation name
                    dataType       = (int)BabylonAnimation.DataType.Matrix,
                    loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = Loader.GetFPS(),
                    keys           = keys.ToArray(),
                    keysFull       = keysFull,
                    property       = "_matrix"
                };
            }

            return(animation);
        }
Esempio n. 19
0
        private IList <BabylonAnimation> GetSubAnimations(BabylonBone babylonBone, float from, float to)
        {
            IList <BabylonAnimation> subAnimations = new List <BabylonAnimation>();

            // clone the animation
            BabylonAnimation animation = (BabylonAnimation)babylonBone.animation.Clone();

            // Select usefull keys
            var keys = animation.keysFull = animation.keysFull.FindAll(k => from <= k.frame && k.frame <= to);

            // Optimize these keys
            OptimizeAnimations(keys, false);

            //
            animation.keys = keys.ToArray();
            subAnimations.Add(animation);

            return(subAnimations);
        }
Esempio n. 20
0
        private void SetNodePosition(ref BabylonNode node, ref BabylonScene babylonScene, float[] newPosition)
        {
            float[] offset = new float[] { newPosition[0] - node.position[0], newPosition[1] - node.position[1], newPosition[2] - node.position[2] };
            node.position = newPosition;

            List <BabylonAnimation> animations        = new List <BabylonAnimation>(node.animations);
            BabylonAnimation        animationPosition = animations.Find(animation => animation.property.Equals("position"));

            if (animationPosition != null)
            {
                foreach (BabylonAnimationKey key in animationPosition.keys)
                {
                    key.values = new float[] {
                        key.values[0] + offset[0],
                        key.values[1] + offset[1],
                        key.values[2] + offset[2]
                    };
                }
            }
        }
Esempio n. 21
0
        bool DumpInterpolator(string name, string property, NovaFloatInterpolator interpolator, NovaScene scene, List <BabylonAnimation> animations, float mult = 1.0f)
        {
            if (interpolator.Ready && !IsInterpolatorIsEmpty(interpolator))
            {
                var fps = scene.AnimationFramerate < 1 ? 30 : scene.AnimationFramerate;
                var babylonAnimation = new BabylonAnimation {
                    name = name, property = property, dataType = BabylonAnimation.DataType.Float, framePerSecond = fps
                };

                babylonAnimation.keys = interpolator.Datas.Select(value => new BabylonAnimationKey {
                    frame = value.Key / scene.AnimationKeyStep, values = new[] { value.Value *mult }
                }).ToArray();

                babylonAnimation.loopBehavior = interpolator.LoopAfter;

                animations.Add(babylonAnimation);
                return(true);
            }

            return(false);
        }
Esempio n. 22
0
        bool DumpInterpolator(string name, string property, NovaQuaternionInterpolator interpolator, NovaScene scene, List <BabylonAnimation> animations)
        {
            if (interpolator.Ready)
            {
                var fps = scene.AnimationFramerate < 1 ? 30 : scene.AnimationFramerate;
                var babylonAnimation = new BabylonAnimation {
                    name = name, property = property, dataType = BabylonAnimation.DataType.Quaternion, framePerSecond = fps
                };

                babylonAnimation.keys = interpolator.Datas.Select(value => new BabylonAnimationKey {
                    frame = value.Key / scene.AnimationKeyStep, values = value.Value.ToArray()
                }).ToArray();

                babylonAnimation.loopBehavior = interpolator.LoopAfter;

                animations.Add(babylonAnimation);
                return(true);
            }

            return(false);
        }
Esempio n. 23
0
        private IList <BabylonAnimation> GetSubAnimations(BabylonMorphTarget babylonMorphTarget, float from, float to)
        {
            IList <BabylonAnimation> subAnimations = new List <BabylonAnimation>();

            foreach (BabylonAnimation morphTargetAnimation in babylonMorphTarget.animations)
            {
                // clone the animation
                BabylonAnimation animation = (BabylonAnimation)morphTargetAnimation.Clone();

                // Select usefull keys
                var keys = animation.keysFull.FindAll(k => from <= k.frame && k.frame <= to);

                bool keysInRangeAreRelevant = true;

                // Optimize these keys
                if (exportParameters.optimizeAnimations)
                {
                    // Optimize these keys
                    OptimizeAnimations(keys, true);
                    keysInRangeAreRelevant = IsAnimationKeysRelevant(keys, animation.property);

                    // if we are baking the animation frames, then do a less efficient check against all frames in the scene for this animation channel if the first check fails.
                    if (!keysInRangeAreRelevant && exportParameters.bakeAnimationFrames)
                    {
                        List <BabylonAnimationKey> optimizedKeysFull = new List <BabylonAnimationKey>(animation.keysFull);
                        OptimizeAnimations(optimizedKeysFull, true);
                        keysInRangeAreRelevant = IsAnimationKeysRelevant(optimizedKeysFull, animation.property);
                    }
                }

                // If animation keys should be included in export, add to animation list.
                if (keysInRangeAreRelevant)
                {
                    animation.keys = keys.ToArray();
                    subAnimations.Add(animation);
                }
            }

            return(subAnimations);
        }
Esempio n. 24
0
        private BabylonAnimation GetDummyAnimation(GLTFNode gltfNode, int startFrame, int endFrame)
        {
            BabylonAnimation dummyAnimation = new BabylonAnimation();

            dummyAnimation.name           = "Dummy";
            dummyAnimation.property       = "scaling";
            dummyAnimation.framePerSecond = Loader.Global.FrameRate;
            dummyAnimation.dataType       = (int)BabylonAnimation.DataType.Vector3;

            BabylonAnimationKey startKey = new BabylonAnimationKey();

            startKey.frame  = startFrame;
            startKey.values = gltfNode.scale;

            BabylonAnimationKey endKey = new BabylonAnimationKey();

            endKey.frame  = endFrame;
            endKey.values = gltfNode.scale;

            dummyAnimation.keys = new BabylonAnimationKey[] { startKey, endKey };

            return(dummyAnimation);
        }
Esempio n. 25
0
        public BabylonAnimation GetDummyAnimation(GLTFNode gltfNode, int startFrame, int endFrame, BabylonScene babylonScene)
        {
            BabylonAnimation dummyAnimation = new BabylonAnimation();

            dummyAnimation.name           = "Dummy";
            dummyAnimation.property       = "scaling";
            dummyAnimation.framePerSecond = babylonScene.TimelineFramesPerSecond;
            dummyAnimation.dataType       = (int)BabylonAnimation.DataType.Vector3;

            BabylonAnimationKey startKey = new BabylonAnimationKey();

            startKey.frame  = startFrame;
            startKey.values = gltfNode.scale;

            BabylonAnimationKey endKey = new BabylonAnimationKey();

            endKey.frame  = endFrame;
            endKey.values = gltfNode.scale;

            dummyAnimation.keys = new BabylonAnimationKey[] { startKey, endKey };

            return(dummyAnimation);
        }
Esempio n. 26
0
        private void ParseAnimationClip(SkinningData skinningData, BabylonSkeleton skeleton)
        {
            foreach (var clipKey in skinningData.AnimationClips.Keys)
            {
                var clip     = skinningData.AnimationClips[clipKey];
                var duration = clip.Duration.TotalMilliseconds;
                var dic      = new Dictionary <int, List <BabylonAnimationKey> >();

                foreach (var keyframe in clip.Keyframes)
                {
                    if (!dic.ContainsKey(keyframe.Bone))
                    {
                        dic.Add(keyframe.Bone, new List <BabylonAnimationKey>());
                    }

                    var currentTime = (float)(keyframe.Time.TotalMilliseconds * 100.0 / duration);

                    dic[keyframe.Bone].Add(new BabylonAnimationKey
                    {
                        frame  = currentTime,
                        values = keyframe.Transform.ToMatrix().ToArray()
                    });
                }

                foreach (var index in dic.Keys)
                {
                    var bone             = skeleton.bones[index];
                    var babylonAnimation = new BabylonAnimation {
                        name = bone.name + "Animation", property = "_matrix", dataType = BabylonAnimation.DataType.Matrix, loopBehavior = InterpolationLoop.Cycle, framePerSecond = 60
                    };
                    babylonAnimation.keys = dic[index].ToArray();
                    bone.animation        = babylonAnimation;
                }

                return; // Only one animation track
            }
        }
        private static BabylonAnimation ExportAnimation(string property, Func <int, float[]> extractValueFunc, BabylonAnimation.DataType dataType, bool removeLinearAnimationKeys = true)
        {
            var optimizeAnimations = !Loader.Core.RootNode.GetBoolProperty("babylonjs_donotoptimizeanimations"); // reverse negation for clarity

            var start = Loader.Core.AnimRange.Start;
            var end   = Loader.Core.AnimRange.End;

            float[] previous = null;
            var     keys     = new List <BabylonAnimationKey>();

            for (var key = start; key <= end; key += Ticks)
            {
                var current = extractValueFunc(key);

                keys.Add(new BabylonAnimationKey()
                {
                    frame  = key / Ticks,
                    values = current
                });

                previous = current;
            }

            if (optimizeAnimations)
            {
                OptimizeAnimations(keys, removeLinearAnimationKeys);
            }

            if (keys.Count > 1)
            {
                var animationPresent = true;

                if (keys.Count == 2)
                {
                    if (keys[0].values.IsEqualTo(keys[1].values))
                    {
                        animationPresent = false;
                    }
                }

                if (animationPresent)
                {
                    if (keys[keys.Count - 1].frame != end / Ticks)
                    {
                        keys.Add(new BabylonAnimationKey()
                        {
                            frame  = end / Ticks,
                            values = keys[keys.Count - 1].values
                        });
                    }

                    var babylonAnimation = new BabylonAnimation
                    {
                        dataType       = (int)dataType,
                        name           = property + " animation",
                        keys           = keys.ToArray(),
                        framePerSecond = Loader.Global.FrameRate,
                        loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                        property       = property
                    };
                    return(babylonAnimation);
                }
            }
            return(null);
        }
Esempio n. 28
0
        private static void ExportAnimation(string property, List <BabylonAnimation> animations, Func <int, float[]> extractValueFunc, BabylonAnimation.DataType dataType)
        {
            var exportNonOptimizedAnimations = Loader.Core.RootNode.GetBoolProperty("babylonjs_exportnonoptimizedanimations");

            var start = Loader.Core.AnimRange.Start;
            var end   = Loader.Core.AnimRange.End;

            float[] previous = null;
            var     keys     = new List <BabylonAnimationKey>();

            for (var key = start; key <= end; key += Ticks)
            {
                var current = extractValueFunc(key);

                if (exportNonOptimizedAnimations && previous != null && previous.IsEqualTo(current))
                {
                    continue; // Do not add key
                }

                keys.Add(new BabylonAnimationKey()
                {
                    frame  = key / Ticks,
                    values = current
                });

                previous = current;
            }

            if (!exportNonOptimizedAnimations)
            {
                RemoveLinearAnimationKeys(keys);
            }

            if (keys.Count > 1)
            {
                var animationPresent = true;

                if (keys.Count == 2)
                {
                    if (keys[0].values.IsEqualTo(keys[1].values))
                    {
                        animationPresent = false;
                    }
                }

                if (animationPresent)
                {
                    if (keys[keys.Count - 1].frame != end / Ticks)
                    {
                        keys.Add(new BabylonAnimationKey()
                        {
                            frame  = end / Ticks,
                            values = keys[keys.Count - 1].values
                        });
                    }

                    var babylonAnimation = new BabylonAnimation
                    {
                        dataType       = (int)dataType,
                        name           = property + " animation",
                        keys           = keys.ToArray(),
                        framePerSecond = Loader.Global.FrameRate,
                        loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                        property       = property
                    };

                    animations.Add(babylonAnimation);
                }
            }
        }
Esempio n. 29
0
        private static bool ExportController(IControl control, string property, List <BabylonAnimation> animations, uint classId, BabylonAnimation.DataType dataType, Func <int, IIKeyControl, BabylonAnimationKey> generateFunc)
        {
            if (control == null)
            {
                return(false);
            }

            var keyControl = control.GetInterface(InterfaceID.Keycontrol) as IIKeyControl;

            if (keyControl == null)
            {
                return(false);
            }

            if (control.ClassID.PartA != classId)
            {
                return(false);
            }

            var keys = new List <BabylonAnimationKey>();

            BabylonAnimation.LoopBehavior loopBehavior;

            switch (control.GetORT(2))
            {
            case 2:
                loopBehavior = BabylonAnimation.LoopBehavior.Cycle;
                break;

            default:
                loopBehavior = BabylonAnimation.LoopBehavior.Relative;
                break;
            }

            for (var index = 0; index < keyControl.NumKeys; index++)
            {
                keys.Add(generateFunc(index, keyControl));
            }

            if (keys.Count == 0)
            {
                return(false);
            }

            var end = Loader.Core.AnimRange.End;

            if (keys[keys.Count - 1].frame != end / Ticks)
            {
                keys.Add(new BabylonAnimationKey()
                {
                    frame  = end / Ticks,
                    values = keys[keys.Count - 1].values
                });
            }

            var babylonAnimation = new BabylonAnimation
            {
                dataType       = (int)dataType,
                name           = property + " animation",
                keys           = keys.ToArray(),
                framePerSecond = Loader.Global.FrameRate,
                loopBehavior   = (int)loopBehavior,
                property       = property
            };

            animations.Add(babylonAnimation);

            return(true);
        }
Esempio n. 30
0
        bool DumpInterpolator(string name, string property, NovaQuaternionInterpolator interpolator, NovaScene scene, List<BabylonAnimation> animations)
        {
            if (interpolator.Ready)
            {
                var fps = scene.AnimationFramerate < 1 ? 30 : scene.AnimationFramerate;
                var babylonAnimation = new BabylonAnimation { name = name, property = property, dataType = BabylonAnimation.DataType.Quaternion, framePerSecond = fps };

                babylonAnimation.keys = interpolator.Datas.Select(value => new BabylonAnimationKey { frame = value.Key / scene.AnimationKeyStep, values = value.Value.ToArray() }).ToArray();

                babylonAnimation.loopBehavior = interpolator.LoopAfter;

                animations.Add(babylonAnimation);
                return true;
            }

            return false;
        }
Esempio n. 31
0
        bool DumpInterpolator(string name, string property, NovaFloatInterpolator interpolator, NovaScene scene, List<BabylonAnimation> animations, float mult = 1.0f)
        {
            if (interpolator.Ready && !IsInterpolatorIsEmpty(interpolator))
            {
                var fps = scene.AnimationFramerate < 1 ? 30 : scene.AnimationFramerate;
                var babylonAnimation = new BabylonAnimation { name = name, property = property, dataType = BabylonAnimation.DataType.Float, framePerSecond = fps };

                babylonAnimation.keys = interpolator.Datas.Select(value => new BabylonAnimationKey { frame = value.Key / scene.AnimationKeyStep, values = new[] { value.Value * mult } }).ToArray();

                babylonAnimation.loopBehavior = interpolator.LoopAfter;

                animations.Add(babylonAnimation);
                return true;
            }

            return false;
        }
Esempio n. 32
0
        private void ParseAnimationClip(SkinningData skinningData, BabylonSkeleton skeleton)
        {
            foreach (var clipKey in skinningData.AnimationClips.Keys)
            {
                var clip = skinningData.AnimationClips[clipKey];
                var duration = clip.Duration.TotalMilliseconds;
                var dic = new Dictionary<int, List<BabylonAnimationKey>>();

                foreach (var keyframe in clip.Keyframes)
                {
                    if (!dic.ContainsKey(keyframe.Bone))
                    {
                        dic.Add(keyframe.Bone, new List<BabylonAnimationKey>());
                    }

                    var currentTime = (float)(keyframe.Time.TotalMilliseconds * 100.0 / duration);

                    dic[keyframe.Bone].Add(new BabylonAnimationKey
                    {
                        frame = currentTime,
                        values = keyframe.Transform.ToMatrix().ToArray()
                    });
                }

                foreach (var index in dic.Keys)
                {
                    var bone = skeleton.bones[index];
                    var babylonAnimation = new BabylonAnimation { name = bone.name + "Animation", property = "_matrix", dataType = BabylonAnimation.DataType.Matrix, loopBehavior = InterpolationLoop.Cycle, framePerSecond = 60 };
                    babylonAnimation.keys = dic[index].ToArray();
                    bone.animation = babylonAnimation;
                }

                return; // Only one animation track
            }
        }
Esempio n. 33
0
        /// <summary>
        /// In 3DS Max default element can look in different direction than the same default element in Babylon or in glTF.
        /// This function correct the node rotation.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="babylonScene"></param>
        /// <param name="angle"></param>
        private void FixNodeRotation(ref BabylonNode node, ref BabylonScene babylonScene, double angle)
        {
            string id = node.id;
            IList <BabylonMesh> meshes = babylonScene.MeshesList.FindAll(mesh => mesh.parentId == null ? false : mesh.parentId.Equals(id));

            RaiseMessage($"{node.name}", 2);

            // fix the vue
            // Rotation around the axis X of PI / 2 in the indirect direction for camera
            // double angle = Math.PI / 2; // for camera
            // double angle = -Math.PI / 2; // for light

            if (node.rotation != null)
            {
                node.rotation[0] += (float)angle;
            }
            if (node.rotationQuaternion != null)
            {
                BabylonQuaternion rotationQuaternion = FixCameraQuaternion(node, angle);

                node.rotationQuaternion = rotationQuaternion.ToArray();
                node.rotation           = rotationQuaternion.toEulerAngles().ToArray();
            }

            // animation
            List <BabylonAnimation> animations = new List <BabylonAnimation>(node.animations);
            BabylonAnimation        animationRotationQuaternion = animations.Find(animation => animation.property.Equals("rotationQuaternion"));

            if (animationRotationQuaternion != null)
            {
                foreach (BabylonAnimationKey key in animationRotationQuaternion.keys)
                {
                    key.values = FixCameraQuaternion(key.values, angle);
                }
            }
            else   // if the camera has a lockedTargetId, it is the extraAnimations that stores the rotation animation
            {
                if (node.extraAnimations != null)
                {
                    List <BabylonAnimation> extraAnimations = new List <BabylonAnimation>(node.extraAnimations);
                    animationRotationQuaternion = extraAnimations.Find(animation => animation.property.Equals("rotationQuaternion"));
                    if (animationRotationQuaternion != null)
                    {
                        foreach (BabylonAnimationKey key in animationRotationQuaternion.keys)
                        {
                            key.values = FixCameraQuaternion(key.values, angle);
                        }
                    }
                }
            }

            // fix direct children
            // Rotation around the axis X of -PI / 2 in the direct direction for camera children
            angle = -angle;
            foreach (var mesh in meshes)
            {
                RaiseVerbose($"{mesh.name}", 3);
                mesh.position = new float[] { mesh.position[0], mesh.position[2], -mesh.position[1] };

                // Add a rotation of PI/2 axis X in direct direction
                if (mesh.rotationQuaternion != null)
                {
                    // Rotation around the axis X of -PI / 2 in the direct direction
                    BabylonQuaternion quaternion = FixChildQuaternion(mesh, angle);

                    mesh.rotationQuaternion = quaternion.ToArray();
                }
                if (mesh.rotation != null)
                {
                    mesh.rotation[0] += (float)angle;
                }


                // Animations
                animations = new List <BabylonAnimation>(mesh.animations);
                // Position
                BabylonAnimation animationPosition = animations.Find(animation => animation.property.Equals("position"));
                if (animationPosition != null)
                {
                    foreach (BabylonAnimationKey key in animationPosition.keys)
                    {
                        key.values = new float[] { key.values[0], key.values[2], -key.values[1] };
                    }
                }

                // Rotation
                animationRotationQuaternion = animations.Find(animation => animation.property.Equals("rotationQuaternion"));
                if (animationRotationQuaternion != null)
                {
                    foreach (BabylonAnimationKey key in animationRotationQuaternion.keys)
                    {
                        key.values = FixChildQuaternion(key.values, angle);
                    }
                }
            }
        }