public override byte[] Rebuild() { FileOutput f = new FileOutput(); f.Endian = Endianness.Big; f.writeString("MTA4"); f.writeInt((int)unknown); f.writeInt((int)numFrames); f.writeInt(0); f.writeInt((int)numFrames - 1); f.writeInt((int)frameRate); f.writeInt(matEntries.Count); if (matEntries.Count > 0) { f.writeInt(0x38); } else { f.writeInt(0); } f.writeInt(visEntries.Count); if (visEntries.Count > 0) { f.writeInt(0x38 + 4 * matEntries.Count); } else { f.writeInt(0); } for (int i = 0; i < 0x10; i++) { f.writeByte(0); } List <byte[]> matEntriesBuilt = new List <byte[]>(); List <byte[]> visEntriesBuilt = new List <byte[]>(); int position = 0x38 + matEntries.Count + visEntries.Count; while (position % 0x10 != 0) { position++; } foreach (MatEntry m in matEntries) { byte[] b = m.Rebuild(position); matEntriesBuilt.Add(b); f.writeInt(position); position += b.Length; while (position % 0x10 != 0) { position++; } } foreach (VisEntry v in visEntries) { byte[] b = v.Rebuild(position); matEntriesBuilt.Add(b); f.writeInt(position); position += b.Length; while (position % 0x10 != 0) { position++; } } while (f.pos() % 0x10 != 0) { f.writeByte(0); } foreach (byte[] b in matEntriesBuilt) { f.writeBytes(b); while (f.pos() % 0x10 != 0) { f.writeByte(0); } } foreach (byte[] b in visEntriesBuilt) { f.writeBytes(b); while (f.pos() % 0x10 != 0) { f.writeByte(0); } } return(f.getBytes()); }
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 byte[] Rebuild(int pos) { FileOutput f = new FileOutput(); f.Endian = Endianness.Big; f.writeInt(pos + f.pos() + 0x20); f.writeInt(matHash); f.writeInt(properties.Count); int nameOffset = pos + f.pos() + 0x15 + name.Length; while (nameOffset % 4 != 0) { nameOffset++; } f.writeInt(nameOffset); f.writeFlag(hasPat); f.writeBytes(new byte[3]); //Write all the mat data into a buffer (g) then write pat offset int pos2 = pos + f.pos() + 4; FileOutput g = new FileOutput(); g.Endian = Endianness.Big; if (matHash2 != 0) { g.writeInt(pos2 + g.pos() + 0x8); g.writeInt(matHash); } else { g.writeBytes(new byte[8]); } g.writeString(name); g.writeByte(0); while ((pos2 + g.pos()) % 0x10 != 0) { g.writeByte(0); } int position = pos2 + g.pos() + properties.Count * 4; while (position % 16 != 0) { position++; } List <byte[]> builtProperties = new List <byte[]>(); foreach (MatData prop in properties) { g.writeInt(position); byte[] b = prop.Rebuild(position); builtProperties.Add(b); position += b.Length; while (position % 16 != 0) { position++; } } while ((pos2 + g.pos()) % 16 != 0) { g.writeByte(0); } foreach (byte[] b in builtProperties) { g.writeBytes(b); while ((pos2 + g.pos()) % 16 != 0) { g.writeByte(0); } } f.writeInt(pos2 + g.pos()); f.writeBytes(g.getBytes()); if (hasPat) { f.writeBytes(pat0.Rebuild(f.pos())); } return(f.getBytes()); }
public byte[] Rebuild(bool dump = false) { FileOutput o = new FileOutput(); TextWriter oldOut = Console.Out; MemoryStream ostrm = new MemoryStream(0xA00000); StreamWriter writer = new StreamWriter(ostrm); Console.SetOut(writer); // TODO: write correct filesize in header. // It isn't checked by the game, but what the hell, right? header.Write(o); writeSymbols(o); writeColors(o); writeTransforms(o); writePositions(o); writeBounds(o); Actionscript.Write(o); if (Actionscript2 != null) { Actionscript2.Write(o); } writeAtlases(o); unkF008.Write(o); unkF009.Write(o); unkF00A.Write(o); unk000A.Write(o); unkF00B.Write(o); properties.Write(o); Defines.numShapes = (uint)Shapes.Count; Defines.numSprites = (uint)Sprites.Count; Defines.numTexts = (uint)Texts.Count; Defines.Write(o); writeShapes(o); writeSprites(o); writeTexts(o); o.writeInt((int)TagType.End); o.writeInt(0); int padSize = (4 - (o.size() % 4)) % 4; for (int i = 0; i < padSize; i++) { o.writeByte(0); } if (dump) { writer.Flush(); using (var filestream = new FileStream("dump.txt", FileMode.Create)) ostrm.WriteTo(filestream); } Console.SetOut(oldOut); return(o.getBytes()); }
public override byte[] Rebuild() { FileOutput o = new FileOutput(); FileOutput data = new FileOutput(); o.writeInt(0x4E545033); // "NTP3" o.writeShort(Version); o.writeShort(Nodes.Count); o.writeInt(0); o.writeInt(0); //calculate total header size int headerLength = 0; foreach (NutTexture texture in Nodes) { int headerSize = 0x50; if (texture.mipmaps.Count > 1) { headerSize += texture.mipmaps.Count * 4; while (headerSize % 16 != 0) { headerSize += 4; } } headerLength += headerSize; } // write headers+data foreach (NutTexture texture in Nodes) { int size = 0; foreach (var mip in texture.mipmaps) { size += mip.Length; while (size % 16 != 0) { size += 1; } } int headerSize = 0x50; // calculate header size if (texture.mipmaps.Count > 1) { headerSize += texture.mipmaps.Count * 4; //align to 16 while (headerSize % 16 != 0) { headerSize += 1; } } o.writeInt(size + headerSize); o.writeInt(0x00); //padding o.writeInt(size); o.writeShort(headerSize); //+ (texture.mipmaps.Count - 4 > 0 ? texture.mipmaps.Count - 4 : 0) * 4 o.writeShort(0); o.writeShort(texture.mipmaps.Count); o.writeShort(texture.getNutFormat()); o.writeShort(texture.Width); o.writeShort(texture.Height); o.writeInt(0); o.writeInt(0); o.writeInt(headerLength + data.size()); headerLength -= headerSize; o.writeInt(0); o.writeInt(0); o.writeInt(0); if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17) { foreach (byte[] mip in texture.mipmaps) { for (int t = 0; t < mip.Length; t += 4) { byte t1 = mip[t + 3]; mip[t + 3] = mip[t + 2]; mip[t + 2] = mip[t + 1]; mip[t + 1] = mip[t]; mip[t] = t1; } } } foreach (var mip in texture.mipmaps) { int ds = data.size(); data.writeBytes(mip); data.align(0x10); if (texture.mipmaps.Count > 1) { o.writeInt(data.size() - ds); } } o.align(16); if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17) { foreach (byte[] mip in texture.mipmaps) { for (int t = 0; t < mip.Length; t += 4) { byte t1 = mip[t]; mip[t] = mip[t + 1]; mip[t + 1] = mip[t + 2]; mip[t + 2] = mip[t + 3]; mip[t + 3] = t1; } } } o.writeInt(0x65587400); // "eXt\0" o.writeInt(0x20); o.writeInt(0x10); o.writeInt(0x00); o.writeInt(0x47494458); // "GIDX" o.writeInt(0x10); o.writeInt(texture.HASHID); o.writeInt(0); } o.writeOutput(data); return(o.getBytes()); }
public override byte[] Rebuild() { FileOutput o = new FileOutput(); FileOutput data = new FileOutput(); o.writeUInt(0x4E545033); // "NTP3" o.writeUShort(Version); o.writeUShort((ushort)Nodes.Count); o.writeInt(0); o.writeInt(0); //calculate total header size uint headerLength = 0; foreach (NutTexture texture in Nodes) { byte surfaceCount = (byte)texture.surfaces.Count; bool isCubemap = surfaceCount == 6; if (surfaceCount < 1 || surfaceCount > 6) { throw new NotImplementedException($"Unsupported surface amount {surfaceCount} for texture with hash 0x{texture.HashId:X}. 1 to 6 faces are required."); } else if (surfaceCount > 1 && surfaceCount < 6) { throw new NotImplementedException($"Unsupported cubemap face amount for texture with hash 0x{texture.HashId:X}. Six faces are required."); } byte mipmapCount = (byte)texture.surfaces[0].mipmaps.Count; ushort headerSize = 0x50; if (isCubemap) { headerSize += 0x10; } if (mipmapCount > 1) { headerSize += (ushort)(mipmapCount * 4); while (headerSize % 0x10 != 0) { headerSize += 1; } } headerLength += headerSize; } // write headers+data foreach (NutTexture texture in Nodes) { byte surfaceCount = (byte)texture.surfaces.Count; bool isCubemap = surfaceCount == 6; byte mipmapCount = (byte)texture.surfaces[0].mipmaps.Count; uint dataSize = 0; foreach (var mip in texture.GetAllMipmaps()) { dataSize += (uint)mip.Length; while (dataSize % 0x10 != 0) { dataSize += 1; } } ushort headerSize = 0x50; if (isCubemap) { headerSize += 0x10; } if (mipmapCount > 1) { headerSize += (ushort)(mipmapCount * 4); while (headerSize % 0x10 != 0) { headerSize += 1; } } o.writeUInt(dataSize + headerSize); o.writeUInt(0); o.writeUInt(dataSize); o.writeUShort(headerSize); o.writeUShort(0); o.writeByte(0); o.writeByte(mipmapCount); o.writeByte(0); o.writeByte(texture.getNutFormat()); o.writeShort(texture.Width); o.writeShort(texture.Height); o.writeInt(0); o.writeUInt(texture.DdsCaps2); o.writeUInt((uint)(headerLength + data.size())); headerLength -= headerSize; o.writeInt(0); o.writeInt(0); o.writeInt(0); if (isCubemap) { o.writeInt(texture.surfaces[0].mipmaps[0].Length); o.writeInt(texture.surfaces[0].mipmaps[0].Length); o.writeInt(0); o.writeInt(0); } if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17) { texture.SwapChannelOrderDown(); } for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) { int ds = data.size(); data.writeBytes(texture.surfaces[surfaceLevel].mipmaps[mipLevel]); data.align(0x10); if (mipmapCount > 1 && surfaceLevel == 0) { o.writeInt(data.size() - ds); } } } o.align(0x10); if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17) { texture.SwapChannelOrderUp(); } o.writeUInt(0x65587400); // "eXt\0" o.writeInt(0x20); o.writeInt(0x10); o.writeInt(0x00); o.writeUInt(0x47494458); // "GIDX" o.writeInt(0x10); o.writeInt(texture.HashId); o.writeInt(0); } o.writeOutput(data); return(o.getBytes()); }
public override byte[] Rebuild() { FileOutput f = new FileOutput(); f.Endian = Endianness.Little; FileOutput fv = new FileOutput(); fv.Endian = Endianness.Little; f.writeShort(format); f.writeShort(unkown); f.writeInt(flags); f.writeInt(mode); bool hasNameTable = (flags & 2) > 0; f.writeInt(mesh.Count); int vertSize = 0; // Vertex Bank for (int i = 0; i < 1; i++) { if (mode == 0 || i == 0) { Descriptor des = descript[i]; if (format != 4) { foreach (Vertex v in vertices) { for (int k = 0; k < des.type.Length; k++) { fv.align(2, 0x00); switch (des.type[k]) { case 0: //Position writeType(fv, v.pos.X, des.format[k], des.scale[k]); writeType(fv, v.pos.Y, des.format[k], des.scale[k]); writeType(fv, v.pos.Z, des.format[k], des.scale[k]); break; case 1: //Normal writeType(fv, v.nrm.X, des.format[k], des.scale[k]); writeType(fv, v.nrm.Y, des.format[k], des.scale[k]); writeType(fv, v.nrm.Z, des.format[k], des.scale[k]); break; case 2: //Color writeType(fv, v.col.X, des.format[k], des.scale[k]); writeType(fv, v.col.Y, des.format[k], des.scale[k]); writeType(fv, v.col.Z, des.format[k], des.scale[k]); writeType(fv, v.col.W, des.format[k], des.scale[k]); break; case 3: //Tex0 writeType(fv, v.tx[0].X, des.format[k], des.scale[k]); writeType(fv, v.tx[0].Y, des.format[k], des.scale[k]); break; case 4: //Tex1 writeType(fv, v.tx[1].X, des.format[k], des.scale[k]); writeType(fv, v.tx[1].Y, des.format[k], des.scale[k]); break; case 5: //Bone Index fv.writeByte(v.node[0]); fv.writeByte(v.node[1]); break; case 6: //Bone Weight writeType(fv, v.weight[0], des.format[k], des.scale[k]); writeType(fv, v.weight[1], des.format[k], des.scale[k]); break; //default: // Console.WriteLine("WTF is this"); } } } vertSize = fv.size(); fv.align(32, 0xFF); } } for (int j = 0; j < mesh.Count; j++) { foreach (List <int> l in mesh[j].faces) { foreach (int index in l) { fv.writeShort(index); } fv.align(32, 0xFF); } } } for (int i = 0; i < mesh.Count; i++) { if (i == 0 && mode == 1) { descript[0].WriteDescription(f); f.writeInt(vertSize); } f.writeInt(mesh[i].nodeList.Count); //Console.WriteLine(mesh[i].faces.Count + " " + mesh[i].nodeList.Count); for (int j = 0; j < mesh[i].nodeList.Count; j++) { f.writeInt(mesh[i].nodeList[j].Count); for (int k = 0; k < mesh[i].nodeList[j].Count; k++) { f.writeInt(mesh[i].nodeList[j][k]); } f.writeInt(mesh[i].faces[j].Count); // TODO: This stuff if (hasNameTable) { //int nameId = d.readInt(); } /*if (mode == 0) * { * if (format == 4) * { * int[] buffer = new int[primitiveCount]; * for (int k = 0; k < primitiveCount; k++) * { * buffer[k] = d.readShort(); * } * d.align(4); * List<int> buf = new List<int>(); * buf.AddRange(buffer); * m.faces.Add(buf); * } * else * { * Descriptor des = new Descriptor(); * des.ReadDescription(d); * descript.Add(des); * } * * }*/ } } // TODO: STRING TABLE /*if (hasNameTable) * { * for (int i = 0; i < mesh.Count; i++) * { * int index = d.readByte(); * nameTable.Add(d.readString()); * } * }*/ if (format != 4) { f.align(32, 0xFF); } f.writeOutput(fv); return(f.getBytes()); }
public override byte[] Rebuild() { FileOutput f = new FileOutput(); f.Endian = Endianness.Big; f.writeHex("4C494748"); //LIGH f.writeInt(version); f.writeInt(frameCount); if (version == 5) { f.writeInt(frameDuration); } //Offsets int padding = 0; while ((((frameCount * 3) + padding) % 4) != 0) //All offsets must be multiples of 4 or the game won't use the file properly { padding++; } int[] offsets = new int[6]; int currOff = 0x24; if (version == 4) { currOff = 0x24; } else if (version == 5) { currOff = 0x28; } for (int i = 0; i < 5; i++) { offsets[i + 1] = (rgbProperties[i].enabled) ? currOff : 0x0; if (rgbProperties[i].enabled) { currOff += (frameCount * 3) + padding; } } offsets[0] = currOff; for (int i = 0; i < 6; i++) { f.writeInt(offsets[i]); } //RGB properties for (int i = 0; i < 5; i++) { for (int j = 0; j < frameCount; j++) { for (int k = 0; k < 3; k++) { f.writeByte(rgbProperties[i].frames[j][k]); } } for (int j = 0; j < padding; j++) { f.writeByte(0); } } //Light data for (int i = 0; i < frameCount; i++) { for (int j = 0; j < 17; j++) { for (int k = 0; k < 4; k++) { f.writeInt((int)lightFrames[i].lightSets[j].lights[k].enabled); for (int l = 0; l < 3; l++) { f.writeFloat(lightFrames[i].lightSets[j].lights[k].angle[l]); } f.writeFloat(lightFrames[i].lightSets[j].lights[k].colorHue); f.writeFloat(lightFrames[i].lightSets[j].lights[k].colorSat); f.writeFloat(lightFrames[i].lightSets[j].lights[k].colorVal); } f.writeByte(lightFrames[i].lightSets[j].fog.unknown); for (int k = 0; k < 3; k++) { f.writeByte(lightFrames[i].lightSets[j].fog.color[k]); } } f.writeByte(lightFrames[i].effect.unknown); for (int j = 0; j < 3; j++) { f.writeByte(lightFrames[i].effect.color[j]); } for (int j = 0; j < 3; j++) { f.writeFloat(lightFrames[i].effect.position[j]); } } return(f.getBytes()); }
public override byte[] Rebuild() { FileOutput f = new FileOutput(); f.Endian = Endianness.Big; f.writeHex("000000010A014C564431"); f.writeByte(1); f.writeInt(collisions.Count); foreach (Collision c in collisions) { c.save(f); } f.writeByte(1); f.writeInt(spawns.Count); foreach (Spawn s in spawns) { s.save(f); } f.writeByte(1); f.writeInt(respawns.Count); foreach (Spawn s in respawns) { s.save(f); } f.writeByte(1); f.writeInt(cameraBounds.Count); foreach (Bounds b in cameraBounds) { b.save(f); } f.writeByte(1); f.writeInt(blastzones.Count); foreach (Bounds b in blastzones) { b.save(f); } f.writeByte(1); f.writeInt(enemySpawns.Count); foreach (EnemyGenerator e in enemySpawns) { e.save(f); } for (int i = 0; i < 5; i++) { f.writeByte(1); f.writeInt(0); } f.writeByte(1); f.writeInt(damageShapes.Count); foreach (DamageShape shape in damageShapes) { shape.save(f); } f.writeByte(1); f.writeInt(itemSpawns.Count); foreach (ItemSpawner item in itemSpawns) { item.save(f); } f.writeByte(1); f.writeInt(generalShapes.Count); foreach (GeneralShape shape in generalShapes) { shape.save(f); } f.writeByte(1); f.writeInt(generalPoints.Count); foreach (GeneralPoint p in generalPoints) { p.save(f); } for (int i = 0; i < 4; i++) { f.writeByte(1); f.writeInt(0); } return(f.getBytes()); }
public override byte[] Rebuild() { FileOutput o = new FileOutput(); FileOutput data = new FileOutput(); //We always want BE for the first six bytes o.Endian = Endianness.Big; data.Endian = Endianness.Big; if (Endian == Endianness.Big) { o.writeUInt(0x4E545033); //NTP3 } else if (Endian == Endianness.Little) { o.writeUInt(0x4E545744); //NTWD } //Most NTWU NUTs are 0x020E, which isn't valid for NTP3/NTWD if (Version > 0x0200) { Version = 0x0200; } o.writeUShort(Version); //After that, endian is used appropriately o.Endian = Endian; data.Endian = Endian; o.writeUShort((ushort)Nodes.Count); o.writeInt(0); o.writeInt(0); //calculate total header size uint headerLength = 0; foreach (NutTexture texture in Nodes) { byte surfaceCount = (byte)texture.surfaces.Count; bool isCubemap = surfaceCount == 6; if (surfaceCount < 1 || surfaceCount > 6) { throw new NotImplementedException($"Unsupported surface amount {surfaceCount} for texture with hash 0x{texture.HashId:X}. 1 to 6 faces are required."); } else if (surfaceCount > 1 && surfaceCount < 6) { throw new NotImplementedException($"Unsupported cubemap face amount for texture with hash 0x{texture.HashId:X}. Six faces are required."); } byte mipmapCount = (byte)texture.surfaces[0].mipmaps.Count; ushort headerSize = 0x50; if (isCubemap) { headerSize += 0x10; } if (mipmapCount > 1) { headerSize += (ushort)(mipmapCount * 4); while (headerSize % 0x10 != 0) { headerSize += 1; } } headerLength += headerSize; } // write headers+data foreach (NutTexture texture in Nodes) { byte surfaceCount = (byte)texture.surfaces.Count; bool isCubemap = surfaceCount == 6; byte mipmapCount = (byte)texture.surfaces[0].mipmaps.Count; uint dataSize = 0; foreach (var mip in texture.GetAllMipmaps()) { dataSize += (uint)mip.Length; while (dataSize % 0x10 != 0) { dataSize += 1; } } ushort headerSize = 0x50; if (isCubemap) { headerSize += 0x10; } if (mipmapCount > 1) { headerSize += (ushort)(mipmapCount * 4); while (headerSize % 0x10 != 0) { headerSize += 1; } } o.writeUInt(dataSize + headerSize); o.writeUInt(0); o.writeUInt(dataSize); o.writeUShort(headerSize); o.writeUShort(0); o.writeByte(0); o.writeByte(mipmapCount); o.writeByte(0); o.writeByte(texture.getNutFormat()); o.writeShort(texture.Width); o.writeShort(texture.Height); o.writeInt(0); o.writeUInt(texture.DdsCaps2); if (Version < 0x0200) { o.writeUInt(0); } else if (Version >= 0x0200) { o.writeUInt((uint)(headerLength + data.size())); } headerLength -= headerSize; o.writeInt(0); o.writeInt(0); o.writeInt(0); if (isCubemap) { o.writeInt(texture.surfaces[0].mipmaps[0].Length); o.writeInt(texture.surfaces[0].mipmaps[0].Length); o.writeInt(0); o.writeInt(0); } if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17) { texture.SwapChannelOrderDown(); } for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) { int ds = data.size(); data.writeBytes(texture.surfaces[surfaceLevel].mipmaps[mipLevel]); data.align(0x10); if (mipmapCount > 1 && surfaceLevel == 0) { o.writeInt(data.size() - ds); } } } o.align(0x10); if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17) { texture.SwapChannelOrderUp(); } o.writeBytes(new byte[] { 0x65, 0x58, 0x74, 0x00 }); // "eXt\0" o.writeInt(0x20); o.writeInt(0x10); o.writeInt(0x00); o.writeBytes(new byte[] { 0x47, 0x49, 0x44, 0x58 }); // "GIDX" o.writeInt(0x10); o.writeInt(texture.HashId); o.writeInt(0); if (Version < 0x0200) { o.writeOutput(data); data = new FileOutput(); } } if (Version >= 0x0200) { o.writeOutput(data); } return(o.getBytes()); }
public override byte[] Rebuild() { FileOutput f = new FileOutput(); f.Endian = Endianness.Big; f.writeHex("000000010A014C56443101"); f.writeInt(collisions.Count); foreach (Collision c in collisions) { c.save(f); } f.writeByte(1); f.writeInt(spawns.Count); foreach (Point p in spawns) { f.writeHex("020401017735BB750000000201"); f.writeString(p.name.PadRight(0x38, (char)0)); f.writeByte(1); f.writeString(p.subname.PadRight(0x40, (char)0)); f.writeByte(1); f.writeHex("00000000000000000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); f.writeFloat(p.x); f.writeFloat(p.y); } f.writeByte(1); f.writeInt(respawns.Count); foreach (Point p in respawns) { f.writeHex("020401017735BB750000000201"); f.writeString(p.name.PadRight(0x38, (char)0)); f.writeByte(1); f.writeString(p.subname.PadRight(0x40, (char)0)); f.writeByte(1); f.writeHex("00000000000000000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); f.writeFloat(p.x); f.writeFloat(p.y); } f.writeByte(1); f.writeInt(cameraBounds.Count); foreach (Bounds b in cameraBounds) { f.writeHex("020401017735BB750000000201"); f.writeString(b.name.PadRight(0x38, (char)0)); f.writeByte(1); f.writeString(b.subname.PadRight(0x40, (char)0)); f.writeByte(1); f.writeHex("00000000000000000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); f.writeFloat(b.left); f.writeFloat(b.right); f.writeFloat(b.top); f.writeFloat(b.bottom); } f.writeByte(1); f.writeInt(blastzones.Count); foreach (Bounds b in blastzones) { f.writeHex("020401017735BB750000000201"); f.writeString(b.name.PadRight(0x38, (char)0)); f.writeByte(1); f.writeString(b.subname.PadRight(0x40, (char)0)); f.writeByte(1); f.writeHex("00000000000000000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); f.writeFloat(b.left); f.writeFloat(b.right); f.writeFloat(b.top); f.writeFloat(b.bottom); } for (int i = 0; i < 7; i++) { f.writeByte(1); f.writeInt(0); } f.writeByte(1); f.writeInt(items.Count); foreach (ItemSpawner item in items) { item.save(f); } f.writeByte(1); f.writeInt(generalShapes.Count); foreach (LVDGeneralShape shape in generalShapes) { shape.save(f); } f.writeByte(1); f.writeInt(generalPoints.Count); foreach (Point p in generalPoints) { f.writeHex("010401017735BB750000000201"); f.writeChars(p.name.PadRight(0x38, (char)0).ToCharArray()); f.writeByte(1); f.writeChars(p.subname.PadRight(0x40, (char)0).ToCharArray()); f.writeByte(1); f.writeHex("00000000432100000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000004"); f.writeFloat(p.x); f.writeFloat(p.y); f.writeBytes(new byte[0x14]); } for (int i = 0; i < 4; i++) { f.writeByte(1); f.writeInt(0); } return(f.getBytes()); }
public override byte[] Rebuild() { FileOutput o = new FileOutput(); o.writeInt(0x4E545033); // "NTP3" o.writeShort(0x0200); o.writeShort(textures.Count); o.writeInt(0); o.writeInt(0); int offset = textures.Count * 0x60; foreach (var texture in textures) { int size = 0; int headerSize = 0x60; foreach (var mip in texture.mipmaps) { size += mip.Length; } // // headerSize 0x50 seems to crash with models //if (texture.mipmaps.Count == 1) //{ // headerSize = 0x50; //} o.writeInt(size + headerSize); o.writeInt(0x00); o.writeInt(size); o.writeShort(headerSize); o.writeShort(0); o.writeShort(texture.mipmaps.Count); o.writeShort(texture.getNutFormat()); o.writeShort(texture.width); o.writeShort(texture.height); o.writeInt(0); o.writeInt(0); o.writeInt(offset); o.writeInt(0); o.writeInt(0); o.writeInt(0); if (headerSize > 0x50) { foreach (var mip in texture.mipmaps) { o.writeInt(mip.Length); } // Sizes for missing mips. for (int j = 0; j < 4 - texture.mipmaps.Count; j++) { o.writeInt(0); } } o.writeInt(0x65587400); // "eXt\0" o.writeInt(0x20); o.writeInt(0x10); o.writeInt(0x00); o.writeInt(0x47494458); // "GIDX" o.writeInt(0x10); o.writeInt(texture.id); o.writeInt(0); offset += (size - headerSize); } foreach (var texture in textures) { foreach (var mip in texture.mipmaps) { o.writeBytes(mip); } } return(o.getBytes()); }
public static byte[] encodeETCa4(Bitmap b) { int width = b.Width; int height = b.Height; int[] pixels = new int[width * height]; int i, j; FileOutput o = new FileOutput(); o.Endian = System.IO.Endianness.Little; for (i = 0; i < height; i += 8) { for (j = 0; j < width; j += 8) { int x, y; Color[] temp = new Color[16]; int pi = 0; for (x = i; x < i + 4; x++) { for (y = j; y < j + 4; y++) { temp[pi++] = b.GetPixel(y, x); } } for (int ax = 0; ax < 4; ax++) { for (int ay = 0; ay < 4; ay++) { int a = (temp[ax + ay * 4].A >> 4); ay++; a |= (temp[ax + ay * 4].A >> 4) << 4; o.writeByte(a); } } ulong g = GenETC1(temp); o.writeInt((int)(g & 0xFFFFFFFF)); o.writeInt((int)((g >> 32) & 0xFFFFFFFF)); temp = new Color[16]; pi = 0; for (x = i; x < i + 4; x++) { for (y = j + 4; y < j + 8; y++) { temp[pi++] = b.GetPixel(y, x); } } for (int ax = 0; ax < 4; ax++) { for (int ay = 0; ay < 4; ay++) { int a = (temp[ax + ay * 4].A >> 4); ay++; a |= (temp[ax + ay * 4].A >> 4) << 4; o.writeByte(a); } } g = GenETC1(temp); o.writeInt((int)(g & 0xFFFFFFFF)); o.writeInt((int)((g >> 32) & 0xFFFFFFFF)); temp = new Color[16]; pi = 0; for (x = i + 4; x < i + 8; x++) { for (y = j; y < j + 4; y++) { temp[pi++] = b.GetPixel(y, x); } } for (int ax = 0; ax < 4; ax++) { for (int ay = 0; ay < 4; ay++) { int a = (temp[ax + ay * 4].A >> 4); ay++; a |= (temp[ax + ay * 4].A >> 4) << 4; o.writeByte(a); } } g = GenETC1(temp); o.writeInt((int)(g & 0xFFFFFFFF)); o.writeInt((int)((g >> 32) & 0xFFFFFFFF)); temp = new Color[16]; pi = 0; for (x = i + 4; x < i + 8; x++) { for (y = j + 4; y < j + 8; y++) { temp[pi++] = b.GetPixel(y, x); } } for (int ax = 0; ax < 4; ax++) { for (int ay = 0; ay < 4; ay++) { int a = (temp[ax + ay * 4].A >> 4); ay++; a |= (temp[ax + ay * 4].A >> 4) << 4; o.writeByte(a); } } g = GenETC1(temp); o.writeInt((int)(g & 0xFFFFFFFF)); o.writeInt((int)((g >> 32) & 0xFFFFFFFF)); } } return(o.getBytes()); }
public static byte[] CreateOMOFromAnimation(Animation a, VBN vbn) { if (vbn == null || a == null) { return new byte[] { } } ; 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); //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); if (node == null) { continue; } if (hasTrans[j] && !conTrans[j]) { t2.writeShort((int)(((node.pos.X - minT[j].X) / maxT[j].X) * 0xFFFF)); t2.writeShort((int)(((node.pos.Y - minT[j].Y) / maxT[j].Y) * 0xFFFF)); t2.writeShort((int)(((node.pos.Z - minT[j].Z) / maxT[j].Z) * 0xFFFF)); } if (hasRot[j] && !conRot[j]) { Quaternion r = node.rot; 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)(((node.sca.X - minS[j].X) / maxS[j].X) * 0xFFFF)); t2.writeShort((int)(((node.sca.Y - minS[j].Y) / maxS[j].Y) * 0xFFFF)); t2.writeShort((int)(((node.sca.Z - minS[j].Z) / maxS[j].Z) * 0xFFFF)); } } if (go) { o.writeShortAt(t2.size(), 0x12); go = false; } } o.writeOutput(t2); return(o.getBytes()); } }
public static byte[] encodeETC(Bitmap b) { int width = b.Width; int height = b.Height; int[] pixels = new int[width * height]; init(); int i, j; FileOutput o = new FileOutput(); o.Endian = System.IO.Endianness.Little; for (i = 0; i < height; i += 8) { for (j = 0; j < width; j += 8) { int x, y; Color[] temp = new Color[16]; int pi = 0; for (x = i; x < i + 4; x++) { for (y = j; y < j + 4; y++) { temp[pi++] = b.GetPixel(y, x); } } o.writeBytes(GenETC1(temp)); temp = new Color[16]; pi = 0; for (x = i; x < i + 4; x++) { for (y = j + 4; y < j + 8; y++) { temp[pi++] = b.GetPixel(y, x); } } o.writeBytes(GenETC1(temp)); temp = new Color[16]; pi = 0; for (x = i + 4; x < i + 8; x++) { for (y = j; y < j + 4; y++) { temp[pi++] = b.GetPixel(y, x); } } o.writeBytes(GenETC1(temp)); temp = new Color[16]; pi = 0; for (x = i + 4; x < i + 8; x++) { for (y = j + 4; y < j + 8; y++) { temp[pi++] = b.GetPixel(y, x); } } o.writeBytes(GenETC1(temp)); } } return(o.getBytes()); }
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; } for (int i = 0; i < 4; i++) { file.writeInt((int)boneCountPerType[i]); } 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()); }