public override void Load(Stream fileStream) { ExtendedBinaryReader reader = new ExtendedBinaryReader(fileStream) { Offset = 0x20 }; long pos = 0; NinjaInfo = new NinjaInfo() { NodeName = new string(reader.ReadChars(4)) }; uint NodeLength = reader.ReadUInt32(); uint NodeCount = reader.ReadUInt32(); uint Unknown1 = reader.ReadUInt32(); //Seems to always be 0x20 (at least in XN*s)? uint Unknown2 = reader.ReadUInt32(); //Footer Offset Table Start? uint Unknown3 = reader.ReadUInt32(); //Footer Offset Table Data Start? uint Unknown4 = reader.ReadUInt32(); //Footer Offset Table Length? uint Unknown5 = reader.ReadUInt32(); //Seems to always be 1 (at least in XN*s)? for (int i = 0; i < NodeCount; i++) { //Determine type of node to read string NextNodeName = new string(reader.ReadChars(4)); uint NextNodeLength = reader.ReadUInt32(); reader.JumpBehind(8); switch (NextNodeName) { case "NXTL": case "NZTL": NinjaTextureList = ReadNinjaTextureList(reader, pos); break; case "NXEF": NinjaEffectList = ReadNinjaEffectList(reader, pos); break; case "NXNN": NinjaNodeNameList = ReadNinjaNodeNameList(reader, pos); break; case "NXOB": case "NZOB": NinjaObject = ReadNinjaObject(reader, pos); break; default: reader.JumpAhead(8); reader.JumpAhead(NextNodeLength); //Console.WriteLine($"Block {NextNodeName} Not Implemented!"); break; } } }
public override void Load(Stream fileStream) { ExtendedBinaryReader reader = new ExtendedBinaryReader(fileStream) { Offset = 0x20 }; long pos = 0; // NINJA INFO [N*IF] InfoList = new NXIF() { HeaderInfoNode = new string(reader.ReadChars(4)), NodeLength = reader.ReadUInt32(), NodeCount = reader.ReadUInt32() }; reader.JumpTo(InfoList.NodeLength + 8); for (int i = 0; i < InfoList.NodeCount; i++) { string nodeName = new string(reader.ReadChars(4)); uint nodeLength = reader.ReadUInt32(); reader.JumpBehind(8); switch (nodeName) { case "NXTL": case "NZTL": // NINJA TEXTURE LIST [N*TL] TextureList = ReadTextureList(reader, pos); break; case "NXEF": // NINJA EFFECTS [N*EF] EffectList = ReadEffectList(reader, pos); break; case "NXNN": // NINJA NODE NAMES [N*NN] NodeTree = ReadNodeNames(reader, pos); break; case "NXOB": case "NZOB": ObjectList = ReadNodes(reader, pos); break; default: reader.JumpAhead(8); reader.JumpAhead(nodeLength); Console.WriteLine($"Block {nodeName} Not Implemented!"); break; } } }
public NXNN ReadNodeNames(ExtendedBinaryReader reader, long pos) { NodeTree = new NXNN() { TreeNode = new string(reader.ReadChars(4)), NodeLength = reader.ReadUInt32() }; pos = reader.BaseStream.Position; //Save Position reader.JumpTo(reader.ReadUInt32() + 4, false); var nodeCount = reader.ReadUInt32(); reader.JumpTo(reader.ReadUInt32(), false); for (int i = 0; i < nodeCount; i++) { NodeTree node = new NodeTree(); node.NodeIndex = reader.ReadUInt32(); var nameOffset = reader.ReadUInt32(); long nodePos = reader.BaseStream.Position; //Save Position reader.JumpTo(nameOffset, false); node.NodeName = reader.ReadNullTerminatedString(); reader.JumpTo(nodePos); NodeTree.Nodes.Add(node); } reader.JumpTo(pos); reader.JumpAhead(NodeTree.NodeLength); return(NodeTree); }
public NXTL ReadTextureList(ExtendedBinaryReader reader, long pos) { TextureList = new NXTL() { TextureListNode = new string(reader.ReadChars(4)), NodeLength = reader.ReadUInt32() }; pos = reader.BaseStream.Position; //Save Position reader.JumpTo(reader.ReadUInt32(), false); TextureList.TextureCount = reader.ReadUInt32(); uint textureListOffset = reader.ReadUInt32(); reader.JumpTo(textureListOffset, false); for (int i = 0; i < TextureList.TextureCount; i++) { reader.JumpAhead(0x4); uint textureNameOffset = reader.ReadUInt32(); long texturePos = reader.BaseStream.Position; //Save Position reader.JumpTo(textureNameOffset, false); TEXFILE tex = new TEXFILE(); tex.Filename = reader.ReadNullTerminatedString(); reader.JumpTo(texturePos); tex.Filters = reader.ReadUInt32(); reader.JumpAhead(0x8); TextureList.Textures.Add(tex); } reader.JumpTo(pos); reader.JumpAhead(TextureList.NodeLength); return(TextureList); }
// Methods public static void Read(HavokFile h, ExtendedBinaryReader reader) { // Header reader.JumpAhead(0x10); // A lot of this was gathered from the Max Havok exporter. byte bytesInPointer = reader.ReadByte(); reader.IsBigEndian = !reader.ReadBoolean(); byte reusePaddingOpt = reader.ReadByte(); byte emptyBaseClassOpt = reader.ReadByte(); // We jump around a lot here, but there's not really a much cleaner way to do it. reader.JumpTo(8, true); h.UserTag = reader.ReadUInt32(); h.ClassVersion = reader.ReadInt32(); reader.JumpAhead(4); uint sectionsCount = reader.ReadUInt32(); uint unknown1 = reader.ReadUInt32(); ulong padding1 = reader.ReadUInt64(); uint unknown2 = reader.ReadUInt32(); h.ContentsVersion = reader.ReadNullTerminatedString(); reader.JumpAhead(9); // Seems to be padding // Sections for (uint i = 0; i < sectionsCount; ++i) { string sectionName = new string(reader.ReadChars(0x10)); sectionName = sectionName.Replace("\0", string.Empty); // TODO reader.JumpAhead(0x20); } // Padding Checks if (padding1 != 0) { Console.WriteLine($"WARNING: Padding1 != 0 ({padding1})"); } // TODO throw new NotImplementedException(); }
public NXEF ReadEffectList(ExtendedBinaryReader reader, long pos) { EffectList = new NXEF() { EffectNode = new string(reader.ReadChars(4)), NodeLength = reader.ReadUInt32() }; pos = reader.BaseStream.Position; //Save Position reader.JumpTo(reader.ReadUInt32() + 4, false); var effectTypeCount = reader.ReadUInt32(); var effectTypeOffset = reader.ReadUInt32(); var techiqueCount = reader.ReadUInt32(); var techniqueOffset = reader.ReadUInt32(); reader.JumpTo(effectTypeOffset, false); for (int i = 0; i < effectTypeCount; i++) { EFFFILE effFile = new EFFFILE(); effFile.Type = reader.ReadUInt32(); var jumpPoint = reader.ReadUInt32(); long effectPos = reader.BaseStream.Position; //Save Position reader.JumpTo(jumpPoint, false); effFile.Filename = reader.ReadNullTerminatedString(); reader.JumpTo(effectPos); EffectList.Effects.Add(effFile); } reader.JumpTo(techniqueOffset, false); for (int i = 0; i < techiqueCount; i++) { TECHNAME tech = new TECHNAME(); tech.Type = reader.ReadUInt32(); tech.NodeID = reader.ReadUInt32(); var jumpPoint = reader.ReadUInt32(); long techPos = reader.BaseStream.Position; //Save Position reader.JumpTo(jumpPoint, false); tech.Filename = reader.ReadNullTerminatedString(); reader.JumpTo(techPos); EffectList.Techs.Add(tech); } reader.JumpTo(pos); reader.JumpAhead(EffectList.NodeLength); return(EffectList); }
public NinjaTextureList ReadNinjaTextureList(ExtendedBinaryReader reader, long pos) { NinjaTextureList = new NinjaTextureList() { NodeName = new string(reader.ReadChars(4)) }; uint NodeLength = reader.ReadUInt32(); pos = reader.BaseStream.Position; //Save Position uint NodeOffset = reader.ReadUInt32(); reader.JumpTo(NodeOffset, false); uint TextureCount = reader.ReadUInt32(); uint TextureListOffset = reader.ReadUInt32(); reader.JumpTo(TextureListOffset, false); for (int i = 0; i < TextureCount; i++) { uint Unknown1 = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?) uint TextureNameOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(TextureNameOffset, false); NinjaTextureFile TextureFile = new NinjaTextureFile() { TextureName = reader.ReadNullTerminatedString() }; reader.JumpTo(currentPos, true); TextureFile.Filters = reader.ReadUInt32(); uint Unknown2 = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?) uint Unknown3 = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?) NinjaTextureList.TextureFiles.Add(TextureFile); } reader.JumpTo(pos, true); reader.JumpAhead(NodeLength); return(NinjaTextureList); }
public NinjaNodeNameList ReadNinjaNodeNameList(ExtendedBinaryReader reader, long pos) { NinjaNodeNameList = new NinjaNodeNameList() { NodeName = new string(reader.ReadChars(4)) }; uint NodeLength = reader.ReadUInt32(); pos = reader.BaseStream.Position; //Save Position uint NodeOffset = reader.ReadUInt32(); reader.JumpTo(NodeOffset, false); uint Unknown1 = reader.ReadUInt32(); //Padding? uint NodeTableCount = reader.ReadUInt32(); uint NodeTableOffset = reader.ReadUInt32(); reader.JumpTo(NodeTableOffset, false); for (int i = 0; i < NodeTableCount; i++) { NinjaNodeName NodeName = new NinjaNodeName() { ID = reader.ReadUInt32() }; uint NodeNameIndex = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(NodeNameIndex, false); NodeName.Name = reader.ReadNullTerminatedString(); reader.JumpTo(currentPos, true); NinjaNodeNameList.NinjaNodeNames.Add(NodeName); } reader.JumpTo(pos, true); reader.JumpAhead(NodeLength); return(NinjaNodeNameList); }
/// <summary> /// Reads a SEAnim from a stream /// </summary> /// <param name="Stream">The stream to read from</param> /// <returns>A SEAnim if successful, otherwise throws an error and returns null</returns> public static SEModel Read(Stream Stream) { // Create a new model var model = new SEModel(); // Setup a new reader using (ExtendedBinaryReader readFile = new ExtendedBinaryReader(Stream)) { // Magic var Magic = readFile.ReadChars(7); // Version var Version = readFile.ReadInt16(); // Header size var HeaderSize = readFile.ReadInt16(); // Check magic if (!Magic.SequenceEqual(new char[] { 'S', 'E', 'M', 'o', 'd', 'e', 'l' })) { // Bad file throw new Exception("Bad SEModel file, magic was invalid"); } // Data present flags var DataPresentFlags = readFile.ReadByte(); // Bone data present flags var BoneDataPresentFlags = readFile.ReadByte(); // Mesh data present flags var MeshDataPresentFlags = readFile.ReadByte(); // Read counts var BoneCount = readFile.ReadInt32(); var MeshCount = readFile.ReadInt32(); var MatCount = readFile.ReadInt32(); // Skip 3 reserved bytes readFile.BaseStream.Position += 3; // Read bone tag names List <string> BoneNames = new List <string>(); // Loop for (int i = 0; i < BoneCount; i++) { BoneNames.Add(readFile.ReadNullTermString()); } // Loop and read bones for (int i = 0; i < BoneCount; i++) { // Read bone flags (unused) var BoneFlags = readFile.ReadByte(); // Read bone index var ParentIndex = readFile.ReadInt32(); // Check for global matricies Vector3 GlobalPosition = Vector3.Zero; Quaternion GlobalRotation = Quaternion.Identity; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_GLOBAL_MATRIX)) { GlobalPosition = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); GlobalRotation = new Quaternion(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Check for local matricies Vector3 LocalPosition = Vector3.Zero; Quaternion LocalRotation = Quaternion.Identity; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_LOCAL_MATRIX)) { LocalPosition = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); LocalRotation = new Quaternion(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Check for scales Vector3 Scale = Vector3.One; // Check if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_SCALES)) { Scale = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } // Add the bone model.AddBone(BoneNames[i], ParentIndex, GlobalPosition, GlobalRotation, LocalPosition, LocalRotation, Scale); } // Loop and read meshes for (int i = 0; i < MeshCount; i++) { // Make a new submesh var mesh = new SEModelMesh(); // Read mesh flags (unused) var MeshFlags = readFile.ReadByte(); // Read counts var MatIndiciesCount = readFile.ReadByte(); var MaxSkinInfluenceCount = readFile.ReadByte(); var VertexCount = readFile.ReadInt32(); var FaceCount = readFile.ReadInt32(); // Loop and read positions for (int v = 0; v < VertexCount; v++) { mesh.AddVertex(new SEModelVertex() { Position = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()) }); } // Read uvlayers if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_UVSET)) { for (int v = 0; v < VertexCount; v++) { for (int l = 0; l < MatIndiciesCount; l++) { mesh.Verticies[v].UVSets.Add(new Vector2(readFile.ReadSingle(), readFile.ReadSingle())); } } } // Read normals if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_NORMALS)) { // Loop and read vertex normals for (int v = 0; v < VertexCount; v++) { mesh.Verticies[v].VertexNormal = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle()); } } // Read colors if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_COLOR)) { // Loop and read colors for (int v = 0; v < VertexCount; v++) { mesh.Verticies[v].VertexColor = new Color(readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte()); } } // Read weights if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_WEIGHTS)) { for (int v = 0; v < VertexCount; v++) { // Read IDs and Values for (int l = 0; l < MaxSkinInfluenceCount; l++) { if (BoneCount <= 0xFF) { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadByte(), BoneWeight = readFile.ReadSingle() }); } else if (BoneCount <= 0xFFFF) { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadUInt16(), BoneWeight = readFile.ReadSingle() }); } else { mesh.Verticies[v].Weights.Add(new SEModelWeight() { BoneIndex = readFile.ReadUInt32(), BoneWeight = readFile.ReadSingle() }); } } } } // Loop and read faces for (int f = 0; f < FaceCount; f++) { if (VertexCount <= 0xFF) { mesh.AddFace(readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte()); } else if (VertexCount <= 0xFFFF) { mesh.AddFace(readFile.ReadUInt16(), readFile.ReadUInt16(), readFile.ReadUInt16()); } else { mesh.AddFace(readFile.ReadUInt32(), readFile.ReadUInt32(), readFile.ReadUInt32()); } } // Read material reference indicies for (int f = 0; f < MatIndiciesCount; f++) { mesh.AddMaterialIndex(readFile.ReadInt32()); } // Add the mesh model.AddMesh(mesh); } // Loop and read materials for (int m = 0; m < MatCount; m++) { var mat = new SEModelMaterial(); // Read the name mat.Name = readFile.ReadNullTermString(); // Read IsSimpleMaterial var IsSimpleMaterial = readFile.ReadBoolean(); // Read the material if (IsSimpleMaterial) { mat.MaterialData = new SEModelSimpleMaterial() { DiffuseMap = readFile.ReadNullTermString(), NormalMap = readFile.ReadNullTermString(), SpecularMap = readFile.ReadNullTermString() }; } // Add the material model.AddMaterial(mat); } } // Return result return(model); }
public const uint TAGMagic = 0x30474154; // "TAG0" in little-endian // Methods public static void Read(HavokFile h, ExtendedBinaryReader reader) { var fs = reader.BaseStream; long pos = fs.Position; long endPos = pos; var types = new List <string>(); reader.IsBigEndian = true; while (pos < fs.Length) { uint size = reader.ReadUInt32(); string type = new string(reader.ReadChars(4)); bool isParam = (((size & 0xC0000000) >> 24) == 0x40); // Remove the param marker from the beginning of the size if (isParam) { size &= 0xFFFFFF; } size -= 8; pos = fs.Position; endPos = pos + size; Console.WriteLine("{0}: \"{1}\"", (isParam) ? "Parameter" : "Section", type); // Read based on type switch (type) { // SDK Version case "SDKV": h.ContentsVersion = new string(reader.ReadChars((int)size)); Console.WriteLine($"Contents Version: {h.ContentsVersion}"); break; case "DATA": ReadDATASection(); break; // Type Strings case "TSTR": { Console.WriteLine(); while (fs.Position < endPos) { string t = reader.ReadNullTerminatedString(); if (string.IsNullOrEmpty(t)) { continue; } Console.WriteLine(t); types.Add(t); // TODO } Console.WriteLine(); break; } // Type Names (??) case "TNAM": { uint unknown1 = reader.ReadUInt32(); // TODO break; } // Format Strings case "FSTR": { Console.WriteLine(); while (fs.Position < endPos) { string t = reader.ReadNullTerminatedString(); if (string.IsNullOrEmpty(t)) { continue; } Console.WriteLine(t); // TODO } Console.WriteLine(); // TODO break; } } // TODO // Jump ahead to the next parameter if (isParam) { pos = endPos; if (fs.Position != pos) { reader.JumpTo(pos); } } } // Sub-Methods //HavokSection ReadSection() //{ // var section = new HavokSection(); // // TODO // return section; //} void ReadDATASection() { reader.IsBigEndian = false; // TODO ulong unknown1 = reader.ReadUInt64(); ulong unknown2 = reader.ReadUInt64(); ulong unknown3 = reader.ReadUInt64(); ulong unknown4 = reader.ReadUInt64(); ulong unknown5 = reader.ReadUInt64(); for (uint i = 0; i < unknown1; ++i) { string s = reader.ReadNullTerminatedString(); Console.WriteLine(s); } // TODO // Padding Checks if (unknown2 != 0) { Console.WriteLine($"WARNING: DATA Unknown2 != 0 ({unknown2})"); } reader.IsBigEndian = true; // TODO } }
// Methods public static List <SetObject> Read(ExtendedBinaryReader reader, Dictionary <string, SetObjectType> objectTemplates, SOBJType type) { var objs = new List <SetObject>(); // SOBJ Header var sig = reader.ReadChars(4); if (!reader.IsBigEndian) { Array.Reverse(sig); } string sigString = new string(sig); if (sigString != Signature) { throw new InvalidSignatureException(Signature, sigString); } uint unknown1 = reader.ReadUInt32(); uint objTypeCount = reader.ReadUInt32(); uint objTypeOffsetsOffset = reader.ReadUInt32(); reader.JumpAhead(4); uint objOffsetsOffset = reader.ReadUInt32(); uint objCount = reader.ReadUInt32(); uint unknown2 = reader.ReadUInt32(); // Probably just padding if (unknown2 != 0) { Console.WriteLine("WARNING: Unknown2 != 0! ({0})", unknown2); } uint transformsCount = reader.ReadUInt32(); // Object Offsets var objOffsets = new uint[objCount]; reader.JumpTo(objOffsetsOffset, false); for (uint i = 0; i < objCount; ++i) { objOffsets[i] = reader.ReadUInt32(); objs.Add(new SetObject()); } // Object Types reader.JumpTo(objTypeOffsetsOffset, false); for (uint i = 0; i < objTypeCount; ++i) { // Object Type string objName = reader.GetString(); uint objOfTypeCount = reader.ReadUInt32(); uint objIndicesOffset = reader.ReadUInt32(); long curTypePos = reader.BaseStream.Position; // Objects reader.JumpTo(objIndicesOffset, false); for (uint i2 = 0; i2 < objOfTypeCount; ++i2) { ushort objIndex = reader.ReadUInt16(); long curPos = reader.BaseStream.Position; var obj = new SetObject(); // We do this check here so we can print an offset that's actually helpful if (!objectTemplates.ContainsKey(objName)) { Console.WriteLine("{0} \"{1}\" (Offset: 0x{2:X})! Skipping this object...", "WARNING: No object template exists for object type", objName, (objOffsets[objIndex] + reader.Offset)); // Object Data without a template reader.JumpTo(objOffsets[objIndex], false); obj = ReadObject(reader, null, objName, type); } else { // Object Data with a template reader.JumpTo(objOffsets[objIndex], false); obj = ReadObject(reader, objectTemplates[objName], objName, type); } objs[objIndex] = obj; reader.BaseStream.Position = curPos; } reader.BaseStream.Position = curTypePos; } return(objs); }
public NinjaObject ReadNinjaObject(ExtendedBinaryReader reader, long pos) { NinjaObject = new NinjaObject() { NodeName = new string(reader.ReadChars(4)) }; uint NodeLength = reader.ReadUInt32(); pos = reader.BaseStream.Position; //Save Position uint NodeOffset = reader.ReadUInt32(); reader.JumpTo(NodeOffset, false); NinjaObject.ObjectCenter = reader.ReadVector3(); NinjaObject.ObjectRadius = reader.ReadSingle(); uint ObjectMaterialCount = reader.ReadUInt32(); uint ObjectMaterialOffset = reader.ReadUInt32(); uint ObjectVTXCount = reader.ReadUInt32(); uint ObjectVTXOffset = reader.ReadUInt32(); uint ObjectPrimitiveCount = reader.ReadUInt32(); uint ObjectPrimitiveOffset = reader.ReadUInt32(); uint ObjectNodeCount = reader.ReadUInt32(); NinjaObject.ObjectMaxNodeDepth = reader.ReadUInt32(); uint ObjectNodeOffset = reader.ReadUInt32(); NinjaObject.ObjectMTXPAL = reader.ReadUInt32(); uint ObjectSubObjectCount = reader.ReadUInt32(); uint ObjectSubObjectOffset = reader.ReadUInt32(); NinjaObject.ObjectTextureCount = reader.ReadUInt32(); //Materials reader.JumpTo(ObjectMaterialOffset, false); for (int i = 0; i < ObjectMaterialCount; i++) { //TO-DO: Figure out how all this fits together NinjaObjectMaterial ObjectMaterial = new NinjaObjectMaterial() { MaterialType = reader.ReadUInt32() }; uint MaterialOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(MaterialOffset, false); ObjectMaterial.MaterialFlags = reader.ReadUInt32(); ObjectMaterial.User = reader.ReadUInt32(); uint MaterialColourOffset = reader.ReadUInt32(); uint MaterialLogicOffset = reader.ReadUInt32(); uint MaterialTexDescOffset = reader.ReadUInt32(); reader.JumpTo(MaterialColourOffset, false); ObjectMaterial.MaterialDiffuse = reader.ReadVector4(); ObjectMaterial.MaterialAmbient = reader.ReadVector4(); ObjectMaterial.MaterialSpecular = reader.ReadVector4(); ObjectMaterial.MaterialEmissive = reader.ReadVector4(); ObjectMaterial.MaterialPower = reader.ReadSingle(); reader.JumpTo(MaterialLogicOffset, false); ObjectMaterial.MaterialBlendenable = reader.ReadUInt32(); ObjectMaterial.MaterialSRCBlend = reader.ReadUInt32(); ObjectMaterial.MaterialDSTBlend = reader.ReadUInt32(); ObjectMaterial.MaterialBlendFactor = reader.ReadUInt32(); ObjectMaterial.MaterialBlendOP = reader.ReadUInt32(); ObjectMaterial.MaterialLogicOP = reader.ReadUInt32(); ObjectMaterial.MaterialAlphaEnable = reader.ReadUInt32(); ObjectMaterial.MaterialAlphaFunction = reader.ReadUInt32(); ObjectMaterial.MaterialAlphaRef = reader.ReadUInt32(); ObjectMaterial.MaterialZCompenable = reader.ReadUInt32(); ObjectMaterial.MaterialZFunction = reader.ReadUInt32(); ObjectMaterial.MaterialZUpdateEnable = reader.ReadUInt32(); reader.JumpTo(MaterialTexDescOffset, false); ObjectMaterial.TextureTexMapType = reader.ReadUInt32(); ObjectMaterial.TextureID = reader.ReadUInt32(); ObjectMaterial.TextureOffset = reader.ReadVector2(); ObjectMaterial.TextureBlend = reader.ReadSingle(); ObjectMaterial.TextureInfoPTR = reader.ReadUInt32(); ObjectMaterial.TextureMinFilter = reader.ReadUInt32(); ObjectMaterial.TextureMagFilter = reader.ReadUInt32(); ObjectMaterial.TextureMipMapBias = reader.ReadSingle(); ObjectMaterial.TextureMaxMipLevel = reader.ReadUInt32(); reader.JumpTo(currentPos, true); NinjaObject.ObjectMaterialList.Add(ObjectMaterial); } //Vertexes reader.JumpTo(ObjectVTXOffset, false); for (int i = 0; i < ObjectVTXCount; i++) { NinjaObjectVertex ObjectVertex = new NinjaObjectVertex() { Type = reader.ReadUInt32() }; uint VTXOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(VTXOffset, false); ObjectVertex.VTXFormat = reader.ReadUInt32(); ObjectVertex.VTXFVF = reader.ReadUInt32(); ObjectVertex.VTXSize = reader.ReadUInt32(); uint VTXNumber = reader.ReadUInt32(); uint VTXListOffset = reader.ReadUInt32(); ObjectVertex.VTXBlendNum = reader.ReadUInt32(); uint VTXMTXOffset = reader.ReadUInt32(); ObjectVertex.VTXHDRCommon = reader.ReadUInt32(); ObjectVertex.VTXHDRData = reader.ReadUInt32(); ObjectVertex.VTXHDRLock = reader.ReadUInt32(); reader.JumpTo(VTXListOffset, false); for (int v = 0; v < VTXNumber; v++) { NinjaObjectVertexList Vertex = new NinjaObjectVertexList(); switch (ObjectVertex.VTXSize) { //Any ones other than 52 & 76 are probably wrong here, as they're not in the XTO and are instead based on the MaxScript //This is such a mess case 20: Vertex.Position = reader.ReadVector3(); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 24: Vertex.Position = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 28: Vertex.Position = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); ObjectVertex.Vertexes.Add(Vertex); break; case 32: Vertex.Position = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 36: Vertex.Position = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 44: Vertex.Position = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); Vertex.UnknownV2 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 48: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 52: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.MTXIDX = reader.ReadBytes(4); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); ObjectVertex.Vertexes.Add(Vertex); break; case 60: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.Normals = reader.ReadVector3(); Vertex.Tan = reader.ReadVector3(); Vertex.BNormal = reader.ReadVector3(); ObjectVertex.Vertexes.Add(Vertex); break; case 72: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.MTXIDX = reader.ReadBytes(4); Vertex.Normals = reader.ReadVector3(); Vertex.ST0 = reader.ReadVector2(); Vertex.Tan = reader.ReadVector3(); Vertex.BNormal = reader.ReadVector3(); ObjectVertex.Vertexes.Add(Vertex); break; case 76: Vertex.Position = reader.ReadVector3(); Vertex.Weight3 = reader.ReadVector3(); Vertex.MTXIDX = reader.ReadBytes(4); Vertex.Normals = reader.ReadVector3(); Vertex.RGBA8888 = reader.ReadBytes(4); Vertex.ST0 = reader.ReadVector2(); Vertex.Tan = reader.ReadVector3(); Vertex.BNormal = reader.ReadVector3(); ObjectVertex.Vertexes.Add(Vertex); break; default: Console.WriteLine($"Vertex Size of {ObjectVertex.VTXSize} not handled!"); continue; } } if (VTXMTXOffset != 0) { reader.JumpTo(VTXMTXOffset, false); ObjectVertex.VTXMTX = reader.ReadInt32(); } reader.JumpTo(currentPos, true); NinjaObject.ObjectVertexList.Add(ObjectVertex); } reader.JumpTo(ObjectPrimitiveOffset, false); for (int i = 0; i < ObjectPrimitiveCount; i++) { NinjaObjectPrimitive ObjectPrimitive = new NinjaObjectPrimitive() { Type = reader.ReadUInt32() }; uint PrimitiveListOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(PrimitiveListOffset, false); ObjectPrimitive.Format = reader.ReadUInt32(); ObjectPrimitive.Index = reader.ReadUInt32(); ObjectPrimitive.Strip = reader.ReadUInt32(); uint LengthOffset = reader.ReadUInt32(); uint IndexOffset = reader.ReadUInt32(); ObjectPrimitive.IndexBuf = reader.ReadUInt32(); reader.JumpTo(LengthOffset, false); ObjectPrimitive.IndexLength = reader.ReadUInt16(); //May be the same as Index all the time??? reader.JumpTo(IndexOffset, false); for (int v = 0; v < ObjectPrimitive.Index; v++) { ObjectPrimitive.VertexIndexList.Add(reader.ReadUInt16()); } reader.JumpTo(currentPos, true); NinjaObject.ObjectPrimitiveList.Add(ObjectPrimitive); } reader.JumpTo(ObjectNodeOffset, false); for (int i = 0; i < ObjectNodeCount; i++) { NinjaObjectNodeList Node = new NinjaObjectNodeList() { Type = reader.ReadUInt32(), Matrix = reader.ReadUInt16(), Parent = reader.ReadUInt16(), Child = reader.ReadUInt16(), Sibling = reader.ReadUInt16(), Transform = reader.ReadVector3(), Rotation = reader.ReadVector3(), Scale = reader.ReadVector3() }; for (int v = 0; v < 16; v++) { Node.Invinit.Add(reader.ReadSingle()); } Node.Center = reader.ReadVector3(); Node.User = reader.ReadUInt32(); Node.RSV0 = reader.ReadUInt32(); Node.RSV1 = reader.ReadUInt32(); Node.RSV2 = reader.ReadUInt32(); reader.JumpAhead(0x4); NinjaObject.ObjectNodeList.Add(Node); } reader.JumpTo(ObjectSubObjectOffset, false); for (int i = 0; i < ObjectSubObjectCount; i++) { uint Type = reader.ReadUInt32(); uint NMSST = reader.ReadUInt32(); uint MSSTOffset = reader.ReadUInt32(); uint Textures = reader.ReadUInt32(); uint TexturesOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(MSSTOffset, false); for (int v = 0; v < NMSST; v++) { NinjaObjectSubObject SubObject = new NinjaObjectSubObject() { Center = reader.ReadVector3(), Radius = reader.ReadSingle(), Node = reader.ReadUInt32(), Matrix = reader.ReadUInt32(), Material = reader.ReadUInt32(), VertexList = reader.ReadUInt32(), PrimList = reader.ReadUInt32(), ShaderList = reader.ReadUInt32() }; NinjaObject.ObjectSubObjectList.Add(SubObject); } reader.JumpTo(currentPos, true); } reader.JumpTo(pos, true); reader.JumpAhead(NodeLength); return(NinjaObject); }
public NinjaEffectList ReadNinjaEffectList(ExtendedBinaryReader reader, long pos) { NinjaEffectList = new NinjaEffectList() { NodeName = new string(reader.ReadChars(4)) }; uint NodeLength = reader.ReadUInt32(); pos = reader.BaseStream.Position; //Save Position uint NodeOffset = reader.ReadUInt32(); reader.JumpTo(NodeOffset, false); uint Unknown1 = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?) uint EffectTypeCount = reader.ReadUInt32(); uint EffectTypeOffset = reader.ReadUInt32(); uint TechniqueCount = reader.ReadUInt32(); uint TechniqueOffset = reader.ReadUInt32(); uint TechniqueIDXCount = reader.ReadUInt32(); uint TechniqueIDXOffset = reader.ReadUInt32(); //Effect Files reader.JumpTo(EffectTypeOffset, false); for (int i = 0; i < EffectTypeCount; i++) { NinjaEffectFile EffectFile = new NinjaEffectFile() { Type = reader.ReadUInt32() }; uint EffectFilenameOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(EffectFilenameOffset, false); EffectFile.Filename = reader.ReadNullTerminatedString(); reader.JumpTo(currentPos, true); NinjaEffectList.EffectFiles.Add(EffectFile); } //Effect List reader.JumpTo(TechniqueOffset, false); for (int i = 0; i < TechniqueCount; i++) { NinjaEffectTechnique Technique = new NinjaEffectTechnique() { Type = reader.ReadUInt32(), ID = reader.ReadUInt32() }; uint TechniqueNameOffset = reader.ReadUInt32(); long currentPos = reader.BaseStream.Position; //Save Position reader.JumpTo(TechniqueNameOffset, false); Technique.TechniqueName = reader.ReadNullTerminatedString(); reader.JumpTo(currentPos, true); NinjaEffectList.Techniques.Add(Technique); } //Technique IDX (not sure what this is for) reader.JumpTo(TechniqueIDXOffset, false); for (int i = 0; i < TechniqueIDXCount; i++) { NinjaEffectList.TechniqueIDX.Add(reader.ReadUInt16()); } reader.JumpTo(pos, true); reader.JumpAhead(NodeLength); return(NinjaEffectList); }
public NXOB ReadNodes(ExtendedBinaryReader reader, long pos) { /* * Sonic 4 Decompilation Ref * public NNS_NODE( AppMain.NNS_NODE node ) * { * this.fType = node.fType; * this.iMatrix = node.iMatrix; * this.iParent = node.iParent; * this.iChild = node.iChild; * this.iSibling = node.iSibling; * this.Translation.Assign( node.Translation ); * this.Rotation = node.Rotation; * this.Scaling.Assign( node.Scaling ); * this.InvInitMtx.Assign( node.InvInitMtx ); * this.Center.Assign( node.Center ); * this.Radius = node.Radius; * this.User = node.User; * this.SIIKBoneLength = node.SIIKBoneLength; * this.BoundingBoxY = node.BoundingBoxY; * this.BoundingBoxZ = node.BoundingBoxZ; * } */ ObjectList = new NXOB() { ObjectList = new string(reader.ReadChars(4)), NodeLength = reader.ReadUInt32() }; pos = reader.BaseStream.Position; //Save Position reader.JumpTo(reader.ReadUInt32(), false); reader.JumpAhead(0x10); //Variable Names Copy & Pasted from MaxScript var TexElmTotal = reader.ReadUInt32(); var TexElmOffset = reader.ReadUInt32(); var VertGroupTotal = reader.ReadUInt32(); var VertGroupOffset = reader.ReadUInt32(); var PolyElmTotal = reader.ReadUInt32(); var PolyElmOffset = reader.ReadUInt32(); //Nodes var NodeTotal = reader.ReadUInt32(); var UnknownCount1 = reader.ReadUInt32(); //Count of SOMETHING? var NodeOffset = reader.ReadUInt32(); var UnknownCount2 = reader.ReadUInt32(); //MaxScript calls this NodeTotal, but I'm sure what they call BoneTotal is actually NodeTotal? Seems to be a Count of something var LinkTotal = reader.ReadUInt32(); var LinkOffset = reader.ReadUInt32(); var UnknownCount3 = reader.ReadUInt32(); //Count of SOMETHING? //NNS_NODE reader.JumpTo(NodeOffset, false); for (int i = 0; i < NodeTotal; i++) { Node node = new Node(); node.NODE_TYPE = reader.ReadUInt32(); node.NODE_MATRIX = reader.ReadUInt16(); node.NODE_PARENT = reader.ReadUInt16(); node.NODE_CHILD = reader.ReadUInt16(); node.NODE_SIBLING = reader.ReadUInt16(); for (int n = 0; n < 3; n++) { node.NODE_TRN.Add(reader.ReadSingle()); } for (int n = 0; n < 3; n++) { node.NODE_ROT.Add(reader.ReadSingle()); } for (int n = 0; n < 3; n++) { node.NODE_SCL.Add(reader.ReadSingle()); } for (int n = 0; n < 16; n++) { node.NODE_INVINIT_MTX.Add(reader.ReadSingle()); } for (int n = 0; n < 3; n++) { node.NODE_CENTER.Add(reader.ReadSingle()); } node.NODE_RADIUS = reader.ReadSingle(); node.NODE_USER = reader.ReadUInt32(); node.NODE_RSV0 = reader.ReadUInt32(); node.NODE_RSV1 = reader.ReadUInt32(); node.NODE_RSV2 = reader.ReadUInt32(); ObjectList.Nodes.Add(node); } reader.JumpTo(TexElmOffset, false); var Unknown1 = reader.ReadUInt32(); //Assume this is a count??? reader.JumpTo(reader.ReadUInt32(), false); return(ObjectList); }