Esempio n. 1
0
 public void Reset(bool destroying)
 {
     if (!isReset)
     {
         ReturnFrame(destroying);
         isFading     = false;
         endTime      = 0;
         currentFrame = 0;
         framesNeeded = 0;
         fromFrame    = null;
         toFrame      = null;
         isReset      = true;
     }
 }
Esempio n. 2
0
        public void StartCrossfade(MeshFrameDataBase fromFrame, MeshFrameDataBase toFrame)
        {
            Reset(false);
            isReset        = false;
            this.fromFrame = fromFrame;
            this.toFrame   = toFrame;
            int matrixLength = fromFrame.exposedTransforms != null ? fromFrame.exposedTransforms.Length : 0;

            if (matrixLength > 0)
            {
                if (exposedTransformJobs == null)
                {
                    exposedTransformJobs = AllocatedArray <LerpMatrix4x4Job> .Get(framesNeeded);
                }
                if (exposedTransformJobHandles == null)
                {
                    exposedTransformJobHandles = AllocatedArray <JobHandle> .Get(framesNeeded);
                }
                if (outputMatrix == null)
                {
                    outputMatrix = AllocatedArray <NativeArray <Matrix4x4> > .Get(framesNeeded);
                }
                fromMatrix = new NativeArray <Matrix4x4>(matrixLength, Allocator.Persistent);
                toMatrix   = new NativeArray <Matrix4x4>(matrixLength, Allocator.Persistent);
                fromMatrix.CopyFrom(fromFrame.exposedTransforms);
                toMatrix.CopyFrom(toFrame.exposedTransforms);

                for (int i = 0; i < framesNeeded; i++)
                {
                    float delta = i / (float)framesNeeded;
                    outputMatrix[i] = new NativeArray <Matrix4x4>(matrixLength, Allocator.Persistent);
                    var matrixJob = new LerpMatrix4x4Job()
                    {
                        from   = fromMatrix,
                        to     = toMatrix,
                        output = outputMatrix[i],
                        delta  = delta
                    };
                    exposedTransformJobs[i]       = matrixJob;
                    exposedTransformJobHandles[i] = matrixJob.Schedule(matrixLength, 64);
                }
            }
        }
Esempio n. 3
0
        public float GetInterpolatingFrames(int frame, out MeshFrameDataBase previousFrame, out MeshFrameDataBase nextFrame)
        {
            bool needsInterp = frame % frameSkip != 0;
            var  frameData   = Frames;

            if (!needsInterp)
            {
                int frameIndex = frame / frameSkip;
                previousFrame = frameData[frameIndex];
                if (frameIndex + 1 >= frameData.Length)
                {
                    nextFrame = frameData[0];
                }
                else
                {
                    nextFrame = frameData[frameIndex + 1];
                }
                return(0);
            }
            float framePerc = (float)frame / (float)(frameSkip * frameData.Length);
            int   skipFrame = (int)(framePerc * frameData.Length);

            float prevFramePerc = (float)skipFrame / (float)frameData.Length;
            float nextFramePerc = Mathf.Clamp01((float)(skipFrame + 1) / (float)frameData.Length);

            previousFrame = frameData[skipFrame];
            if (skipFrame + 1 >= frameData.Length)
            {
                nextFrame = frameData[0];
            }
            else
            {
                nextFrame = frameData[skipFrame + 1];
            }

            float lerpVal = Mathf.Lerp(0, 1, (framePerc - prevFramePerc) / (nextFramePerc - prevFramePerc));

            return(lerpVal);
        }
Esempio n. 4
0
        /// <summary>
        /// The main update loop called from the MeshAnimatorManager
        /// </summary>
        /// <param name="time">Current time</param>
        public void UpdateTick(float time)
        {
            if (initialized == false)
            {
                return;
            }
            if (animationCount == 0)
            {
                return;
            }
            if (currentAnimIndex < 0 || currentAnimIndex > animationCount)
            {
                if (defaultAnimation != null)
                {
                    Play(defaultAnimation.AnimationName);
                }
                else
                {
                    Play(0);
                }
            }
            if ((isVisible == false && updateWhenOffscreen == false) || isPaused || speed == 0 || currentAnimation.playbackSpeed == 0) // return if offscreen or crossfading
            {
                return;
            }
            // update the lod level if needed
            if (LODLevels.Length > 0 && time > nextLODCheck)
            {
                if (!hasLODCamera)
                {
                    int cameraCount = Camera.allCamerasCount;
                    if (cameraCount > 0)
                    {
                        Camera[] cameras = AllocatedArray <Camera> .Get(cameraCount);

                        cameraCount = Camera.GetAllCameras(cameras);
                        LODCamera   = cameras[0].transform;
                        AllocatedArray <Camera> .Return(cameras);

                        hasLODCamera = true;
                    }
                }
                if (hasLODCamera)
                {
                    float dis      = (LODCamera.position - mTransform.position).sqrMagnitude;
                    int   lodLevel = 0;
                    for (int i = 0; i < LODLevels.Length; i++)
                    {
                        if (dis > LODLevels[i].distanceSquared)
                        {
                            lodLevel = i;
                        }
                    }
                    if (currentLodLevel != lodLevel)
                    {
                        currentLodLevel = lodLevel;
                    }
                }
                nextLODCheck = time + UnityEngine.Random.Range(0.5f, 1.5f);
            }
            // if the speed is below the normal playback speed, wait until the next frame can display
            float lodFPS = LODLevels.Length > currentLodLevel ? LODLevels[currentLodLevel].fps : FPS;

            if (lodFPS == 0.0f)
            {
                return;
            }
            float totalSpeed     = Math.Abs(currentAnimation.playbackSpeed * speed);
            float calculatedTick = 1f / lodFPS / totalSpeed;
            float tickRate       = 0.0001f;

            if (calculatedTick > 0.0001f)
            {
                tickRate = calculatedTick;
            }
            float actualDelta = time - lastFrameTime;
            bool  finished    = false;

            float pingPongMult = pingPong ? -1 : 1;

            if (speed * currentAnimation.playbackSpeed < 0)
            {
                currentAnimTime -= actualDelta * pingPongMult * totalSpeed;
            }
            else
            {
                currentAnimTime += actualDelta * pingPongMult * totalSpeed;
            }

            if (currentAnimTime < 0)
            {
                currentAnimTime = currentAnimation.length;
                finished        = true;
            }
            else if (currentAnimTime > currentAnimation.length)
            {
                if (currentAnimation.wrapMode == WrapMode.Loop)
                {
                    currentAnimTime = currentAnimTime - currentAnimation.length;
                }
                finished = true;
            }

            nextTick      = time + tickRate;
            lastFrameTime = time;

            float normalizedTime = currentAnimTime / currentAnimation.length;
            int   previousFrame  = currentFrame;
            int   totalFrames    = currentAnimation.TotalFrames;

            currentFrame = Math.Min((int)Math.Round(normalizedTime * totalFrames), totalFrames - 1);

            // do WrapMode.PingPong
            if (currentAnimation.wrapMode == WrapMode.PingPong)
            {
                if (finished)
                {
                    pingPong = !pingPong;
                }
            }

            if (finished)
            {
                bool stopUpdate = false;
                if (queuedAnims != null && queuedAnims.Count > 0)
                {
                    Play(queuedAnims.Dequeue());
                    stopUpdate = true;
                }
                else if (currentAnimation.wrapMode != WrapMode.Loop && currentAnimation.wrapMode != WrapMode.PingPong)
                {
                    nextTick   = float.MaxValue;
                    stopUpdate = true;
                }
                if (stopUpdate)
                {
                    isPaused = true;
                }
                if (OnAnimationFinished != null)
                {
                    OnAnimationFinished(currentAnimation.AnimationName);
                }
                OnAnimationCompleted(stopUpdate);
                if (stopUpdate)
                {
                    FireAnimationEvents(currentAnimation, totalSpeed, finished);
                    return;
                }
            }

            bool updateFrameTransforms = DisplayFrame(previousFrame);

            if (updateFrameTransforms && currentFrame != previousFrame)
            {
                bool applyRootMotion = currentAnimation.rootMotionMode == RootMotionMode.AppliedToTransform;
                if (hasExposedTransforms || applyRootMotion)
                {
                    MeshFrameDataBase fromFrame   = currentAnimation.GetNearestFrame(currentFrame);
                    MeshFrameDataBase targetFrame = null;
                    int   frameGap    = currentFrame % currentAnimation.FrameSkip;
                    bool  needsInterp = actualDelta > 0 && frameGap != 0;
                    float blendDelta  = 0;
                    if (needsInterp)
                    {
                        blendDelta = currentAnimation.GetInterpolatingFrames(currentFrame, out fromFrame, out targetFrame);
                    }
                    // move exposed transforms
                    if (hasExposedTransforms)
                    {
                        var exposedTransforms = currentAnimation.ExposedTransforms;
                        for (int i = 0; i < exposedTransforms.Length; i++)
                        {
                            Transform child = null;
                            if (fromFrame.exposedTransforms.Length > i && childMap.TryGetValue(exposedTransforms[i], out child))
                            {
                                if (needsInterp)
                                {
                                    Matrix4x4 c = MatrixLerp(fromFrame.exposedTransforms[i], targetFrame.exposedTransforms[i], blendDelta);
                                    MatrixUtils.FromMatrix4x4(child, c);
                                }
                                else
                                {
                                    MatrixUtils.FromMatrix4x4(child, fromFrame.exposedTransforms[i]);
                                }
                            }
                        }
                    }
                    // apply root motion
                    if (applyRootMotion)
                    {
                        if (previousFrame > currentFrame)
                        {
                            // animation looped around, apply motion for skipped frames at the end of the animation
                            for (int i = previousFrame + 1; i < currentAnimation.Frames.Length; i++)
                            {
                                MeshFrameDataBase rootFrame = currentAnimation.GetNearestFrame(i);
                                transform.Translate(rootFrame.rootMotionPosition, Space.Self);
                                transform.Rotate(rootFrame.rootMotionRotation.eulerAngles * actualDelta, Space.Self);
                            }
                            // now apply motion from first frame to current frame
                            for (int i = 0; i <= currentFrame; i++)
                            {
                                MeshFrameDataBase rootFrame = currentAnimation.GetNearestFrame(i);
                                transform.Translate(rootFrame.rootMotionPosition, Space.Self);
                                transform.Rotate(rootFrame.rootMotionRotation.eulerAngles * actualDelta, Space.Self);
                            }
                        }
                        else
                        {
                            for (int i = previousFrame + 1; i <= currentFrame; i++)
                            {
                                MeshFrameDataBase rootFrame = currentAnimation.GetNearestFrame(i);
                                transform.Translate(rootFrame.rootMotionPosition, Space.Self);
                                transform.Rotate(rootFrame.rootMotionRotation.eulerAngles * actualDelta, Space.Self);
                            }
                        }
                    }
                }
            }
            if (OnFrameUpdated != null)
            {
                OnFrameUpdated();
            }

            FireAnimationEvents(currentAnimation, totalSpeed, finished);
        }
Esempio n. 5
0
 public abstract void SetFrameData(int frame, MeshFrameDataBase frameData);