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.t_type = 1; node.r_type = 1; node.s_type = 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); }
/* * 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> base_frames = frames; frames = new List <KeyFrame>(); int fCount = 0; foreach (KeyFrame k in base_frames) { 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 = base_frames[0], f2 = base_frames[0]; if (base_frames.Count > 1) { for (int j = 0; j < base_frames.Count - 1; j++) { if (base_frames[j].frame <= i && base_frames[j + 1].frame >= i && base_frames[j].contains(id) && base_frames[j + 1].contains(id)) { f1 = base_frames[j]; f2 = base_frames[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.t_type = k1.t_type; n.r_type = k1.r_type; n.s_type = k1.s_type; 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); }
public static SkelAnimation 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 numOfBones = d.readShort(); int frameSize = d.readShort(); int frameStart = d.readShort(); int offset1 = d.readInt(); int offset2 = d.readInt(); int offset3 = d.readInt(); SkelAnimation anim = new SkelAnimation(); anim.Tag = d; //anim.setModel(m); // base frames // These are linked to bones somehow, hash?? d.seek(offset1); // int[] framekey = new int[numOfBones]; KeyNode[] baseNode = new KeyNode[numOfBones]; for (int i = 0; i < numOfBones; i++) { 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.t_type = 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.t_type = KeyNode.CONSTANT; node.t = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } } if (hasRot) { if ((rFlag & 0xF) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0) { //Console.WriteLine(rFlag); } if ((rFlag & 0xF0) == 0xA0) { node.r_type = 3; } if ((rFlag & 0xF0) == 0x50) { // interpolated node.r_type = 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) == 0x70 || (rFlag & 0xF0) == 0x60) { // constant node.r_type = KeyNode.CONSTANT; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); if ((rFlag & 0xF0) == 0x60) { d.skip(4); } } } if (hasScale) { if ((sFlag & 0xF0) == 0x80) { // interpolated node.s_type = KeyNode.INTERPOLATED; node.s = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.s2 = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } if ((rFlag & 0x0F) == 0x02 || (rFlag & 0x0F) == 0x03) { // constant node.s_type = KeyNode.CONSTANT; node.s = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } } d.seek(temp); } d.seek(offset3); for (int i = 0; i < frameSize; i++) { KeyFrame key = new KeyFrame(); key.frame = i; int off = d.pos(); for (int j = 0; j < numOfBones; j++) { KeyNode node = new KeyNode(); node.t_type = baseNode[j].t_type; node.r_type = baseNode[j].r_type; node.s_type = baseNode[j].s_type; node.id = baseNode[j].id; node.hash = baseNode[j].hash; d.seek(off + framekey[j]); if (baseNode[j].t_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / 0xffff); float i2 = ((float)d.readShort() / 0xffff); float i3 = ((float)d.readShort() / 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); } else { node.t = baseNode[j].t; } if (baseNode[j].r_type == 3) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (0xffff)); float i4 = ((float)d.readShort() / (0xffff)); node.r = new Quaternion(new Vector3(i1, i2, i3), i4); //Console.WriteLine(node.r.ToString()); //node.r = VBN.FromEulerAngles(i4 * i1, i4 * i2, i4 * i3); node.r_type = KeyNode.INTERPOLATED; //node.r.Normalize(); } else if (baseNode[j].r_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (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))); node.r = new Quaternion(new Vector3(x, y, z), w); node.r.Normalize(); } else { float x = baseNode[j].rv.X; float y = baseNode[j].rv.Y; float z = baseNode[j].rv.Z; float w = (float)Math.Sqrt(1 - (x * x + y * y + z * z)); node.r = new Quaternion(baseNode[j].rv, w); } if (baseNode[j].s_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (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); } else { node.s = baseNode[j].s; } key.addNode(node); } d.seek(off + frameStart); anim.addKeyframe(key); } return(anim); }
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); for (int i = 0; i < a.size(); i++) { a.nextFrame(vbn); for (int j = 0; j < nodeid.Count; j++) { Bone node = getNodeId(vbn, nodeid[j]); if (minmax[j] == null) { hasRot[j] = false; hasScale[j] = false; hasTrans[j] = false; KeyNode n = a.getFirstNode(nodeid[j]); if (n != null) { if (n.r_type != -1) { hasRot[j] = true; } if (n.t_type != -1) { hasTrans[j] = true; } if (n.s_type != -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 = (int)getNodeId(vbn, nodeid[i]).boneId; //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(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); for (int i = 0; i < a.size(); i++) { a.nextFrame(vbn); for (int j = 0; j < nodeid.Count; j++) { 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)); } } if (i == 0) { o.writeShortAt(t2.size(), 0x12); } } o.writeOutput(t2); return(o.getBytes()); }
public static SkelAnimation read(string filename, VBN vbn) { StreamReader reader = File.OpenText(filename); string line; bool isHeader = true; string angularUnit, linearUnit, timeUnit; int startTime = 0; int endTime = 0; List <AnimBone> bones = new List <AnimBone>(); AnimBone current; AnimData att = new AnimData(); bool inKeys = false; while ((line = reader.ReadLine()) != null) { string[] args = line.Replace(";", "").TrimStart().Split(' '); if (isHeader) { if (args [0].Equals("anim")) { isHeader = false; } else if (args [0].Equals("angularUnit")) { angularUnit = args [1]; } else if (args [0].Equals("endTime")) { endTime = (int)Math.Ceiling(float.Parse(args [1])); } else if (args [0].Equals("startTime")) { startTime = (int)Math.Ceiling(float.Parse(args [1])); } } if (!isHeader) { if (inKeys) { if (args[0].Equals("}")) { inKeys = false; continue; } AnimKey k = new AnimKey(); att.keys.Add(k); k.input = float.Parse(args [0]); k.output = float.Parse(args [1]); k.intan = (args [2]); k.outtan = (args [3]); if (args.Length > 7 && att.weighted) { k.t1 = float.Parse(args[7]) * (float)(Math.PI / 180f); k.w1 = float.Parse(args[8]); } } if (args [0].Equals("anim")) { inKeys = false; if (args.Length == 5) { //TODO: finish this type // can be name of attribute } if (args.Length == 7) { // see of the bone of this attribute exists current = null; foreach (AnimBone b in bones) { if (b.name.Equals(args [3])) { current = b; break; } } if (current == null) { current = new AnimBone(); bones.Add(current); } current.name = args [3]; att = new AnimData(); att.type = args [2]; current.atts.Add(att); // row child attribute aren't needed here } } if (args [0].Equals("input")) { att.input = args [1]; } if (args [0].Equals("output")) { att.output = args [1]; } if (args [0].Equals("weighted")) { att.weighted = args [1].Equals("1"); } if (args [0].Equals("preInfinity")) { att.preInfinity = args [1]; } if (args [0].Equals("postInfinity")) { att.postInfinity = args [1]; } // begining keys section if (args [0].Contains("keys")) { inKeys = true; } } } SkelAnimation a = new SkelAnimation(); for (int i = 0; i < endTime - startTime + 1; i++) { KeyFrame key = new KeyFrame(); a.addKeyframe(key); foreach (AnimBone b in bones) { KeyNode n = new KeyNode(); n.id = vbn.boneIndex(b.name); if (n.id == -1) { continue; } else { n.hash = vbn.bones[n.id].boneId; } foreach (AnimData d in b.atts) { if (d.type.Contains("translate")) { n.t_type = KeyNode.INTERPOLATED; if (d.type.Contains("X")) { n.t.X = d.getValue(i); } if (d.type.Contains("Y")) { n.t.Y = d.getValue(i); } if (d.type.Contains("Z")) { n.t.Z = d.getValue(i); } } if (d.type.Contains("rotate")) { n.r_type = KeyNode.INTERPOLATED; if (d.type.Contains("X")) { n.r.X = d.getValue(i) * (float)(Math.PI / 180f); } if (d.type.Contains("Y")) { n.r.Y = d.getValue(i) * (float)(Math.PI / 180f); } if (d.type.Contains("Z")) { n.r.Z = d.getValue(i) * (float)(Math.PI / 180f); } } if (d.type.Contains("scale")) { n.s_type = KeyNode.INTERPOLATED; if (d.type.Contains("X")) { n.s.X = d.getValue(i); } if (d.type.Contains("Y")) { n.s.Y = d.getValue(i); } if (d.type.Contains("Z")) { n.s.Z = d.getValue(i); } } } key.addNode(n); } } // keynode rotations need caluclation foreach (KeyFrame f in a.frames) { foreach (KeyNode n in f.nodes) { n.r = VBN.FromEulerAngles(n.r.Z, n.r.Y, n.r.X); } } reader.Close(); return(a); }
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 createANIM(string fname, SkelAnimation a, VBN vbn) { using (System.IO.StreamWriter file = new System.IO.StreamWriter(@fname)) { file.WriteLine("animVersion 1.1;"); file.WriteLine("mayaVersion 2014 x64;\ntimeUnit ntscf;\nlinearUnit cm;\nangularUnit deg;\nstartTime 1;\nendTime " + (a.size()) + ";"); a.setFrame(a.size() - 1); //from last frame for (int li = 0; li < a.size(); ++li) //go through each frame with nextFrame { a.nextFrame(vbn); } a.nextFrame(vbn); //go on first frame List <int> nodes = a.getNodes(true, vbn); //getting node indexes int i = 0; // writing node attributes foreach (Bone b in vbn.getBoneTreeOrder()) { i = vbn.boneIndex(b.Text); if (nodes.Contains(i)) { // write the bone attributes // count the attributes KeyNode n = a.getNode(0, i); int ac = 0; if (n.t_type != -1) { file.WriteLine("anim translate.translateX translateX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "translateX", n.t_type); file.WriteLine("}"); file.WriteLine("anim translate.translateY translateY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "translateY", n.t_type); file.WriteLine("}"); file.WriteLine("anim translate.translateZ translateZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "translateZ", n.t_type); file.WriteLine("}"); } if (n.r_type != -1) { file.WriteLine("anim rotate.rotateX rotateX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "rotateX", n.r_type); file.WriteLine("}"); file.WriteLine("anim rotate.rotateY rotateY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "rotateY", n.r_type); file.WriteLine("}"); file.WriteLine("anim rotate.rotateZ rotateZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "rotateZ", n.r_type); file.WriteLine("}"); } if (n.s_type != -1) { file.WriteLine("anim scale.scaleX scaleX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "scaleX", n.s_type); file.WriteLine("}"); file.WriteLine("anim scale.scaleY scaleY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "scaleY", n.s_type); file.WriteLine("}"); file.WriteLine("anim scale.scaleZ scaleZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, a, i, "scaleZ", n.s_type); file.WriteLine("}"); } } else { file.WriteLine("anim " + b.Text + " 0 0 0;"); } } } }
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.r_type = 1; } else if (part.Contains("S")) { n.s_type = 1; } else { n.t_type = 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; } } }
public static void process(FileData d, int type, int secOff, SkelAnimation anim, String part, int nid, bool debug, VBN vbn) { int offset = d.readInt() + secOff; int temp = d.pos(); d.seek(offset); // System.out.println(d.pos()); int max = 0; int fCount = -1; float scale = 0; float[] frame = null, step = null, tan = null; if (type == 0x1) { fCount = d.readShort(); d.skip(2); scale = d.readFloat(); float stepb = d.readFloat(); float base2 = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readByte(); int th = d.readThree(); step[i] = base2 + ((th >> 12) & 0xfff) * stepb; tan[i] = (FileData.sign12Bit(th & 0xfff) / 32f); if (frame[i] > max) { max = (int)frame[i]; } } } if (type == 0x2) { //if(debug) //System.out.println(part + "\tInterpolated 6\t" + Integer.toHexString(offset)); fCount = d.readShort(); d.skip(2); scale = d.readFloat(); float stepb = d.readFloat(); float base2 = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readShort() / 32f; step[i] = base2 + d.readShort() * stepb; tan[i] = ((short)d.readShort() / 256f); if (frame[i] > max) { max = (int)frame[i]; } } } if (type == 0x3) { //if(debug) //System.out.println(part + "\tInterpolated 12 " + Integer.toHexString(offset)); fCount = d.readShort(); d.skip(2); scale = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readFloat(); step[i] = d.readFloat(); tan[i] = d.readFloat(); if (frame[i] > max) { max = (int)frame[i]; } } } if (frame != null) { generateInter(anim, max, nid, part, frame, tan, step, vbn); } if (type == 0x4) { //if(debug) //System.out.println(part + "\tLkin 1 " + Integer.toHexString(offset) + " " + anim.size()); float stepb = d.readFloat(); float base2 = d.readFloat(); for (int i = 0; i < anim.size(); i++) { KeyNode n = anim.getNode(i, nid); if (part.Contains("R")) { n.r_type = 1; } else if (part.Contains("S")) { n.s_type = 1; } else { n.t_type = 1; } float v = base2 + stepb * (d.readByte()); // float f = d.readFloat(); // System.out.println(stepb + " " + base + " " + (byte)d.readByte()); switch (part) { case "RX": n.r.X = (float)(Math.PI / 180f) * (v); break; case "RY": n.r.Y = (float)(Math.PI / 180f) * (v); break; case "RZ": n.r.Z = (float)(Math.PI / 180f) * (v); break; case "X": n.t.X = v; break; case "Y": n.t.Y = v; break; case "Z": n.t.Z = v; break; case "SX": n.s.X = v; break; case "SY": n.s.Y = v; break; case "SZ": n.s.Z = v; break; } } // System.out.println(d.pos()); } if (type == 0x6) { //if(debug) //System.out.println(part + "\tLin 4"); for (int i = 0; i < anim.size(); i++) { KeyNode n = anim.getNode(i, nid); if (part.Contains("R")) { n.r_type = 1; } else if (part.Contains("S")) { n.s_type = 1; } else { n.t_type = 1; } float v = d.readFloat(); switch (part) { case "RX": n.r.X = (float)(Math.PI / 180) * (v); break; case "RY": n.r.Y = (float)(Math.PI / 180) * (v); break; case "RZ": n.r.Z = (float)(Math.PI / 180) * (v); break; case "X": n.t.X = v; break; case "Y": n.t.Y = v; break; case "Z": n.t.Z = v; break; case "SX": n.s.X = v; break; case "SY": n.s.Y = v; break; case "SZ": n.s.Z = v; break; } } } d.seek(temp); }
public static SkelAnimation readAnim(FileData d, VBN m) { int offset = d.readInt(); int nameoff = d.readInt(); d.skip(4); int fCount = d.readShort(); int animDataCount = d.readShort(); d.skip(8); SkelAnimation anim = new SkelAnimation(); //anim.setModel(m); d.seek(offset); int sectionOffset = d.readInt() + offset; int size = d.readInt(); // size again for (int i = 0; i < size; i++) { // System.out.print(d.readShort()); // id d.skip(4); // id and unknown d.readShort(); //left d.readShort(); //right int nameOffset = d.readInt() + offset; int dataOffset = d.readInt() + offset; if (dataOffset == offset) { i--; continue; // d.skip(8); // nameOffset = d.readInt() + 4; // dataOffset = d.readInt() + offset; } int temp = d.pos(); d.seek(dataOffset); int pos = d.pos(); int nameOff = d.readInt() + sectionOffset + (d.pos() - sectionOffset) - 4; int flags = d.readInt(); int t_type = (flags >> 0x1e) & 0x3; int r_type = (flags >> 0x1b) & 0x7; int s_type = (flags >> 0x19) & 0x3; int hasT = (flags >> 0x18) & 0x1; int hasR = (flags >> 0x17) & 0x1; int hasS = (flags >> 0x16) & 0x1; int Zfixed = (flags >> 0x15) & 0x1; int Yfixed = (flags >> 0x14) & 0x1; int Xfixed = (flags >> 0x13) & 0x1; int RZfixed = (flags >> 0x12) & 0x1; int RYfixed = (flags >> 0x11) & 0x1; int RXfixed = (flags >> 0x10) & 0x1; int SZfixed = (flags >> 0xf) & 0x1; int SYfixed = (flags >> 0xe) & 0x1; int SXfixed = (flags >> 0xd) & 0x1; int Tiso = (flags >> 0x6) & 0x1; int Riso = (flags >> 0x5) & 0x1; int Siso = (flags >> 0x4) & 0x1; if (hasS == 1) { if (Siso == 1) { //System.out.println("S is ISO"); int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); node.s_type = 1; float iss = d.readFloat(); node.s = new OpenTK.Vector3(iss, iss, iss); } else { int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); node.s_type = 1; // System.out.println("Scale: " + SXfixed + " " + SYfixed + " " + SZfixed + " " + s_type); node.s = new OpenTK.Vector3(-99, -99, -99); if (SXfixed == 1) { node.s.X = d.readFloat(); } else { process(d, s_type, pos, anim, "SX", nid, false, m); } if (SYfixed == 1) { node.s.Y = d.readFloat(); } else { process(d, s_type, pos, anim, "SY", nid, false, m); } if (SZfixed == 1) { node.s.Z = d.readFloat(); } else { process(d, s_type, pos, anim, "SZ", nid, false, m); } } } if (hasR == 1) { if (Riso == 1) { //System.out.println("R is ISO"); int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); Console.WriteLine(nid.ToString("x")); KeyNode node = anim.getNode(0, nid); node.r_type = 1; float iss = (float)((d.readFloat()) * Math.PI / 180f); node.r = VBN.FromEulerAngles(iss, iss, iss); } else { int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); // System.out.println("Rot: " + RXfixed + " " + RYfixed + " " + RZfixed); node.r = new OpenTK.Quaternion(-99, -99, -99, 0); if (RXfixed == 1) { node.r.X = (float)(Math.PI / 180f) * (d.readFloat()); } else { process(d, r_type, pos, anim, "RX", nid, false, m); } if (RYfixed == 1) { node.r.Y = (float)(Math.PI / 180f) * (d.readFloat()); } else { process(d, r_type, pos, anim, "RY", nid, false, m); } if (RZfixed == 1) { node.r.Z = (float)(Math.PI / 180f) * (d.readFloat()); } else { process(d, r_type, pos, anim, "RZ", nid, false, m); } } } if (hasT == 1) { if (Tiso == 1) { //System.out.println("T is ISO"); int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); node.t_type = 1; float iss = d.readFloat(); node.t = new OpenTK.Vector3(iss, iss, iss); } else { int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); node.t_type = 1; // System.out.println("Trans: " + Xfixed + " " + Yfixed + " " + Zfixed); node.t = new OpenTK.Vector3(-99, -99, -99); if (Xfixed == 1) { node.t.X = d.readFloat(); } else { process(d, t_type, pos, anim, "X", nid, false, m); } if (Yfixed == 1) { node.t.Y = d.readFloat(); } else { process(d, t_type, pos, anim, "Y", nid, false, m); } if (Zfixed == 1) { node.t.Z = d.readFloat(); } else { process(d, t_type, pos, anim, "Z", nid, false, m); } } } d.seek(temp); } // keynode rotations need caluclation foreach (KeyFrame f in anim.frames) { foreach (KeyNode n in f.nodes) { n.r = VBN.FromEulerAngles(n.r.Z, n.r.Y, n.r.X); } } //anim.calcMax(); return(anim); }
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.readShort(); int frameCount = d.readShort(); int frameSize = d.readShort(); 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.t_type = 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.t_type = 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.t_type = 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.r_type = KeyNode.COMPRESSED; } if ((rFlag & 0xF0) == 0x50) { // interpolated node.r_type = 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.r_type = KeyNode.KEYFRAME; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.r_extra = d.readFloat() / 65535; } if ((rFlag & 0xF0) == 0x70) { node.r_type = KeyNode.CONSTANT; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } } if (hasScale) { if ((sFlag & 0xF0) == 0x80) { // interpolated node.s_type = 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.s_type = 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].t_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / 0xffff); float i2 = ((float)d.readShort() / 0xffff); float i3 = ((float)d.readShort() / 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].t_type == 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].t_type == 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].r_type == 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].r_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (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].r_type == KeyNode.KEYFRAME) { float scale = d.readShort() * baseNode[j].r_extra; 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].s_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (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); }
private static void writeKey(StreamWriter file, SkelAnimation a, int i, string type, int tt) { file.WriteLine("animData {\n input time;\n output linear;\n weighted 1;\n preInfinity constant;\n postInfinity constant;\n keys {"); int size = a.size(); if (tt == KeyNode.CONSTANT) { size = 1; } for (int f = 0; f < size; f++) { KeyNode node = a.getNode(f, i); float v = 0; switch (type) { case "translateX": v = node.t.X; break; case "translateY": v = node.t.Y; break; case "translateZ": v = node.t.Z; break; case "rotateX": v = quattoeul(node.r).X *(float)(180f / Math.PI); break; case "rotateY": v = quattoeul(node.r).Y *(float)(180f / Math.PI); break; case "rotateZ": v = quattoeul(node.r).Z *(float)(180f / Math.PI); break; case "scaleX": v = node.s.X; break; case "scaleY": v = node.s.Y; break; case "scaleZ": v = node.s.Z; break; } file.WriteLine(" " + (f + 1) + " {0:N6} fixed fixed 1 1 0 0 1 0 1;", v); } file.WriteLine(" }"); }
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.t_type = 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 void read(string fname, SkelAnimation a, VBN v) { StreamReader reader = File.OpenText(fname); string line; string current = ""; bool readBones = false; int frame = 0, prevframe = 0; KeyFrame k = new KeyFrame(); VBN vbn = v; if (v.bones.Count == 0) { readBones = true; } else { vbn = new VBN(); } while ((line = reader.ReadLine()) != null) { line = Regex.Replace(line, @"\s+", " "); string[] args = line.Replace(";", "").TrimStart().Split(' '); if (args[0].Equals("nodes") || args[0].Equals("skeleton") || args[0].Equals("end") || args[0].Equals("time")) { current = args[0]; if (args.Length > 1) { prevframe = frame; frame = int.Parse(args[1]); /*if (frame != prevframe + 1) { * Console.WriteLine ("Needs interpolation " + frame); * }*/ k = new KeyFrame(); k.frame = frame; a.addKeyframe(k); } continue; } if (current.Equals("nodes")) { Bone b = new Bone(vbn); b.Text = args[1].Replace("\"", ""); b.parentIndex = int.Parse(args[2]); //b.children = new System.Collections.Generic.List<int> (); vbn.totalBoneCount++; vbn.bones.Add(b); } if (current.Equals("time")) { KeyNode n = new KeyNode(); n.id = v.boneIndex(vbn.bones[int.Parse(args[0])].Text); if (n.id == -1) { continue; } else { n.hash = v.bones[n.id].boneId; } // only if it finds the node k.addNode(n); // reading the skeleton if this isn't an animation if (readBones && frame == 0) { Bone b = vbn.bones[n.id]; b.position = new float[3]; b.rotation = new float[3]; b.scale = new float[3]; b.position[0] = float.Parse(args[1]); b.position[1] = float.Parse(args[2]); b.position[2] = float.Parse(args[3]); b.rotation[0] = float.Parse(args[4]); b.rotation[1] = float.Parse(args[5]); b.rotation[2] = float.Parse(args[6]); b.scale[0] = 1f; b.scale[1] = 1f; b.scale[2] = 1f; b.pos = new Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3])); b.rot = VBN.FromEulerAngles(float.Parse(args[6]), float.Parse(args[5]), float.Parse(args[4])); //if(b.parentIndex!=-1) // vbn.bones [b.parentIndex].children.Add (int.Parse(args[0])); } n.t_type = KeyNode.INTERPOLATED; n.t = new Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3])); n.r_type = KeyNode.INTERPOLATED; n.r = VBN.FromEulerAngles(float.Parse(args[6]), float.Parse(args[5]), float.Parse(args[4])); } } v.boneCountPerType[0] = (uint)vbn.bones.Count; v.update(); a.bakeFramesLinear(); }