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()); }