private void exportBtn_Click(object sender, EventArgs e) { if (objSaveDialog.ShowDialog() == DialogResult.OK) { string OBJfilename = objSaveDialog.FileName; string MTLfilename = objSaveDialog.FileName.Split('.')[0] + ".mtl"; if (modelsListTree.SelectedNode.Level == 1) { if (modelsListTree.SelectedNode.Parent.Index == 0) //Level model { RatchetModel_General selectedModel = DataStore.spawnableModels[modelsListTree.SelectedNode.Index]; SpawnableToObj(ref selectedModel, OBJfilename, MTLfilename); Console.WriteLine("OBJ file created: " + OBJfilename); Console.WriteLine("MTL file created: " + MTLfilename); } else if (modelsListTree.SelectedNode.Parent.Index == 3) //Terrain { RatchetModel_Terrain model = DataStore.terrainModel; terrainMeshToObj(ref model, OBJfilename, MTLfilename); Console.WriteLine("OBJ file created: " + OBJfilename); Console.WriteLine("MTL file created: " + MTLfilename); } else { MessageBox.Show("Not currently supported"); } } } }
private void glControl1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); glControl1.MakeCurrent(); GL.UseProgram(pgm2ID); GL.EnableVertexAttribArray(0); camX.Text = cPosition.X.ToString(); camY.Text = cPosition.Y.ToString(); camZ.Text = cPosition.Z.ToString(); Matrix4 View = Matrix4.LookAt(cPosition, cTarget, Vector3.UnitZ); Matrix4 worldView = View * projection; if (modReady && mobyCheck.Checked) { GL.ClearColor(0, 0, 0, 0); foreach (RatchetMoby mob in DataStore.mobs) { objModel = DataStore.spawnableModels.Find(x => x.modelID == mob.modelID); int insx = mobList.IndexOf((uint)objModel.modelID); if (insx != -1) { int mobNum = DataStore.mobs.IndexOf(mob); byte[] cols = BitConverter.GetBytes(mobNum); Matrix4 modTrans = Matrix4.CreateTranslation(mob.x, mob.y, mob.z); Matrix4 modScale = Matrix4.CreateScale(objModel.size * mob.size); Matrix4 xRot = Matrix4.CreateRotationX(mob.rot1); Matrix4 yRot = Matrix4.CreateRotationY(mob.rot2); Matrix4 zRot = Matrix4.CreateRotationZ(mob.rot3); Matrix4 modRot = xRot * yRot * zRot; mvp = modScale * modRot * modTrans * worldView; //Has to be done in this order to work correctly GL.UniformMatrix4(MatrixID, false, ref mvp); GL.BindBuffer(BufferTarget.ArrayBuffer, mobVerts[insx]); GL.BindBuffer(BufferTarget.ElementArrayBuffer, mobInds[insx]); //Verts GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, 0); GL.Uniform4(pgmID_rcID, new Vector4(cols[0] / 255f, cols[1] / 255f, cols[2] / 255f, 1)); GL.DrawElements(PrimitiveType.Triangles, objModel.indiceBuff.Count(), DrawElementsType.UnsignedShort, 0); } } Byte4 pixel = new Byte4(); GL.ReadPixels(glControl1.PointToClient(Cursor.Position).X, glControl1.Height - glControl1.PointToClient(Cursor.Position).Y, 1, 1, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, ref pixel); if (pixel.A == 0) { mainForm.objViewer.selectList(pixel.ToUInt32()); } GL.ClearColor(Color.SkyBlue); } glControl1.Invalidate(); } }
private void modelsListTree_AfterSelect(object sender, TreeViewEventArgs e) { if (e.Node.Level == 1 && e.Node.Tag != null) { //Check that we're actually on a model switch ((ModelType)e.Node.Tag) { case ModelType.Spawnable: if (e.Node.Name.IndexOf("Mission_") != -1) { selectedModel = DataStore.missions[int.Parse(e.Node.Name.Substring(8))].spawnableModels[e.Node.Index]; } else { selectedModel = DataStore.spawnableModels[e.Node.Index]; } break; case ModelType.Level: selectedModel = DataStore.levelModels[e.Node.Index]; break; case ModelType.Scenery: selectedModel = DataStore.sceneryModels[e.Node.Index]; break; case ModelType.Terrain: RatchetModel_Terrain terrModel = DataStore.terrainModel; modelDataList.Items.Clear(); modelDataList.Items.Add("RENDERING DISABLED"); modelDataList.Items.Add("Faces: " + terrModel.indiceBuff.Count.ToString("X")); modelDataList.Items.Add("Vertices: " + terrModel.vertBuff.Count.ToString("X")); break; } inval(); } else { modelDataList.Items.Clear(); } }
public static void parseMap(string path, string fileName) { FileStream fs = File.OpenRead(path + "/" + fileName); FileStream vfs = null; if (File.Exists(path + "/vram.ps3")) { vfs = File.OpenRead(path + "/vram.ps3"); } FileStream gpf = null; if (File.Exists(path + "/gameplay_ntsc")) { gpf = File.OpenRead(path + "/gameplay_ntsc"); } uint racNum = 0; ushort magic = BAToUInt16(ReadBlock(fs, 0xB0, 2), 0); switch (magic) { case 0x7533: racNum = 1; break; case 0xEA9C: racNum = 2; break; case 0x0000: case 0x755D: racNum = 3; break; } Console.WriteLine("Game determined to be ratchet" + racNum.ToString()); List <MobyPropertyVariables> pVarConfigs = new List <MobyPropertyVariables>(); string jsonString = File.ReadAllText(String.Format("./Config/Rac{0}/MobyPropertyVariables.json", racNum)); pVarConfigs = JsonConvert.DeserializeObject <List <MobyPropertyVariables> >(jsonString); DataStore.pVarMap = pVarConfigs; #region GameplayHeader GameplayHeader gameplayHeader = new GameplayHeader(gpf, racNum); DataStore.gameplayHeader = gameplayHeader; #endregion #region pVars List <byte[]> pVars; uint numpVars; byte[] pVarHeadBlock; uint pVarSectionLength; byte[] pVarBlock; switch (racNum) { case 1: case 2: case 3: pVars = new List <byte[]>(); numpVars = (gameplayHeader.pVarPointer - gameplayHeader.pVarListPointer) / 8; pVarHeadBlock = ReadBlock(gpf, gameplayHeader.pVarListPointer, numpVars * 8); pVarSectionLength = 0; for (uint i = 0; i < numpVars; i++) { pVarSectionLength += BAToUInt32(pVarHeadBlock, (i * 8) + 0x04); } pVarBlock = ReadBlock(gpf, gameplayHeader.pVarPointer, pVarSectionLength); for (uint i = 0; i < numpVars; i++) { uint mobpVarsStart = BAToUInt32(pVarHeadBlock, (i * 8)); uint mobpVarsCount = BAToUInt32(pVarHeadBlock, (i * 8) + 0x04); byte[] mobpVars = new byte[mobpVarsCount]; mobpVars = getBytes(pVarBlock, (int)mobpVarsStart, (int)mobpVarsCount); pVars.Add(mobpVars); } DataStore.pVarList = pVars; break; } #endregion pVars #region Mobies uint mobyCount = BAToUInt32(ReadBlock(gpf, gameplayHeader.mobyPointer, 4), 0); byte[] mobyBlock = ReadBlock(gpf, gameplayHeader.mobyPointer + 0x10, mobyCount * gameplayHeader.mobyElemSize); for (uint i = 0; i < mobyCount; i++) { RatchetMoby mob = new RatchetMoby(racNum, mobyBlock, i); DataStore.mobs.Add(mob); } #endregion DataStore.splines = new List <Spline>(); uint splineCount = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer, 4), 0); uint splineOffset = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer + 4, 4), 0); uint splineSectionSize = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer + 8, 4), 0); byte[] splineHeadBlock = ReadBlock(gpf, gameplayHeader.splinePointer + 0x10, splineCount * 4); byte[] splineBlock = ReadBlock(gpf, gameplayHeader.splinePointer + splineOffset, splineSectionSize); for (uint i = 0; i < splineCount; i++) { uint offset = BAToUInt32(splineHeadBlock, (i * 4)); DataStore.splines.Add(new Spline(splineBlock, offset)); } gpf.Close(); EngineHeader engineHeader = new EngineHeader(fs, 1); DataStore.engineHeader = engineHeader; //Load UYA Spawnable Models #region Spawnables uint spawnablesCount = BAToUInt32(ReadBlock(fs, engineHeader.spawnablesPointer, 4), 0); byte[] idBlock = ReadBlock(fs, engineHeader.spawnablesPointer + 4, spawnablesCount * 8); for (int x = 0; x < spawnablesCount; x++) { RatchetModel_General model = new RatchetModel_General(); model.modelType = ModelType.Spawnable; model.modelID = BAToShort(idBlock, (uint)(x * 8) + 2); model.offset = BAToUInt32(idBlock, (uint)(x * 8) + 4); if (model.offset != 0) { uint modelHeadSize = BAToUInt32(ReadBlock(fs, model.offset, 4), 0); if (modelHeadSize > 0) { byte[] headBlock = ReadBlock(fs, model.offset, modelHeadSize + 0x20); //Head + objectDetails uint objectPtr = BAToUInt32(headBlock, 0); model.animationsCount = headBlock[0x0C]; //(0x04)null //(0x08)[count for 0x14 and 0x18][unknown][unknown][unknown] //(0x0c)[animation count][unknown][unknown][unknown] //(0x10)Pointer to list //(0x14)Pointer to skeleton joints (0x40 structure) //(0x18)Pointer to skeleton somethings (0x16 structure) //(0x1C)Pointer to left arm animations (Ratchet) //(0x20)null model.size = BAToFloat(headBlock, 0x24); uint texCount = BAToUInt32(headBlock, objectPtr + 0x00); uint otherCount = BAToUInt32(headBlock, objectPtr + 0x04); uint texBlockPointer = BAToUInt32(headBlock, objectPtr + 0x08); uint otherBlockPointer = BAToUInt32(headBlock, objectPtr + 0x0C); uint vertPointer = BAToUInt32(headBlock, objectPtr + 0x10); uint indexPointer = BAToUInt32(headBlock, objectPtr + 0x14); model.vertexCount = BAToUInt16(headBlock, objectPtr + 0x18); //(0x1A)count //(0x1C)count //(0x1E)null //model.rawData = getModelDataRaw(model.modelType, model.modelID, path + "/" + fileName); model.animPointer = new List <uint>(); for (uint i = 0; i < model.animationsCount; i++) { model.animPointer.Add(BAToUInt32(headBlock, (i * sizeof(uint)) + 0x48)); } uint texElemSize = 0x10; byte[] texBlock = ReadBlock(fs, model.offset + texBlockPointer, texCount * texElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.faceCount = 0; for (uint t = 0; t < texCount; t++) { RatchetTexture_Model modTex = new RatchetTexture_Model(); modTex.ID = BAToUInt32(texBlock, (t * texElemSize) + 0x0); modTex.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04); modTex.size = BAToUInt32(texBlock, (t * texElemSize) + 0x08); model.textureConfig.Add(modTex); model.faceCount += modTex.size; } //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved] uint vertElemSize = 0x28; uint vertBuffSize = model.vertexCount * vertElemSize; byte[] vertBlock = ReadBlock(fs, model.offset + vertPointer, vertBuffSize); model.vertBuff = new List <float>(); for (uint i = 0; i < model.vertexCount; i++) { model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //Vertx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //Verty model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //Vertz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //Nomrx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //Normy model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //Normz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x18)); //UVu model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x1C)); //UVv } //Flip endianness of index array byte[] indiceBuff = ReadBlock(fs, model.offset + indexPointer, model.faceCount * sizeof(ushort)); model.indiceBuff = new List <ushort>(); for (uint i = 0; i < model.faceCount; i++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort))); } } } DataStore.spawnableModels.Add(model); } #endregion //Load UYA Level Models #region Level Models uint levelElemSize = 0x40; byte[] levelBlock = ReadBlock(fs, engineHeader.levelModelsPointer, engineHeader.levelModelsCount * levelElemSize); for (uint x = 0; x < engineHeader.levelModelsCount; x++) { RatchetModel_General model = new RatchetModel_General(); model.modelType = ModelType.Level; model.size = 0.5f; uint vertPointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x10); uint UVPointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x14); uint indicePointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x18); uint texPointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x1C); model.vertexCount = (ushort)BAToUInt32(levelBlock, (x * levelElemSize) + 0x24); ushort texCount = BAToUInt16(levelBlock, (x * levelElemSize) + 0x28); model.modelID = BAToShort(levelBlock, (x * levelElemSize) + 0x30); model.offset = (uint)(x * 0x40) + engineHeader.levelModelsPointer; model.modelType = ModelType.Level; uint texElemSize = 0x18; byte[] texBlock = ReadBlock(fs, texPointer, texCount * texElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.faceCount = 0; for (uint t = 0; t < texCount; t++) { RatchetTexture_Model dlt = new RatchetTexture_Model(); dlt.ID = BAToUInt32(texBlock, (t * texElemSize) + 0x00); dlt.start = BAToUInt32(texBlock, (t * texElemSize) + 0x08); dlt.size = BAToUInt32(texBlock, (t * texElemSize) + 0x0C); model.textureConfig.Add(dlt); model.faceCount += dlt.size; } //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved] uint vertElemSize = 0x18; uint vertBuffSize = model.vertexCount * vertElemSize; byte[] vertBlock = ReadBlock(fs, vertPointer, vertBuffSize); uint UVElemsize = 0x08; uint UVBuffSize = model.vertexCount * UVElemsize; byte[] UVBlock = ReadBlock(fs, UVPointer, UVBuffSize); model.vertBuff = new List <float>(); for (uint i = 0; i < model.vertexCount; i++) { model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //vertx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //verty model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //vertz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //normx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //normy model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //normz model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x00)); //UVu model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x04)); //UVv } //Flip endianness of index array byte[] indiceBuff = ReadBlock(fs, indicePointer, model.faceCount * sizeof(ushort)); model.indiceBuff = new List <ushort>(); for (uint i = 0; i < model.faceCount; i++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort))); } DataStore.levelModels.Add(model); } #endregion //Load UYA Scenery Models #region Scenery Models uint sceneElemSize = 0x40; byte[] sceneBlock = ReadBlock(fs, engineHeader.sceneryModelsPointer, engineHeader.sceneryModelsCount * sceneElemSize); for (uint x = 0; x < engineHeader.sceneryModelsCount; x++) { RatchetModel_General model = new RatchetModel_General(); model.modelType = ModelType.Scenery; model.size = 0.5f; uint vertPointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x10); uint UVPointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x14); uint indicePointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x18); uint texPointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x1C); model.vertexCount = (ushort)BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x24); ushort texCount = BAToUInt16(sceneBlock, (x * sceneElemSize) + 0x28); model.modelID = BAToShort(sceneBlock, (x * sceneElemSize) + 0x30); uint texElemSize = 0x10; byte[] texBlock = ReadBlock(fs, texPointer, texCount * texElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.faceCount = 0; for (uint t = 0; t < texCount; t++) { RatchetTexture_Model dlt = new RatchetTexture_Model(); dlt.ID = BAToUInt32(texBlock, (t * texElemSize) + 0x00); dlt.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04); dlt.size = BAToUInt32(texBlock, (t * texElemSize) + 0x08); model.textureConfig.Add(dlt); model.faceCount += dlt.size; } //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved] uint vertElemSize = 0x18; uint vertBuffSize = model.vertexCount * vertElemSize; byte[] vertBlock = ReadBlock(fs, vertPointer, vertBuffSize); uint UVElemsize = 0x08; uint UVBuffSize = model.vertexCount * UVElemsize; byte[] UVBlock = ReadBlock(fs, UVPointer, UVBuffSize); model.vertBuff = new List <float>(); for (uint i = 0; i < model.vertexCount; i++) { model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //vertx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //verty model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //vertz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //normx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //normy model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //normz model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x00)); //UVu model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x04)); //UVv } //Flip endianness of index array byte[] indiceBuff = ReadBlock(fs, indicePointer, model.faceCount * sizeof(ushort)); model.indiceBuff = new List <ushort>(); for (uint i = 0; i < model.faceCount; i++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort))); } DataStore.sceneryModels.Add(model); //Console.WriteLine("Scenery Model Added: 0x" + model.modelID.ToString("X4")); } #endregion //Load Terrain #region Terrain { uint terrainElemSize = 0x30; uint texElemSize = 0x10; uint vertElemSize = 0x1c; uint UVElemSize = 0x08; uint ColorElemSize = 0x04; RatchetModel_Terrain model = new RatchetModel_Terrain(); model.offset = engineHeader.terrainPointer; model.modelID = 1111; model.modelType = ModelType.Terrain; byte[] terrainHeadBlock = ReadBlock(fs, engineHeader.terrainPointer, 0x60); uint headPointer = BAToUInt32(terrainHeadBlock, 0x0); ushort headCount = BAToUInt16(terrainHeadBlock, 0x06); byte[] terrainBlock = ReadBlock(fs, headPointer, headCount * terrainElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.vertBuff = new List <float>(); model.indiceBuff = new List <uint>(); uint vertCount = 0; uint prevVertCount = 0; uint prevFaceCount = 0; uint prevHeadCount = 0; uint prevPrevFaceCount = 0; for (uint i = 0; i < 4; i++) //I have yet to see any level have more than two of these, but the header theoretically has space for 4 { uint vertPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x08); uint colPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x18); uint UVPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x28); uint indicePointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x38); prevFaceCount = 0; if (vertPointer != 0 && UVPointer != 0 && indicePointer != 0) //Check that there's data at the pointers { //Loop throught the heads, and stop when the overflow counter increases for (uint ii = prevHeadCount; ii < headCount && i == BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x22); ii++) { uint localFaceCount = 0; uint texPointer = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x10); uint texCount = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x14); ushort vertStart = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x18); ushort headVertCount = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x1A); vertCount += headVertCount; byte[] texBlock = ReadBlock(fs, texPointer, texElemSize * texCount); for (uint iii = 0; iii < texCount; iii++) { RatchetTexture_Model tex = new RatchetTexture_Model(); tex.ID = BAToUInt32(texBlock, (iii * texElemSize) + 0x00); tex.start = BAToUInt32(texBlock, (iii * texElemSize) + 0x04) + prevPrevFaceCount; tex.size = BAToUInt32(texBlock, (iii * texElemSize) + 0x08) + prevPrevFaceCount; localFaceCount += BAToUInt32(texBlock, (iii * texElemSize) + 0x08); model.textureConfig.Add(tex); } byte[] vertBlock = ReadBlock(fs, vertPointer + vertStart * vertElemSize, headVertCount * vertElemSize); byte[] colBlock = ReadBlock(fs, colPointer + vertStart * ColorElemSize, headVertCount * ColorElemSize); byte[] UVBlock = ReadBlock(fs, UVPointer + vertStart * UVElemSize, headVertCount * UVElemSize); for (uint iii = 0; iii < headVertCount; iii++) { model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x00)); //vertx model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x04)); //verty model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x08)); //vertz model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x0C)); //normx model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x10)); //normy model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x14)); //normz model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x00)); //UVu model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x04)); //UVv model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x00] / 255f); //color r model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x01] / 255f); //color g model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x02] / 255f); //color b model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x03] / 255f); //color a } byte[] indiceBuff = ReadBlock(fs, indicePointer + prevFaceCount * sizeof(ushort), localFaceCount * sizeof(ushort)); for (uint iii = 0; iii < localFaceCount; iii++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, iii * sizeof(ushort)) + prevVertCount); } prevFaceCount += localFaceCount; prevHeadCount = ii + 1; } prevVertCount = vertCount; prevPrevFaceCount = prevFaceCount; } } model.vertexCount = vertCount; model.faceCount = prevFaceCount; DataStore.terrainModel = model; } #endregion //Load Level Objects #region Level objects byte[] levelObjectBlock = ReadBlock(fs, engineHeader.levelObjectPointer, engineHeader.levelObjectCount * 0x70); DataStore.levelObjects = new List <LevelObject>(); for (uint i = 0; i < engineHeader.levelObjectCount; i++) { LevelObject levObj = new LevelObject(levelObjectBlock, i); DataStore.levelObjects.Add(levObj); } #endregion //Load Scenery Objects #region Scenery objects byte[] sceneryObjectBlock = ReadBlock(fs, engineHeader.sceneryObjectsPointer, engineHeader.sceneryObjectsCount * 0x70); DataStore.sceneryObjects = new List <LevelObject>(); for (uint i = 0; i < engineHeader.sceneryObjectsCount; i++) { LevelObject levObj = new LevelObject(sceneryObjectBlock, i); DataStore.sceneryObjects.Add(levObj); } #endregion //Load Textures #region Textures RatchetTexture_General texture = new RatchetTexture_General(); for (int x = 0; x < engineHeader.UYATextureCount; x++) { texture.texHeader = ReadBlock(fs, engineHeader.texturesPointer + (uint)(0x24 * x), 0x24); uint nextTexturePointer = x < engineHeader.UYATextureCount - 1 ? ReadUInt32(ReadBlock(fs, engineHeader.texturesPointer + (uint)(0x24 * (x + 1)), 0x4), 0) : vfs != null ? (uint)vfs.Length : 0; uint currentTexturePointer = ReadUInt32(texture.texHeader, 0); //Console.WriteLine("Parsing texture " + x + " " + currentTexturePointer.ToString("X") + " " + nextTexturePointer.ToString("X")); texture.ID = x; texture.width = BAToShort(texture.texHeader, 0x18); texture.height = BAToShort(texture.texHeader, 0x1A); texture.texData = vfs != null?ReadBlock(vfs, currentTexturePointer, nextTexturePointer - currentTexturePointer) : null; texture.reverseRGB = false; DataStore.textures.Add(texture); //Console.WriteLine("Texture : " + x + " Width: " + texture.width + " Height: " + texture.height); } #endregion //Terrain Collision #region Terrain Collision float div = 1024f; uint collisionVertCount = 0; uint collisionStart = engineHeader.collisionPointer + BAToUInt32(ReadBlock(fs, engineHeader.collisionPointer + 0x00, 4), 0); uint collisionLength = engineHeader.collisionPointer + collisionStart + BAToUInt32(ReadBlock(fs, engineHeader.collisionPointer + 0x04, 4), 0); byte[] collision = ReadBlock(fs, collisionStart, collisionLength); List <float> collisionVertexBuff = new List <float>(); List <uint> collisionIndiceBuff = new List <uint>(); ushort zShift = BAToUInt16(collision, 0); ushort zCount = BAToUInt16(collision, 2); for (uint z = 0; z < zCount; z++) { uint yOffset = BAToUInt32(collision, (z * 4) + 0x04); if (yOffset != 0) { ushort yShift = BAToUInt16(collision, yOffset + 0); ushort yCount = BAToUInt16(collision, yOffset + 2); for (uint y = 0; y < yCount; y++) { uint xOffset = BAToUInt32(collision, yOffset + (y * 4) + 0x04); if (xOffset != 0) { ushort xShift = BAToUInt16(collision, xOffset + 0); ushort xCount = BAToUInt16(collision, xOffset + 2); for (uint x = 0; x < xCount; x++) { uint vOffset = BAToUInt32(collision, xOffset + (x * 4) + 4); ushort faceCount = BAToUInt16(collision, vOffset); byte vertexCount = collision[vOffset + 2]; byte rCount = collision[vOffset + 3]; if (vOffset != 0) { byte[] collisionType = new byte[vertexCount]; //Console.WriteLine("Facecount: " + faceCount.ToString("X2") + "VertCount: " + vertexCount.ToString("X2")); for (uint f = 0; f < faceCount; f++) { uint fOffset = vOffset + ((uint)12 * vertexCount) + 4 + (f * 4); byte[] fArray = new byte[4]; Array.Copy(collision, fOffset, fArray, 0, 4); collisionType[fArray[0]] = fArray[3]; collisionType[fArray[1]] = fArray[3]; collisionType[fArray[2]] = fArray[3]; uint f1 = collisionVertCount + fArray[0]; uint f2 = collisionVertCount + fArray[1]; uint f3 = collisionVertCount + fArray[2]; collisionIndiceBuff.Add(f1); collisionIndiceBuff.Add(f2); collisionIndiceBuff.Add(f3); if (f < rCount) { uint rOffset = vOffset + 4 + (uint)(12 * vertexCount) + (uint)(4 * faceCount) + f; uint f4 = collisionVertCount + collision[rOffset]; collisionIndiceBuff.Add(f1); collisionIndiceBuff.Add(f3); collisionIndiceBuff.Add(f4); collisionType[collision[rOffset]] = fArray[3]; } } for (uint v = 0; v < vertexCount; v++) { uint pOffset = vOffset + (12 * v) + 4; float pX = BAToFloat(collision, pOffset + 0) / div + 4 * (xShift + x + 0.5f); float pY = BAToFloat(collision, pOffset + 4) / div + 4 * (yShift + y + 0.5f); float pZ = BAToFloat(collision, pOffset + 8) / div + 4 * (zShift + z + 0.5f); collisionVertexBuff.Add(pX); collisionVertexBuff.Add(pY); collisionVertexBuff.Add(pZ); switch (collisionType[v]) { case 0x1F: collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); break; case 0x08: collisionVertexBuff.Add(1.0f); collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); break; case 0x0C: collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(1.0f); collisionVertexBuff.Add(0.0f); break; case 0x01: //This collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); break; case 0x3F: collisionVertexBuff.Add(0.5f); collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); break; case 0x0B: collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.5f); collisionVertexBuff.Add(0.0f); break; case 0x0A: collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.5f); break; case 0x28: collisionVertexBuff.Add(0.25f); collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); break; case 0x5F: collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.25f); collisionVertexBuff.Add(0.0f); break; case 0x09: collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.25f); break; case 0x00: collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(0.0f); collisionVertexBuff.Add(1.0f); break; case 0x6C: collisionVertexBuff.Add(0.5f); collisionVertexBuff.Add(0.5f); collisionVertexBuff.Add(0.5f); break; default: collisionVertexBuff.Add(1.0f); collisionVertexBuff.Add(1.0f); collisionVertexBuff.Add(1.0f); break; } collisionVertCount++; } } } } } } } DataStore.collVertBuff = collisionVertexBuff; DataStore.collIndBuff = collisionIndiceBuff; #endregion #region Chunks List <int> chunkIds = new List <int>(); for (int chunkIndex = 0; chunkIndex < 5; chunkIndex++) { if (File.Exists(path + "/chunk" + chunkIndex + ".ps3")) { chunkIds.Add(chunkIndex); } } foreach (int chunkId in chunkIds) { FileStream cfs = File.OpenRead(path + "/chunk" + chunkId + ".ps3"); Console.WriteLine("Loading chunk " + chunkId); uint terrainElemSize = 0x30; uint texElemSize = 0x10; uint vertElemSize = 0x1c; uint UVElemSize = 0x08; uint ColorElemSize = 0x04; RatchetModel_Terrain model = new RatchetModel_Terrain(); model.offset = 0x10; model.modelID = 1111; model.modelType = ModelType.Terrain; byte[] terrainHeadBlock = ReadBlock(cfs, 0x10, 0x60); uint headPointer = BAToUInt32(terrainHeadBlock, 0x0); ushort headCount = BAToUInt16(terrainHeadBlock, 0x06); byte[] terrainBlock = ReadBlock(cfs, headPointer, headCount * terrainElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.vertBuff = new List <float>(); model.indiceBuff = new List <uint>(); uint vertCount = 0; uint prevVertCount = 0; uint prevFaceCount = 0; uint prevHeadCount = 0; uint prevPrevFaceCount = 0; for (uint i = 0; i < 4; i++) //I have yet to see any level have more than two of these, but the header theoretically has space for 4 { uint vertPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x08); uint colPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x18); uint UVPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x28); uint indicePointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x38); prevFaceCount = 0; if (vertPointer != 0 && UVPointer != 0 && indicePointer != 0) //Check that there's data at the pointers { //Loop throught the heads, and stop when the overflow counter increases for (uint ii = prevHeadCount; ii < headCount && i == BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x22); ii++) { uint localFaceCount = 0; uint texPointer = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x10); uint texCount = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x14); ushort vertStart = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x18); ushort headVertCount = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x1A); vertCount += headVertCount; byte[] texBlock = ReadBlock(cfs, texPointer, texElemSize * texCount); for (uint iii = 0; iii < texCount; iii++) { RatchetTexture_Model tex = new RatchetTexture_Model(); tex.ID = BAToUInt32(texBlock, (iii * texElemSize) + 0x00); tex.start = BAToUInt32(texBlock, (iii * texElemSize) + 0x04) + prevPrevFaceCount; tex.size = BAToUInt32(texBlock, (iii * texElemSize) + 0x08) + prevPrevFaceCount; localFaceCount += BAToUInt32(texBlock, (iii * texElemSize) + 0x08); model.textureConfig.Add(tex); } byte[] vertBlock = ReadBlock(cfs, vertPointer + vertStart * vertElemSize, headVertCount * vertElemSize); byte[] colBlock = ReadBlock(cfs, colPointer + vertStart * ColorElemSize, headVertCount * ColorElemSize); byte[] UVBlock = ReadBlock(cfs, UVPointer + vertStart * UVElemSize, headVertCount * UVElemSize); for (uint iii = 0; iii < headVertCount; iii++) { model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x00)); //vertx model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x04)); //verty model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x08)); //vertz model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x0C)); //normx model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x10)); //normy model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x14)); //normz model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x00)); //UVu model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x04)); //UVv model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x00] / 255f); //color r model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x01] / 255f); //color g model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x02] / 255f); //color b model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x03] / 255f); //color a } byte[] indiceBuff = ReadBlock(cfs, indicePointer + prevFaceCount * sizeof(ushort), localFaceCount * sizeof(ushort)); //Console.WriteLine(localFaceCount.ToString("X8")); for (uint iii = 0; iii < localFaceCount; iii++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, iii * sizeof(ushort)) + prevVertCount); } prevFaceCount += localFaceCount; prevHeadCount = ii + 1; } prevVertCount = vertCount; prevPrevFaceCount = prevFaceCount; } } model.vertexCount = vertCount; model.faceCount = prevFaceCount; DataStore.chunks.Add(model); } #endregion //TODO: textureConfig - Menus //TODO: textureConfig - 2D GFX //TODO: Sprites //Load the remaining unknown or unhandled data #region Remaining Data /* * DataStore.mapRenderDefintions = getSection(fs, 0x04); * DataStore.Ptr_08 = getSection(fs, 0x08); * DataStore.Ptr_0C = getSection(fs, 0x0C); * DataStore.skyBox = getSection(fs, 0x10); * DataStore.collisionMap = getSection(fs, 0x14); * DataStore.campaignPlayerAnimations = getSection(fs, 0x18); * DataStore.Ptr_40 = getSection(fs, 0x40); * DataStore.Ptr_44 = getSection(fs, 0x44); * DataStore.soundsConfig = getSection(fs, 0x48); * DataStore.Ptr_4C = getSection(fs, 0x4C); * DataStore.Ptr_50 = getSection(fs, 0x50); * DataStore.lighting = getSection(fs, 0x5C); * DataStore.lightingConfig = getSection(fs, 0x64); * DataStore.textureConfigMenu = getSection(fs, 0x68); * DataStore.textureConfig2DGFX = getSection(fs, 0x70); * DataStore.spriteDef = getSection(fs, 0x74); */ #endregion #region raw Data //need to properly handle these eventually //DataStore.terrainModel.rawData = getSection(fs, 0x3C); //rawLevelModelBlock = getSection(fs, 0x1C); //rawSceneryModelBlock = getSection(fs, 0x2C); #endregion fs.Close(); Console.WriteLine("Engine data loaded with new engine parser for UYA."); }
public static void parseMap(string path, string fileName) { FileStream fs = File.OpenRead(path + "/" + fileName); FileStream vfs = null; if (File.Exists(path + "/vram.ps3")) { vfs = File.OpenRead(path + "/vram.ps3"); } FileStream gpf = null; if (File.Exists(path + "/gameplay_ntsc")) { gpf = File.OpenRead(path + "/gameplay_ntsc"); } loadMobyPvarMap(); uint racNum = 4; #region GameplayHeader GameplayHeader gameplayHeader = new GameplayHeader(gpf, racNum); DataStore.gameplayHeader = gameplayHeader; #endregion #region pVars List <byte[]> pVars; uint numpVars; byte[] pVarHeadBlock; uint pVarSectionLength; byte[] pVarBlock; switch (racNum) { case 4: pVars = new List <byte[]>(); numpVars = (gameplayHeader.pVarPointer - gameplayHeader.pVarListPointer) / 8; pVarHeadBlock = ReadBlock(gpf, gameplayHeader.pVarListPointer, numpVars * 8); pVarSectionLength = 0; for (uint i = 0; i < numpVars; i++) { pVarSectionLength += BAToUInt32(pVarHeadBlock, (i * 8) + 0x04); } pVarBlock = ReadBlock(gpf, gameplayHeader.pVarPointer, pVarSectionLength); for (uint i = 0; i < numpVars; i++) { uint mobpVarsStart = BAToUInt32(pVarHeadBlock, (i * 8)); uint mobpVarsCount = BAToUInt32(pVarHeadBlock, (i * 8) + 0x04); byte[] mobpVars = new byte[mobpVarsCount]; mobpVars = getBytes(pVarBlock, (int)mobpVarsStart, (int)mobpVarsCount); pVars.Add(mobpVars); } DataStore.pVarList = pVars; break; } #endregion pVars #region Mobies uint mobyCount = BAToUInt32(ReadBlock(gpf, gameplayHeader.mobyPointer, 4), 0); byte[] mobyBlock = ReadBlock(gpf, gameplayHeader.mobyPointer + 0x10, mobyCount * gameplayHeader.mobyElemSize); for (uint i = 0; i < mobyCount; i++) { RatchetMoby mob = new RatchetMoby(racNum, mobyBlock, i); DataStore.mobs.Add(mob); } #endregion DataStore.splines = new List <Spline>(); uint splineCount = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer, 4), 0); uint splineOffset = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer + 4, 4), 0); uint splineSectionSize = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer + 8, 4), 0); byte[] splineHeadBlock = ReadBlock(gpf, gameplayHeader.splinePointer + 0x10, splineCount * 4); byte[] splineBlock = ReadBlock(gpf, gameplayHeader.splinePointer + splineOffset, splineSectionSize); for (uint i = 0; i < splineCount; i++) { uint offset = BAToUInt32(splineHeadBlock, (i * 4)); DataStore.splines.Add(new Spline(splineBlock, offset)); } #region EngineHeader byte[] engineHeader = ReadBlock(fs, 0, 0x90); //Data from header uint spawnablesPointer = BAToUInt32(engineHeader, 0x00); //(0x04)Map render definitions //(0x08)null //(0x0C)null //(0x14)Skybox //(0x18)Collisionmap uint levelModelsPointer = BAToUInt32(engineHeader, 0x20); uint levelModelsCount = BAToUInt32(engineHeader, 0x24); uint levelModelsPlacementPointer = BAToUInt32(engineHeader, 0x28); uint levelObjectsCount = BAToUInt32(engineHeader, 0x2C); uint sceneryModelsPointer = BAToUInt32(engineHeader, 0x34); uint sceneryModelsCount = BAToUInt32(engineHeader, 0x38); uint sceneryModelsPlacementPointer = BAToUInt32(engineHeader, 0x3C); uint sceneryObjectsCount = BAToUInt32(engineHeader, 0x40); uint terrainPointer = BAToUInt32(engineHeader, 0x48); //(0x44) ?? //(0x54)Sound config (Menus + terrain) uint texturesPointer = BAToUInt32(engineHeader, 0x60); uint textureCount = BAToUInt32(engineHeader, 0x64); //(0x68)Lighting pointer uint lightingLevel = BAToUInt32(engineHeader, 0x6C); uint textureConfigMenuCount = BAToUInt32(engineHeader, 0x78); //(0x7C)textureConfig2DGFX //(0x80)Sprite def //(0x88) sound config (spawnables + everything else) EngineHeader engHead = new EngineHeader(fs, 4); DataStore.engineHeader = engHead; #endregion //Load DL Spawnable Models #region Spawnables uint spawnablesCount = BAToUInt32(ReadBlock(fs, spawnablesPointer, 4), 0); byte[] idBlock = ReadBlock(fs, spawnablesPointer + 4, spawnablesCount * 8); for (int x = 0; x < spawnablesCount; x++) { RatchetModel_General model = new RatchetModel_General(); model.modelType = ModelType.Spawnable; model.modelID = BAToShort(idBlock, (uint)(x * 8) + 2); model.offset = BAToUInt32(idBlock, (uint)(x * 8) + 4); if (model.offset != 0) { uint modelHeadSize = BAToUInt32(ReadBlock(fs, model.offset, 4), 0); if (modelHeadSize > 0) { byte[] headBlock = ReadBlock(fs, model.offset, modelHeadSize + 0x20); //Head + objectDetails uint objectPtr = BAToUInt32(headBlock, 0); model.animationsCount = headBlock[0x0C]; //(0x04)null //(0x08)[count for 0x14 and 0x18][unknown][unknown][unknown] //(0x0c)[animation count][unknown][unknown][unknown] //(0x10)Pointer to list //(0x14)Pointer to skeleton joints (0x40 structure) //(0x18)Pointer to skeleton somethings (0x16 structure) //(0x1C)Pointer to left arm animations (Ratchet) //(0x20)null model.size = BAToFloat(headBlock, 0x24); uint texCount = BAToUInt32(headBlock, objectPtr + 0x00); uint otherCount = BAToUInt32(headBlock, objectPtr + 0x04); uint texBlockPointer = BAToUInt32(headBlock, objectPtr + 0x08); uint otherBlockPointer = BAToUInt32(headBlock, objectPtr + 0x0C); uint vertPointer = BAToUInt32(headBlock, objectPtr + 0x10); uint indexPointer = BAToUInt32(headBlock, objectPtr + 0x14); model.vertexCount = BAToUInt16(headBlock, objectPtr + 0x18); //(0x1A)count //(0x1C)count //(0x1E)null //model.rawData = getModelDataRaw(model.modelType, model.modelID, path + "/" + fileName); model.animPointer = new List <uint>(); for (uint i = 0; i < model.animationsCount; i++) { model.animPointer.Add(BAToUInt32(headBlock, (i * sizeof(uint)) + 0x48)); } uint texElemSize = 0x10; byte[] texBlock = ReadBlock(fs, model.offset + texBlockPointer, texCount * texElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.faceCount = 0; for (uint t = 0; t < texCount; t++) { RatchetTexture_Model modTex = new RatchetTexture_Model(); modTex.ID = BAToUInt32(texBlock, (t * texElemSize) + 0x0); modTex.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04); modTex.size = BAToUInt32(texBlock, (t * texElemSize) + 0x08); model.textureConfig.Add(modTex); model.faceCount += modTex.size; } //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved] uint vertElemSize = 0x28; uint vertBuffSize = model.vertexCount * vertElemSize; byte[] vertBlock = ReadBlock(fs, model.offset + vertPointer, vertBuffSize); model.vertBuff = new List <float>(); for (uint i = 0; i < model.vertexCount; i++) { model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //Vertx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //Verty model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //Vertz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //Nomrx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //Normy model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //Normz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x18)); //UVu model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x1C)); //UVv } //Flip endianness of index array byte[] indiceBuff = ReadBlock(fs, model.offset + indexPointer, model.faceCount * sizeof(ushort)); model.indiceBuff = new List <ushort>(); for (uint i = 0; i < model.faceCount; i++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort))); } } } DataStore.spawnableModels.Add(model); } #endregion //Load DL Level Models #region Level Models uint levelElemSize = 0x40; byte[] levelBlock = ReadBlock(fs, levelModelsPointer, levelModelsCount * levelElemSize); for (uint x = 0; x < levelModelsCount; x++) { RatchetModel_General model = new RatchetModel_General(); model.modelType = ModelType.Level; model.size = 0.5f; uint vertPointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x10); uint UVPointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x14); uint indicePointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x18); uint texPointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x1C); model.vertexCount = (ushort)BAToUInt32(levelBlock, (x * levelElemSize) + 0x24); ushort texCount = BAToUInt16(levelBlock, (x * levelElemSize) + 0x28); model.modelID = BAToShort(levelBlock, (x * levelElemSize) + 0x30); model.offset = (uint)(x * 0x40) + levelModelsPointer; model.modelType = ModelType.Level; uint texElemSize = 0x18; byte[] texBlock = ReadBlock(fs, texPointer, texCount * texElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.faceCount = 0; for (uint t = 0; t < texCount; t++) { RatchetTexture_Model dlt = new RatchetTexture_Model(); dlt.ID = BAToUInt32(texBlock, (t * texElemSize) + 0x00); dlt.start = BAToUInt32(texBlock, (t * texElemSize) + 0x08); dlt.size = BAToUInt32(texBlock, (t * texElemSize) + 0x0C); model.textureConfig.Add(dlt); model.faceCount += dlt.size; } //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved] uint vertElemSize = 0x18; uint vertBuffSize = model.vertexCount * vertElemSize; byte[] vertBlock = ReadBlock(fs, vertPointer, vertBuffSize); uint UVElemsize = 0x08; uint UVBuffSize = model.vertexCount * UVElemsize; byte[] UVBlock = ReadBlock(fs, UVPointer, UVBuffSize); model.vertBuff = new List <float>(); for (uint i = 0; i < model.vertexCount; i++) { model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //vertx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //verty model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //vertz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //normx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //normy model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //normz model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x00)); //UVu model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x04)); //UVv } //Flip endianness of index array byte[] indiceBuff = ReadBlock(fs, indicePointer, model.faceCount * sizeof(ushort)); model.indiceBuff = new List <ushort>(); for (uint i = 0; i < model.faceCount; i++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort))); } DataStore.levelModels.Add(model); } #endregion //Load DL Scenery Models #region Scenery Models uint sceneElemSize = 0x40; byte[] sceneBlock = ReadBlock(fs, sceneryModelsPointer, sceneryModelsCount * sceneElemSize); for (uint x = 0; x < sceneryModelsCount; x++) { RatchetModel_General model = new RatchetModel_General(); model.modelType = ModelType.Scenery; model.size = 0.5f; uint vertPointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x10); uint UVPointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x14); uint indicePointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x18); uint texPointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x1C); model.vertexCount = (ushort)BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x24); ushort texCount = BAToUInt16(sceneBlock, (x * sceneElemSize) + 0x28); model.modelID = BAToShort(sceneBlock, (x * sceneElemSize) + 0x30); uint texElemSize = 0x10; byte[] texBlock = ReadBlock(fs, texPointer, texCount * texElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.faceCount = 0; for (uint t = 0; t < texCount; t++) { RatchetTexture_Model dlt = new RatchetTexture_Model(); dlt.ID = BAToUInt32(texBlock, (t * texElemSize) + 0x00); dlt.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04); dlt.size = BAToUInt32(texBlock, (t * texElemSize) + 0x08); model.textureConfig.Add(dlt); model.faceCount += dlt.size; } //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved] uint vertElemSize = 0x18; uint vertBuffSize = model.vertexCount * vertElemSize; byte[] vertBlock = ReadBlock(fs, vertPointer, vertBuffSize); uint UVElemsize = 0x08; uint UVBuffSize = model.vertexCount * UVElemsize; byte[] UVBlock = ReadBlock(fs, UVPointer, UVBuffSize); model.vertBuff = new List <float>(); for (uint i = 0; i < model.vertexCount; i++) { model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //vertx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //verty model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //vertz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //normx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //normy model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //normz model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x00)); //UVu model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x04)); //UVv } //Flip endianness of index array byte[] indiceBuff = ReadBlock(fs, indicePointer, model.faceCount * sizeof(ushort)); model.indiceBuff = new List <ushort>(); for (uint i = 0; i < model.faceCount; i++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort))); } DataStore.sceneryModels.Add(model); //Console.WriteLine("Scenery Model Added: 0x" + model.modelID.ToString("X4")); } #endregion //Load Terrain #region Terrain { uint terrainElemSize = 0x30; uint texElemSize = 0x10; uint vertElemSize = 0x1c; uint UVElemSize = 0x08; uint ColorElemSize = 0x04; RatchetModel_Terrain model = new RatchetModel_Terrain(); model.offset = terrainPointer; model.modelID = 1111; model.modelType = ModelType.Terrain; byte[] terrainHeadBlock = ReadBlock(fs, terrainPointer, 0x60); uint headPointer = BAToUInt32(terrainHeadBlock, 0x0); ushort headCount = BAToUInt16(terrainHeadBlock, 0x06); byte[] terrainBlock = ReadBlock(fs, headPointer, headCount * terrainElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.vertBuff = new List <float>(); model.indiceBuff = new List <uint>(); uint vertCount = 0; uint prevVertCount = 0; uint prevFaceCount = 0; uint prevHeadCount = 0; uint prevPrevFaceCount = 0; for (uint i = 0; i < 4; i++) //I have yet to see any level have more than two of these, but the header theoretically has space for 4 { uint vertPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x08); uint colPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x18); uint UVPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x28); uint indicePointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x38); prevFaceCount = 0; if (vertPointer != 0 && UVPointer != 0 && indicePointer != 0) //Check that there's data at the pointers { //Loop throught the heads, and stop when the overflow counter increases for (uint ii = prevHeadCount; ii < headCount && i == BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x22); ii++) { uint localFaceCount = 0; uint texPointer = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x10); uint texCount = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x14); ushort vertStart = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x18); ushort headVertCount = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x1A); vertCount += headVertCount; byte[] texBlock = ReadBlock(fs, texPointer, texElemSize * texCount); for (uint iii = 0; iii < texCount; iii++) { RatchetTexture_Model tex = new RatchetTexture_Model(); tex.ID = BAToUInt32(texBlock, (iii * texElemSize) + 0x00); tex.start = BAToUInt32(texBlock, (iii * texElemSize) + 0x04) + prevPrevFaceCount; tex.size = BAToUInt32(texBlock, (iii * texElemSize) + 0x08) + prevPrevFaceCount; localFaceCount += BAToUInt32(texBlock, (iii * texElemSize) + 0x08); model.textureConfig.Add(tex); } byte[] vertBlock = ReadBlock(fs, vertPointer + vertStart * vertElemSize, headVertCount * vertElemSize); byte[] colBlock = ReadBlock(fs, colPointer + vertStart * ColorElemSize, headVertCount * ColorElemSize); byte[] UVBlock = ReadBlock(fs, UVPointer + vertStart * UVElemSize, headVertCount * UVElemSize); for (uint iii = 0; iii < headVertCount; iii++) { model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x00)); //vertx model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x04)); //verty model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x08)); //vertz model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x0C)); //normx model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x10)); //normy model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x14)); //normz model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x00)); //UVu model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x04)); //UVv model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x00] / 255f); //color r model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x01] / 255f); //color g model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x02] / 255f); //color b model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x03] / 255f); //color a } byte[] indiceBuff = ReadBlock(fs, indicePointer + prevFaceCount * sizeof(ushort), localFaceCount * sizeof(ushort)); for (uint iii = 0; iii < localFaceCount; iii++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, iii * sizeof(ushort)) + prevVertCount); } prevFaceCount += localFaceCount; prevHeadCount = ii + 1; } prevVertCount = vertCount; prevPrevFaceCount = prevFaceCount; } } model.vertexCount = vertCount; model.faceCount = prevFaceCount; DataStore.terrainModel = model; } #endregion #region Chunks List <int> chunkIds = new List <int>(); for (int chunkIndex = 0; chunkIndex < 5; chunkIndex++) { if (File.Exists(path + "/chunk" + chunkIndex + ".ps3")) { chunkIds.Add(chunkIndex); } } foreach (int chunkId in chunkIds) { FileStream cfs = File.OpenRead(path + "/chunk" + chunkId + ".ps3"); Console.WriteLine("Loading chunk " + chunkId); uint terrainElemSize = 0x30; uint texElemSize = 0x10; uint vertElemSize = 0x1c; uint UVElemSize = 0x08; uint ColorElemSize = 0x04; RatchetModel_Terrain model = new RatchetModel_Terrain(); model.offset = 0x10; model.modelID = 1111; model.modelType = ModelType.Terrain; byte[] terrainHeadBlock = ReadBlock(cfs, 0x10, 0x60); uint headPointer = BAToUInt32(terrainHeadBlock, 0x0); ushort headCount = BAToUInt16(terrainHeadBlock, 0x06); byte[] terrainBlock = ReadBlock(cfs, headPointer, headCount * terrainElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.vertBuff = new List <float>(); model.indiceBuff = new List <uint>(); uint vertCount = 0; uint prevVertCount = 0; uint prevFaceCount = 0; uint prevHeadCount = 0; uint prevPrevFaceCount = 0; for (uint i = 0; i < 4; i++) //I have yet to see any level have more than two of these, but the header theoretically has space for 4 { uint vertPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x08); uint colPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x18); uint UVPointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x28); uint indicePointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x38); prevFaceCount = 0; if (vertPointer != 0 && UVPointer != 0 && indicePointer != 0) //Check that there's data at the pointers { //Loop throught the heads, and stop when the overflow counter increases for (uint ii = prevHeadCount; ii < headCount && i == BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x22); ii++) { uint localFaceCount = 0; uint texPointer = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x10); uint texCount = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x14); ushort vertStart = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x18); ushort headVertCount = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x1A); vertCount += headVertCount; byte[] texBlock = ReadBlock(cfs, texPointer, texElemSize * texCount); for (uint iii = 0; iii < texCount; iii++) { RatchetTexture_Model tex = new RatchetTexture_Model(); tex.ID = BAToUInt32(texBlock, (iii * texElemSize) + 0x00); tex.start = BAToUInt32(texBlock, (iii * texElemSize) + 0x04) + prevPrevFaceCount; tex.size = BAToUInt32(texBlock, (iii * texElemSize) + 0x08) + prevPrevFaceCount; localFaceCount += BAToUInt32(texBlock, (iii * texElemSize) + 0x08); model.textureConfig.Add(tex); } byte[] vertBlock = ReadBlock(cfs, vertPointer + vertStart * vertElemSize, headVertCount * vertElemSize); byte[] colBlock = ReadBlock(cfs, colPointer + vertStart * ColorElemSize, headVertCount * ColorElemSize); byte[] UVBlock = ReadBlock(cfs, UVPointer + vertStart * UVElemSize, headVertCount * UVElemSize); for (uint iii = 0; iii < headVertCount; iii++) { model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x00)); //vertx model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x04)); //verty model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x08)); //vertz model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x0C)); //normx model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x10)); //normy model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x14)); //normz model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x00)); //UVu model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x04)); //UVv model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x00] / 255f); //color r model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x01] / 255f); //color g model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x02] / 255f); //color b model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x03] / 255f); //color a } byte[] indiceBuff = ReadBlock(cfs, indicePointer + prevFaceCount * sizeof(ushort), localFaceCount * sizeof(ushort)); //Console.WriteLine(localFaceCount.ToString("X8")); for (uint iii = 0; iii < localFaceCount; iii++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, iii * sizeof(ushort)) + prevVertCount); } prevFaceCount += localFaceCount; prevHeadCount = ii + 1; } prevVertCount = vertCount; prevPrevFaceCount = prevFaceCount; } } model.vertexCount = vertCount; model.faceCount = prevFaceCount; DataStore.chunks.Add(model); } #endregion //Load Level Model Placement byte[] levelObjectBlock = ReadBlock(fs, levelModelsPlacementPointer, levelObjectsCount * 0x70); DataStore.levelObjects = new List <LevelObject>(); for (uint i = 0; i < levelObjectsCount; i++) { LevelObject levObj = new LevelObject(levelObjectBlock, i); DataStore.levelObjects.Add(levObj); } //Load Scenery Model Placement byte[] sceneryObjectBlock = ReadBlock(fs, sceneryModelsPlacementPointer, sceneryObjectsCount * 0x70); DataStore.sceneryObjects = new List <LevelObject>(); for (uint i = 0; i < sceneryObjectsCount; i++) { LevelObject levObj = new LevelObject(sceneryObjectBlock, i); DataStore.sceneryObjects.Add(levObj); } /* * //Load Level Model Placement #region Level Model Placement * for (int x = 0; x < UYALevelObjectsCount; x++) * { * UYALevelObjectConfig levelObject = new UYALevelObjectConfig(); * byte[] objectBlock = ReadBlock(fs, levelModelsPlacementPointer + (uint)(0x70 * x), 0x70); * * levelObject.v1 = BAToQuaternion(objectBlock, 0x00); * levelObject.v2 = BAToQuaternion(objectBlock, 0x10); * levelObject.v3 = BAToQuaternion(objectBlock, 0x20); * levelObject.off = BAToQuaternion(objectBlock, 0x30); * levelObject.size = BAToFloat(objectBlock, 0x3C); * levelObject.off_40 = BAToUInt32(objectBlock, 0x40); * levelObject.off_44 = BAToUInt32(objectBlock, 0x44); * levelObject.off_48 = BAToUInt32(objectBlock, 0x48); * levelObject.off_4C = BAToUInt32(objectBlock, 0x4C); * levelObject.ID = (ushort)BAToShort(objectBlock, 0x52); * levelObject.off_54 = BAToUInt32(objectBlock, 0x54); * levelObject.off_58 = BAToUInt32(objectBlock, 0x58); * levelObject.off_5C = BAToUInt32(objectBlock, 0x5C); * levelObject.ptr_60 = BAToUInt32(objectBlock, 0x60); * levelObject.off_64 = BAToUInt32(objectBlock, 0x64); * levelObject.off_68 = BAToUInt32(objectBlock, 0x68); * levelObject.off_6C = BAToUInt32(objectBlock, 0x6C); * if (x + 1 < UYALevelObjectsCount) * levelObject.unknown_data_block = ReadBlock(fs, levelObject.ptr_60, (BAToUInt32(ReadBlock(fs, levelModelsPlacementPointer + (uint)(0x70 * (x + 1)) + 0x60, 4), 0x00) - levelObject.ptr_60)); * else * levelObject.unknown_data_block = ReadBlock(fs, levelObject.ptr_60, FindNextLargest(engineHeader, 0x24) - levelObject.ptr_60); * UYALevelObjects.Add(levelObject); * } #endregion * * //Load Scenery Models Placement #region Scenery Model Placement * for (int x = 0; x < UYASceneryObjectsCount; x++) * { * UYASceneryObjectConfig sceneryObject = new UYASceneryObjectConfig(); * byte[] objectBlock = ReadBlock(fs, sceneryModelsPlacementPointer + (uint)(0x70 * x), 0x70); * * sceneryObject.v1 = BAToQuaternion(objectBlock, 0x00); * sceneryObject.v2 = BAToQuaternion(objectBlock, 0x10); * sceneryObject.v3 = BAToQuaternion(objectBlock, 0x20); * sceneryObject.off = BAToQuaternion(objectBlock, 0x30); * sceneryObject.size = BAToFloat(objectBlock, 0x3C); * sceneryObject.off_40 = BAToUInt32(objectBlock, 0x40); * sceneryObject.off_44 = BAToUInt32(objectBlock, 0x44); * sceneryObject.off_48 = BAToUInt32(objectBlock, 0x48); * sceneryObject.off_4C = BAToUInt32(objectBlock, 0x4C); * sceneryObject.ID = (ushort)BAToShort(objectBlock, 0x52); * sceneryObject.off_54 = BAToUInt32(objectBlock, 0x54); * sceneryObject.off_54 = BAToUInt32(objectBlock, 0x58); * sceneryObject.off_54 = BAToUInt32(objectBlock, 0x5C); * sceneryObject.off_60 = BAToUInt32(objectBlock, 0x60); * sceneryObject.off_64 = BAToUInt32(objectBlock, 0x64); * sceneryObject.off_64 = BAToUInt32(objectBlock, 0x68); * sceneryObject.off_64 = BAToUInt32(objectBlock, 0x6C); * * UYASceneryObjects.Add(sceneryObject); * } #endregion */ //Load Textures #region Textures RatchetTexture_General texture = new RatchetTexture_General(); for (int x = 0; x < textureCount; x++) { texture.texHeader = ReadBlock(fs, texturesPointer + (uint)(0x24 * x), 0x24); uint nextTexturePointer = x < textureCount - 1 ? ReadUInt32(ReadBlock(fs, texturesPointer + (uint)(0x24 * (x + 1)), 0x4), 0) : vfs != null ? (uint)vfs.Length : 0; uint currentTexturePointer = ReadUInt32(texture.texHeader, 0); //Console.WriteLine("Parsing texture " + x + " " + currentTexturePointer.ToString("X") + " " + nextTexturePointer.ToString("X")); texture.ID = x; texture.width = BAToShort(texture.texHeader, 0x18); texture.height = BAToShort(texture.texHeader, 0x1A); texture.texData = vfs != null?ReadBlock(vfs, currentTexturePointer, nextTexturePointer - currentTexturePointer) : null; texture.reverseRGB = false; DataStore.textures.Add(texture); //Console.WriteLine("Texture : " + x + " Width: " + texture.width + " Height: " + texture.height); } #endregion //TODO: textureConfig - Menus //TODO: textureConfig - 2D GFX //TODO: Sprites //Load the remaining unknown or unhandled data #region Remaining Data DataStore.mapRenderDefintions = getSection(fs, 0x04); DataStore.Ptr_08 = getSection(fs, 0x08); DataStore.Ptr_0C = getSection(fs, 0x0C); DataStore.skyBox = getSection(fs, 0x14); DataStore.collisionMap = getSection(fs, 0x18); DataStore.Ptr_44 = getSection(fs, 0x44); DataStore.soundsConfig = getSection(fs, 0x54); DataStore.Ptr_4C = getSection(fs, 0x4C); DataStore.Ptr_50 = getSection(fs, 0x50); DataStore.lighting = getSection(fs, 0x68); DataStore.lightingConfig = getSection(fs, 0x6C); DataStore.textureConfigMenu = getSection(fs, 0x74); DataStore.textureConfig2DGFX = getSection(fs, 0x7C); DataStore.spriteDef = getSection(fs, 0x80); #endregion #region raw Data //need to properly handle these eventually DataStore.terrainModel.rawData = getSection(fs, 0x48); //rawLevelModelBlock = getSection(fs, 0x1C); //rawSceneryModelBlock = getSection(fs, 0x2C); #endregion #region Missions MissionParser.parseMissions(path); #endregion fs.Close(); gpf.Close(); Console.WriteLine("Engine data loaded with new engine parser for DL."); }
public static void parseMissions(string path) { List <int> missionIds = new List <int>(); //Because its unlikely there will be more than 50 missions in a map //We use a list because some missions might be missing/cut so we cant simply break the loop for (int fileIndex = 0; fileIndex < 50; fileIndex++) { if (File.Exists(path + "/gameplay_mission_classes[" + fileIndex + "].ps3")) { missionIds.Add(fileIndex); } } foreach (int missionIndex in missionIds) { RatchetMission mission = new RatchetMission(); FileStream fs = File.OpenRead(path + "/gameplay_mission_classes[" + missionIndex + "].ps3"); FileStream vfs = File.OpenRead(path + "/gameplay_mission_classes[" + missionIndex + "].vram"); Console.WriteLine("Loading mission " + missionIndex); byte[] header = ReadBlock(fs, 0, 0x0c); uint spawnablesCount = BAToUInt32(ReadBlock(fs, 0x00, 4), 0); byte[] idBlock = ReadBlock(fs, 0x10, spawnablesCount * 8); #region Spawnables mission.spawnableModels = new List <RatchetModel_General>(); for (int x = 0; x < spawnablesCount; x++) { RatchetModel_General model = new RatchetModel_General(); model.modelType = ModelType.Spawnable; model.modelID = BAToShort(idBlock, (uint)(x * 8) + 2); model.offset = BAToUInt32(idBlock, (uint)(x * 8) + 4); if (model.offset != 0) { uint modelHeadSize = BAToUInt32(ReadBlock(fs, model.offset, 4), 0); if (modelHeadSize > 0) { byte[] headBlock = ReadBlock(fs, model.offset, modelHeadSize + 0x20); //Head + objectDetails uint objectPtr = BAToUInt32(headBlock, 0); model.animationsCount = headBlock[0x0C]; //(0x04)null //(0x08)[count for 0x14 and 0x18][unknown][unknown][unknown] //(0x0c)[animation count][unknown][unknown][unknown] //(0x10)Pointer to list //(0x14)Pointer to skeleton joints (0x40 structure) //(0x18)Pointer to skeleton somethings (0x16 structure) //(0x1C)Pointer to left arm animations (Ratchet) //(0x20)null model.size = BAToFloat(headBlock, 0x24); uint texCount = BAToUInt32(headBlock, objectPtr + 0x00); uint otherCount = BAToUInt32(headBlock, objectPtr + 0x04); uint texBlockPointer = BAToUInt32(headBlock, objectPtr + 0x08); uint otherBlockPointer = BAToUInt32(headBlock, objectPtr + 0x0C); uint vertPointer = BAToUInt32(headBlock, objectPtr + 0x10); uint indexPointer = BAToUInt32(headBlock, objectPtr + 0x14); model.vertexCount = BAToUInt16(headBlock, objectPtr + 0x18); //(0x1A)count //(0x1C)count //(0x1E)null //model.rawData = getModelDataRaw(model.modelType, model.modelID, path + "/" + fileName); model.animPointer = new List <uint>(); for (uint i = 0; i < model.animationsCount; i++) { model.animPointer.Add(BAToUInt32(headBlock, (i * sizeof(uint)) + 0x48)); } uint texElemSize = 0x10; byte[] texBlock = ReadBlock(fs, model.offset + texBlockPointer, texCount * texElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.faceCount = 0; for (uint t = 0; t < texCount; t++) { RatchetTexture_Model modTex = new RatchetTexture_Model(); modTex.ID = BAToUInt32(texBlock, (t * texElemSize) + 0x0); modTex.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04); modTex.size = BAToUInt32(texBlock, (t * texElemSize) + 0x08); model.textureConfig.Add(modTex); model.faceCount += modTex.size; } //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved] uint vertElemSize = 0x28; uint vertBuffSize = model.vertexCount * vertElemSize; byte[] vertBlock = ReadBlock(fs, model.offset + vertPointer, vertBuffSize); model.vertBuff = new List <float>(); for (uint i = 0; i < model.vertexCount; i++) { model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //Vertx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //Verty model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //Vertz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //Nomrx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //Normy model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //Normz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x18)); //UVu model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x1C)); //UVv } //Flip endianness of index array byte[] indiceBuff = ReadBlock(fs, model.offset + indexPointer, model.faceCount * sizeof(ushort)); model.indiceBuff = new List <ushort>(); for (uint i = 0; i < model.faceCount; i++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort))); } } } mission.spawnableModels.Add(model); } #endregion #region Textures int textureCount = (int)BAToUInt32(ReadBlock(fs, 0x04, 4), 0); uint texturesPointer = BAToUInt32(ReadBlock(fs, 0x08, 4), 0); mission.textures = new List <RatchetTexture_General>(); RatchetTexture_General texture = new RatchetTexture_General(); for (int x = 0; x < textureCount; x++) { texture.texHeader = ReadBlock(fs, texturesPointer + (uint)(0x24 * x), 0x24); uint nextTexturePointer = x < textureCount - 1 ? ReadUInt32(ReadBlock(fs, texturesPointer + (uint)(0x24 * (x + 1)), 0x4), 0) : vfs != null ? (uint)vfs.Length : 0; uint currentTexturePointer = ReadUInt32(texture.texHeader, 0); texture.ID = x; texture.width = BAToShort(texture.texHeader, 0x18); texture.height = BAToShort(texture.texHeader, 0x1A); texture.texData = vfs != null?ReadBlock(vfs, currentTexturePointer, nextTexturePointer - currentTexturePointer) : null; texture.reverseRGB = false; mission.textures.Add(texture); } #endregion DataStore.missions.Add(mission); fs.Close(); } }
private void sceneryButton_Click(object sender, EventArgs e) { sceneryList = new List <uint>(); sceneryTexList = new List <uint>(); foreach (LevelObject levObj in DataStore.sceneryObjects) { if (!sceneryList.Contains(levObj.modelID)) { objModel = DataStore.sceneryModels.Find(x => x.modelID == levObj.modelID); if (objModel.vertBuff != null) { sceneryList.Add(levObj.modelID); } } } int levCount = sceneryList.Count(); sceneryVerts = new int[levCount]; sceneryInds = new int[levCount]; GL.GenBuffers(levCount, sceneryVerts); GL.GenBuffers(levCount, sceneryInds); for (int i = 0; i < sceneryList.Count(); i++) { objModel = DataStore.sceneryModels.Find(x => x.modelID == sceneryList[i]); if (objModel.vertBuff != null) { int vertCnt = objModel.vertBuff.Count; float[] vertArr = objModel.vertBuff.ToArray(); GL.BindBuffer(BufferTarget.ArrayBuffer, sceneryVerts[i]); GL.BufferData(BufferTarget.ArrayBuffer, vertCnt * sizeof(float), vertArr, BufferUsageHint.StaticDraw); int indCnt = objModel.indiceBuff.Count; UInt16[] indArr = objModel.indiceBuff.ToArray(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, sceneryInds[i]); GL.BufferData(BufferTarget.ElementArrayBuffer, indCnt * sizeof(UInt16), indArr, BufferUsageHint.StaticDraw); foreach (RatchetTexture_Model tex in objModel.textureConfig) { if (!sceneryTexList.Contains(tex.ID)) { sceneryTexList.Add(tex.ID); } } } } int texCount = sceneryTexList.Count; sceneryTexIDArr = new int[texCount]; GL.GenTextures(texCount, sceneryTexIDArr); for (int ii = 0; ii < texCount; ii++) { Bitmap file = getTextureImage((int)sceneryTexList[ii]); if (file != null) { GL.BindTexture(TextureTarget.Texture2D, sceneryTexIDArr[ii]); BitmapData data = file.LockBits(new System.Drawing.Rectangle(0, 0, file.Width, file.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0); file.UnlockBits(data); //The DDS files have built in mipmaps, should probably use those instead GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); } else { Console.WriteLine("Error loading texture: File was null"); } } sceneryCheck.Checked = true; sceneryReady = true; glControl1.Invalidate(); }
private void glControl1_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.ClearColor(Color.SkyBlue); glControl1.MakeCurrent(); GL.UseProgram(pgm2ID); GL.EnableVertexAttribArray(0); camX.Text = cPosition.X.ToString(); camY.Text = cPosition.Y.ToString(); camZ.Text = cPosition.Z.ToString(); Matrix4 View = Matrix4.LookAt(cPosition, cTarget, Vector3.UnitZ); Matrix4 worldView = View * projection; if (splineCheck.Checked) { GL.UniformMatrix4(MatrixID, false, ref worldView); foreach (Spline spline in DataStore.splines) { spline.getVBO(); GL.DrawArrays(PrimitiveType.LineStrip, 0, spline.vertexBuffer.Length / 3); } } GL.EnableVertexAttribArray(1); if (modReady && mobyCheck.Checked == true) { foreach (RatchetMoby mob in DataStore.mobs) { objModel = DataStore.spawnableModels.Find(x => x.modelID == mob.modelID); int insx = mobList.IndexOf((uint)objModel.modelID); if (insx != -1) { Matrix4 modTrans = Matrix4.CreateTranslation(mob.x, mob.y, mob.z); Matrix4 modScale = Matrix4.CreateScale(objModel.size * mob.size); Matrix4 xRot = Matrix4.CreateRotationX(mob.rot1); Matrix4 yRot = Matrix4.CreateRotationY(mob.rot2); Matrix4 zRot = Matrix4.CreateRotationZ(mob.rot3); Matrix4 modRot = xRot * yRot * zRot; mvp = modScale * modRot * modTrans * worldView; //Has to be done in this order to work correctly GL.UniformMatrix4(MatrixID, false, ref mvp); GL.BindBuffer(BufferTarget.ArrayBuffer, mobVerts[insx]); GL.BindBuffer(BufferTarget.ElementArrayBuffer, mobInds[insx]); //Verts GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, 0); //UV's GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 6); //Bind textures one by one, applying it to the relevant vertices based on the index array foreach (RatchetTexture_Model tex in objModel.textureConfig) { int indx = modTexList.IndexOf(tex.ID); GL.BindTexture(TextureTarget.Texture2D, mobTexIDArr[indx]); if (DataStore.selectedMoby == mob) { GL.Uniform4(pgmID_rcID, new Vector4(1, 1, 1, 1)); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); GL.DrawElements(PrimitiveType.Triangles, (int)tex.size, DrawElementsType.UnsignedShort, (int)tex.start * sizeof(ushort)); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } GL.Uniform4(pgmID_rcID, new Vector4(mob.r / 255f, mob.g / 255f, mob.b / 255f, 0.5f)); GL.DrawElements(PrimitiveType.Triangles, (int)tex.size, DrawElementsType.UnsignedShort, (int)tex.start * sizeof(ushort)); } } } } if (levelReady && levelCheck.Checked == true) { foreach (LevelObject levObj in DataStore.levelObjects) { objModel = DataStore.levelModels.Find(x => x.modelID == levObj.modelID); int insx = levelList.IndexOf((uint)objModel.modelID); if (insx != -1) { mvp = levObj.mat * worldView; //Has to be done in this order to work correctly GL.UniformMatrix4(MatrixID, false, ref mvp); GL.BindBuffer(BufferTarget.ArrayBuffer, levelVerts[insx]); GL.BindBuffer(BufferTarget.ElementArrayBuffer, levelInds[insx]); //Verts GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, 0); //UV's GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 6); //Bind textures one by one, applying it to the relevant vertices based on the index array foreach (RatchetTexture_Model tex in objModel.textureConfig) { int indx = levelTexList.IndexOf(tex.ID); GL.BindTexture(TextureTarget.Texture2D, levelbTexIDArr[indx]); if (DataStore.selectedLevelObject == levObj) { GL.Uniform4(pgmID_rcID, new Vector4(1, 1, 1, 1)); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); GL.DrawElements(PrimitiveType.Triangles, (int)tex.size, DrawElementsType.UnsignedShort, (int)tex.start * sizeof(ushort)); GL.Uniform4(pgmID_rcID, new Vector4(0, 0, 0, 0)); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } GL.DrawElements(PrimitiveType.Triangles, (int)tex.size, DrawElementsType.UnsignedShort, (int)tex.start * sizeof(ushort)); } } } } if (sceneryReady && sceneryCheck.Checked == true) { foreach (LevelObject sceneryObj in DataStore.sceneryObjects) { objModel = DataStore.sceneryModels.Find(x => x.modelID == sceneryObj.modelID); int insx = sceneryList.IndexOf((uint)objModel.modelID); if (insx != -1) { mvp = sceneryObj.mat * worldView; //Has to be done in this order to work correctly GL.UniformMatrix4(MatrixID, false, ref mvp); GL.BindBuffer(BufferTarget.ArrayBuffer, sceneryVerts[insx]); GL.BindBuffer(BufferTarget.ElementArrayBuffer, sceneryInds[insx]); //Verts GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, 0); //UV's GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 6); //Bind textures one by one, applying it to the relevant vertices based on the index array foreach (RatchetTexture_Model tex in objModel.textureConfig) { int indx = sceneryTexList.IndexOf(tex.ID); GL.BindTexture(TextureTarget.Texture2D, sceneryTexIDArr[indx]); GL.DrawElements(PrimitiveType.Triangles, (int)tex.size, DrawElementsType.UnsignedShort, (int)tex.start * sizeof(ushort)); } } } } if (collReady && collCheck.Checked) { GL.UseProgram(colorOnlyShaderID); mvp = worldView; GL.UniformMatrix4(MatrixID, false, ref mvp); GL.BindBuffer(BufferTarget.ArrayBuffer, collVBO); GL.BindBuffer(BufferTarget.ElementArrayBuffer, collInd); //Verts GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 6, 0); //Colors GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, sizeof(float) * 6, sizeof(float) * 3); GL.UseProgram(pgmID); GL.UniformMatrix4(MatrixID, false, ref mvp); GL.Uniform4(pgmID_rcID, new Vector4(1, 1, 1, 1)); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); GL.DrawElements(PrimitiveType.Triangles, DataStore.collIndBuff.Count, DrawElementsType.UnsignedInt, 0); GL.UseProgram(colorOnlyShaderID); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); GL.DrawElements(PrimitiveType.Triangles, DataStore.collIndBuff.Count, DrawElementsType.UnsignedInt, 0); } if (ready && terrainCheck.Checked) { GL.UseProgram(pgmID); mvp = worldView; GL.UniformMatrix4(MatrixID, false, ref mvp); GL.EnableVertexAttribArray(2); GL.BindBuffer(BufferTarget.ArrayBuffer, VBO); GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBufferID); //Verts GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 12, 0); //UV's GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 6); //Colors GL.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 8); //Bind textures one by one, applying it to the relevant vertices based on the index array foreach (RatchetTexture_Model tex in selectedModel.textureConfig) { int indx = texList.IndexOf(tex.ID); GL.BindTexture(TextureTarget.Texture2D, texIDarr[indx]); if (false) { GL.Uniform4(pgmID_rcID, new Vector4(1, 1, 1, 1)); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); GL.DrawElements(PrimitiveType.Triangles, (int)tex.size, DrawElementsType.UnsignedInt, (int)tex.start * sizeof(uint)); } GL.Uniform4(pgmID_rcID, new Vector4(0, 0, 0, 0)); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); GL.DrawElements(PrimitiveType.Triangles, (int)tex.size, DrawElementsType.UnsignedInt, (int)tex.start * sizeof(uint)); } GL.DisableVertexAttribArray(2); } if (chunksReady && chunkCheck.Checked) { for (int i = 0; i < DataStore.chunks.Count; i++) { RatchetModel_Terrain chunk = DataStore.chunks[i]; GL.UseProgram(pgmID); mvp = worldView; GL.UniformMatrix4(MatrixID, false, ref mvp); GL.EnableVertexAttribArray(2); GL.BindBuffer(BufferTarget.ArrayBuffer, chunkVerts[i]); GL.BindBuffer(BufferTarget.ElementArrayBuffer, chunkInds[i]); //Verts GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 12, 0); //UV's GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 6); //Colors GL.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 8); //Bind textures one by one, applying it to the relevant vertices based on the index array foreach (RatchetTexture_Model tex in chunk.textureConfig) { int indx = chunkTexList.IndexOf(tex.ID); GL.BindTexture(TextureTarget.Texture2D, chunkTexIDArr[indx]); GL.Uniform4(pgmID_rcID, new Vector4(0, 0, 0, 0)); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); GL.DrawElements(PrimitiveType.Triangles, (int)tex.size, DrawElementsType.UnsignedInt, (int)tex.start * sizeof(uint)); } GL.DisableVertexAttribArray(2); } } GL.DisableVertexAttribArray(1); GL.DisableVertexAttribArray(0); glControl1.SwapBuffers(); }
public static void parseMoby(string path, string fileName) { FileStream fs = File.OpenRead(path + "/" + fileName); Console.WriteLine("Loading file " + path + "/" + fileName); #region Moby Textures uint texturePointer = BAToUInt32(ReadBlock(fs, 0x08, 4), 0); uint textureDataPointer = BAToUInt32(ReadBlock(fs, 0x0C, 4), 0); uint textureCount = BAToUInt32(ReadBlock(fs, 0x04, 4), 0); MemoryStream vfs = new MemoryStream(ReadBlock(fs, textureDataPointer, (uint)fs.Length - textureDataPointer)); Console.WriteLine("Texture Count: " + textureCount); for (int x = 0; x < textureCount; x++) { RatchetTexture_General texture = new RatchetTexture_General(); texture.texHeader = ReadBlock(fs, texturePointer + (uint)(0x24 * x), 0x24); uint nextTexturePointer = x < textureCount - 1 ? ReadUInt32(ReadBlock(fs, texturePointer + (uint)(0x24 * (x + 1)), 0x4), 0) : vfs != null ? (uint)vfs.Length : 0; uint currentTexturePointer = ReadUInt32(texture.texHeader, 0); //Console.WriteLine("Parsing texture " + x + " " + currentTexturePointer.ToString("X") + " " + nextTexturePointer.ToString("X")); texture.ID = x; texture.width = BAToShort(texture.texHeader, 0x18); texture.height = BAToShort(texture.texHeader, 0x1A); texture.texData = vfs != null?ReadBlock(vfs, currentTexturePointer, nextTexturePointer - currentTexturePointer) : null; texture.reverseRGB = false; DataStore.textures.Add(texture); } #endregion #region Moby Model uint mobyCount = BAToUInt32(ReadBlock(fs, 0x00, 4), 0); byte[] pointerBlock = ReadBlock(fs, 0x10, (mobyCount * 0x0C)); //Used for mapping textures to models int modelIndex = 0; for (int x = 0; x < mobyCount; x++) { RatchetModel_General model = new RatchetModel_General(); model.modelID = (short)BAToUInt32(pointerBlock, (uint)(x * 0x0C) + 0x04); Console.WriteLine("Model ID: " + model.modelID.ToString("X")); model.offset = BAToUInt32(pointerBlock, (uint)(x * 0x0C)); // Console.WriteLine("Model: " + model.modelID.ToString("X4") + " Offset: " + model.offset.ToString("X")); if (model.offset != 0) { uint modelHeadSize = BAToUInt32(ReadBlock(fs, model.offset, 4), 0); if (modelHeadSize > 0) { byte[] headBlock = ReadBlock(fs, model.offset, modelHeadSize + 0x20); //Head + objectDetails uint objectPtr = BAToUInt32(headBlock, 0); model.animationsCount = headBlock[0x0C]; model.size = BAToFloat(headBlock, 0x24); uint texCount = BAToUInt32(headBlock, objectPtr + 0x00); uint otherCount = BAToUInt32(headBlock, objectPtr + 0x04); uint texBlockPointer = BAToUInt32(headBlock, objectPtr + 0x08); uint otherBlockPointer = BAToUInt32(headBlock, objectPtr + 0x0C); uint vertPointer = BAToUInt32(headBlock, objectPtr + 0x10); uint indexPointer = BAToUInt32(headBlock, objectPtr + 0x14); model.vertexCount = BAToUInt16(headBlock, objectPtr + 0x18); //(0x1A)count //(0x1C)count //(0x1E)null model.modelType = ModelType.Spawnable; //model.rawData = getModelDataRaw(model.modelType, model.modelID, path + "/" + fileName); model.animPointer = new List <uint>(); for (uint i = 0; i < model.animationsCount; i++) { model.animPointer.Add(BAToUInt32(headBlock, (i * sizeof(uint)) + 0x48)); } uint texElemSize = 0x10; byte[] texBlock = ReadBlock(fs, model.offset + texBlockPointer, texCount * texElemSize); model.textureConfig = new List <RatchetTexture_Model>(); model.faceCount = 0; for (uint t = 0; t < texCount; t++) { RatchetTexture_Model modTex = new RatchetTexture_Model(); modTex.ID = (uint)BAToUInt32(texBlock, (t * texElemSize) + 0x0); modTex.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04); modTex.size = BAToUInt32(texBlock, (t * texElemSize) + 0x08); model.textureConfig.Add(modTex); model.faceCount += modTex.size; } //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved] uint vertElemSize = 0x28; uint vertBuffSize = model.vertexCount * vertElemSize; byte[] vertBlock = ReadBlock(fs, model.offset + vertPointer, vertBuffSize); model.vertBuff = new List <float>(); for (uint i = 0; i < model.vertexCount; i++) { model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //Vertx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //Verty model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //Vertz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //Nomrx model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //Normy model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //Normz model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x18)); //UVu model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x1C)); //UVv } if (model.vertBuff != null) { modelIndex++; } //Flip endianness of index array byte[] indiceBuff = ReadBlock(fs, model.offset + indexPointer, model.faceCount * sizeof(ushort)); model.indiceBuff = new List <ushort>(); for (uint i = 0; i < model.faceCount; i++) { model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort))); } } } DataStore.spawnableModels.Add(model); } #endregion }
//Passing it by reference to avoid making a copy public static void SpawnableToObj(ref RatchetModel_General model, string OBJfilename, string MTLfilename) { StreamWriter OBJfs = new StreamWriter(OBJfilename); StreamWriter MTLfs = new StreamWriter(MTLfilename); OBJfs.WriteLine("o Object_" + model.modelID.ToString("X4")); if (model.textureConfig != null) { OBJfs.WriteLine("mtllib " + MTLfilename.Split('\\').Last()); } List <uint> usedMtls = new List <uint>(); //To prevent it from making double mtl entries for (int i = 0; i < model.textureConfig.Count; i++) { uint modelTextureID = model.textureConfig[i].ID; if (!usedMtls.Contains(modelTextureID)) { MTLfs.WriteLine("newmtl mtl_" + modelTextureID); MTLfs.WriteLine("Ns 1000"); MTLfs.WriteLine("Ka 1.000000 1.000000 1.000000"); MTLfs.WriteLine("Kd 1.000000 1.000000 1.000000"); MTLfs.WriteLine("Ni 1.000000"); MTLfs.WriteLine("d 0.000000"); MTLfs.WriteLine("illum 1"); MTLfs.WriteLine("map_Kd tex_" + model.textureConfig[i].ID + ".png"); usedMtls.Add(modelTextureID); } } MTLfs.Close(); //Vertices, normals, UV's float[] vertData = model.vertBuff.ToArray(); for (int x = 0; x < model.vertexCount; x++) { float px = vertData[(x * 0x08) + 0x0]; float py = vertData[(x * 0x08) + 0x1]; float pz = vertData[(x * 0x08) + 0x2]; float nx = vertData[(x * 0x08) + 0x3]; float ny = vertData[(x * 0x08) + 0x4]; float nz = vertData[(x * 0x08) + 0x5]; float tu = vertData[(x * 0x08) + 0x6]; float tv = 1f - vertData[(x * 0x08) + 0x7]; OBJfs.WriteLine("v " + px.ToString("G") + " " + py.ToString("G") + " " + pz.ToString("G")); OBJfs.WriteLine("vn " + nx.ToString("G") + " " + ny.ToString("G") + " " + nz.ToString("G")); OBJfs.WriteLine("vt " + tu.ToString("G") + " " + tv.ToString("G")); } //Faces int tCnt = 0; ushort[] inds = model.indiceBuff.ToArray(); for (int i = 0; i < model.indiceBuff.Count / 3; i++) { if (model.textureConfig != null && tCnt < model.textureConfig.Count) { if (i * 3 >= model.textureConfig[tCnt].start) { OBJfs.WriteLine("usemtl mtl_" + model.textureConfig[tCnt].ID.ToString("")); OBJfs.WriteLine("g Texture_" + model.textureConfig[tCnt].ID.ToString("")); tCnt++; } } int f1 = inds[i * 3 + 0] + 1; int f2 = inds[i * 3 + 1] + 1; int f3 = inds[i * 3 + 2] + 1; OBJfs.WriteLine("f " + (f1 + "/" + f1 + "/" + f1) + " " + (f2 + "/" + f2 + "/" + f2) + " " + (f3 + "/" + f3 + "/" + f3)); //OBJfs.WriteLine("f " + (f3 + "/" + f3 + "/" + f3) + " " + (f2 + "/" + f2 + "/" + f2) + " " + (f1 + "/" + f1 + "/" + f1)); } OBJfs.Close(); }