public SkelAnimation BakeToSkel(VBN skel) { SkelAnimation a = new SkelAnimation(); for (int i = 1; i < anim.frameCount + 1; i++) { a.frames.Add(new KeyFrame()); } for (int i = 0; i < anim.nodes.Count; i++) { Frame[] frames = Bake(i); int fr = 0; foreach (Frame f in frames) { if (fr == 0) { fr++; continue; } if (i >= skel.bones.Count) { continue; } KeyFrame frame = a.frames[fr - 1]; KeyNode node = new KeyNode(); frame.nodes.Add(node); node.hash = skel.bones[i].boneId; node.tType = 1; node.rType = 1; node.sType = 1; node.t.X = f.x != -99 ? f.x : skel.bones[i].position[0]; node.t.Y = f.y != -99 ? f.y : skel.bones[i].position[1]; node.t.Z = f.z != -99 ? f.z : skel.bones[i].position[2]; node.r.X = f.rx != -99 ? f.rx * (float)Math.PI / 180 : skel.bones[i].rotation[0]; node.r.Y = f.ry != -99 ? f.ry * (float)Math.PI / 180 : skel.bones[i].rotation[1]; node.r.Z = f.rz != -99 ? f.rz * (float)Math.PI / 180 : skel.bones[i].rotation[2]; node.s.X = f.sx != -99 ? f.sx : skel.bones[i].scale[0]; node.s.Y = f.sy != -99 ? f.sy : skel.bones[i].scale[1]; node.s.Z = f.sz != -99 ? f.sz : skel.bones[i].scale[2]; node.r = VBN.FromEulerAngles(node.r.Z, node.r.Y, node.r.X); fr++; } } return(a); }
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 KeyNode GetNode(int i) { for (int j = 0; j < nodes.Count; j++) { if (nodes[j].id == i) { return(nodes[j]); } } KeyNode ne = new KeyNode(); ne.id = i; AddNode(ne); return(ne); }
public static void MakePichu(string path = "C:\\Pichu\\") { if (!path.EndsWith("\\")) { path += "\\"; } DAT dat = new DAT(); dat.Read(new FileData(path + "PlPcNr.dat")); dat.PreRender(); dat.ExportTextures(path, 0x401B1000); BoneNameFix(dat.bones); // model-------------------------------------------------------- ModelContainer converted = dat.wrapToNUD(); Nud nud = converted.NUD; float sca = 0.6f; removeLowPolyNr(nud); nud.UpdateRenderMeshes(); //Runtime.ModelContainers.Add(converted); //------------------------------------------------- Runtime.TargetVbn = converted.VBN; MainForm.HashMatch(); Dictionary <string, SkelAnimation> anims = DAT_Animation.LoadAJ(path + "PlPcAJ.dat", converted.VBN); //ArrangeBones(converted.vbn, converted.nud); // note bone 40 - 51 is disabled for pika foreach (string an in anims.Keys) { effectiveScale(anims[an], Matrix4.CreateTranslation(0, 0, 0) * Matrix4.CreateScale(sca, sca, sca)); } effectiveScale(converted.NUD, converted.VBN, Matrix4.CreateTranslation(0, 0, 0) * Matrix4.CreateScale(sca, sca, sca)); Directory.CreateDirectory(path + "build\\model\\body\\c00\\"); nud.Save(path + "build\\model\\body\\c00\\model.nud"); converted.VBN.Endian = Endianness.Little; converted.VBN.Save(path + "build\\model\\body\\c00\\model.vbn"); PAC org = new PAC(); PAC npac = new PAC(); org.Read(path + "main.pac"); foreach (string key in org.Files.Keys) { byte[] d = org.Files[key]; foreach (string an in anims.Keys) { string name = an.Replace("PlyPichu5K_Share_ACTION_", "").Replace("_figatree", ""); if (key.Contains(name)) { Console.WriteLine("Matched " + name + " with " + key); if (!anims[an].GetNodes(true).Contains(0) && !key.Contains("Cliff")) { KeyNode node = anims[an].GetNode(0, 0); node.tType = 1; } d = OMOOld.createOMO(anims[an], converted.VBN); break; } } npac.Files.Add(key, d); } Directory.CreateDirectory(path + "build\\motion\\"); npac.Save(path + "build\\motion\\main.pac"); /*FileOutput omo = new FileOutput(); * converted.vbn.reset(); * converted.vbn.totalBoneCount = (uint)converted.vbn.bones.Count; * omo.writeBytes(OMO.createOMO(anims["PlyPichu5K_Share_ACTION_Wait1_figatree"], converted.vbn)); * omo.save(path + "PlyPichu5K_Share_ACTION_Wait1_figatree.omo");*/ }
public static Animation read(FileData d) { d.endian = Endianness.Big; d.Skip(4); // header OMO d.Skip(4); // two shorts, idk d.Skip(4); //flags? d.Skip(2); int boneCount = d.ReadUShort(); int frameCount = d.ReadUShort(); int frameSize = d.ReadUShort(); int offset1 = d.ReadInt(); // nodeOffset int offset2 = d.ReadInt(); // interOffset int offset3 = d.ReadInt(); // keyOffset SkelAnimation anim = new SkelAnimation(); anim.tag = d; if (boneCount > offset2 / 0x10) { boneCount = offset2 / 0x10; anim.tag = null; } // base frames // These are linked to bones via hashes d.Seek(offset1); // int[] framekey = new int[boneCount]; KeyNode[] baseNode = new KeyNode[boneCount]; // Start positions for bones/nodes for (int i = 0; i < boneCount; i++) { flagsused = flagsused | d.ReadInt(); d.Seek(d.Pos() - 4); //Console.WriteLine(flagsused.ToString("x")); int flags = d.ReadByte(); int tFlag = d.ReadByte(); int rFlag = d.ReadByte(); int sFlag = d.ReadByte(); int hash = d.ReadInt(); // used to find the identifying bone int off1 = d.ReadInt() + offset2; framekey[i] = d.ReadInt(); bool hasTrans = (flags & 0x01) == 0x01; bool hasScale = (flags & 0x04) == 0x04; bool hasRot = (flags & 0x02) == 0x02; KeyNode node = new KeyNode(); baseNode[i] = node; node.hash = (uint)hash; int temp = d.Pos(); d.Seek(off1); if (hasTrans) { if (tFlag == 0x8) { // interpolated node.tType = KeyNode.Interpolated; node.t = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); node.t2 = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); } else if (tFlag == 0x20) { node.tType = KeyNode.Constant; node.t = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); } else if (tFlag == 0x4) { // entire Vector3 provided in keyframe data i.e. KEYFRAME type node.tType = KeyNode.Keyframe; } } if (hasRot) { if ((rFlag & 0xF0) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0) { //Console.WriteLine(rFlag); } if ((rFlag & 0xF0) == 0xA0) { // All data is in the keyframe for this type node.rType = KeyNode.Compressed; } if ((rFlag & 0xF0) == 0x50) { // interpolated node.rType = KeyNode.Interpolated; node.rv = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); node.rv2 = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); } if ((rFlag & 0xF0) == 0x60) { node.rType = KeyNode.Keyframe; node.rv = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); node.rExtra = d.ReadFloat() / 65535; } if ((rFlag & 0xF0) == 0x70) { node.rType = KeyNode.Constant; node.rv = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); } } if (hasScale) { if ((sFlag & 0xF0) == 0x80) { // interpolated node.sType = KeyNode.Interpolated; node.s = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); node.s2 = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); } // TODO: investigate the difference between these if ((rFlag & 0x0F) == 0x02 || (rFlag & 0x0F) == 0x03) { // constant node.sType = KeyNode.Constant; node.s = new Vector3(d.ReadFloat(), d.ReadFloat(), d.ReadFloat()); } } d.Seek(temp); } // Interpolated type below here is always a set translation/rotation/scale // from the coords specified with the bone node above Animation a = new Animation("Anim"); a.Tag = anim.tag; a.frameCount = frameCount; d.Seek(offset3); for (int j = 0; j < boneCount; j++) { string bid = ""; int hash = -1; if (!MainForm.hashes.ids.TryGetValue(baseNode[j].hash, out bid)) { hash = (int)baseNode[j].hash; } Animation.KeyNode n = new Animation.KeyNode(bid); n.hash = hash; a.bones.Add(n); n.type = Animation.BoneType.Normal; /*foreach (ModelContainer con in Runtime.ModelContainers) * if (con.VBN != null) * bid = con.VBN.getBone(baseNode[j].hash) == null ? "" : con.VBN.getBone(baseNode[j].hash).Text;*/ for (int i = 0; i < a.frameCount; i++) { d.Seek(offset3 + frameSize * i + framekey[j]); if (baseNode[j].tType == KeyNode.Interpolated) { float i1 = ((float)d.ReadUShort() / 0xffff); float i2 = ((float)d.ReadUShort() / 0xffff); float i3 = ((float)d.ReadUShort() / 0xffff); float x = baseNode[j].t.X + (baseNode[j].t2.X * (i1)); float y = baseNode[j].t.Y + (baseNode[j].t2.Y * (i2)); float z = baseNode[j].t.Z + (baseNode[j].t2.Z * (i3)); //node.t = new Vector3(x, y, z); // Translation n.xpos.keys.Add(new Animation.KeyFrame(x, i)); n.ypos.keys.Add(new Animation.KeyFrame(y, i)); n.zpos.keys.Add(new Animation.KeyFrame(z, i)); } else if (baseNode[j].tType == KeyNode.Constant) { //node.t = baseNode[j].t; n.xpos.keys.Add(new Animation.KeyFrame(baseNode[j].t.X, i)); n.ypos.keys.Add(new Animation.KeyFrame(baseNode[j].t.Y, i)); n.zpos.keys.Add(new Animation.KeyFrame(baseNode[j].t.Z, i)); } else if (baseNode[j].tType == 2) { float x = d.ReadFloat(); float y = d.ReadFloat(); float z = d.ReadFloat(); //node.t = new Vector3(x, y, z); n.xpos.keys.Add(new Animation.KeyFrame(x, i)); n.ypos.keys.Add(new Animation.KeyFrame(y, i)); n.zpos.keys.Add(new Animation.KeyFrame(z, i)); } if (baseNode[j].rType == KeyNode.Compressed) { // There are 64 bits present for each node of this rot type // The format is: 20bits * 3 of encoded floats, and 4 bits of flags // The flags describe which 3 components of the quaternion are being presented int b1 = d.ReadByte(); int b2 = d.ReadByte(); int b3 = d.ReadByte(); int b4 = d.ReadByte(); int b5 = d.ReadByte(); int b6 = d.ReadByte(); int b7 = d.ReadByte(); int b8 = d.ReadByte(); // Capture 20 bits at a time of the raw data int f1 = (b1 << 12) | (b2 << 4) | ((b3 & 0xF0) >> 4); int f2 = ((b3 & 0xF) << 16) | (b4 << 8) | b5; int f3 = (b6 << 12) | (b7 << 4) | ((b8 & 0xF0) >> 4); int flags = b8 & 0xF; Quaternion r = new Quaternion(); switch (flags) { case 0: // y, z, w provided r.Y = encodedRot10ToQuaternionComponent(f1); r.Z = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.X = (float)Math.Sqrt(Math.Abs(1 - (r.Y * r.Y + r.Z * r.Z + r.W * r.W))); break; case 1: // x, z, w provided r.X = encodedRot10ToQuaternionComponent(f1); r.Z = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.Y = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Z * r.Z + r.W * r.W))); break; case 2: // x, y, w provided r.X = encodedRot10ToQuaternionComponent(f1); r.Y = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.Z = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.W * r.W))); break; case 3: // x, y, z, provided r.X = encodedRot10ToQuaternionComponent(f1); r.Y = encodedRot10ToQuaternionComponent(f2); r.Z = encodedRot10ToQuaternionComponent(f3); r.W = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.Z * r.Z))); break; default: Console.WriteLine("Unknown rotation type3 flags: " + flags); break; } n.rotType = Animation.RotationType.Quaternion; n.xrot.keys.Add(new Animation.KeyFrame(r.X, i)); n.yrot.keys.Add(new Animation.KeyFrame(r.Y, i)); n.zrot.keys.Add(new Animation.KeyFrame(r.Z, i)); n.wrot.keys.Add(new Animation.KeyFrame(r.W, i)); } else if (baseNode[j].rType == KeyNode.Interpolated) { float i1 = ((float)d.ReadUShort() / (0xffff)); float i2 = ((float)d.ReadUShort() / (0xffff)); float i3 = ((float)d.ReadUShort() / (0xffff)); float x = baseNode[j].rv.X + (baseNode[j].rv2.X * (i1)); float y = baseNode[j].rv.Y + (baseNode[j].rv2.Y * (i2)); float z = baseNode[j].rv.Z + (baseNode[j].rv2.Z * (i3)); float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z))); Quaternion r = new Quaternion(new Vector3(x, y, z), w); r.Normalize(); n.rotType = Animation.RotationType.Quaternion; n.xrot.keys.Add(new Animation.KeyFrame(r.X, i)); n.yrot.keys.Add(new Animation.KeyFrame(r.Y, i)); n.zrot.keys.Add(new Animation.KeyFrame(r.Z, i)); n.wrot.keys.Add(new Animation.KeyFrame(r.W, i)); } else if (baseNode[j].rType == KeyNode.Keyframe) { float scale = d.ReadUShort() * baseNode[j].rExtra; float x = baseNode[j].rv.X; float y = baseNode[j].rv.Y; float z = baseNode[j].rv.Z + scale; float w = rot6CalculateW(x, y, z); Quaternion r = new Quaternion(x, y, z, w); n.rotType = Animation.RotationType.Quaternion; n.xrot.keys.Add(new Animation.KeyFrame(r.X, i)); n.yrot.keys.Add(new Animation.KeyFrame(r.Y, i)); n.zrot.keys.Add(new Animation.KeyFrame(r.Z, i)); n.wrot.keys.Add(new Animation.KeyFrame(r.W, i)); } else { float x = baseNode[j].rv.X; float y = baseNode[j].rv.Y; float z = baseNode[j].rv.Z; float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z))); Quaternion r = new Quaternion(baseNode[j].rv, w); r.Normalize(); n.rotType = Animation.RotationType.Quaternion; n.xrot.keys.Add(new Animation.KeyFrame(r.X, i)); n.yrot.keys.Add(new Animation.KeyFrame(r.Y, i)); n.zrot.keys.Add(new Animation.KeyFrame(r.Z, i)); n.wrot.keys.Add(new Animation.KeyFrame(r.W, i)); } if (baseNode[j].sType == KeyNode.Interpolated) { float i1 = ((float)d.ReadUShort() / (0xffff)); float i2 = ((float)d.ReadUShort() / (0xffff)); float i3 = ((float)d.ReadUShort() / (0xffff)); float x = baseNode[j].s.X + (baseNode[j].s2.X * (i1)); float y = baseNode[j].s.Y + (baseNode[j].s2.Y * (i2)); float z = baseNode[j].s.Z + (baseNode[j].s2.Z * (i3)); //node.s = new Vector3(x, y, z); n.xsca.keys.Add(new Animation.KeyFrame(x, i)); n.ysca.keys.Add(new Animation.KeyFrame(y, i)); n.zsca.keys.Add(new Animation.KeyFrame(z, i)); } else { //node.s = baseNode[j].s; n.xsca.keys.Add(new Animation.KeyFrame(baseNode[j].s.X, i)); n.ysca.keys.Add(new Animation.KeyFrame(baseNode[j].s.Y, i)); n.zsca.keys.Add(new Animation.KeyFrame(baseNode[j].s.Z, i)); } } } return(a); }
public static byte[] createOMO(SkelAnimation a, VBN vbn) { List <int> nodeid = a.GetNodes(true, vbn); int startNode = 0; int sizeNode = nodeid.Count; 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(sizeNode); // numOfNodes o.WriteShort(a.frames.Count); // frame size o.WriteShort(0); // frame start ?? o.WriteInt(0); o.WriteInt(0); o.WriteInt(0); o.WriteIntAt(o.Size(), 0x14); // ASSESSMENT KeyNode[] minmax = new KeyNode[sizeNode]; bool[] hasScale = new bool[sizeNode]; bool[] hasTrans = new bool[sizeNode]; bool[] hasRot = new bool[sizeNode]; bool[] conScale = new bool[sizeNode]; bool[] conTrans = new bool[sizeNode]; bool[] conRot = new bool[sizeNode]; a.SetFrame(0); List <List <Bone> > Frames = new List <List <Bone> >(); VBN tempvbn = new VBN(); for (int i = 0; i < a.Size(); i++) { a.NextFrame(vbn, true); List <Bone> bonelist = new List <Bone>(); for (int j = 0; j < nodeid.Count; j++) { Bone node = getNodeId(vbn, nodeid[j]); Bone f1 = new Bone(tempvbn); f1.pos = node.pos; f1.rot = node.rot; f1.sca = node.sca; bonelist.Add(f1); if (minmax[j] == null) { hasRot[j] = false; hasScale[j] = false; hasTrans[j] = false; KeyNode n = a.GetFirstNode(nodeid[j]); if (n != null) { if (n.rType != -1) { hasRot[j] = true; } if (n.tType != -1) { hasTrans[j] = true; } if (n.sType != -1) { hasScale[j] = true; } } minmax[j] = new KeyNode(); minmax[j].t = new Vector3(999f, 999f, 999f); minmax[j].r = new Quaternion(999f, 999f, 999f, 999f); minmax[j].s = new Vector3(999f, 999f, 999f); minmax[j].t2 = new Vector3(-999f, -999f, -999f); minmax[j].r2 = new Quaternion(-999f, -999f, -999f, -999f); minmax[j].s2 = new Vector3(-999f, -999f, -999f); } if (node.pos.X < minmax[j].t.X) { minmax[j].t.X = node.pos.X; } if (node.pos.X > minmax[j].t2.X) { minmax[j].t2.X = node.pos.X; } if (node.pos.Y < minmax[j].t.Y) { minmax[j].t.Y = node.pos.Y; } if (node.pos.Y > minmax[j].t2.Y) { minmax[j].t2.Y = node.pos.Y; } if (node.pos.Z < minmax[j].t.Z) { minmax[j].t.Z = node.pos.Z; } if (node.pos.Z > minmax[j].t2.Z) { minmax[j].t2.Z = node.pos.Z; } // float[] fix = Node.fix360(node.nrx, node.nry, node.nrz); //float[] f = Bone.CalculateRotation(node.nrx, node.nry, node.nrz); Quaternion r = node.rot; if (r.X < minmax[j].r.X) { minmax[j].r.X = r.X; } if (r.X > minmax[j].r2.X) { minmax[j].r2.X = r.X; } if (r.Y < minmax[j].r.Y) { minmax[j].r.Y = r.Y; } if (r.Y > minmax[j].r2.Y) { minmax[j].r2.Y = r.Y; } if (r.Z < minmax[j].r.Z) { minmax[j].r.Z = r.Z; } if (r.Z > minmax[j].r2.Z) { minmax[j].r2.Z = r.Z; } if (node.sca.X < minmax[j].s.X) { minmax[j].s.X = node.sca.X; } if (node.sca.X > minmax[j].s2.X) { minmax[j].s2.X = node.sca.X; } if (node.sca.Y < minmax[j].s.Y) { minmax[j].s.Y = node.sca.Y; } if (node.sca.Y > minmax[j].s2.Y) { minmax[j].s2.Y = node.sca.Y; } if (node.sca.Z < minmax[j].s.Z) { minmax[j].s.Z = node.sca.Z; } if (node.sca.Z > minmax[j].s2.Z) { minmax[j].s2.Z = node.sca.Z; } } } // NODE INFO int t2Size = 0; for (int i = 0; i < sizeNode; i++) { int flag = 0; conRot[i] = false; conScale[i] = false; conTrans[i] = false; // check for constant if (minmax[i].t.Equals(minmax[i].t2)) { conTrans[i] = true; } if (minmax[i].r.Equals(minmax[i].r2)) { conRot[i] = true; } if (minmax[i].s.Equals(minmax[i].s2)) { 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; int hash = -1; if (MainForm.hashes.names.ContainsKey(getNodeId(vbn, nodeid[i]).Text)) { hash = (int)MainForm.hashes.names[getNodeId(vbn, nodeid[i]).Text]; } //else hash = (int)FileData.crc12(getNodeId(vbn, nodeid[i]).Text); 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(minmax[i].t.X); t1.WriteFloat(minmax[i].t.Y); t1.WriteFloat(minmax[i].t.Z); if (!conTrans[i]) { minmax[i].t2.X -= minmax[i].t.X; minmax[i].t2.Y -= minmax[i].t.Y; minmax[i].t2.Z -= minmax[i].t.Z; t1.WriteFloat(minmax[i].t2.X); t1.WriteFloat(minmax[i].t2.Y); t1.WriteFloat(minmax[i].t2.Z); t2Size += 6; } } if (hasRot[i]) { t1.WriteFloat(minmax[i].r.X); t1.WriteFloat(minmax[i].r.Y); t1.WriteFloat(minmax[i].r.Z); if (!conRot[i]) { minmax[i].r2.X -= minmax[i].r.X; minmax[i].r2.Y -= minmax[i].r.Y; minmax[i].r2.Z -= minmax[i].r.Z; t1.WriteFloat(minmax[i].r2.X); t1.WriteFloat(minmax[i].r2.Y); t1.WriteFloat(minmax[i].r2.Z); t2Size += 6; } } if (hasScale[i]) { t1.WriteFloat(minmax[i].s.X); t1.WriteFloat(minmax[i].s.Y); t1.WriteFloat(minmax[i].s.Z); if (!conScale[i]) { minmax[i].s2.X -= minmax[i].s.X; minmax[i].s2.Y -= minmax[i].s.Y; minmax[i].s2.Z -= minmax[i].s.Z; t1.WriteFloat(minmax[i].s2.X); t1.WriteFloat(minmax[i].s2.Y); t1.WriteFloat(minmax[i].s2.Z); t2Size += 6; } } } o.WriteIntAt(o.Size(), 0x18); o.WriteOutput(t1); o.WriteIntAt(o.Size(), 0x1C); // INTERPOLATION //a.setFrame(0); bool go = false; foreach (List <Bone> bonelist in Frames) { //a.nextFrame(vbn); int j = 0; foreach (Bone node in bonelist) { //Bone node = getNodeId(vbn, nodeid[j]); if (hasTrans[j] && !conTrans[j]) { t2.WriteShort((int)(((node.pos.X - minmax[j].t.X) / minmax[j].t2.X) * 0xFFFF)); t2.WriteShort((int)(((node.pos.Y - minmax[j].t.Y) / minmax[j].t2.Y) * 0xFFFF)); t2.WriteShort((int)(((node.pos.Z - minmax[j].t.Z) / minmax[j].t2.Z) * 0xFFFF)); } if (hasRot[j] && !conRot[j]) { // float[] fix = Node.fix360(node.nrx, node.nry, node.nrz); //float[] f = CalculateRotation(node.nrx, node.nry, node.nrz); Quaternion r = node.rot; t2.WriteShort((int)(((r.X - minmax[j].r.X) / minmax[j].r2.X) * 0xFFFF)); t2.WriteShort((int)(((r.Y - minmax[j].r.Y) / minmax[j].r2.Y) * 0xFFFF)); t2.WriteShort((int)(((r.Z - minmax[j].r.Z) / minmax[j].r2.Z) * 0xFFFF)); } if (hasScale[j] && !conScale[j]) { t2.WriteShort((int)(((node.sca.X - minmax[j].s.X) / minmax[j].s2.X) * 0xFFFF)); t2.WriteShort((int)(((node.sca.Y - minmax[j].s.Y) / minmax[j].s2.Y) * 0xFFFF)); t2.WriteShort((int)(((node.sca.Z - minmax[j].s.Z) / minmax[j].s2.Z) * 0xFFFF)); } j++; } if (!go) { o.WriteShortAt(t2.Size(), 0x12); go = true; } } o.WriteOutput(t2); return(o.GetBytes()); }
/*public void readStageAnim() * { * FileData d = new FileData("C:\\Users\\ploaj_000\\Desktop\\Melee\\GrIz.dat"); * d.Endian = System.IO.Endianness.Big; * Debug = true; * readKeyFrame(d, 8, 0x107300, 0x04, 0x00, 0x08, 0, 0x06); * }*/ public void readKeyFrame(FileData d, int length, int dataoff, int valueFormat, int tanFormat, int keyframeCount, int boneId, int trackType) { int temp = d.Pos(); d.Seek(dataoff); if (Debug) { Console.WriteLine("Start 0x" + d.Pos() + " " + keyframeCount); } DATAnimTrack track = new DATAnimTrack(); track.type = (AnimType)trackType; nodes[boneId].Add(track); while (d.Pos() < dataoff + length) { int type = readExtendedByte(d); int interpolation = ((type) & 0x0F); int numOfKey = ((type >> 4) & 0xFF) + 1; if (Debug) { Console.WriteLine("Interpolation type: " + (InterpolationType)interpolation + "\tnumofkey: " + numOfKey); } for (int i = 0; i < numOfKey; i++) { double value = -99, tan = -99; int time = 0; if (interpolation == 1) { // step value = readVal(d, valueFormat); time = readExtendedByte(d); if (Debug) { Console.WriteLine("\t" + value + "\t" + time); } } if (interpolation == 2) { // linear value = readVal(d, valueFormat); time = readExtendedByte(d); //Console.WriteLine("\t" + value + "\t" + time); } if (interpolation == 3) { // hermite value = readVal(d, valueFormat); tan = 0; time = readExtendedByte(d); if (Debug) { Console.WriteLine("\t" + value + "\t" + time); } } if (interpolation == 4) { // hermite value = readVal(d, valueFormat); tan = readVal(d, tanFormat); time = readExtendedByte(d); if (Debug) { Console.WriteLine("\t" + value + "\t" + tan + "\t" + time); } } if (interpolation == 5) { // hermite tan = readVal(d, tanFormat); if (Debug) { Console.WriteLine("\t" + "Tan" + tan); } } if (interpolation == 6) { // constant value = readVal(d, valueFormat); time = readExtendedByte(d); //Console.WriteLine("\t" + value + "\t" + time); } KeyNode node = new KeyNode(); node.value = (float)value; node.frame = time; node.tan = (float)tan; node.interpolationType = (InterpolationType)interpolation; track.keys.Add(node); //node.boneID = boneId; } d.endian = System.IO.Endianness.Big; } //Console.WriteLine("Ends at: " + (d.pos() + 8 - (d.pos() % 8)).ToString("x")); d.Seek(temp); }
public static void generateInter(SkelAnimation anim, int max, int nid, String part, float[] frame, float[] tan, float[] step, VBN vbn) { int in2 = 0; int out2 = 1; float degrad = (float)(Math.PI / 180f); for (int i = 0; i < max; i++) { KeyNode n = anim.GetNode(i, nid); if (part.Contains("R")) { n.rType = 1; } else if (part.Contains("S")) { n.sType = 1; } else { n.tType = 1; } if (i > frame[out2]) { in2++; out2++; } float inv = frame[in2]; float tanin = tan[in2]; float stepin = step[in2]; if (frame[0] > i) { inv = 0; tanin = 0; stepin = anim.GetBaseNodeValue(nid, part, vbn); out2 = 0; in2 = 0; } if (frame[0] == i && out2 == 0) { out2 = 1; in2 = 0; } switch (part) { case "RX": n.r.X = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]) * degrad; break; case "RY": n.r.Y = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]) * degrad; break; case "RZ": n.r.Z = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]) * degrad; break; case "X": n.t.X = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]); break; case "Y": n.t.Y = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]); break; case "Z": n.t.Z = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]); break; case "SX": n.s.X = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]); break; case "SY": n.s.Y = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]); break; case "SZ": n.s.Z = interHermite(i, inv, frame[out2], tanin, tan[out2], stepin, step[out2]); break; } } }
/* * TODO: Fix this * the key frame needs to check if it occurs within a time frame AND * it has the node it is looking for */ public void BakeFramesLinear() { List <int> nodeids = GetNodes(false); List <KeyFrame> baseFrames = frames; frames = new List <KeyFrame>(); int fCount = 0; foreach (KeyFrame k in baseFrames) { if (k.frame > fCount) { fCount = k.frame; } } for (int i = 0; i < fCount; i++) { KeyFrame k = new KeyFrame(); k.frame = i; frames.Add(k); // add all the nodes at this frame foreach (int id in nodeids) { KeyFrame f1 = baseFrames[0], f2 = baseFrames[0]; if (baseFrames.Count > 1) { for (int j = 0; j < baseFrames.Count - 1; j++) { if (baseFrames[j].frame <= i && baseFrames[j + 1].frame >= i && baseFrames[j].Contains(id) && baseFrames[j + 1].Contains(id)) { f1 = baseFrames[j]; f2 = baseFrames[j + 1]; break; } } } // interpolate the values KeyNode n = new KeyNode(); n.id = id; KeyNode k1 = f1.GetNodeid(id), k2 = f2.GetNodeid(id); n.hash = k1.hash; n.tType = k1.tType; n.rType = k1.rType; n.sType = k1.sType; n.t.X = Lerp(k1.t.X, k2.t.X, f1.frame, f2.frame, i); n.t.Y = Lerp(k1.t.Y, k2.t.Y, f1.frame, f2.frame, i); n.t.Z = Lerp(k1.t.Z, k2.t.Z, f1.frame, f2.frame, i); n.r.X = Lerp(k1.r.X, k2.r.X, f1.frame, f2.frame, i); n.r.Y = Lerp(k1.r.Y, k2.r.Y, f1.frame, f2.frame, i); n.r.Z = Lerp(k1.r.Z, k2.r.Z, f1.frame, f2.frame, i); n.r.W = Lerp(k1.r.W, k2.r.W, f1.frame, f2.frame, i); //n.s.X = lerp (k1.s.X, k2.s.X, f1.frame, f2.frame, i); //n.s.Y = lerp (k1.s.Y, k2.s.Y, f1.frame, f2.frame, i); //n.s.Z = lerp (k1.s.Z, k2.s.Z, f1.frame, f2.frame, i); k.AddNode(n); } } }
public void AddNode(KeyNode n) { nodes.Add(n); }