示例#1
0
        public void Populate(Transform m, ref GlTF_Accessor invBindMatricesAccessor, int invBindAccessorIndex)
        {
            SkinnedMeshRenderer skinMesh = m.GetComponent <SkinnedMeshRenderer>();

            if (!skinMesh)
            {
                return;
            }

            // Populate bind poses. From https://docs.unity3d.com/ScriptReference/Mesh-bindposes.html:
            // The bind pose is bone's inverse transformation matrix
            // In this case we also make this matrix relative to the root
            // So that we can move the root game object around freely

            joints = new List <Transform>();
            //Collect all bones from skin object. Order should be kept here since bones are referenced in the mesh
            foreach (Transform t in skinMesh.bones)
            {
                joints.Add(t);
            }

            Matrix4x4[] invBindMatrices = new Matrix4x4[joints.Count];
            for (int i = 0; i < skinMesh.bones.Length; ++i)
            {
                // Generates inverseWorldMatrix in right-handed coordinate system
                Matrix4x4 invBind = skinMesh.sharedMesh.bindposes[i];
                convertMatrixLeftToRightHandedness(ref invBind);
                invBindMatrices[i] = invBind;
            }

            invBindMatricesAccessor.Populate(invBindMatrices, m);
            invBindMatricesAccessorIndex = invBindAccessorIndex;
        }
示例#2
0
        public void Populate(AnimationClip clip, Transform tr, bool bake = true)
        {
            // 1. browse clip, collect all curves and create a TargetCurveSet for each target
            Dictionary <string, TargetCurveSet> targetCurvesBinding = new Dictionary <string, TargetCurveSet>();

            collectClipCurves(clip, ref targetCurvesBinding);

            // Baking needs all properties, fill missing curves with transform data in 2 keyframes (start, endTime)
            // where endTime is clip duration
            generateMissingCurves(clip.length, ref tr, ref targetCurvesBinding);

            if (bake)
            {
                // Bake animation for all animated nodes
                foreach (string target in targetCurvesBinding.Keys)
                {
                    Transform targetTr = target.Length > 0 ? tr.Find(target) : tr;
                    if (targetTr == null)
                    {
                        continue;
                    }

                    Transform targetObject = targetTr;
                    string    targetId     = GlTF_Node.GetNameFromObject(targetObject);

                    // Initialize accessors for current animation
                    GlTF_Accessor timeAccessor = new GlTF_Accessor(targetId + "_TimeAccessor_" + clip.name, GlTF_Accessor.Type.SCALAR, GlTF_Accessor.ComponentType.FLOAT);
                    timeAccessor.bufferView = GlTF_Writer.floatBufferView;
                    int timeAccessorIndex = GlTF_Writer.accessors.Count;
                    GlTF_Writer.accessors.Add(timeAccessor);

                    // Translation
                    GlTF_Channel chTranslation     = new GlTF_Channel("translation", animSamplers.Count);
                    GlTF_Target  targetTranslation = new GlTF_Target();
                    targetTranslation.id   = targetId;
                    targetTranslation.path = "translation";
                    chTranslation.target   = targetTranslation;
                    channels.Add(chTranslation);

                    GlTF_AnimSampler sTranslation        = new GlTF_AnimSampler(timeAccessorIndex, GlTF_Writer.accessors.Count);
                    GlTF_Accessor    translationAccessor = new GlTF_Accessor(targetId + "_TranslationAccessor_" + clip.name, GlTF_Accessor.Type.VEC3, GlTF_Accessor.ComponentType.FLOAT);
                    translationAccessor.bufferView = GlTF_Writer.vec3BufferViewAnim;
                    GlTF_Writer.accessors.Add(translationAccessor);
                    animSamplers.Add(sTranslation);

                    // Rotation
                    GlTF_Channel chRotation     = new GlTF_Channel("rotation", animSamplers.Count);
                    GlTF_Target  targetRotation = new GlTF_Target();
                    targetRotation.id   = GlTF_Node.GetNameFromObject(targetObject);
                    targetRotation.path = "rotation";
                    chRotation.target   = targetRotation;
                    channels.Add(chRotation);

                    GlTF_AnimSampler sRotation        = new GlTF_AnimSampler(timeAccessorIndex, GlTF_Writer.accessors.Count);
                    GlTF_Accessor    rotationAccessor = new GlTF_Accessor(targetId + "_RotationAccessor_" + clip.name, GlTF_Accessor.Type.VEC4, GlTF_Accessor.ComponentType.FLOAT);
                    rotationAccessor.bufferView = GlTF_Writer.vec4BufferViewAnim;
                    GlTF_Writer.accessors.Add(rotationAccessor);
                    animSamplers.Add(sRotation);

                    // Scale
                    GlTF_Channel chScale     = new GlTF_Channel("scale", animSamplers.Count);
                    GlTF_Target  targetScale = new GlTF_Target();
                    targetScale.id   = GlTF_Node.GetNameFromObject(targetObject);
                    targetScale.path = "scale";
                    chScale.target   = targetScale;
                    channels.Add(chScale);

                    GlTF_AnimSampler sScale        = new GlTF_AnimSampler(timeAccessorIndex, GlTF_Writer.accessors.Count);
                    GlTF_Accessor    scaleAccessor = new GlTF_Accessor(targetId + "_ScaleAccessor_" + clip.name, GlTF_Accessor.Type.VEC3, GlTF_Accessor.ComponentType.FLOAT);
                    scaleAccessor.bufferView = GlTF_Writer.vec3BufferViewAnim;
                    GlTF_Writer.accessors.Add(scaleAccessor);
                    animSamplers.Add(sScale);

                    // Bake and populate animation data
                    float[]   times     = null;
                    Vector3[] positions = null;
                    Vector3[] scales    = null;
                    Vector4[] rotations = null;
                    bakeCurveSet(targetCurvesBinding[target], clip.length, bakingFramerate, ref times, ref positions, ref rotations, ref scales);

                    // Populate accessors
                    timeAccessor.Populate(times);
                    translationAccessor.Populate(positions);
                    rotationAccessor.Populate(rotations, false);
                    scaleAccessor.Populate(scales, true);
                }
            }
            else
            {
                Debug.LogError("Only baked animation is supported for now. Skipping animation");
            }
        }