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 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."); }
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(); }
private void TerrainViewer_Load(object sender, EventArgs e) { projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, glControl1.Width / (float)glControl1.Height, 0.1f, 800.0f); GL.ClearColor(Color.SkyBlue); pgmID = GL.CreateProgram(); loadShader("shaders/vs_colored.glsl", ShaderType.VertexShader, pgmID, out vsID); loadShader("shaders/fs_colored.glsl", ShaderType.FragmentShader, pgmID, out fsID); GL.LinkProgram(pgmID); //Console.WriteLine(GL.GetProgramInfoLog(pgmID)); pgm2ID = GL.CreateProgram(); loadShader("shaders/vs.glsl", ShaderType.VertexShader, pgm2ID, out vsID); loadShader("shaders/fs.glsl", ShaderType.FragmentShader, pgm2ID, out fsID); GL.LinkProgram(pgm2ID); //Console.WriteLine(GL.GetProgramInfoLog(pgm2ID)); colorOnlyShaderID = GL.CreateProgram(); loadShader("shaders/vs_color_only.glsl", ShaderType.VertexShader, colorOnlyShaderID, out vsID); loadShader("shaders/fs_color_only.glsl", ShaderType.FragmentShader, colorOnlyShaderID, out fsID); GL.LinkProgram(colorOnlyShaderID); //Console.WriteLine(GL.GetProgramInfoLog(colorOnlyShaderID)); GL.GenVertexArrays(1, out vertexArrayID); GL.BindVertexArray(vertexArrayID); MatrixID = GL.GetUniformLocation(pgmID, "MVP"); pgmID_rcID = GL.GetUniformLocation(pgmID, "replacementColor"); GL.Enable(EnableCap.DepthTest); GL.LineWidth(1.0f); GL.GenBuffers(1, out VBO); GL.GenBuffers(1, out indexBufferID); selectedModel = DataStore.terrainModel; if (selectedModel.vertBuff != null) //Check that there's actually vertex data to be rendered { int vertCnt = selectedModel.vertBuff.Count; float[] vertArr = selectedModel.vertBuff.ToArray(); GL.BindBuffer(BufferTarget.ArrayBuffer, VBO); GL.BufferData(BufferTarget.ArrayBuffer, vertCnt * sizeof(float), vertArr, BufferUsageHint.StaticDraw); indCnt = selectedModel.indiceBuff.Count; uint[] indArr = selectedModel.indiceBuff.ToArray(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBufferID); GL.BufferData(BufferTarget.ElementArrayBuffer, indCnt * sizeof(uint), indArr, BufferUsageHint.StaticDraw); //Delete old textures, so we don't fill up the GPU memory if (texIDarr != null) { GL.DeleteTextures(texIDarr.Count(), texIDarr); } texList = new List <uint>(); foreach (RatchetTexture_Model tex in selectedModel.textureConfig) { if (!texList.Contains(tex.ID)) { texList.Add(tex.ID); } } int texCount = texList.Count; texIDarr = new int[texCount]; GL.GenTextures(texCount, texIDarr); for (int i = 0; i < texCount; i++) { Bitmap file = getTextureImage((int)texList[i]); if (file != null) { GL.BindTexture(TextureTarget.Texture2D, texIDarr[i]); BitmapData data = file.LockBits(new 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"); } } ready = true; glControl1.Invalidate(); } }
private void button3_Click(object sender, EventArgs e) { int chunkCount = DataStore.chunks.Count(); chunkVerts = new int[chunkCount]; chunkInds = new int[chunkCount]; GL.GenBuffers(chunkCount, chunkVerts); GL.GenBuffers(chunkCount, chunkInds); chunkTexList = new List <uint>(); Console.WriteLine("Checking chunk"); for (int i = 0; i < chunkCount; i++) { RatchetModel_Terrain chunk = DataStore.chunks[i]; if (chunk.vertBuff != null) //Check that there's actually vertex data to be rendered { int vertCnt = chunk.vertBuff.Count; float[] vertArr = chunk.vertBuff.ToArray(); GL.BindBuffer(BufferTarget.ArrayBuffer, chunkVerts[i]); GL.BufferData(BufferTarget.ArrayBuffer, vertCnt * sizeof(float), vertArr, BufferUsageHint.StaticDraw); indCnt = chunk.indiceBuff.Count; uint[] indArr = chunk.indiceBuff.ToArray(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, chunkInds[i]); GL.BufferData(BufferTarget.ElementArrayBuffer, indCnt * sizeof(uint), indArr, BufferUsageHint.StaticDraw); //Delete old textures, so we don't fill up the GPU memory if (chunkTexIDArr != null) { GL.DeleteTextures(chunkTexIDArr.Count(), chunkTexIDArr); } foreach (RatchetTexture_Model tex in chunk.textureConfig) { if (!chunkTexList.Contains(tex.ID)) { chunkTexList.Add(tex.ID); } } } } //Console.WriteLine(chunkTexList.Count.ToString("X8")); int texCount = chunkTexList.Count; chunkTexIDArr = new int[texCount]; GL.GenTextures(texCount, chunkTexIDArr); for (int t = 0; t < texCount; t++) { Bitmap file = getTextureImage((int)chunkTexList[t]); if (file != null) { GL.BindTexture(TextureTarget.Texture2D, chunkTexIDArr[t]); BitmapData data = file.LockBits(new 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"); } } chunksReady = true; chunkCheck.Checked = true; glControl1.Invalidate(); }
public static void terrainMeshToObj(ref RatchetModel_Terrain 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(); int vertElemSize = 0x0C; //Vertices, normals, UV's float[] vertData = model.vertBuff.ToArray(); for (int x = 0; x < model.vertexCount; x++) { float px = vertData[x * vertElemSize + 0x0]; float py = vertData[x * vertElemSize + 0x1]; float pz = vertData[x * vertElemSize + 0x2]; float nx = vertData[x * vertElemSize + 0x3]; float ny = vertData[x * vertElemSize + 0x4]; float nz = vertData[x * vertElemSize + 0x5]; float tu = vertData[x * vertElemSize + 0x6]; float tv = 1f - vertData[x * vertElemSize + 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; uint[] 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++; } } uint f1 = inds[i * 3 + 0] + 1; uint f2 = inds[i * 3 + 1] + 1; uint 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(); }