public void Write(FileOutput o) { Console.WriteLine($"Properties {{ // offset=0x{o.Size():X2}"); Console.WriteLine($"\tunk0: 0x{unk0:X8}"); Console.WriteLine($"\tunk1: 0x{unk1:X8}"); Console.WriteLine($"\tunk2: 0x{unk2:X8}"); Console.WriteLine($"\tmaxCharacterId: 0x{maxCharacterId:X8}"); Console.WriteLine($"\tunk4: 0x{unk4:X8}"); Console.WriteLine($"\tmaxCharacterId2: 0x{maxCharacterId2:X2}"); Console.WriteLine($"\tmaxDepth: 0x{maxDepth:X4}"); Console.WriteLine($"\tunk7: 0x{unk7:X4}"); Console.WriteLine($"\tframerate: {framerate}"); Console.WriteLine($"\tdimensions: {width}x{height}"); Console.WriteLine($"\tunk8: 0x{unk8:X8}"); Console.WriteLine($"\tunk9: 0x{unk9:X8}"); Console.WriteLine("}\n"); o.WriteInt((int)TagType.Properties); o.WriteInt(12); o.WriteInt((int)unk0); o.WriteInt((int)unk1); o.WriteInt((int)unk2); o.WriteInt((int)maxCharacterId); o.WriteInt(unk4); o.WriteInt((int)maxCharacterId2); o.WriteShort((short)maxDepth); o.WriteShort((short)unk7); o.WriteFloat(framerate); o.WriteFloat(width); o.WriteFloat(height); o.WriteInt((int)unk8); o.WriteInt((int)unk9); }
public override byte[] Rebuild() { FileOutput buf = new FileOutput(); buf.endian = Endianness.Little; var flagsOffset = 0x10; var entriesOffset = flagsOffset + (atlases.Count * 4); var stringsOffset = entriesOffset + (textures.Count * 0x20); buf.WriteInt(0x544C5354); // TLST buf.WriteShort(0); // idk buf.WriteShort((short)atlases.Count); buf.WriteShort((short)textures.Count); buf.WriteShort((short)flagsOffset); buf.WriteShort((short)entriesOffset); buf.WriteShort((short)stringsOffset); // flags foreach (var flag in atlases) { buf.WriteInt((int)flag); } // entries int namePtr = 0; foreach (var texture in textures) { buf.WriteInt(namePtr); buf.WriteInt(namePtr); namePtr += texture.name.Length + 1; buf.WriteFloat(texture.topLeft.X); buf.WriteFloat(texture.topLeft.Y); buf.WriteFloat(texture.botRight.X); buf.WriteFloat(texture.botRight.Y); buf.WriteShort(texture.width); buf.WriteShort(texture.height); buf.WriteShort(texture.atlasId); buf.WriteShort(0); // pad } //strings foreach (var texture in textures) { buf.WriteString(texture.name); buf.WriteByte(0); } buf.WriteByte(0); return(buf.GetBytes()); }
public int Rebuild(FileOutput o) { int size = o.Size(); o.WriteInt(hash); o.WriteInt(unk1); o.WriteByte(name.Length + 1); o.WriteString(name); o.WriteByte(0); o.Align(4); o.WriteInt(0); o.WriteInt(8); o.WriteInt(offset); o.WriteInt(this.size); // write data foreach (float f in param) { o.WriteFloat(f); } o.WriteInt(offsets.Length); foreach (int f in offsets) { o.WriteInt(f); } o.WriteInt(unkvalues.Length); int v = 0; foreach (float f in unkvalues) { o.WriteInt(v++); o.WriteFloat(f); } foreach (int f in unkending) { o.WriteInt(f); } foreach (int f in end) { o.WriteInt(f); } return(o.Size() - size); }
void writePositions(FileOutput o) { Console.WriteLine($"Positions = [ // offset=0x{o.Size():X2}"); o.WriteInt((int)TagType.Positions); o.WriteInt(Positions.Count * 2 + 1); o.WriteInt(Positions.Count); for (int i = 0; i < Positions.Count; i++) { var position = Positions[i]; Console.WriteLine($"\t0x{i:X4}: [{position.X}, {position.Y}] // offset=0x{o.Size():X2}"); o.WriteFloat(position.X); o.WriteFloat(position.Y); } Console.WriteLine("]\n"); }
public override byte[] Rebuild() { FileOutput f = new FileOutput(); f.endian = Endian; f.WriteUInt(0x0000FEFF); f.endian = Endianness.Big; f.WriteUInt(Magic); f.endian = Endian; f.WriteInt(0); // Always 0 f.WriteInt(Frames.Count); for (int i = 0; i < Frames.Count; i++) { f.WriteFloat(Frames[i].qx); f.WriteFloat(Frames[i].qy); f.WriteFloat(Frames[i].qz); f.WriteFloat(Frames[i].qw); f.WriteFloat(Frames[i].x); f.WriteFloat(Frames[i].y); f.WriteFloat(Frames[i].z); } return(f.GetBytes()); }
void writeBounds(FileOutput o) { Console.WriteLine($"Bounds = [ // offset=0x{o.Size():X2}"); o.WriteInt((int)TagType.Bounds); o.WriteInt(Bounds.Count * 4 + 1); o.WriteInt(Bounds.Count); for (int i = 0; i < Bounds.Count; i++) { var bb = Bounds[i]; Console.WriteLine($"\t0x{i:X2}: {bb} // offset=0x{o.Size():X2}"); o.WriteFloat(bb.TopLeft.X); o.WriteFloat(bb.TopLeft.Y); o.WriteFloat(bb.BottomRight.X); o.WriteFloat(bb.BottomRight.Y); } Console.WriteLine("]\n"); }
public void WriteDescription(FileOutput f) { // TODO: Calculate Length f.WriteInt(type.Length); for (int i = 0; i < type.Length; i++) { f.WriteInt(type[i]); f.WriteInt(format[i]); f.WriteFloat(scale[i]); } }
void writeTransforms(FileOutput o) { Console.WriteLine($"Transforms = [ // offset=0x{o.Size():X2}"); o.WriteInt((int)TagType.Transforms); o.WriteInt(Transforms.Count * 6 + 1); o.WriteInt(Transforms.Count); for (int i = 0; i < Transforms.Count; i++) { var transform = Transforms[i]; Console.WriteLine($"\t[{transform.M11:f2}, {transform.M21:f2}] // offset=0x{o.Size():X2}"); Console.WriteLine($"\t[{transform.M12:f2}, {transform.M22:f2}]"); Console.WriteLine($"\t[{transform.M41:f2}, {transform.M42:f2}]\n"); o.WriteFloat(transform.M11); o.WriteFloat(transform.M21); o.WriteFloat(transform.M12); o.WriteFloat(transform.M22); o.WriteFloat(transform.M41); o.WriteFloat(transform.M42); } Console.WriteLine("]\n"); }
public void Save(string filename) { FileOutput f = new FileOutput(); f.endian = System.IO.Endianness.Big; f.WriteChars("ATKD".ToCharArray()); f.WriteInt(entries.Count); f.WriteUInt(commonSubactions); f.WriteUInt(uniqueSubactions); foreach (Entry e in entries) { f.WriteUShort(e.subaction); f.WriteUShort(0); f.WriteUShort(e.startFrame); f.WriteUShort(e.lastFrame); f.WriteFloat(e.xmin); f.WriteFloat(e.xmax); f.WriteFloat(e.ymin); f.WriteFloat(e.ymax); } f.Save(filename); }
void writeAtlases(FileOutput o) { Console.WriteLine($"TextureAtlases = [ // offset=0x{o.Size():X2}"); o.WriteInt((int)TagType.TextureAtlases); o.WriteInt(Atlases.Count * 4 + 1); o.WriteInt(Atlases.Count); for (int i = 0; i < Atlases.Count; i++) { var atlas = Atlases[i]; Console.WriteLine($"\tatlas 0x{atlas.id:X2} {{ // offset=0x{o.Size():X2}"); Console.WriteLine($"\t\t\"name\": \"{Strings[atlas.nameId]}\""); Console.WriteLine($"\t\tdimensions: {atlas.width}x{atlas.height}"); Console.WriteLine("\t}\n"); o.WriteInt(atlas.id); o.WriteInt(atlas.nameId); o.WriteFloat(atlas.width); o.WriteFloat(atlas.height); } Console.WriteLine("]\n"); }
public static void WriteKeyData(Animation.KeyGroup group, FileOutput boneHeader, FileOutput keyData, FileOutput d_Main3, int start, ref int track) { if (group.keys.Count == 1) { boneHeader.WriteFloat(group.keys[0].Value); } else if (group.keys.Count == 0) { boneHeader.WriteInt(0); } else { int off = (group.keys.Count * 4); boneHeader.WriteOffset(start + keyData.Size(), d_Main3); // bone offset keyData.WriteFloat(0); keyData.WriteFloat(group.FrameCount); keyData.WriteInt(track++ << 16); // track keyData.WriteInt((group.keys.Count << 16) | 0x0701); // 7 is quantinization and 1 is linear interpolation float minv = 999, maxv = -999; float minf = 999, maxf = -999; foreach (Animation.KeyFrame key in group.keys) { minv = Math.Min(key.Value, minv); maxv = Math.Max(key.Value, maxv); minf = Math.Min(key.Frame, minf); maxf = Math.Max(key.Frame, maxf); } maxv -= minv; keyData.WriteFloat(maxv / 0xFFFFF); // value scale keyData.WriteFloat(minv); // value offset keyData.WriteFloat(1f); // frame scale keyData.WriteFloat(minf); // frame offset keyData.WriteOffset(start + keyData.Size() + 4, d_Main3); // useless flags foreach (Animation.KeyFrame key in group.keys) { keyData.WriteInt((((int)(((key.Value - minv) / (maxv)) * 0xFFFFF)) << 12) | (((int)(key.Frame - minf)) & 0xFFF)); } } //------ }
public int Rebuild(FileOutput o) { int size = o.Size(); o.WriteInt(hash); o.WriteInt(unk1); o.WriteByte(name.Length + 1); o.WriteString(name); o.WriteByte(0); o.Align(4); // write data foreach (float f in data) { o.WriteFloat(f); } return(o.Size() - size); }
private void WriteType(FileOutput d, float data) { switch (format) { case 0: d.WriteFloat(data / scale); break; case 1: d.WriteByte((byte)(data / scale)); break; case 2: d.WriteByte((byte)(data / scale)); break; case 3: d.WriteShort((short)(data / scale)); break; } }
private static void writeType(FileOutput d, float value, int format, float scale) { switch (format) { case 0: d.WriteFloat(value / scale); break; case 1: d.WriteByte((byte)(value / scale)); break; case 2: d.WriteByte((byte)(value / scale)); break; case 3: d.WriteShort((short)(value / scale)); break; } }
public byte[] Rebuild(int pos) { FileOutput f = new FileOutput(); f.endian = Endianness.Big; f.WriteInt(pos + f.Pos() + 0x20); f.WriteInt(unknown); f.WriteInt(valueCount); f.WriteInt(frames.Count); f.WriteShort(unknown2); f.WriteShort(animType); int position = pos + f.Pos() + 0xC + name.Length + 1; while (position % 0x10 != 0) { position++; } f.WriteInt(position); f.WriteBytes(new byte[8]); f.WriteString(name); f.WriteByte(0); while ((pos + f.Pos()) % 0x10 != 0) { f.WriteByte(0); } foreach (frame fr in frames) { for (int i = 0; i < valueCount; i++) { f.WriteFloat(fr.values[i]); } } f.WriteBytes(new byte[0x10]); return(f.GetBytes()); }
public void Write(FileOutput o) { o.WriteInt((int)TagType.DynamicText); o.WriteInt(16); o.WriteInt(CharacterId); o.WriteInt(unk1); o.WriteInt(placeholderTextId); o.WriteInt(unk2); o.WriteInt(strokeColorId); o.WriteInt(unk3); o.WriteInt(unk4); o.WriteInt(unk5); o.WriteShort((short)alignment); o.WriteShort(unk6); o.WriteInt(unk7); o.WriteInt(unk8); o.WriteFloat(size); o.WriteInt(unk9); o.WriteInt(unk10); o.WriteInt(unk11); o.WriteInt(unk12); }
public override byte[] Rebuild() { FileOutput file = new FileOutput(); if (file != null) { if (Endian == Endianness.Little) { file.endian = Endianness.Little; file.WriteString(" NBV"); file.WriteShort(0x02); file.WriteShort(0x01); } else if (Endian == Endianness.Big) { file.endian = Endianness.Big; file.WriteString("VBN "); file.WriteShort(0x01); file.WriteShort(0x02); } file.WriteInt(bones.Count); if (boneCountPerType[0] == 0) { boneCountPerType[0] = (uint)bones.Count; } List <Bone> Normal = new List <Bone>(); List <Bone> Unk = new List <Bone>(); List <Bone> Helper = new List <Bone>(); List <Bone> Swing = new List <Bone>(); string[] SpecialBones = new string[] { "TransN", "RotN", "HipN", "LLegJ", "LKneeJ", "LFootJ", "LToeN", "RLegJ", "RKneeJ", "RFootJ", "RToeN", "WaistN", "BustN", "LShoulderN", "LShoulderJ", "LArmJ", "LHandN", "RShoulderN", "RShoulderJ", "RArmJ", "RHandN", "NeckN", "HeadN", "RHaveN", "LHaveN", "ThrowN" }; Bone[] Special = new Bone[SpecialBones.Length]; int specialCount = 0; // OrderPass foreach (Bone b in bones) { for (int i = 0; i < SpecialBones.Length; i++) { if (b.Text.Equals(SpecialBones[i]) || (SpecialBones[i].Equals("RotN") && b.Text.Equals("XRotN"))) { specialCount++; Special[i] = b; break; } } } Console.WriteLine(SpecialBones.Length + " " + specialCount); if (specialCount == SpecialBones.Length) { Normal.AddRange(Special); } //Gather Each Bone Type foreach (Bone b in bones) { switch (b.boneType) { case 0: if (!Normal.Contains(b)) { Normal.Add(b); } break; case 2: Helper.Add(b); break; case 3: Swing.Add(b); break; default: Unk.Add(b); break; } } file.WriteInt(Normal.Count); file.WriteInt(Unk.Count); file.WriteInt(Helper.Count); file.WriteInt(Swing.Count); List <Bone> NewBoneOrder = new List <Bone>(); NewBoneOrder.AddRange(Normal); NewBoneOrder.AddRange(Unk); NewBoneOrder.AddRange(Helper); NewBoneOrder.AddRange(Swing); bones.Clear(); bones = NewBoneOrder; for (int i = 0; i < bones.Count; i++) { file.WriteString(bones[i].Text); for (int j = 0; j < 64 - bones[i].Text.Length; j++) { file.WriteByte(0); } file.WriteInt((int)bones[i].boneType); if (bones[i].parentIndex == -1) { file.WriteInt(0x0FFFFFFF); } else { file.WriteInt(bones[i].parentIndex); } file.WriteInt((int)bones[i].boneId); } for (int i = 0; i < bones.Count; i++) { file.WriteFloat(bones[i].position[0]); file.WriteFloat(bones[i].position[1]); file.WriteFloat(bones[i].position[2]); file.WriteFloat(bones[i].rotation[0]); file.WriteFloat(bones[i].rotation[1]); file.WriteFloat(bones[i].rotation[2]); file.WriteFloat(bones[i].scale[0]); file.WriteFloat(bones[i].scale[1]); file.WriteFloat(bones[i].scale[2]); } } return(file.GetBytes()); }
public static void Rebuild(string fname, List <Animation> animations) { // poopity doo da // headery deadery FileOutput o = new FileOutput(); o.WriteString("BCH"); o.Align(4); o.WriteByte(0x21); // version stuffs o.WriteByte(0x21); // version stuffs o.endian = System.IO.Endianness.Little; o.WriteShort(0xA755); // version FileOutput d_Main = new FileOutput(); d_Main.endian = System.IO.Endianness.Little; FileOutput d_Main2 = new FileOutput(); d_Main2.endian = System.IO.Endianness.Little; FileOutput d_Main3 = new FileOutput(); d_Main3.endian = System.IO.Endianness.Little; FileOutput d_String = new FileOutput(); d_String.endian = System.IO.Endianness.Little; FileOutput d_GPU = new FileOutput(); d_GPU.endian = System.IO.Endianness.Little; FileOutput d_Data = new FileOutput(); d_Data.endian = System.IO.Endianness.Little; FileOutput Reloc = new FileOutput(); Reloc.endian = System.IO.Endianness.Little; //Offsets o.WriteInt(0); //main o.WriteInt(0); //string o.WriteInt(0); //gpu o.WriteInt(0); //data o.WriteInt(0); //dataext o.WriteInt(0); //relocationtable //Length o.WriteInt(0); //main o.WriteInt(0); //string o.WriteInt(0); //gpu o.WriteInt(0); //data o.WriteInt(0); //dataext o.WriteInt(0); //relocationtable o.WriteInt(0); //datasection o.WriteInt(0); // o.WriteShort(1); //flag o.WriteShort(0); //addcount //Contents in the main header...... d_Main.WriteInt(0); // Model d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // Material d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // Shader d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // Texture d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // MaterialLUT d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // Lights d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // Camera d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // Fog d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); // SkeAnim { // Names need to be in patricia tree....... Dictionary <string, int> NameBank = new Dictionary <string, int>(); NameBank.Add("BustN", d_String.Size()); d_String.WriteString("BustN"); d_String.WriteByte(0); List <PatriciaTree.PatriciaTreeNode> Nodes = new List <PatriciaTree.PatriciaTreeNode>(); int maxlength = 0; foreach (Animation a in animations) { maxlength = Math.Max(maxlength, a.Text.Length); } Nodes.Add(new PatriciaTree.PatriciaTreeNode() { ReferenceBit = uint.MaxValue }); foreach (Animation a in animations) { PatriciaTree.Insert(Nodes, new PatriciaTree.PatriciaTreeNode() { Name = a.Text }, maxlength); } int nameOff = 0xb4 + d_Main2.Size(); foreach (PatriciaTree.PatriciaTreeNode node in Nodes) { d_Main2.WriteInt((int)node.ReferenceBit); d_Main2.WriteShort(node.LeftNodeIndex); d_Main2.WriteShort(node.RightNodeIndex); if (node.Name.Equals("")) { d_Main2.WriteInt(0); } else { NameBank.Add(node.Name, d_String.Size()); d_Main2.WriteOffset(d_String.Size(), d_String); d_String.WriteString(node.Name); d_String.WriteByte(0); } } // bones // Okay, first create the animation data then create the table pointng to it side by side int dataOff = 0xb4 + d_Main2.Size(); foreach (Animation a in animations) { d_Main2.WriteOffset(d_Main3.Size(), d_Main2); // now create the actual animation data I guess d_Main3.WriteOffset(NameBank[a.Text], d_String); // name offset d_Main3.WriteInt(0x2); // Flags TODO: What are these d_Main3.WriteFloat(a.frameCount + 1); d_Main3.WriteOffset(d_Main3.Size() + 12, d_Main3); // bone offset d_Main3.WriteInt(a.bones.Count); // bonecount d_Main3.WriteInt(0); // metadata nonsense FileOutput boneHeader = new FileOutput(); boneHeader.endian = System.IO.Endianness.Little; FileOutput keyData = new FileOutput(); keyData.endian = System.IO.Endianness.Little; int start = d_Main3.Size() + (a.bones.Count * 4); int track = 0; foreach (Animation.KeyNode node in a.bones) { d_Main3.WriteOffset(start + boneHeader.Size(), d_Main3); // bone offset // name type and flags if (!NameBank.ContainsKey(node.Text)) { NameBank.Add(node.Text, d_String.Size()); d_String.WriteString(node.Text); d_String.WriteByte(0); } boneHeader.WriteOffset(NameBank[node.Text], d_String); // name offset boneHeader.WriteInt(0x040000); // animation type flags, default is just simply transform // Actual Flags int flags = 0; flags |= (((node.xsca.keys.Count > 0) ? 0 : 1) << (16 + 0)); flags |= (((node.ysca.keys.Count > 0) ? 0 : 1) << (16 + 1)); flags |= (((node.zsca.keys.Count > 0) ? 0 : 1) << (16 + 2)); flags |= (((node.xrot.keys.Count > 0) ? 0 : 1) << (16 + 3)); flags |= (((node.yrot.keys.Count > 0) ? 0 : 1) << (16 + 4)); flags |= (((node.zrot.keys.Count > 0) ? 0 : 1) << (16 + 5)); flags |= (((node.xpos.keys.Count > 0) ? 0 : 1) << (16 + 6)); flags |= (((node.ypos.keys.Count > 0) ? 0 : 1) << (16 + 7)); flags |= (((node.zpos.keys.Count > 0) ? 0 : 1) << (16 + 8)); flags |= (((node.xsca.keys.Count == 1) ? 1 : 0) << (6 + 0)); flags |= (((node.ysca.keys.Count == 1) ? 1 : 0) << (6 + 1)); flags |= (((node.zsca.keys.Count == 1) ? 1 : 0) << (6 + 2)); flags |= (((node.xrot.keys.Count == 1) ? 1 : 0) << (6 + 3)); flags |= (((node.yrot.keys.Count == 1) ? 1 : 0) << (6 + 4)); flags |= (((node.zrot.keys.Count == 1) ? 1 : 0) << (6 + 5)); flags |= (((node.xpos.keys.Count == 1) ? 1 : 0) << (6 + 7)); flags |= (((node.ypos.keys.Count == 1) ? 1 : 0) << (6 + 8)); flags |= (((node.zpos.keys.Count == 1) ? 1 : 0) << (6 + 9)); boneHeader.WriteInt(flags); // Create KeyFrame Data int sta = start + (a.bones.Count * 12 * 4); WriteKeyData(node.xsca, boneHeader, keyData, d_Main3, sta, ref track); WriteKeyData(node.ysca, boneHeader, keyData, d_Main3, sta, ref track); WriteKeyData(node.zsca, boneHeader, keyData, d_Main3, sta, ref track); WriteKeyData(node.xrot, boneHeader, keyData, d_Main3, sta, ref track); WriteKeyData(node.yrot, boneHeader, keyData, d_Main3, sta, ref track); WriteKeyData(node.zrot, boneHeader, keyData, d_Main3, sta, ref track); WriteKeyData(node.xpos, boneHeader, keyData, d_Main3, sta, ref track); WriteKeyData(node.ypos, boneHeader, keyData, d_Main3, sta, ref track); WriteKeyData(node.zpos, boneHeader, keyData, d_Main3, sta, ref track); } d_Main3.WriteOutput(boneHeader); d_Main3.WriteOutput(keyData); } d_Main.WriteOffset(dataOff, d_Main); d_Main.WriteInt(animations.Count); // d_Main.WriteOffset(nameOff, d_Main); // } d_Main.WriteInt(0); // MaterialAnim d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // VisAnim d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // LightAnim d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // CameraAnim d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // FogAnim d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteInt(0); // Scene d_Main.WriteInt(0); // d_Main.WriteOffset(0xB4 + d_Main2.Size(), d_Main); // d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main2.WriteInt(0); d_Main.WriteOutput(d_Main2); d_Main.WriteOutput(d_Main3); int headSize = o.Size(); o.WriteIntAt(headSize, 0x08); o.WriteIntAt(d_Main.Size(), 0x20); o.WriteOutput(d_Main); o.Align(4); int stringSize = o.Size(); o.WriteIntAt(stringSize, 0x0C); o.WriteIntAt(d_String.Size(), 0x24); o.WriteOutput(d_String); o.Align(4); int gpuSize = o.Size(); o.WriteIntAt(d_GPU.Size() > 0 ? gpuSize : 0, 0x10); o.WriteIntAt(d_GPU.Size(), 0x28); o.WriteOutput(d_GPU); o.Align(0x100); int dataSize = o.Size(); o.WriteIntAt(dataSize, 0x14); o.WriteIntAt(dataSize, 0x18); o.WriteIntAt(d_Data.Size(), 0x2C); o.WriteIntAt(d_Data.Size(), 0x30); o.WriteOutput(d_Data); //Create Relocation Table // Flag is 7 bits // 0 - main 1 - string 2 - gpu 3 - data foreach (FileOutput.RelocOffset off in o.offsets) { int size = 0; int code = 0; int div = 4; if (off.output == d_Main || off.output == d_Main2 || off.output == d_Main3) { size = headSize; code = 0; if (off.output == d_Main3) { off.value += headSize; } if (off.output == d_Main2) { off.value += d_Main2.Size() + headSize; } } if (off.output == d_String) { size = stringSize; code = 1; div = 1; } if (off.output == d_GPU) { size = gpuSize; code = 2; } if (off.output == d_Data) { size = dataSize; code = 3; } o.WriteIntAt(off.value - size, off.position); int reloc = (code << 25) | (((off.position - headSize) / div) & 0x1FFFFFF); Reloc.WriteInt(reloc); } int relocSize = o.Size(); o.WriteIntAt(relocSize, 0x1C); o.WriteIntAt(Reloc.Size(), 0x34); o.WriteOutput(Reloc); o.Save(fname); }
void writeShapes(FileOutput o) { Console.WriteLine($"Shapes = [ // offset=0x{o.Size():X2}"); for (int i = 0; i < Shapes.Count; i++) { var shape = Shapes[i]; Console.WriteLine($"\tCharacterId: 0x{shape.CharacterId:X4} // offset=0x{o.Size():X2}"); Console.WriteLine($"\tUnk1: 0x{shape.Unk1:X8}"); Console.WriteLine($"\tBounds: {Bounds[shape.BoundsId]} (0x{shape.BoundsId:X2})"); Console.WriteLine($"\tUnk3: 0x{shape.Unk3:X8}"); Console.WriteLine("\t["); o.WriteInt((int)TagType.Shape); o.WriteInt(5); o.WriteInt(shape.CharacterId); o.WriteInt(shape.Unk1); o.WriteInt(shape.BoundsId); o.WriteInt(shape.Unk3); o.WriteInt(shape.Graphics.Length); foreach (var graphic in shape.Graphics) { Console.WriteLine($"\t\tGraphic {{ // offset=0x{o.Size():X2}"); Console.WriteLine($"\t\t\tAtlasId: {graphic.AtlasId}"); Console.WriteLine($"\t\t\tFillType: {graphic.FillType} (0x{(short)graphic.FillType:X2})"); var graphicTag = new FileOutput(); graphicTag.WriteInt(graphic.AtlasId); graphicTag.WriteShort((short)graphic.FillType); graphicTag.WriteShort((short)graphic.Verts.Length); graphicTag.WriteInt(graphic.Indices.Length); foreach (var vert in graphic.Verts) { Console.WriteLine($"\t\t\t\t{vert}"); graphicTag.WriteFloat(vert.X); graphicTag.WriteFloat(vert.Y); graphicTag.WriteFloat(vert.U); graphicTag.WriteFloat(vert.V); } Console.Write("\t\t\t["); foreach (var index in graphic.Indices) { Console.Write($"{index}, "); graphicTag.WriteShort((short)index); } Console.WriteLine("]"); Console.WriteLine("\t\t}\n"); if ((graphic.Indices.Length % 2) != 0) { graphicTag.WriteShort(0); } o.WriteInt((int)TagType.Graphic); o.WriteInt(graphicTag.Size() / 4); o.WriteOutput(graphicTag); } Console.WriteLine("\t]\n"); } Console.WriteLine("]\n"); }
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 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 SaveAsMBN(string fname) { int format = 6; FileOutput o = new FileOutput(); o.endian = Endianness.Little; o.WriteShort(format); o.WriteShort(0xFFFF); o.WriteInt(0); //flags o.WriteInt(1); //mode o.WriteInt(Nodes.Count); // Write Vertex Attributes { o.WriteInt(attributes.Count); foreach (VertexAttribute va in attributes) { o.WriteInt(va.type); o.WriteInt(va.format); o.WriteFloat(va.scale); } } //Vertex Buffer FileOutput vertexBuffer = new FileOutput(); vertexBuffer.endian = Endianness.Little; for (int i = 0; i < vertices.Length; i++) { foreach (VertexAttribute va in attributes) { //Write Data va.WriteVertex(vertexBuffer, ref vertices[i]); } } o.WriteInt(vertexBuffer.Size()); // Vertex Buffer Size //Mesh Information FileOutput indexBuffer = new FileOutput(); indexBuffer.endian = Endianness.Little; foreach (BCH_Mesh mesh in Nodes) { o.WriteInt(mesh.Nodes.Count); foreach (BCH_PolyGroup pg in mesh.Nodes) { // Node List o.WriteInt(pg.BoneList.Length); foreach (int b in pg.BoneList) { o.WriteInt(b); } // Triangle Count o.WriteInt(pg.Faces.Length); // o.writeInt(0); something if format == 4 // Index Buffer foreach (int i in pg.Faces) { indexBuffer.WriteShort(i); } indexBuffer.Align(0x20, 0xFF); } } if (format != 4) { o.Align(0x20, 0xFF); } o.WriteOutput(vertexBuffer); o.Align(0x20, 0xFF); o.WriteOutput(indexBuffer); o.Save(fname); }
public override byte[] Rebuild() { FileOutput o = new FileOutput(); o.endian = Endianness.Little; o.WriteString(" BWS"); o.WriteShort(0x05); o.WriteShort(0x01); o.WriteInt(bones.Count); foreach (SBEntry s in bones) { o.WriteInt((int)s.hash); o.WriteFloat(s.param1_1); o.WriteInt(s.param1_2); o.WriteInt(s.param1_3); o.WriteFloat(s.param2_1); o.WriteFloat(s.param2_2); o.WriteInt(s.param2_3); o.WriteFloat(s.rx1); o.WriteFloat(s.rx2); o.WriteFloat(s.ry1); o.WriteFloat(s.ry2); o.WriteFloat(s.rz1); o.WriteFloat(s.rz2); for (int j = 0; j < 8; j++) { o.WriteInt((int)s.boneHashes[j]); } for (int j = 0; j < 4; j++) { o.WriteFloat(s.unks1[j]); } for (int j = 0; j < 6; j++) { o.WriteFloat(s.unks2[j]); } o.WriteFloat(s.factor); for (int j = 0; j < 3; j++) { o.WriteInt(s.ints[j]); } } return(o.GetBytes()); }