public void Apply(VBN vbn, int frame) { if (frame == 0) { vbn.reset(); } OMOFrame keys = Frames[frame]; foreach (OMONode node in Nodes) { foreach (Bone b in vbn.bones) { if (b.boneId == node.hash) { // apply interpolation frames Console.WriteLine(b.Text); node.Apply(b, keys); break; } } } vbn.update(); }
public void Apply(VBN bone) { for (int i = 0; i < nodes.Count; i++) { List <AnimType> used = new List <AnimType>(); Bone b = bone.bones[i]; Vector3 erot = ANIM.quattoeul(b.rot); foreach (DATAnimTrack track in nodes[i]) { KeyNode node = track.keys[0]; if (Debug) { Console.WriteLine("Bone " + i + " " + track.type + " " + node.value); } switch (track.type) { case AnimType.XPOS: b.pos.X = node.value; break; case AnimType.YPOS: b.pos.Y = node.value; break; case AnimType.ZPOS: b.pos.Z = node.value; break; case AnimType.XROT: erot.X = node.value; break; case AnimType.YROT: erot.Y = node.value; break; case AnimType.ZROT: erot.Z = node.value; break; } } b.rot = VBN.FromEulerAngles(erot.Z, erot.Y, erot.X); } bone.update(); }
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 VBN GetVBN(FileData d) { VBN v = new VBN(); d.endian = Endianness.Big; d.Seek(8); int ver = d.ReadInt(); d.Skip(4); //outer offset to brres int boneHeader = 0x40; // for version 9 only int dlist = d.ReadInt(); int boneSec = d.ReadInt(); int vertSec = d.ReadInt(); int normSec = d.ReadInt(); int colrSec = d.ReadInt(); int texcSec = d.ReadInt(); d.Skip(8); int polySec = d.ReadInt(); d.Seek(0x40); d.Skip(16); int vertCount = d.ReadInt(); int faceCount = d.ReadInt(); d.Skip(4); int boneCount = d.ReadInt(); v.totalBoneCount = (uint)boneCount; for (int i = 0; i < 3; i++) { v.boneCountPerType[i + 1] = 0; } d.Skip(4); int bonetableoff = d.ReadInt() + boneHeader; d.Seek(bonetableoff); int bcount = d.ReadInt(); int[] nodeIndex = new int[bcount]; for (int i = 0; i < bcount; i++) { nodeIndex[i] = d.ReadInt(); } Random rng = new Random(); uint boneID = (uint)rng.Next(1, 0xFFFFFF); // BONES----------------------------------------------- d.Seek(boneSec); d.Skip(4); // length int bseccount = d.ReadInt(); for (int i = 0; i < bseccount; i++) { Debug.Write(i); d.Skip(4); // entry id and unknown d.Skip(4); // left and right index int name = d.ReadInt() + boneSec; int data = d.ReadInt() + boneSec; int temp = d.Pos(); if (name != boneSec && data != boneSec) { // read bone data d.Seek(data); d.Skip(8); int nameOff = d.ReadInt() + data; int index = d.ReadInt(); // id d.Skip(4); // index d.Skip(8); // idk billboard settings and padding Bone n = new Bone(v); n.scale = new float[3]; n.position = new float[3]; n.rotation = new float[3]; d.Skip(4); // index n.scale[0] = d.ReadFloat(); n.scale[1] = d.ReadFloat(); n.scale[2] = d.ReadFloat(); n.rotation[0] = toRadians(d.ReadFloat()); n.rotation[1] = toRadians(d.ReadFloat()); n.rotation[2] = toRadians(d.ReadFloat()); n.position[0] = d.ReadFloat(); n.position[1] = d.ReadFloat(); n.position[2] = d.ReadFloat(); n.pos = new Vector3(n.position[0], n.position[1], n.position[2]); n.sca = new Vector3(n.scale[0], n.scale[1], n.scale[2]); n.rot = (VBN.FromEulerAngles(n.rotation [2], n.rotation [1], n.rotation [0])); d.Skip(24); d.Seek(data + 0x5C); d.Seek(d.ReadInt() + data + 12); int parentid = 0x0FFFFFFF; if (d.Pos() != data + 12) { parentid = d.ReadInt(); } n.parentIndex = (int)parentid; n.Text = d.ReadString(nameOff, -1); n.boneId = boneID; boneID++; v.bones.Add(n); } else { bseccount++; } d.Seek(temp); } v.update(); //v.updateChildren(); v.boneCountPerType[0] = (uint)v.bones.Count; return(v); }
public void NextFrame(VBN vbn, bool isChild = false) { if (frame >= frames.Count) { return; } if (frame == 0 && (!isChild || children.Count > 0)) { vbn.reset(); /*foreach (ModelContainer con in Runtime.ModelContainers) * { * if (con.NUD != null && con.mta != null) * { * con.NUD.applyMTA(con.mta, 0); * } * }*/ } foreach (object child in children) { if (child is SkelAnimation) { ((SkelAnimation)child).SetFrame(frame); ((SkelAnimation)child).NextFrame(vbn, isChild: true); } if (child is MTA) { /*foreach(ModelContainer con in Runtime.ModelContainers) * { * if(con.NUD != null) * { * con.NUD.applyMTA(((MTA)child), frame); * } * }*/ } } KeyFrame key = frames[frame]; foreach (KeyNode n in key.nodes) { //if (n.id == -1) // continue; //if (n.hash == 0) { //continue; //n.hash = vbn.bones [n.id].boneId; //} int id = -1; foreach (Bone bo in vbn.bones) { if (bo.boneId == n.hash) { id = vbn.bones.IndexOf(bo); n.id = id; break; } } if (id == -1) { continue; } Bone b = vbn.bones[id]; if (n.tType != -1)// !b.isSwingBone) { b.pos = n.t; } // We don't do the same swingBone check on rotation because as of yet // I have not seen an example of the rotation data being garbage, and it's // actually used properly in the animations - Struz if (n.rType != -1) { if (b.Text.Equals("HeadN")) { //Console.WriteLine(b.transform.ExtractRotation().ToString()); //Console.WriteLine(VBN.FromEulerAngles(b.rotation[0], b.rotation[1], b.rotation[2]).ToString()); //Console.WriteLine(n.r.ToString() + " " + Math.Sqrt(n.r.X* n.r.X + n.r.Y* n.r.Y + n.r.Z* n.r.Z + n.r.W*n.r.W) + " " + n.r.Normalized().ToString()); } //Console.WriteLine(new string(b.boneName) + " " + b.rot.ToString() + " " + n.r.ToString() + "\n" + (n.r.X + n.r.Y + n.r.X + n.r.W)); b.rot = n.r; } if (n.sType != -1) { b.sca = n.s; } else { b.sca = new Vector3(b.scale[0], b.scale[1], b.scale[2]); } } frame++; if (frame >= frames.Count) { frame = 0; } vbn.update(); }