public void GetCurrentSnapShot() { if (lastFrameStatus == null) { lastFrameStatus = new BoneStatus(); lastFrameStatus.Init(); for (int i = 0; i < bo.Count; i++) { lastFrameStatus.BoneQuat.Add(new MyQuaternion()); if (i == 0) { lastFrameStatus.BonePos = new MyVector(); } } for (int i = 0; i < dummy.Count; i++) { lastFrameStatus.DummyQuat.Add(new MyQuaternion()); lastFrameStatus.DummyPos.Add(new MyVector()); } } for (int i = 0; i < bo.Count; i++) { lastFrameStatus.BoneQuat[i] = bo[i].localRotation; if (i == 0) { lastFrameStatus.BonePos = bo[i].localPosition; } } for (int i = 0; i < dummy.Count; i++) { lastFrameStatus.DummyQuat[i] = dummy[i].localRotation; lastFrameStatus.DummyPos[i] = dummy[i].localPosition; } }
public static void HermiteInterpolatePose(BoneStatus prev, BoneStatus next, ref BoneStatus calcOut, float percent) { if (prev == null && next != null) { next.Clone(ref calcOut); return; } else if (prev != null && next == null) { prev.Clone(ref calcOut); return; } calcOut.BonePos = Vector3.Lerp(prev.BonePos, next.BonePos, percent); for (int i = 0; i < calcOut.DummyQuat.Count; i++) { calcOut.DummyQuat[i] = Quaternion.Slerp(prev.DummyQuat[i], next.DummyQuat[i], percent); } for (int i = 0; i < calcOut.DummyPos.Count; i++) { calcOut.DummyPos[i] = Vector3.Lerp(prev.DummyPos[i], next.DummyPos[i], percent); } for (int i = 0; i < calcOut.BoneQuat.Count; i++) { calcOut.BoneQuat[i] = Quaternion.Slerp(prev.BoneQuat[i], next.BoneQuat[i], percent); } }
public SortedDictionary <int, BoneStatus> Parse(byte[] memory) { MemoryStream ms = new MemoryStream(memory); BinaryReader binRead = new BinaryReader(ms); //BANIM=BoneAnimation binRead.BaseStream.Seek(5, SeekOrigin.Begin); int bone = binRead.ReadInt32(); int dummy = binRead.ReadInt32(); int frames = binRead.ReadInt32(); Pose.FPS = binRead.ReadInt32(); Pose.FCS = 1.0f / Pose.FPS; //Debug.Log("Fps:" + Pose.FPS); SortedDictionary <int, BoneStatus> innerValue = new SortedDictionary <int, BoneStatus>(); for (int i = 0; i < frames; i++) { BoneStatus status = new BoneStatus(); status.Init(); status.startflag = binRead.ReadInt32(); if (status.startflag != -1) { Debug.LogError("frame:" + i + " startflag:" + status.startflag); } int frameindex = binRead.ReadInt32(); float x = binRead.ReadSingle(); float y = binRead.ReadSingle(); float z = binRead.ReadSingle(); status.BonePos = new Vector3(x, z, y);//首骨骼的相对坐标. for (int j = 0; j < bone; j++) { float w = binRead.ReadSingle(); float xx = -binRead.ReadSingle(); float zz = -binRead.ReadSingle(); float yy = -binRead.ReadSingle(); Quaternion quat = new Quaternion(xx, yy, zz, w); status.BoneQuat.Add(quat); } for (int k = 0; k < dummy; k++) { binRead.BaseStream.Seek(5, SeekOrigin.Current); float dx = binRead.ReadSingle(); float dy = binRead.ReadSingle(); float dz = binRead.ReadSingle(); float dw = binRead.ReadSingle(); float dxx = -binRead.ReadSingle(); float dzz = -binRead.ReadSingle(); float dyy = -binRead.ReadSingle(); status.DummyPos.Add(new Vector3(dx, dz, dy)); status.DummyQuat.Add(new Quaternion(dxx, dyy, dzz, dw)); } innerValue.Add(frameindex, status); } //豪微秒 10^-7秒 //Debug.Log(string.Format("{0}", (double)(System.DateTime.Now.Ticks - s1) / 10000000.0)); return(innerValue); }
public void ChangeFrame(int source, int frame) { Pause = true; BoneStatus status = null; if (source == 0) { status = AmbLoader.CharCommon[frame]; } else if (source == 1) { status = AmbLoader.PlayerAnimation[owner.UnitId][frame]; } else { status = AmbLoader.GetBoneStatus(po.SourceIdx, owner.UnitId, frame); } for (int i = 0; i < bo.Count; i++) { bo[i].localRotation = status.BoneQuat[i]; if (i == 0) { bo[i].localPosition = status.BonePos; } } for (int i = 0; i < dummy.Count; i++) { //if (i == 0) //{ //Debug.LogError("action move"); //if (lastPosIdx == po.Idx && !inlooping) //{ // Vector3 targetPos = status.DummyPos[i]; // Vector3 vec = Target.rotation * (targetPos - lastDBasePos) * moveScale; // //如果忽略位移,或者在动作的循环帧中,即第一次从循环头开始播放后,不再计算位移. // moveDelta += vec; // //if (po.Idx == 151) // // Debug.LogError(string.Format("pose:{0} frame:{1} move: x ={2}, y ={3} z = {4}", po.Idx, curIndex, moveDelta.x, moveDelta.y, moveDelta.z)); // lastDBasePos = targetPos; //} // } // else { dummy[i].localRotation = status.DummyQuat[i]; dummy[i].localPosition = status.DummyPos[i]; } } }
public void Clone(ref BoneStatus clone) { clone.BonePos = BonePos; for (int i = 0; i < DummyPos.Count; i++) { clone.DummyPos[i] = DummyPos[i]; } for (int i = 0; i < BoneQuat.Count; i++) { clone.BoneQuat[i] = BoneQuat[i]; } for (int i = 0; i < DummyQuat.Count; i++) { clone.DummyQuat[i] = DummyQuat[i]; } }
public void ChangeFrame(int source, int frame) { Pause = true; BoneStatus status = null; if (source == 0) { status = AmbLoader.CharCommon[frame]; } else if (source == 1) { status = AmbLoader.FrameBoneAni[CharacterIdx][frame]; } for (int i = 0; i < bo.Count; i++) { bo[i].localRotation = status.BoneQuat[i]; if (i == 0) { bo[i].localPosition = status.BonePos; } } for (int i = 0; i < dummy.Count; i++) { if (i == 0) { if (lastPosIdx == po.Idx) { Vector3 targetPos = status.DummyPos[i]; Vector3 moveDelta = transform.rotation * (targetPos - vTmp); mOwner.Move(moveDelta); vTmp = targetPos; } } else { dummy[i].localRotation = status.DummyQuat[i]; dummy[i].localPosition = status.DummyPos[i]; } } if (mOwner.Attr.IsPlayer && FightWnd.Exist) { FightWnd.Instance.UpdatePoseStatus(-1, frame); } }
public void Add(BoneStatus other) { BonePos.x += other.BonePos.x; BonePos.y += other.BonePos.y; BonePos.z += other.BonePos.z; for (int i = 0; i < DummyPos.Count; i++) { DummyPos[i] = other.DummyPos[i] + DummyPos[i]; } for (int i = 0; i < BoneQuat.Count; i++) { BoneQuat[i] = other.BoneQuat[i] + BoneQuat[i]; } for (int i = 0; i < DummyQuat.Count; i++) { DummyQuat[i] = other.DummyQuat[i] + DummyQuat[i]; } }
public BoneStatus Scale(float scale) { BoneStatus clone = new BoneStatus(); clone.InitWith(BoneQuat.Count, DummyQuat.Count); clone.BonePos.x = BonePos.x * scale; clone.BonePos.y = BonePos.y * scale; clone.BonePos.z = BonePos.z * scale; for (int i = 0; i < DummyPos.Count; i++) { clone.DummyPos[i] = DummyPos[i].Scale(scale); } for (int i = 0; i < BoneQuat.Count; i++) { clone.BoneQuat[i] = BoneQuat[i].Scale(scale); } for (int i = 0; i < DummyQuat.Count; i++) { clone.DummyQuat[i] = DummyQuat[i].Scale(scale); } return(clone); }
public void CharacterUpdate() { if (Pause) { return; } if (po != null) { moveDelta = Vector3.zero; if (CheckStraight) { PoseStraight -= Time.deltaTime; //检查僵直是否过期. if (PoseStraight < 0.0f && loop) { loop = false; curIndex = po.LoopEnd; CheckStraight = false; } } if (blendTime == 0.0f) { lastFramePlayedTimes += Time.deltaTime; float speedScale = GetSpeedScale(); float fps = FPS / (Speed * speedScale); if (lastFramePlayedTimes < fps) { } else { while (lastFramePlayedTimes >= fps) { PlayNextFrame(fps); lastFramePlayedTimes -= fps; speedScale = GetSpeedScale(); fps = FPS / (Speed * speedScale); } } } else { playedTime += Time.deltaTime; //TryPlayEffect(); ChangeWeaponTrail(); BoneStatus status = null; if (po.SourceIdx == 0) { status = AmbLoader.CharCommon[blendStart]; } else if (po.SourceIdx == 1) { status = AmbLoader.FrameBoneAni[CharacterIdx][blendStart]; } if (playedTime < blendTime && blendTime != 0.0f && lastFrameStatus != null) { for (int i = 0; i < bo.Count; i++) { bo[i].localRotation = Quaternion.Slerp(lastFrameStatus.BoneQuat[i], status.BoneQuat[i], playedTime / blendTime); if (i == 0) { bo[i].localPosition = Vector3.Lerp(lastFrameStatus.BonePos, status.BonePos, playedTime / blendTime); } } for (int i = 0; i < dummy.Count; i++) { if (i == 0) { //混合动作,不许移动角色 //if (lastPosIdx == po.Idx) //{ // Vector3 targetPos = Vector3.Lerp(lastFrameStatus.DummyPos[i], status.DummyPos[i], playedTime / blendTime); // Vector3 vec = transform.rotation * (targetPos - lastDBasePos) * moveScale; // if (IgnoreActionMove(po.Idx)) // { // vec.x = 0; // vec.z = 0; // vec.y = 0; // } // else // { // } // moveDelta += vec; // lastDBasePos = targetPos; //} } else { dummy[i].localRotation = Quaternion.Slerp(lastFrameStatus.DummyQuat[i], status.DummyQuat[i], playedTime / blendTime); dummy[i].localPosition = Vector3.Lerp(lastFrameStatus.DummyPos[i], status.DummyPos[i], playedTime / blendTime); } } } else { blendTime = 0.0f; curIndex = lastFrameIndex = blendStart; playedTime = 0; lastFramePlayedTimes = 0; lastSource = po.SourceIdx; } } } }
public void AnimationUpdate(float timeRatio) { float speedScale = GetSpeedScale(); TryPlayEffect(); ChangeAttack(); ChangeWeaponTrail(); if (TestInputLink()) { return; } //超过末尾了. if (loop) { if (curIndex >= po.LoopEnd) { if (curIndex >= po.LoopStart && po.LoopStart == po.LoopEnd) { PlayPosEvent(); curIndex = po.LoopStart; if (loop) { return; } } curIndex = po.LoopStart; } } //else //{ // if (curIndex >= po.End) // { // if (single) // Pause = true; // else // posMng.OnActionFinished(); // return; // } //if (TheFirstFrame == curIndex) // ActionEvent.HandlerFirstActionFrame(mOwner, po.Idx); //if (TheLastFrame == curIndex) // ActionEvent.HandlerFinalActionFrame(mOwner, po.Idx); //} //curIndex = targetIndex; BoneStatus status = null; BoneStatus lastStatus = null; if (lastSource == 0) { lastStatus = AmbLoader.CharCommon[lastFrameIndex]; } else { lastStatus = AmbLoader.FrameBoneAni[CharacterIdx][lastFrameIndex]; } if (po.SourceIdx == 0) { status = AmbLoader.CharCommon[curIndex]; } else if (po.SourceIdx == 1) { status = AmbLoader.FrameBoneAni[CharacterIdx][curIndex]; } if (mOwner.Attr.IsPlayer && FightWnd.Exist) { FightWnd.Instance.UpdatePoseStatus(po.Idx, lastFrameIndex); } for (int i = 0; i < bo.Count; i++) { if (bo[i] == owner.HeadBone && GameBattleEx.Instance.autoTarget != null && owner.Attr.IsPlayer) { } else { bo[i].localRotation = Quaternion.Slerp(lastStatus.BoneQuat[i], status.BoneQuat[i], timeRatio); } if (i == 0) { bo[i].localPosition = Vector3.Lerp(lastStatus.BonePos, status.BonePos, timeRatio); } } for (int i = 0; i < dummy.Count; i++) { if (i == 0) { if (lastPosIdx == po.Idx) { Vector3 targetPos = Vector3.Lerp(lastStatus.DummyPos[i], status.DummyPos[i], timeRatio); Vector3 vec = transform.rotation * (targetPos - lastDBasePos) * moveScale; if (IgnoreActionMove(po.Idx)) { vec.x = 0; vec.z = 0; vec.y = 0; } else { } moveDelta += vec; lastDBasePos = targetPos; } } else { dummy[i].localRotation = Quaternion.Slerp(lastStatus.DummyQuat[i], status.DummyQuat[i], timeRatio); dummy[i].localPosition = Vector3.Lerp(lastStatus.DummyPos[i], status.DummyPos[i], timeRatio); } } //lastFrameIndex = curIndex; //lastSource = po.SourceIdx; //lastPosIdx = po.Idx; }
//人物自身动作,0帧为TPose //招式通用动作,从1帧开始,没有0帧 public Dictionary <int, BoneStatus> LoadAmb(string file) { long s1 = System.DateTime.Now.Ticks; TextAsset asset = Resources.Load <TextAsset>(file); if (asset == null) { Debug.LogError("amb file:" + file + " can not found"); return(null); } MemoryStream ms = new MemoryStream(asset.bytes); BinaryReader binRead = new BinaryReader(ms); binRead.BaseStream.Seek(5, SeekOrigin.Begin); int bone = binRead.ReadInt32(); int dummy = binRead.ReadInt32(); int frames = binRead.ReadInt32(); int unknown = binRead.ReadInt32(); Dictionary <int, BoneStatus> innerValue = new Dictionary <int, BoneStatus>(); for (int i = 1; i <= frames; i++) { BoneStatus status = new BoneStatus(); status.Init(); status.startflag = binRead.ReadInt32(); if (status.startflag != -1) { Debug.LogError("frame:" + i + " startflag:" + status.startflag); } int frameindex = binRead.ReadInt32(); float x = binRead.ReadSingle(); float y = binRead.ReadSingle(); float z = binRead.ReadSingle(); status.BonePos = new Vector3(x, z, y);//首骨骼的相对坐标. for (int j = 0; j < bone; j++) { float w = binRead.ReadSingle(); float xx = -binRead.ReadSingle(); float zz = -binRead.ReadSingle(); float yy = -binRead.ReadSingle(); Quaternion quat = new Quaternion(xx, yy, zz, w); status.BoneQuat.Add(quat); } for (int k = 0; k < dummy; k++) { binRead.BaseStream.Seek(5, SeekOrigin.Current); float dx = binRead.ReadSingle(); float dy = binRead.ReadSingle(); float dz = binRead.ReadSingle(); float dw = binRead.ReadSingle(); float dxx = -binRead.ReadSingle(); float dzz = -binRead.ReadSingle(); float dyy = -binRead.ReadSingle(); status.DummyPos.Add(new Vector3(dx, dz, dy)); status.DummyQuat.Add(new Quaternion(dxx, dyy, dzz, dw)); } innerValue.Add(frameindex, status); } //豪微秒 10^-7秒 //Debug.Log(string.Format("{0}", (double)(System.DateTime.Now.Ticks - s1) / 10000000.0)); return(innerValue); }
public void NetUpdate() { if (Pause) { return; } if (po != null) { moveDelta = Vector3.zero; if (blendTime == 0.0f) { //过渡时间不算硬直,非过渡时间,算在硬直内. if (PoseStraight > 0.0f) { PoseStraight -= FrameReplay.deltaTime; } lastFramePlayedTimes += FrameReplay.deltaTime; float speedScale = owner.ActionSpeed * GetSpeedScale(); float fps = Main.Ins.CombatData.FPS / speedScale; while (lastFramePlayedTimes >= fps) { PlayNextKeyFrame(); lastFramePlayedTimes -= fps; speedScale = GetSpeedScale(); fps = Main.Ins.CombatData.FPS / speedScale; } if (lastFramePlayedTimes < fps && lastFramePlayedTimes > 0) { PlayFrame(lastFramePlayedTimes / fps); } } else { playedTime += FrameReplay.deltaTime; ChangeWeaponTrail(); BoneStatus status = null; if (po.SourceIdx == 0 && AmbLoader.CharCommon.Count > blendStart && blendStart >= 0) { status = AmbLoader.CharCommon[blendStart]; } else if (po.SourceIdx == 1 && AmbLoader.PlayerAnimation.ContainsKey(mOwner.UnitId) && AmbLoader.PlayerAnimation[mOwner.UnitId].Count > blendStart && blendStart >= 0) { status = AmbLoader.PlayerAnimation[mOwner.UnitId][blendStart]; } else { status = AmbLoader.GetBoneStatus(po.SourceIdx, owner.UnitId, blendStart); } if (playedTime < blendTime && blendTime != 0.0f && lastFrameStatus != null && status != null) { bo[0].localRotation = Quaternion.Slerp(lastFrameStatus.BoneQuat[0], status.BoneQuat[0], playedTime / blendTime); bo[0].localPosition = Vector3.Lerp(lastFrameStatus.BonePos, status.BonePos, playedTime / blendTime); for (int i = 1; i < bo.Count; i++) { bo[i].localRotation = Quaternion.Slerp(lastFrameStatus.BoneQuat[i], status.BoneQuat[i], playedTime / blendTime); } lastDBasePos = status.DummyPos[0]; for (int i = 1; i < dummy.Count; i++) { dummy[i].localRotation = Quaternion.Slerp(lastFrameStatus.DummyQuat[i], status.DummyQuat[i], playedTime / blendTime); dummy[i].localPosition = Vector3.Lerp(lastFrameStatus.DummyPos[i], status.DummyPos[i], playedTime / blendTime); } } else { blendTime = 0.0f; curIndex = lastFrameIndex = blendStart; playedTime = 0; lastFramePlayedTimes = 0; lastSource = po.SourceIdx; } } } }
public void PlayFrame(float timeRatio) { TryPlayEffect(); ChangeAttack(); ChangeWeaponTrail(); ActionEvent.HandlerActionEvent(owner, po.Idx, curIndex); if (PoseEvent.ContainsKey(po.Idx)) { //当218发射飞轮,很快返回,还未到219动作时,下次播放219,就得立即取消循环,221 223 PoseEvent.Remove(po.Idx); loop = false; curIndex = po.LoopEnd; } if (TestInputLink()) { return; } if (loop) { if (LockCurrentFrame) { if (PoseStraight <= 0.0f) { loop = false; curIndex = po.LoopEnd + 1; LockCurrentFrame = false; return; } } if (curIndex >= po.LoopEnd) { LoopCount++; PlayPosEvent(); if (loop) { curIndex = po.LoopStart; } return; } } else { if (curIndex > po.End) { posMng.OnActionFinished(); return; } if (TheFirstFrame <= curIndex && TheFirstFrame != -1) { ActionEvent.HandlerFirstActionFrame(mOwner, po.Idx); TheFirstFrame = -1; } if (TheLastFrame <= curIndex && TheLastFrame != -1) { ActionEvent.HandlerFinalActionFrame(mOwner, po.Idx); TheLastFrame = -1; } } //Debug.Log("PlayKeyFrame:" + Time.frameCount); //curIndex = targetIndex; BoneStatus status = null; BoneStatus lastStatus = null; if (lastSource == 0 && AmbLoader.CharCommon.Count > lastFrameIndex && lastFrameIndex >= 0) { lastStatus = AmbLoader.CharCommon[lastFrameIndex]; } else if (AmbLoader.PlayerAnimation.ContainsKey(owner.UnitId) && AmbLoader.PlayerAnimation[owner.UnitId].Count > lastFrameIndex && lastFrameIndex >= 0) { lastStatus = AmbLoader.PlayerAnimation[owner.UnitId][lastFrameIndex]; } if (po.SourceIdx == 0) { status = AmbLoader.CharCommon[curIndex]; } else if (po.SourceIdx == 1) { status = AmbLoader.PlayerAnimation[owner.UnitId][curIndex]; } else { status = AmbLoader.GetBoneStatus(po.SourceIdx, owner.UnitId, curIndex); } if (status != null && lastStatus != null) { bo[0].localRotation = Quaternion.Slerp(lastStatus.BoneQuat[0], status.BoneQuat[0], timeRatio); bo[0].localPosition = Vector3.Lerp(lastStatus.BonePos, status.BonePos, timeRatio); for (int i = 1; i < bo.Count; i++) { bo[i].localRotation = Quaternion.Slerp(lastStatus.BoneQuat[i], status.BoneQuat[i], timeRatio); } } bool IgnoreActionMoves = PoseStatus.IgnoreActionMove(po.Idx); if (owner.IsDebugUnit()) { if (OnAnimationFrame != null) { OnAnimationFrame(po.SourceIdx, po.Idx, curIndex, timeRatio); } //IgnoreActionMoves = false; } bool IgnoreActionXZMove = PoseStatus.IgnoreXZMove(po.Idx); if (lastStatus != null && status != null) { if (lastPosIdx == po.Idx) { Vector3 targetPos = Vector3.Lerp(lastStatus.DummyPos[0], status.DummyPos[0], timeRatio); Vector3 vec = Target.rotation * (targetPos - lastDBasePos) * moveScale; if (IgnoreActionMoves) { vec.x = 0; vec.z = 0; vec.y = 0; } else if (IgnoreActionXZMove) { vec.x = vec.z = 0; } moveDelta += vec; lastDBasePos = targetPos; } for (int i = 1; i < dummy.Count; i++) { dummy[i].localRotation = Quaternion.Slerp(lastStatus.DummyQuat[i], status.DummyQuat[i], timeRatio); dummy[i].localPosition = Vector3.Lerp(lastStatus.DummyPos[i], status.DummyPos[i], timeRatio); } } }
void PlayNextKeyFrame() { TryPlayEffect(); ChangeAttack(); ChangeWeaponTrail(); ActionEvent.HandlerActionEvent(owner, po.Idx, curIndex); if (PoseEvent.ContainsKey(po.Idx)) { //当218发射飞轮,很快返回,还未到219动作时,下次播放219,就得立即取消循环,221 223 PoseEvent.Remove(po.Idx); loop = false; curIndex = po.LoopEnd; } //有连招. if (TestInputLink()) { return; } if (loop) { if (LockCurrentFrame) { if (PoseStraight <= 0.0f) { loop = false; curIndex = po.LoopEnd + 1; LockCurrentFrame = false; return; } } if (curIndex > po.LoopEnd) { if (curIndex > po.LoopStart) { LoopCount++; PlayPosEvent(); if (loop) { curIndex = po.LoopStart; } return; } curIndex = po.LoopStart; } } else { if (curIndex > po.End) { posMng.OnActionFinished(); return; } if (TheFirstFrame <= curIndex && TheFirstFrame != -1) { ActionEvent.HandlerFirstActionFrame(mOwner, po.Idx); TheFirstFrame = -1; } if (TheLastFrame <= curIndex && TheLastFrame != -1) { ActionEvent.HandlerFinalActionFrame(mOwner, po.Idx); TheLastFrame = -1; } } //Debug.Log("PlayKeyFrame:" + Time.frameCount); BoneStatus status = null; if (po.SourceIdx == 0) { status = AmbLoader.CharCommon[curIndex]; } else if (po.SourceIdx == 1) { status = AmbLoader.PlayerAnimation[owner.UnitId][curIndex]; } else { status = AmbLoader.GetBoneStatus(po.SourceIdx, owner.UnitId, curIndex); } //Debug.LogError("play keyframe " + " idx:" + curIndex); if (bo.Count != 0) { bo[0].localRotation = status.BoneQuat[0]; bo[0].localPosition = status.BonePos; } for (int i = 1; i < bo.Count; i++) { bo[i].localRotation = status.BoneQuat[i]; } bool IgnoreActionMoves = PoseStatus.IgnoreActionMove(po.Idx); //if (owner.IsDebugUnit()) // IgnoreActionMoves = false; bool IgnoreActionXZMove = PoseStatus.IgnoreXZMove(po.Idx); if (lastPosIdx == po.Idx) { Vector3 targetPos = status.DummyPos[0]; Vector3 vec = Target.rotation * (targetPos - lastDBasePos) * moveScale; //如果忽略位移,或者在动作的循环帧中,即第一次从循环头开始播放后,不再计算位移. if (IgnoreActionMoves) { vec.x = 0; vec.z = 0; vec.y = 0; } else if (IgnoreActionXZMove) { vec.x = vec.z = 0; } moveDelta += vec; //if (po.Idx == 151) // Debug.LogError(string.Format("pose:{0} frame:{1} move: x ={2}, y ={3} z = {4}", po.Idx, curIndex, moveDelta.x, moveDelta.y, moveDelta.z)); lastDBasePos = targetPos; } for (int i = 1; i < dummy.Count; i++) { dummy[i].localRotation = status.DummyQuat[i]; dummy[i].localPosition = status.DummyPos[i]; } lastFrameIndex = curIndex; curIndex++; lastSource = po.SourceIdx; lastPosIdx = po.Idx; }
//把骨骼的Pose帧信息烘培到曲线上. public void BakeIntoCurve(int unitId, Pose source, AnimationCurve curve, int boneIndex, BakeInto bakeopt, bool keyFrameReduction = true, float epsilon = 0.00001f) { BoneStatus prevFrame = null; BoneStatus nextFrame = null; float time = 0.0f; float value = 0.0f; for (int i = source.Start; i <= source.End; i++) { nextFrame = GetBoneStatus(source.SourceIdx, unitId, i); if (prevFrame != null) { //根据烘培选项,决定如果误差小于某个值,就丢弃掉这个关键帧 switch (bakeopt) { case BakeInto.BakeLocalDummyPosX: if (Utility.CompareApproximately(prevFrame.DummyPos[boneIndex].x, nextFrame.DummyPos[boneIndex].x, epsilon)) { nextFrame = null; } else { value = nextFrame.DummyPos[boneIndex].x; } break; case BakeInto.BakeLocalDummyPosY: if (Utility.CompareApproximately(prevFrame.DummyPos[boneIndex].y, nextFrame.DummyPos[boneIndex].y, epsilon)) { nextFrame = null; } else { value = nextFrame.DummyPos[boneIndex].y; } break; case BakeInto.BakeLocalDummyPosZ: if (Utility.CompareApproximately(prevFrame.DummyPos[boneIndex].z, nextFrame.DummyPos[boneIndex].z, epsilon)) { nextFrame = null; } else { value = nextFrame.DummyPos[boneIndex].z; } break; case BakeInto.BakeLocalDummyRotationX: if (Utility.CompareApproximately(prevFrame.DummyQuat[boneIndex].x, nextFrame.DummyQuat[boneIndex].x, epsilon)) { nextFrame = null; } else { value = nextFrame.DummyQuat[boneIndex].x; } break; case BakeInto.BakeLocalDummyRotationY: if (Utility.CompareApproximately(prevFrame.DummyQuat[boneIndex].y, nextFrame.DummyQuat[boneIndex].y, epsilon)) { nextFrame = null; } else { value = nextFrame.DummyQuat[boneIndex].y; } break; case BakeInto.BakeLocalDummyRotationZ: if (Utility.CompareApproximately(prevFrame.DummyQuat[boneIndex].z, nextFrame.DummyQuat[boneIndex].z, epsilon)) { nextFrame = null; } else { value = nextFrame.DummyQuat[boneIndex].z; } break; case BakeInto.BakeLocalDummyRotationW: if (Utility.CompareApproximately(prevFrame.DummyQuat[boneIndex].w, nextFrame.DummyQuat[boneIndex].w, epsilon)) { nextFrame = null; } else { value = nextFrame.DummyQuat[boneIndex].w; } break; case BakeInto.BakeLocalPosX: if (Utility.CompareApproximately(prevFrame.BonePos.x, nextFrame.BonePos.x, epsilon)) { nextFrame = null; } else { value = nextFrame.BonePos.x; } break; case BakeInto.BakeLocalPosY: if (Utility.CompareApproximately(prevFrame.BonePos.y, nextFrame.BonePos.y, epsilon)) { nextFrame = null; } else { value = nextFrame.BonePos.y; } break; case BakeInto.BakeLocalPosZ: if (Utility.CompareApproximately(prevFrame.BonePos.z, nextFrame.BonePos.z, epsilon)) { nextFrame = null; } else { value = nextFrame.BonePos.z; } break; case BakeInto.BakeLocalRotationX: if (Utility.CompareApproximately(prevFrame.BoneQuat[boneIndex].x, nextFrame.BoneQuat[boneIndex].x, epsilon)) { nextFrame = null; } else { value = nextFrame.BoneQuat[boneIndex].x; } break; case BakeInto.BakeLocalRotationY: if (Utility.CompareApproximately(prevFrame.BoneQuat[boneIndex].y, nextFrame.BoneQuat[boneIndex].y, epsilon)) { nextFrame = null; } else { value = nextFrame.BoneQuat[boneIndex].y; } break; case BakeInto.BakeLocalRotationZ: if (Utility.CompareApproximately(prevFrame.BoneQuat[boneIndex].z, nextFrame.BoneQuat[boneIndex].z, epsilon)) { nextFrame = null; } else { value = nextFrame.BoneQuat[boneIndex].z; } break; case BakeInto.BakeLocalRotationW: if (Utility.CompareApproximately(prevFrame.BoneQuat[boneIndex].w, nextFrame.BoneQuat[boneIndex].w, epsilon)) { nextFrame = null; } else { value = nextFrame.BoneQuat[boneIndex].w; } break; } } else { //根据烘培选项,决定如果误差小于某个值,就丢弃掉这个关键帧 switch (bakeopt) { case BakeInto.BakeLocalDummyPosX: value = nextFrame.DummyPos[boneIndex].x; break; case BakeInto.BakeLocalDummyPosY: value = nextFrame.DummyPos[boneIndex].y; break; case BakeInto.BakeLocalDummyPosZ: value = nextFrame.DummyPos[boneIndex].z; break; case BakeInto.BakeLocalDummyRotationX: value = nextFrame.DummyQuat[boneIndex].x; break; case BakeInto.BakeLocalDummyRotationY: value = nextFrame.DummyQuat[boneIndex].y; break; case BakeInto.BakeLocalDummyRotationZ: value = nextFrame.DummyQuat[boneIndex].z; break; case BakeInto.BakeLocalDummyRotationW: value = nextFrame.DummyQuat[boneIndex].w; break; case BakeInto.BakeLocalPosX: value = nextFrame.BonePos.x; break; case BakeInto.BakeLocalPosY: value = nextFrame.BonePos.y; break; case BakeInto.BakeLocalPosZ: value = nextFrame.BonePos.z; break; case BakeInto.BakeLocalRotationX: value = nextFrame.BoneQuat[boneIndex].x; break; case BakeInto.BakeLocalRotationY: value = nextFrame.BoneQuat[boneIndex].y; break; case BakeInto.BakeLocalRotationZ: value = nextFrame.BoneQuat[boneIndex].z; break; case BakeInto.BakeLocalRotationW: value = nextFrame.BoneQuat[boneIndex].w; break; } } //存在关键帧,记录关键帧的信息 if (nextFrame != null) { curve.AddKey(time, value); prevFrame = keyFrameReduction ? nextFrame:null; } time += (1.0f / Pose.FPS); } if (curve.keys.Count() == 1) { curve.AddKey(time, value); } }
void PlayNextFrame(float delta) { TryPlayEffect(); ChangeAttack(); ChangeWeaponTrail(); if (PoseEvent.ContainsKey(po.Idx)) { //当218发射飞轮,很快返回,还未到219动作时,下次播放219,就得立即取消循环,221 223 if ((PoseEvent[po.Idx] & (int)PoseEvt.WeaponIsReturned) != 0) { PoseEvent[po.Idx] &= ~(int)PoseEvt.WeaponIsReturned; loop = false; curIndex = po.LoopEnd; } } //有连招. if (TestInputLink()) { return; } if (loop) { if (curIndex > po.LoopEnd) { if (curIndex > po.LoopStart) { PlayPosEvent(); curIndex = po.LoopStart; if (loop) { return; } } curIndex = po.LoopStart; } } else { if (curIndex > po.End) { if (single) { Pause = true; } else { posMng.OnActionFinished(); } return; } if (TheFirstFrame == curIndex) { ActionEvent.HandlerFirstActionFrame(mOwner, po.Idx); } if (TheLastFrame == curIndex) { ActionEvent.HandlerFinalActionFrame(mOwner, po.Idx); } } BoneStatus status = null; if (po.SourceIdx == 0) { status = AmbLoader.CharCommon[curIndex]; } else if (po.SourceIdx == 1) { status = AmbLoader.FrameBoneAni[CharacterIdx][curIndex]; } if (mOwner.Attr.IsPlayer && FightWnd.Exist) { FightWnd.Instance.UpdatePoseStatus(po.Idx, curIndex); } for (int i = 0; i < bo.Count; i++) { bo[i].localRotation = status.BoneQuat[i]; if (i == 0) { bo[i].localPosition = status.BonePos; } } bool IgnoreActionMoves = IgnoreActionMove(po.Idx); for (int i = 0; i < dummy.Count; i++) { if (i == 0) { if (lastPosIdx == po.Idx) { Vector3 targetPos = status.DummyPos[i]; Vector3 vec = transform.rotation * (targetPos - lastDBasePos) * moveScale; if (IgnoreActionMoves) { vec.x = 0; vec.z = 0; vec.y = 0; } else { } moveDelta += vec; lastDBasePos = targetPos; } } else { dummy[i].localRotation = status.DummyQuat[i]; dummy[i].localPosition = status.DummyPos[i]; } } lastFrameIndex = curIndex; curIndex++; lastSource = po.SourceIdx; lastPosIdx = po.Idx; }
//Quaternion lastDBaseQuat = Quaternion.identity; //一种是用来动作融合的,指定时间内,从当前POS,转化到目标POS的第一帧 //一种是用帧融合的,表明2个关键帧之间有多少普通帧,这些普通帧都插值 //POSE切换时,不插值位移,只插值 旋转等 //pose关键帧切换时,每个POSE第一帧作为TPOSE,如果后面的帧相对当前TPOSE有移动,旋转,那么计算每2个插值帧之间的差距 //用这个差距来调用charController.Move //特效时间不是太准,需要考虑如何让特效和动作同步. void Update() { if (Pause) { return; } if (po != null) { float speedScale = 1.0f; for (int i = 0; i < po.ActionList.Count; i++) { if (curIndex >= po.ActionList[i].Start && curIndex <= po.ActionList[i].End) { speedScale = (po.ActionList[i].Speed == 0.0f ? 1.0f : po.ActionList[i].Speed); break; } } if (lastFrameToKey >= (1.0f / speedScale * Time.timeScale)) { lastFrameIndex = curIndex; lastSource = po.SourceIdx; lastPosIdx = po.Idx; int targetIndex = curIndex + 1; //超过末尾了. if (loop) { if (targetIndex > po.LoopEnd) { targetIndex = po.LoopStart; } } else { if (targetIndex > po.End) { posMng.TickAction();//整个动作完整播放完毕了,到下一个动作的第一帧 return; } } //播放下一个关键帧 curIndex = targetIndex; lastFrameToKey = 0; } else { } BoneStatus status = null; if (po.SourceIdx == 0) { status = AmbLoader.CharCommon[curIndex]; } else if (po.SourceIdx == 1) { status = AmbLoader.FrameBoneAni[CharacterIdx][curIndex]; } for (int i = 0; i < bo.Count; i++) { bo[i].localRotation = status.BoneQuat[i]; if (i == 0) { bo[i].localPosition = status.BonePos; } } for (int i = 0; i < dummy.Count; i++) { if (i == 0) { if (lastPosIdx == po.Idx) { //Vector3 targetPos = status.DummyPos[i]; //transform.position = targetPos; } } else { dummy[i].localRotation = status.DummyQuat[i]; dummy[i].localPosition = status.DummyPos[i]; } } lastFrameToKey += 1; } }