private BabylonNode BoneToNode(BabylonBone babylonBone)
        {
            BabylonNode babylonNode = new BabylonNode();

            babylonNode.id       = babylonBone.id;
            babylonNode.parentId = babylonBone.parentNodeId;
            babylonNode.name     = babylonBone.name;


            babylonNode.animations = new[] { babylonBone.animation };

            var tm_babylon = new BabylonMatrix();

            tm_babylon.m = babylonBone.matrix.ToArray();
            var s_babylon = new BabylonVector3();
            var q_babylon = new BabylonQuaternion();
            var t_babylon = new BabylonVector3();

            tm_babylon.decompose(s_babylon, q_babylon, t_babylon);
            babylonNode.position           = t_babylon.ToArray();
            babylonNode.rotationQuaternion = q_babylon.ToArray();
            babylonNode.scaling            = s_babylon.ToArray();

            return(babylonNode);
        }
Example #2
0
        private GLTFNode _exportBone(BabylonBone babylonBone, GLTF gltf, BabylonSkeleton babylonSkeleton, List <BabylonBone> bones)
        {
            if (alreadyExportedBones.ContainsKey(babylonBone))
            {
                return(alreadyExportedBones[babylonBone]);
            }

            // Node
            var gltfNode = new GLTFNode
            {
                name = babylonBone.name
            };

            gltfNode.index = gltf.NodesList.Count;
            gltf.NodesList.Add(gltfNode);
            alreadyExportedBones.Add(babylonBone, gltfNode);
            boneToGltfNodeMap.Add(babylonBone, gltfNode);

            // Hierarchy
            if (babylonBone.parentBoneIndex >= 0)
            {
                var babylonParentBone = bones.Find(_babylonBone => _babylonBone.index == babylonBone.parentBoneIndex);
                var gltfParentNode    = _exportBone(babylonParentBone, gltf, babylonSkeleton, bones);
                RaiseMessage("GLTFExporter.Skin | Add " + babylonBone.name + " as child to " + gltfParentNode.name, 3);
                gltfParentNode.ChildrenList.Add(gltfNode.index);
                gltfNode.parent = gltfParentNode;
            }
            else
            {
                // It's a root node
                // Only root nodes are listed in a gltf scene
                RaiseMessage("GLTFExporter.Skin | Add " + babylonBone.name + " as root node to scene", 3);
                gltf.scenes[0].NodesList.Add(gltfNode.index);
            }

            // Transform
            // Bones transform are exported through translation/rotation/scale (TRS) rather than matrix
            // Because gltf node animation can only target TRS properties, not the matrix one
            // Create matrix from array
            var babylonMatrix = new BabylonMatrix();

            babylonMatrix.m = babylonBone.matrix;
            // Decompose matrix into TRS
            var translationBabylon  = new BabylonVector3();
            var rotationQuatBabylon = new BabylonQuaternion();
            var scaleBabylon        = new BabylonVector3();

            babylonMatrix.decompose(scaleBabylon, rotationQuatBabylon, translationBabylon);
            // Store TRS values
            gltfNode.translation = translationBabylon.ToArray();
            gltfNode.rotation    = rotationQuatBabylon.ToArray();
            gltfNode.scale       = scaleBabylon.ToArray();

            // Animations
            //ExportBoneAnimation(babylonBone, gltf, gltfNode);

            return(gltfNode);
        }
Example #3
0
        private void ExportBoneAnimation(GLTFAnimation gltfAnimation, int startFrame, int endFrame, GLTF gltf, BabylonBone babylonBone, GLTFNode gltfNode)
        {
            var channelList = gltfAnimation.ChannelList;
            var samplerList = gltfAnimation.SamplerList;

            if (babylonBone.animation != null && babylonBone.animation.property == "_matrix")
            {
                RaiseMessage("GLTFExporter.Animation | Export animation of bone named: " + babylonBone.name, 2);

                var babylonAnimation = babylonBone.animation;

                // Optimize animation
                var optimizeAnimations = !Loader.Core.RootNode.GetBoolProperty("babylonjs_donotoptimizeanimations"); // reverse negation for clarity
                if (optimizeAnimations)
                {
                    // Filter animation keys to only keep frames between start and end
                    List <BabylonAnimationKey> keysInRangeFull = babylonAnimation.keysFull.FindAll(babylonAnimationKey => babylonAnimationKey.frame >= startFrame && babylonAnimationKey.frame <= endFrame);

                    // Optimization process always keeps first and last frames
                    OptimizeAnimations(keysInRangeFull, false);

                    if (IsAnimationKeysRelevant(keysInRangeFull))
                    {
                        // From now, use optimized animation instead
                        // Override animation keys
                        babylonAnimation.keys = keysInRangeFull.ToArray();
                    }
                }

                // --- Input ---
                var accessorInput = _createAndPopulateInput(gltf, babylonAnimation, startFrame, endFrame);
                if (accessorInput == null)
                {
                    return;
                }

                // --- Output ---
                var paths = new string[] { "translation", "rotation", "scale" };
                var accessorOutputByPath = new Dictionary <string, GLTFAccessor>();

                foreach (string path in paths)
                {
                    GLTFAccessor accessorOutput = _createAccessorOfPath(path, gltf);
                    accessorOutputByPath.Add(path, accessorOutput);
                }

                // Populate accessors
                QuatCorrection quatCorr = new QuatCorrection(); // restart correction for each curve
                foreach (var babylonAnimationKey in babylonAnimation.keys)
                {
                    if (babylonAnimationKey.frame < startFrame)
                    {
                        continue;
                    }

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

                    var matrix = new BabylonMatrix();
                    matrix.m = babylonAnimationKey.values;

                    var translationBabylon  = new BabylonVector3();
                    var rotationQuatBabylon = new BabylonQuaternion();
                    var scaleBabylon        = new BabylonVector3();
                    matrix.decompose(scaleBabylon, rotationQuatBabylon, translationBabylon);

                    translationBabylon.Z *= -1;
                    if (exportParameters.kuesaContQuats)
                    {
                        quatCorr.Quat       = rotationQuatBabylon;
                        rotationQuatBabylon = quatCorr.Quat;
                    }
                    rotationQuatBabylon.X *= -1;
                    rotationQuatBabylon.Y *= -1;

                    var outputValuesByPath = new Dictionary <string, float[]>();
                    outputValuesByPath.Add("translation", translationBabylon.ToArray());
                    outputValuesByPath.Add("rotation", rotationQuatBabylon.ToArray());
                    outputValuesByPath.Add("scale", scaleBabylon.ToArray());

                    // Store values as bytes
                    foreach (string path in paths)
                    {
                        var accessorOutput = accessorOutputByPath[path];
                        var outputValues   = outputValuesByPath[path];

                        foreach (var outputValue in outputValues)
                        {
                            accessorOutput.bytesList.AddRange(BitConverter.GetBytes(outputValue));
                        }
                        accessorOutput.count++;
                    }
                }
                ;

                foreach (string path in paths)
                {
                    var accessorOutput = accessorOutputByPath[path];

                    // Animation sampler
                    var gltfAnimationSampler = new GLTFAnimationSampler
                    {
                        input  = accessorInput.index,
                        output = accessorOutput.index
                    };
                    gltfAnimationSampler.index = samplerList.Count;
                    samplerList.Add(gltfAnimationSampler);

                    // Target
                    var gltfTarget = new GLTFChannelTarget
                    {
                        node = gltfNode.index
                    };
                    gltfTarget.path = path;

                    // Channel
                    var gltfChannel = new GLTFChannel
                    {
                        sampler = gltfAnimationSampler.index,
                        target  = gltfTarget
                    };
                    channelList.Add(gltfChannel);
                }
            }
        }
        private void ExportBoneAnimation(GLTFAnimation gltfAnimation, int startFrame, int endFrame, GLTF gltf, BabylonNode babylonNode, GLTFNode gltfNode, BabylonAnimationGroup animationGroup = null)
        {
            var channelList = gltfAnimation.ChannelList;
            var samplerList = gltfAnimation.SamplerList;

            if (babylonNode.animations != null && babylonNode.animations[0].property == "_matrix")
            {
                logger.RaiseMessage("GLTFExporter.Animation | Export animation of bone named: " + babylonNode.name, 2);

                BabylonAnimation babylonAnimation = null;
                if (animationGroup != null)
                {
                    var targetedAnimation = animationGroup.targetedAnimations.FirstOrDefault(animation => animation.targetId == babylonNode.id);
                    if (targetedAnimation != null)
                    {
                        babylonAnimation = targetedAnimation.animation;
                    }
                }

                // otherwise fall back to the full animation track on the node.
                if (babylonAnimation == null)
                {
                    babylonAnimation = babylonNode.animations[0];
                }

                var babylonAnimationKeysInRange = babylonAnimation.keys.Where(key => key.frame >= startFrame && key.frame <= endFrame);
                if (babylonAnimationKeysInRange.Count() <= 0)
                {
                    return;
                }

                // --- Input ---
                var accessorInput = _createAndPopulateInput(gltf, babylonAnimation, startFrame, endFrame);
                if (accessorInput == null)
                {
                    return;
                }

                // --- Output ---
                var paths = new string[] { "translation", "rotation", "scale" };
                var accessorOutputByPath = new Dictionary <string, GLTFAccessor>();

                foreach (string path in paths)
                {
                    GLTFAccessor accessorOutput = _createAccessorOfPath(path, gltf);
                    accessorOutputByPath.Add(path, accessorOutput);
                }

                // Populate accessors
                foreach (var babylonAnimationKey in babylonAnimationKeysInRange)
                {
                    var matrix = new BabylonMatrix();
                    matrix.m = babylonAnimationKey.values;

                    var translationBabylon  = new BabylonVector3();
                    var rotationQuatBabylon = new BabylonQuaternion();
                    var scaleBabylon        = new BabylonVector3();
                    matrix.decompose(scaleBabylon, rotationQuatBabylon, translationBabylon);

                    // Switch coordinate system at object level
                    translationBabylon.Z  *= -1;
                    rotationQuatBabylon.X *= -1;
                    rotationQuatBabylon.Y *= -1;

                    var outputValuesByPath = new Dictionary <string, float[]>();
                    outputValuesByPath.Add("translation", translationBabylon.ToArray());
                    outputValuesByPath.Add("rotation", rotationQuatBabylon.ToArray());
                    outputValuesByPath.Add("scale", scaleBabylon.ToArray());

                    // Store values as bytes
                    foreach (string path in paths)
                    {
                        var accessorOutput = accessorOutputByPath[path];
                        var outputValues   = outputValuesByPath[path];

                        foreach (var outputValue in outputValues)
                        {
                            accessorOutput.bytesList.AddRange(BitConverter.GetBytes(outputValue));
                        }
                        accessorOutput.count++;
                    }
                }
                ;

                foreach (string path in paths)
                {
                    var accessorOutput = accessorOutputByPath[path];

                    // Animation sampler
                    var gltfAnimationSampler = new GLTFAnimationSampler
                    {
                        input  = accessorInput.index,
                        output = accessorOutput.index
                    };
                    gltfAnimationSampler.index = samplerList.Count;
                    samplerList.Add(gltfAnimationSampler);

                    // Target
                    var gltfTarget = new GLTFChannelTarget
                    {
                        node = gltfNode.index
                    };
                    gltfTarget.path = path;

                    // Channel
                    var gltfChannel = new GLTFChannel
                    {
                        sampler = gltfAnimationSampler.index,
                        target  = gltfTarget
                    };
                    channelList.Add(gltfChannel);
                }
            }

            ExportGLTFExtension(babylonNode, ref gltfAnimation, gltf);
        }
Example #5
0
        private GLTFAnimation ExportBoneAnimation(BabylonBone babylonBone, GLTF gltf, GLTFNode gltfNode)
        {
            GLTFAnimation gltfAnimation = null;

            if (gltf.AnimationsList.Count > 0)
            {
                gltfAnimation = gltf.AnimationsList[0];
            }
            else
            {
                gltfAnimation = new GLTFAnimation();
                gltf.AnimationsList.Add(gltfAnimation);
            }

            var channelList = gltfAnimation.ChannelList;
            var samplerList = gltfAnimation.SamplerList;

            if (babylonBone.animation != null && babylonBone.animation.property == "_matrix")
            {
                RaiseMessage("GLTFExporter.Animation | Export animation of bone named: " + babylonBone.name, 2);

                var babylonAnimation = babylonBone.animation;

                // --- Input ---
                var accessorInput = _createAndPopulateInput(gltf, babylonAnimation);

                // --- Output ---
                var paths = new string[] { "translation", "rotation", "scale" };
                var accessorOutputByPath = new Dictionary <string, GLTFAccessor>();

                foreach (string path in paths)
                {
                    GLTFAccessor accessorOutput = _createAccessorOfPath(path, gltf);
                    accessorOutputByPath.Add(path, accessorOutput);
                }

                // Populate accessors
                foreach (var babylonAnimationKey in babylonAnimation.keys)
                {
                    var matrix = new BabylonMatrix();
                    matrix.m = babylonAnimationKey.values;

                    var translationBabylon  = new BabylonVector3();
                    var rotationQuatBabylon = new BabylonQuaternion();
                    var scaleBabylon        = new BabylonVector3();
                    matrix.decompose(scaleBabylon, rotationQuatBabylon, translationBabylon);

                    translationBabylon.Z *= -1;
                    BabylonVector3 rotationVector3 = rotationQuatBabylon.toEulerAngles();
                    rotationVector3.X  *= -1;
                    rotationVector3.Y  *= -1;
                    rotationQuatBabylon = rotationVector3.toQuaternion();

                    var outputValuesByPath = new Dictionary <string, float[]>();
                    outputValuesByPath.Add("translation", translationBabylon.ToArray());
                    outputValuesByPath.Add("rotation", rotationQuatBabylon.ToArray());
                    outputValuesByPath.Add("scale", scaleBabylon.ToArray());

                    // Store values as bytes
                    foreach (string path in paths)
                    {
                        var accessorOutput = accessorOutputByPath[path];
                        var outputValues   = outputValuesByPath[path];

                        foreach (var outputValue in outputValues)
                        {
                            accessorOutput.bytesList.AddRange(BitConverter.GetBytes(outputValue));
                        }
                        accessorOutput.count++;
                    }
                }
                ;

                foreach (string path in paths)
                {
                    var accessorOutput = accessorOutputByPath[path];

                    // Animation sampler
                    var gltfAnimationSampler = new GLTFAnimationSampler
                    {
                        input  = accessorInput.index,
                        output = accessorOutput.index
                    };
                    gltfAnimationSampler.index = samplerList.Count;
                    samplerList.Add(gltfAnimationSampler);

                    // Target
                    var gltfTarget = new GLTFChannelTarget
                    {
                        node = gltfNode.index
                    };
                    gltfTarget.path = path;

                    // Channel
                    var gltfChannel = new GLTFChannel
                    {
                        sampler = gltfAnimationSampler.index,
                        target  = gltfTarget
                    };
                    channelList.Add(gltfChannel);
                }
            }

            return(gltfAnimation);
        }
Example #6
0
        private void ExportBoneAnimation(GLTFAnimation gltfAnimation, int startFrame, int endFrame, GLTF gltf, BabylonBone babylonBone, GLTFNode gltfNode)
        {
            var channelList = gltfAnimation.ChannelList;
            var samplerList = gltfAnimation.SamplerList;

            if (babylonBone.animation != null && babylonBone.animation.property == "_matrix")
            {
                logger.RaiseMessage("GLTFExporter.Animation | Export animation of bone named: " + babylonBone.name, 2);

                var babylonAnimation = babylonBone.animation;

                // --- Input ---
                var accessorInput = _createAndPopulateInput(gltf, babylonAnimation, startFrame, endFrame);
                if (accessorInput == null)
                {
                    return;
                }

                // --- Output ---
                var paths = new string[] { "translation", "rotation", "scale" };
                var accessorOutputByPath = new Dictionary <string, GLTFAccessor>();

                foreach (string path in paths)
                {
                    GLTFAccessor accessorOutput = _createAccessorOfPath(path, gltf);
                    accessorOutputByPath.Add(path, accessorOutput);
                }

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

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

                    var matrix = new BabylonMatrix();
                    matrix.m = babylonAnimationKey.values;

                    var translationBabylon  = new BabylonVector3();
                    var rotationQuatBabylon = new BabylonQuaternion();
                    var scaleBabylon        = new BabylonVector3();
                    matrix.decompose(scaleBabylon, rotationQuatBabylon, translationBabylon);

                    // Switch coordinate system at object level
                    translationBabylon.Z  *= -1;
                    translationBabylon    *= exportParameters.scaleFactor;
                    rotationQuatBabylon.X *= -1;
                    rotationQuatBabylon.Y *= -1;

                    var outputValuesByPath = new Dictionary <string, float[]>();
                    outputValuesByPath.Add("translation", translationBabylon.ToArray());
                    outputValuesByPath.Add("rotation", rotationQuatBabylon.ToArray());
                    outputValuesByPath.Add("scale", scaleBabylon.ToArray());

                    // Store values as bytes
                    foreach (string path in paths)
                    {
                        var accessorOutput = accessorOutputByPath[path];
                        var outputValues   = outputValuesByPath[path];

                        foreach (var outputValue in outputValues)
                        {
                            accessorOutput.bytesList.AddRange(BitConverter.GetBytes(outputValue));
                        }
                        accessorOutput.count++;
                    }
                }
                ;

                foreach (string path in paths)
                {
                    var accessorOutput = accessorOutputByPath[path];

                    // Animation sampler
                    var gltfAnimationSampler = new GLTFAnimationSampler
                    {
                        input  = accessorInput.index,
                        output = accessorOutput.index
                    };
                    gltfAnimationSampler.index = samplerList.Count;
                    samplerList.Add(gltfAnimationSampler);

                    // Target
                    var gltfTarget = new GLTFChannelTarget
                    {
                        node = gltfNode.index
                    };
                    gltfTarget.path = path;

                    // Channel
                    var gltfChannel = new GLTFChannel
                    {
                        sampler = gltfAnimationSampler.index,
                        target  = gltfTarget
                    };
                    channelList.Add(gltfChannel);
                }
            }
        }