public static void Save(Animation anim, VBN Skeleton, String Fname) { using (System.IO.StreamWriter file = new System.IO.StreamWriter(@Fname)) { file.WriteLine("version 1"); file.WriteLine("nodes"); foreach(Bone b in Skeleton.bones) { file.WriteLine(Skeleton.bones.IndexOf(b) + " \"" + b.Text + "\" " + b.parentIndex); } file.WriteLine("end"); file.WriteLine("skeleton"); anim.SetFrame(0); for(int i = 0; i <= anim.FrameCount; i++) { anim.NextFrame(Skeleton); file.WriteLine("time " + i); foreach (Animation.KeyNode sb in anim.Bones) { Bone b = Skeleton.getBone(sb.Text); if (b == null) continue; Vector3 eul = ANIM.quattoeul(b.rot); file.WriteLine(Skeleton.bones.IndexOf(b) + " " + b.pos.X + " " + b.pos.Y + " " + b.pos.Z + " " + eul.X + " " + eul.Y + " " + eul.Z); } } file.WriteLine("end"); file.Close(); } }
public void NextFrame(VBN skeleton, bool isChild = false) { if (Frame >= FrameCount) { return; } if (Frame == 0 && !isChild) { skeleton.reset(); } foreach (object child in Children) { if (child is Animation) { ((Animation)child).SetFrame(Frame); ((Animation)child).NextFrame(skeleton, isChild: true); } if (child is MTA) { //foreach (ModelContainer con in Runtime.ModelContainers) { if (((ModelContainer)skeleton.Parent).NUD != null) { ((ModelContainer)skeleton.Parent).NUD.ApplyMta(((MTA)child), (int)Frame); } } } if (child is BFRES.MTA) //For BFRES { { if (((ModelContainer)skeleton.Parent).BFRES != null) { ((ModelContainer)skeleton.Parent).BFRES.ApplyMta(((BFRES.MTA)child), (int)Frame); } } } } bool Updated = false; // no need to update skeleton of animations that didn't change foreach (KeyNode node in Bones) { // Get Skeleton Node Bone b = null; if (node.Hash == -1) { b = skeleton.getBone(node.Text); } else { b = skeleton.GetBone((uint)node.Hash); } if (b == null) { continue; } Updated = true; if (node.XPOS.HasAnimation() && b.boneType != 3) { b.pos.X = node.XPOS.GetValue(Frame); } if (node.YPOS.HasAnimation() && b.boneType != 3) { b.pos.Y = node.YPOS.GetValue(Frame); } if (node.ZPOS.HasAnimation() && b.boneType != 3) { b.pos.Z = node.ZPOS.GetValue(Frame); } if (node.XSCA.HasAnimation()) { b.sca.X = node.XSCA.GetValue(Frame); } else { b.sca.X = 1; } if (node.YSCA.HasAnimation()) { b.sca.Y = node.YSCA.GetValue(Frame); } else { b.sca.Y = 1; } if (node.ZSCA.HasAnimation()) { b.sca.Z = node.ZSCA.GetValue(Frame); } else { b.sca.Z = 1; } if (node.XROT.HasAnimation() || node.YROT.HasAnimation() || node.ZROT.HasAnimation()) { if (node.RotType == RotationType.QUATERNION) { KeyFrame[] x = node.XROT.GetFrame(Frame); KeyFrame[] y = node.YROT.GetFrame(Frame); KeyFrame[] z = node.ZROT.GetFrame(Frame); KeyFrame[] w = node.WROT.GetFrame(Frame); Quaternion q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value); Quaternion q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value); if (x[0].Frame == Frame) { b.rot = q1; } else if (x[1].Frame == Frame) { b.rot = q2; } else { b.rot = Quaternion.Slerp(q1, q2, (Frame - x[0].Frame) / (x[1].Frame - x[0].Frame)); } } else if (node.RotType == RotationType.EULER) { float x = node.XROT.HasAnimation() ? node.XROT.GetValue(Frame) : b.rotation[0]; float y = node.YROT.HasAnimation() ? node.YROT.GetValue(Frame) : b.rotation[1]; float z = node.ZROT.HasAnimation() ? node.ZROT.GetValue(Frame) : b.rotation[2]; b.rot = EulerToQuat(z, y, x); } } } Frame += 1f; if (Frame >= FrameCount) { Frame = 0; } if (!isChild && Updated) { skeleton.update(); } }
public static byte[] CreateOMOFromAnimation(Animation a, VBN vbn) { FileOutput o = new FileOutput(); o.Endian = Endianness.Big; FileOutput t1 = new FileOutput(); t1.Endian = Endianness.Big; FileOutput t2 = new FileOutput(); t2.Endian = Endianness.Big; o.writeString("OMO "); o.writeShort(1); //idk o.writeShort(3); //idk o.writeInt(0x091E100C); //flags?? o.writeShort(0); //padding o.writeShort(a.Bones.Count); // numOfNodes o.writeShort(a.FrameCount); // frame size o.writeShort(0); // frame start ?? o.writeInt(0); o.writeInt(0); o.writeInt(0); o.writeIntAt(o.size(), 0x14); // ASSESSMENT Vector3[] maxT = new Vector3[a.Bones.Count], minT = new Vector3[a.Bones.Count]; Vector4[] maxR = new Vector4[a.Bones.Count], minR = new Vector4[a.Bones.Count]; Vector3[] maxS = new Vector3[a.Bones.Count], minS = new Vector3[a.Bones.Count]; bool[] hasScale = new bool[a.Bones.Count]; bool[] hasTrans = new bool[a.Bones.Count]; bool[] hasRot = new bool[a.Bones.Count]; bool[] conScale = new bool[a.Bones.Count]; bool[] conTrans = new bool[a.Bones.Count]; bool[] conRot = new bool[a.Bones.Count]; a.SetFrame(0); //for (int i = 0; i < a.FrameCount; i++) { //a.NextFrame(vbn); for (int j = 0; j < a.Bones.Count; j++) { Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]); if (keynode.XPOS.HasAnimation() || keynode.YPOS.HasAnimation() || keynode.ZPOS.HasAnimation()) { hasTrans[j] = true; } if (keynode.XROT.HasAnimation()) { hasRot[j] = true; } if (keynode.XSCA.HasAnimation() || keynode.YSCA.HasAnimation() || keynode.ZSCA.HasAnimation()) { hasScale[j] = true; } maxT[j] = new Vector3(-999f, -999f, -999f); minT[j] = new Vector3(999f, 999f, 999f); maxS[j] = new Vector3(-999f, -999f, -999f); minS[j] = new Vector3(999f, 999f, 999f); maxR[j] = new Vector4(-999f, -999f, -999f, -999f); minR[j] = new Vector4(999f, 999f, 999f, 999f); foreach (Animation.KeyFrame key in keynode.XPOS.Keys) { maxT[j].X = Math.Max(maxT[j].X, key.Value); minT[j].X = Math.Min(minT[j].X, key.Value); } foreach (Animation.KeyFrame key in keynode.YPOS.Keys) { maxT[j].Y = Math.Max(maxT[j].Y, key.Value); minT[j].Y = Math.Min(minT[j].Y, key.Value); } foreach (Animation.KeyFrame key in keynode.ZPOS.Keys) { maxT[j].Z = Math.Max(maxT[j].Z, key.Value); minT[j].Z = Math.Min(minT[j].Z, key.Value); } foreach (Animation.KeyFrame key in keynode.XSCA.Keys) { maxS[j].X = Math.Max(maxS[j].X, key.Value); minS[j].X = Math.Min(minS[j].X, key.Value); } foreach (Animation.KeyFrame key in keynode.YSCA.Keys) { maxS[j].Y = Math.Max(maxS[j].Y, key.Value); minS[j].Y = Math.Min(minS[j].Y, key.Value); } foreach (Animation.KeyFrame key in keynode.ZSCA.Keys) { maxS[j].Z = Math.Max(maxS[j].Z, key.Value); minS[j].Z = Math.Min(minS[j].Z, key.Value); } //TODO: Euler Rotation Values a.SetFrame(0); Bone b = vbn.getBone(keynode.Text); if (b == null) { continue; } for (int i = 0; i < a.FrameCount; i++) { maxR[j].X = Math.Max(maxR[j].X, b.rot.X); minR[j].X = Math.Min(minR[j].X, b.rot.X); maxR[j].Y = Math.Max(maxR[j].Y, b.rot.Y); minR[j].Y = Math.Min(minR[j].Y, b.rot.Y); maxR[j].Z = Math.Max(maxR[j].Z, b.rot.Z); minR[j].Z = Math.Min(minR[j].Z, b.rot.Z); a.NextFrame(vbn); } if (b != null) { if (maxT[j].X == -999) { maxT[j].X = b.position[0]; } if (maxT[j].Y == -999) { maxT[j].Y = b.position[1]; } if (maxT[j].Z == -999) { maxT[j].Z = b.position[2]; } if (minT[j].X == -999) { minT[j].X = b.position[0]; } if (minT[j].Y == -999) { minT[j].Y = b.position[1]; } if (minT[j].Z == -999) { minT[j].Z = b.position[2]; } if (maxS[j].X == -999) { maxS[j].X = b.scale[0]; } if (maxS[j].Y == -999) { maxS[j].Y = b.scale[1]; } if (maxS[j].Z == -999) { maxS[j].Z = b.scale[2]; } if (minS[j].X == -999) { minS[j].X = b.scale[0]; } if (minS[j].Y == -999) { minS[j].Y = b.scale[1]; } if (minS[j].Z == -999) { minS[j].Z = b.scale[2]; } } } } // NODE INFO int t2Size = 0; for (int i = 0; i < a.Bones.Count; i++) { int flag = 0; conRot[i] = false; conScale[i] = false; conTrans[i] = false; // check for constant if (maxT[i].Equals(minT[i])) { conTrans[i] = true; } if (maxR[i].Equals(minR[i])) { conRot[i] = true; } if (maxS[i].Equals(minS[i])) { conScale[i] = true; } if (hasTrans[i]) { flag |= 0x01000000; } if (hasRot[i]) { flag |= 0x02000000; } if (hasScale[i]) { flag |= 0x04000000; } if (conTrans[i] && hasTrans[i]) { flag |= 0x00200000; } else { flag |= 0x00080000; } if (conRot[i] && hasRot[i]) { flag |= 0x00007000; } else { flag |= 0x00005000; } if (conScale[i] && hasScale[i]) { flag |= 0x00000200; } else { flag |= 0x00000080; } flag |= 0x00000001; //uint id = 999; Bone b = vbn.getBone(a.Bones[i].Text); int hash = -1; if (b != null) { hash = (int)b.boneId; } else { continue; } //if(hash == -1) //hash = (int)FileData.crc32(getNodeId(nodeid.get(i)).name); o.writeInt(flag); // flags... o.writeInt(hash); //hash o.writeInt(t1.size()); // Offset in 1 table o.writeInt(t2Size); // Offset in 2 table // calculate size needed if (hasTrans[i]) { t1.writeFloat(minT[i].X); t1.writeFloat(minT[i].Y); t1.writeFloat(minT[i].Z); if (!conTrans[i]) { maxT[i].X -= minT[i].X; maxT[i].Y -= minT[i].Y; maxT[i].Z -= minT[i].Z; t1.writeFloat(maxT[i].X); t1.writeFloat(maxT[i].Y); t1.writeFloat(maxT[i].Z); t2Size += 6; } } if (hasRot[i]) { t1.writeFloat(minR[i].X); t1.writeFloat(minR[i].Y); t1.writeFloat(minR[i].Z); if (!conRot[i]) { maxR[i].X -= minR[i].X; maxR[i].Y -= minR[i].Y; maxR[i].Z -= minR[i].Z; t1.writeFloat(maxR[i].X); t1.writeFloat(maxR[i].Y); t1.writeFloat(maxR[i].Z); t2Size += 6; } } if (hasScale[i]) { t1.writeFloat(minS[i].X); t1.writeFloat(minS[i].Y); t1.writeFloat(minS[i].Z); if (!conScale[i]) { maxS[i].X -= minS[i].X; maxS[i].Y -= minS[i].Y; maxS[i].Z -= minS[i].Z; t1.writeFloat(maxS[i].X); t1.writeFloat(maxS[i].Y); t1.writeFloat(maxS[i].Z); t2Size += 6; } } } o.writeIntAt(o.size(), 0x18); o.writeOutput(t1); o.writeIntAt(o.size(), 0x1C); // INTERPOLATION a.SetFrame(0); for (int i = 0; i < a.FrameCount; i++) { //Console.WriteLine("Workin on" + i); a.NextFrame(vbn); for (int j = 0; j < a.Bones.Count; j++) { Bone node = vbn.getBone(a.Bones[j].Text); if (node == null) { continue; } if (hasTrans[j] && !conTrans[j]) { t2.writeShort((int)(((node.pos.X - minT[j].X) / maxT[j].X) * 0xFFFF)); t2.writeShort((int)(((node.pos.Y - minT[j].Y) / maxT[j].Y) * 0xFFFF)); t2.writeShort((int)(((node.pos.Z - minT[j].Z) / maxT[j].Z) * 0xFFFF)); } if (hasRot[j] && !conRot[j]) { Quaternion r = node.rot; t2.writeShort((int)(((r.X - minR[j].X) / maxR[j].X) * 0xFFFF)); t2.writeShort((int)(((r.Y - minR[j].Y) / maxR[j].Y) * 0xFFFF)); t2.writeShort((int)(((r.Z - minR[j].Z) / maxR[j].Z) * 0xFFFF)); } if (hasScale[j] && !conScale[j]) { t2.writeShort((int)(((node.sca.X - minS[j].X) / maxS[j].X) * 0xFFFF)); t2.writeShort((int)(((node.sca.Y - minS[j].Y) / maxS[j].Y) * 0xFFFF)); t2.writeShort((int)(((node.sca.Z - minS[j].Z) / maxS[j].Z) * 0xFFFF)); } } if (i == 0) { o.writeShortAt(t2.size(), 0x12); } } //Console.WriteLine("Saving"); o.writeOutput(t2); return(o.getBytes()); }
public static byte[] CreateOMOFromAnimation(Animation a, VBN vbn) { if (vbn == null || a == null) { return new byte[] { } } ; // Test Actual Bones //------------------------- List <Animation.KeyNode> toRem = new List <Animation.KeyNode>(); for (int j = 0; j < a.Bones.Count; j++) { Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]); Bone b = vbn.getBone(keynode.Text); if (b == null) { toRem.Add(keynode); } } foreach (Animation.KeyNode r in toRem) { Console.WriteLine("Removing " + r.Text); a.Bones.Remove(r); } //------------------------- FileOutput o = new FileOutput(); o.Endian = Endianness.Big; FileOutput t1 = new FileOutput(); t1.Endian = Endianness.Big; FileOutput t2 = new FileOutput(); t2.Endian = Endianness.Big; o.writeString("OMO "); o.writeShort(1); //idk o.writeShort(3); //idk o.writeInt(0x091E100C); //flags?? o.writeShort(0); //padding o.writeShort(a.Bones.Count); // numOfNodes o.writeShort(a.FrameCount); // frame size o.writeShort(0); // frame start ?? o.writeInt(0); o.writeInt(0); o.writeInt(0); o.writeIntAt(o.size(), 0x14); // ASSESSMENT Vector3[] maxT = new Vector3[a.Bones.Count], minT = new Vector3[a.Bones.Count]; Vector4[] maxR = new Vector4[a.Bones.Count], minR = new Vector4[a.Bones.Count]; Vector3[] maxS = new Vector3[a.Bones.Count], minS = new Vector3[a.Bones.Count]; bool[] hasScale = new bool[a.Bones.Count]; bool[] hasTrans = new bool[a.Bones.Count]; bool[] hasRot = new bool[a.Bones.Count]; bool[] conScale = new bool[a.Bones.Count]; bool[] conTrans = new bool[a.Bones.Count]; bool[] conRot = new bool[a.Bones.Count]; a.SetFrame(0); List <List <Bone> > Frames = new List <List <Bone> >(); { for (int j = 0; j < a.Bones.Count; j++) { Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]); if (keynode.XPOS.HasAnimation() || keynode.YPOS.HasAnimation() || keynode.ZPOS.HasAnimation()) { hasTrans[j] = true; } if (keynode.XROT.HasAnimation()) { hasRot[j] = true; } if (keynode.XSCA.HasAnimation() || keynode.YSCA.HasAnimation() || keynode.ZSCA.HasAnimation()) { hasScale[j] = true; } maxT[j] = new Vector3(-999f, -999f, -999f); minT[j] = new Vector3(999f, 999f, 999f); maxS[j] = new Vector3(-999f, -999f, -999f); minS[j] = new Vector3(999f, 999f, 999f); maxR[j] = new Vector4(-999f, -999f, -999f, -999f); minR[j] = new Vector4(999f, 999f, 999f, 999f); foreach (Animation.KeyFrame key in keynode.XPOS.Keys) { maxT[j].X = Math.Max(maxT[j].X, key.Value); minT[j].X = Math.Min(minT[j].X, key.Value); } foreach (Animation.KeyFrame key in keynode.YPOS.Keys) { maxT[j].Y = Math.Max(maxT[j].Y, key.Value); minT[j].Y = Math.Min(minT[j].Y, key.Value); } foreach (Animation.KeyFrame key in keynode.ZPOS.Keys) { maxT[j].Z = Math.Max(maxT[j].Z, key.Value); minT[j].Z = Math.Min(minT[j].Z, key.Value); } foreach (Animation.KeyFrame key in keynode.XSCA.Keys) { maxS[j].X = Math.Max(maxS[j].X, key.Value); minS[j].X = Math.Min(minS[j].X, key.Value); } foreach (Animation.KeyFrame key in keynode.YSCA.Keys) { maxS[j].Y = Math.Max(maxS[j].Y, key.Value); minS[j].Y = Math.Min(minS[j].Y, key.Value); } foreach (Animation.KeyFrame key in keynode.ZSCA.Keys) { maxS[j].Z = Math.Max(maxS[j].Z, key.Value); minS[j].Z = Math.Min(minS[j].Z, key.Value); } Bone b = vbn.getBone(keynode.Text); for (int i = 0; i < a.FrameCount; i++) { Quaternion r = new Quaternion(); if (keynode.RotType == Animation.RotationType.QUATERNION) { Animation.KeyFrame[] x = keynode.XROT.GetFrame(i); Animation.KeyFrame[] y = keynode.YROT.GetFrame(i); Animation.KeyFrame[] z = keynode.ZROT.GetFrame(i); Animation.KeyFrame[] w = keynode.WROT.GetFrame(i); Quaternion q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value); Quaternion q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value); if (x[0].Frame == i) { r = q1; } else if (x[1].Frame == i) { r = q2; } else { r = Quaternion.Slerp(q1, q2, (i - x[0].Frame) / (x[1].Frame - x[0].Frame)); } } else if (keynode.RotType == Animation.RotationType.EULER) { float x = keynode.XROT.HasAnimation() ? keynode.XROT.GetValue(i) : b.rotation[0]; float y = keynode.YROT.HasAnimation() ? keynode.YROT.GetValue(i) : b.rotation[1]; float z = keynode.ZROT.HasAnimation() ? keynode.ZROT.GetValue(i) : b.rotation[2]; r = Animation.EulerToQuat(z, y, x); } r.Normalize(); maxR[j].X = Math.Max(maxR[j].X, r.X); minR[j].X = Math.Min(minR[j].X, r.X); maxR[j].Y = Math.Max(maxR[j].Y, r.Y); minR[j].Y = Math.Min(minR[j].Y, r.Y); maxR[j].Z = Math.Max(maxR[j].Z, r.Z); minR[j].Z = Math.Min(minR[j].Z, r.Z); } //if (b == null)continue; if (b != null) { if (maxT[j].X == -999) { maxT[j].X = b.position[0]; } if (maxT[j].Y == -999) { maxT[j].Y = b.position[1]; } if (maxT[j].Z == -999) { maxT[j].Z = b.position[2]; } if (minT[j].X == -999) { minT[j].X = b.position[0]; } if (minT[j].Y == -999) { minT[j].Y = b.position[1]; } if (minT[j].Z == -999) { minT[j].Z = b.position[2]; } if (maxS[j].X == -999) { maxS[j].X = b.scale[0]; } if (maxS[j].Y == -999) { maxS[j].Y = b.scale[1]; } if (maxS[j].Z == -999) { maxS[j].Z = b.scale[2]; } if (minS[j].X == -999) { minS[j].X = b.scale[0]; } if (minS[j].Y == -999) { minS[j].Y = b.scale[1]; } if (minS[j].Z == -999) { minS[j].Z = b.scale[2]; } } } } //TODO: Euler Rotation Values /*VBN tempvbn = new VBN(); * a.SetFrame(0); * for (int i = 0; i < a.FrameCount; i++) * { * //Frames.Add(new List<Bone>()); * for (int j = 0; j < a.Bones.Count; j++) * { * Animation.KeyNode keynode = a.Bones[j]; * Bone b = vbn.getBone(keynode.Text); * //if(b == null) continue; * maxR[j].X = Math.Max(maxR[j].X, b.rot.X); * minR[j].X = Math.Min(minR[j].X, b.rot.X); * maxR[j].Y = Math.Max(maxR[j].Y, b.rot.Y); * minR[j].Y = Math.Min(minR[j].Y, b.rot.Y); * maxR[j].Z = Math.Max(maxR[j].Z, b.rot.Z); * minR[j].Z = Math.Min(minR[j].Z, b.rot.Z); * * Bone f1 = new Bone(tempvbn); * f1.pos = b.pos; * f1.rot = b.rot; * f1.sca = b.sca; * //Frames[i].Add(f1); * } * a.NextFrame(vbn); * }*/ // NODE INFO int t2Size = 0; for (int i = 0; i < a.Bones.Count; i++) { int flag = 0; conRot[i] = false; conScale[i] = false; conTrans[i] = false; // check for constant if (maxT[i].Equals(minT[i])) { conTrans[i] = true; } if (maxR[i].Equals(minR[i])) { conRot[i] = true; } if (maxS[i].Equals(minS[i])) { conScale[i] = true; } if (hasTrans[i]) { flag |= 0x01000000; } if (hasRot[i]) { flag |= 0x02000000; } if (hasScale[i]) { flag |= 0x04000000; } if (conTrans[i] && hasTrans[i]) { flag |= 0x00200000; } else { flag |= 0x00080000; } if (conRot[i] && hasRot[i]) { flag |= 0x00007000; } else { flag |= 0x00005000; } if (conScale[i] && hasScale[i]) { flag |= 0x00000200; } else { flag |= 0x00000080; } flag |= 0x00000001; //uint id = 999; Bone b = vbn.getBone(a.Bones[i].Text); int hash = -1; if (MainForm.Hashes.names.ContainsKey(a.Bones[i].Text)) { hash = (int)MainForm.Hashes.names[a.Bones[i].Text]; } else { if (b != null) { hash = (int)b.boneId; } else { continue; } } //if(hash == -1) //hash = (int)FileData.crc32(getNodeId(nodeid.get(i)).name); o.writeInt(flag); // flags... o.writeInt(hash); //hash o.writeInt(t1.size()); // Offset in 1 table o.writeInt(t2Size); // Offset in 2 table // calculate size needed if (hasTrans[i]) { t1.writeFloat(minT[i].X); t1.writeFloat(minT[i].Y); t1.writeFloat(minT[i].Z); if (!conTrans[i]) { maxT[i].X -= minT[i].X; maxT[i].Y -= minT[i].Y; maxT[i].Z -= minT[i].Z; t1.writeFloat(maxT[i].X); t1.writeFloat(maxT[i].Y); t1.writeFloat(maxT[i].Z); t2Size += 6; } } if (hasRot[i]) { t1.writeFloat(minR[i].X); t1.writeFloat(minR[i].Y); t1.writeFloat(minR[i].Z); if (!conRot[i]) { maxR[i].X -= minR[i].X; maxR[i].Y -= minR[i].Y; maxR[i].Z -= minR[i].Z; t1.writeFloat(maxR[i].X); t1.writeFloat(maxR[i].Y); t1.writeFloat(maxR[i].Z); t2Size += 6; } } if (hasScale[i]) { t1.writeFloat(minS[i].X); t1.writeFloat(minS[i].Y); t1.writeFloat(minS[i].Z); if (!conScale[i]) { maxS[i].X -= minS[i].X; maxS[i].Y -= minS[i].Y; maxS[i].Z -= minS[i].Z; t1.writeFloat(maxS[i].X); t1.writeFloat(maxS[i].Y); t1.writeFloat(maxS[i].Z); t2Size += 6; } } } o.writeIntAt(o.size(), 0x18); o.writeOutput(t1); o.writeIntAt(o.size(), 0x1C); // INTERPOLATION a.SetFrame(0); bool go = true; for (int i = 0; i < a.FrameCount; i++) { //a.NextFrame(vbn); for (int j = 0; j < a.Bones.Count; j++) { Bone node = vbn.getBone(a.Bones[j].Text); Animation.KeyNode anode = a.Bones[j]; //if (node == null) continue; if (hasTrans[j] && !conTrans[j]) { t2.writeShort((int)(((anode.XPOS.GetValue(i) - minT[j].X) / maxT[j].X) * 0xFFFF)); t2.writeShort((int)(((anode.YPOS.GetValue(i) - minT[j].Y) / maxT[j].Y) * 0xFFFF)); t2.writeShort((int)(((anode.ZPOS.GetValue(i) - minT[j].Z) / maxT[j].Z) * 0xFFFF)); } if (hasRot[j] && !conRot[j]) { Quaternion r = new Quaternion(); if (anode.RotType == Animation.RotationType.QUATERNION) { Animation.KeyFrame[] x = anode.XROT.GetFrame(i); Animation.KeyFrame[] y = anode.YROT.GetFrame(i); Animation.KeyFrame[] z = anode.ZROT.GetFrame(i); Animation.KeyFrame[] w = anode.WROT.GetFrame(i); Quaternion q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value); Quaternion q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value); if (x[0].Frame == i) { r = q1; } else if (x[1].Frame == i) { r = q2; } else { r = Quaternion.Slerp(q1, q2, (i - x[0].Frame) / (x[1].Frame - x[0].Frame)); } } else if (anode.RotType == Animation.RotationType.EULER) { float x = anode.XROT.HasAnimation() ? anode.XROT.GetValue(i) : node.rotation[0]; float y = anode.YROT.HasAnimation() ? anode.YROT.GetValue(i) : node.rotation[1]; float z = anode.ZROT.HasAnimation() ? anode.ZROT.GetValue(i) : node.rotation[2]; r = Animation.EulerToQuat(z, y, x); } r.Normalize(); t2.writeShort((int)(((r.X - minR[j].X) / maxR[j].X) * 0xFFFF)); t2.writeShort((int)(((r.Y - minR[j].Y) / maxR[j].Y) * 0xFFFF)); t2.writeShort((int)(((r.Z - minR[j].Z) / maxR[j].Z) * 0xFFFF)); } if (hasScale[j] && !conScale[j]) { t2.writeShort((int)(((anode.XSCA.GetValue(i) - minS[j].X) / maxS[j].X) * 0xFFFF)); t2.writeShort((int)(((anode.YSCA.GetValue(i) - minS[j].Y) / maxS[j].Y) * 0xFFFF)); t2.writeShort((int)(((anode.ZSCA.GetValue(i) - minS[j].Z) / maxS[j].Z) * 0xFFFF)); } } if (go) { o.writeShortAt(t2.size(), 0x12); go = false; } } o.writeOutput(t2); return(o.getBytes()); } }
public void NextFrame(VBN skeleton, bool isChild = false) { if (Frame == 0 && !isChild) { skeleton.reset(); } foreach (object child in Children) { if (child is Animation) { ((Animation)child).SetFrame(Frame); ((Animation)child).NextFrame(skeleton, isChild: true); } if (child is MTA) { foreach (ModelContainer con in Runtime.ModelContainers) { if (con.nud != null) { con.nud.applyMTA(((MTA)child), (int)Frame); } } } } foreach (KeyNode node in Bones) { // Get Skeleton Node Bone b = skeleton.getBone(node.Text); if (b == null) { continue; } if (node.XPOS.HasAnimation()) { b.pos.X = node.XPOS.GetValue(Frame); } if (node.YPOS.HasAnimation()) { b.pos.Y = node.YPOS.GetValue(Frame); } if (node.ZPOS.HasAnimation()) { b.pos.Z = node.ZPOS.GetValue(Frame); } if (node.XSCA.HasAnimation()) { b.sca.X = node.XSCA.GetValue(Frame); } else { b.sca.X = 1; } if (node.YSCA.HasAnimation()) { b.sca.Y = node.YSCA.GetValue(Frame); } else { b.sca.Y = 1; } if (node.ZSCA.HasAnimation()) { b.sca.Z = node.ZSCA.GetValue(Frame); } else { b.sca.Z = 1; } if (node.XROT.HasAnimation()) { if (node.RotType == RotationType.QUATERNION) { KeyFrame[] x = node.XROT.GetFrame(Frame); KeyFrame[] y = node.YROT.GetFrame(Frame); KeyFrame[] z = node.ZROT.GetFrame(Frame); KeyFrame[] w = node.WROT.GetFrame(Frame); Quaternion q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value); Quaternion q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value); if (x[0].Frame == Frame) { b.rot = q1; } else if (x[1].Frame == Frame) { b.rot = q2; } else { b.rot = Quaternion.Slerp(q1, q2, (Frame - x[0].Frame) / (x[1].Frame - x[0].Frame)); } } else if (node.RotType == RotationType.EULER) { float x = node.XROT.HasAnimation() ? node.XROT.GetValue(Frame) : b.rotation[0]; float y = node.YROT.HasAnimation() ? node.YROT.GetValue(Frame) : b.rotation[1]; float z = node.ZROT.HasAnimation() ? node.ZROT.GetValue(Frame) : b.rotation[2]; b.rot = EulerToQuat(z, y, x); } } } Frame += 1f; if (Frame >= FrameCount) { Frame = 0; } skeleton.update(); }