void Instalize(AnimationFrame start) { foreach (var pair in boneReference) { Vector4 rot = start.BonePoritions[pair.Value].Rotation; Vector3 pos = start.BonePoritions[pair.Value].Position; Matrix4 localInv = Matrix4.Identity; Quaternion rotation = Quaternion.Identity; if (_animation.GetRotationType == Animation.RotationType.Quaternion) { rotation = new Quaternion(rot.Xyz, rot.W); } else { rotation = Quaternion.FromAxisAngle(Vector3.UnitZ, rot.Z) * Quaternion.FromAxisAngle(Vector3.UnitY, rot.Y) * Quaternion.FromAxisAngle(Vector3.UnitX, rot.X); } if (_animation.TransType == Animation.TransformType.LocalRelative) { BoneController.GetBone(pair.Key).SetTransform(rotation, pos); } else if (_animation.TransType == Animation.TransformType.LocalAbsolute) { BoneController.GetBone(pair.Key).InitialLocalTransform = Matrix4.CreateFromQuaternion(rotation) * Matrix4.CreateTranslation(pos); } } }
//creaating frames with aproximation void NormalizeFrames(BoneUnsorted[] bonesRaw) { int maxFrames = bonesRaw.Max((BoneUnsorted b) => { return(Math.Max(b.positions.Length, b.rotations.Length)); }); frames = new AnimationFrame[maxFrames]; List <BonePosition>[] bonePosesInterpretated = new List <BonePosition> [maxFrames]; for (int i = 0; i < maxFrames; i++) { bonePosesInterpretated[i] = new List <BonePosition>(); } float framePart = 1f / maxFrames; for (int n = 0; n < bones.Count; n++) { var boneFrames = bonesRaw[n]; float boneTransPart = 1f / boneFrames.positions.Length - 1; float boneRotPart = 1f / boneFrames.rotations.Length - 1; for (int f = 0; f < maxFrames; f++) { float framepos = f * framePart * (boneFrames.positions.Length - 1); float framerot = f * framePart * (boneFrames.rotations.Length - 1); var prevFrameTrans = boneFrames.positions[(int)Math.Floor(framepos)]; var prevFrameRot = boneFrames.rotations[(int)Math.Floor(framerot)]; var nextFrameTrans = boneFrames.positions[(int)Math.Ceiling(framepos)]; var nextFrameRot = boneFrames.rotations[(int)Math.Ceiling(framerot)]; Vector3 stepPos = (nextFrameTrans - prevFrameTrans) * (float)(framepos - Math.Truncate(framepos)); var intQuat = Quaternion.Slerp(prevFrameRot, nextFrameRot, (float)(framerot - Math.Truncate(framerot))); bonePosesInterpretated[f].Add(new BonePosition( prevFrameTrans + stepPos, new Vector4(intQuat.Xyz, intQuat.W), n)); } } for (int i = 0; i < frames.Length; i++) { frames[i] = new AnimationFrame(bonePosesInterpretated[i].ToArray()); } }
//interpolating data on frames void NormalizeFrames(Dictionary <int, List <BoneMotionData> > bonePositions) { List <BonePosition>[] bonePosesIntepr = new List <BonePosition> [_frames.Length]; for (int i = 0; i < bonePosesIntepr.Length; i++) { bonePosesIntepr[i] = new List <BonePosition>(); } for (int n = 0; n < _bones.Count; n++) { var boneFrames = bonePositions[n]; boneFrames = (boneFrames.OrderBy(b => b._frame)).ToList(); for (int f = 0; f < boneFrames.Count; f++) { var prevFrame = boneFrames[f]; var nextFrame = (f == boneFrames.Count - 1) ? boneFrames[0] : boneFrames[f + 1]; int frameCount = nextFrame._frame - prevFrame._frame; var prev = prevFrame._boneposition; Quaternion prevQuat = new Quaternion(prev.Rotation.Xyz, prev.Rotation.W); Quaternion nextQuat = new Quaternion(nextFrame._boneposition.Rotation.Xyz, nextFrame._boneposition.Rotation.W); if (frameCount > 0) { Vector3 stepPos = (nextFrame._boneposition.Position - prev.Position) / (float)frameCount; float stepRot = 1 / (float)frameCount; for (int frm = 0; frm < frameCount; frm++) { var interpQuat = Quaternion.Slerp(prevQuat, nextQuat, (float)frm * stepRot); bonePosesIntepr[prevFrame._frame + frm].Add(new BonePosition( prev.Position + stepPos * frm, new Vector4(interpQuat.Xyz, interpQuat.W), prev.BoneId)); } } else if (frameCount < 0) { frameCount += _frames.Length; int firstPart = _frames.Length - prevFrame._frame; Vector3 stepPos = (nextFrame._boneposition.Position - prev.Position) / (float)frameCount; float stepRot = 1 / (float)frameCount; //to last frame for (int frm = 0; frm < firstPart; frm++) { var interpQuat = Quaternion.Slerp(prevQuat, nextQuat, (float)frm * stepRot); bonePosesIntepr[prevFrame._frame + frm].Add(new BonePosition( prev.Position + stepPos * frm, new Vector4(interpQuat.Xyz, interpQuat.W), prev.BoneId)); } //from first frame for (int frm = 0; frm < nextFrame._frame; frm++) { var intQuat = Quaternion.Slerp(prevQuat, nextQuat, (float)(firstPart + frm) * stepRot); bonePosesIntepr[frm].Add(new BonePosition( prev.Position + stepPos * (firstPart + frm), new Vector4(intQuat.Xyz, intQuat.W), prev.BoneId)); } } else { for (int frm = 0; frm < _frames.Length; frm++) { bonePosesIntepr[prevFrame._frame + frm].Add(new BonePosition( prev.Position, prev.Rotation, prev.BoneId)); } } } } for (int i = 0; i < _frames.Length; i++) { _frames[i] = new AnimationFrame(bonePosesIntepr[i].ToArray()); } }
internal void Update(float delta) { animController?.Update(); if (!_isPlaing) { return; } _isEnded = false; _time += delta; _time = (_time >= _length + _frameLength) ? _time % _length : _time; int prevFrame = (int)(_time / _frameLength); int curFrame = (prevFrame == _animation.frames.Length - 1) ? 0 : prevFrame + 1; float frameDelta = _time / _frameLength; frameDelta = frameDelta - (int)frameDelta; AnimationFrame frame1 = _animation.frames[prevFrame], frame2 = _animation.frames[curFrame]; foreach (var pair in boneReference) { Quaternion rotation = Quaternion.Identity; Vector3 pos = frame1.BonePoritions[pair.Value].Position + (frame2.BonePoritions[pair.Value].Position - frame1.BonePoritions[pair.Value].Position) * frameDelta; if (_animation.GetRotationType == Animation.RotationType.Quaternion) { Quaternion prevQuat = new Quaternion(frame1.BonePoritions[pair.Value].Rotation.Xyz, frame1.BonePoritions[pair.Value].Rotation.W); Quaternion nextQuat = new Quaternion(frame2.BonePoritions[pair.Value].Rotation.Xyz, frame2.BonePoritions[pair.Value].Rotation.W); rotation = Quaternion.Slerp(prevQuat, nextQuat, frameDelta); } else { var deltaRot = frame2.BonePoritions[pair.Value].Rotation - frame1.BonePoritions[pair.Value].Rotation; CycleDeltaCheck(ref deltaRot.X); CycleDeltaCheck(ref deltaRot.Y); CycleDeltaCheck(ref deltaRot.Z); Vector4 rot = frame1.BonePoritions[pair.Value].Rotation + deltaRot * frameDelta; rotation = Quaternion.FromAxisAngle(Vector3.UnitZ, rot.Z) * Quaternion.FromAxisAngle(Vector3.UnitY, rot.Y) * Quaternion.FromAxisAngle(Vector3.UnitX, rot.X); } //skip masked out bone if (!BoneController.GetBone(pair.Key).FollowAnimation) { continue; } if (_animation.TransType == Animation.TransformType.LocalRelative) { BoneController.GetBone(pair.Key).SetTransform(rotation, pos); } else if (_animation.TransType == Animation.TransformType.LocalAbsolute) { BoneController.GetBone(pair.Key).InitialLocalTransform = Matrix4.CreateFromQuaternion(rotation) * Matrix4.CreateTranslation(pos); } } if (curFrame == _animation.frames.Length - 1) { if (!IsRepeat) { //Pause(); _isPlaing = false; _isEnded = true; } } }