From be31c972c43d1de9680421028e45cad60239545d Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Thu, 18 Aug 2022 21:47:54 +0200 Subject: [PATCH] Deconstruct mega-parser in sub parts --- RSPModelLib/include/RSPModel_datatypes.h | 10 +- RSPModelLib/src/RSPModel.c | 2 + RSPModelLib/src/hob_parser.c | 376 +++++++++++++++++++++-- RSPModelLib/src/hob_parser.h | 2 + 4 files changed, 356 insertions(+), 34 deletions(-) diff --git a/RSPModelLib/include/RSPModel_datatypes.h b/RSPModelLib/include/RSPModel_datatypes.h index 53a4f15..2355fdf 100644 --- a/RSPModelLib/include/RSPModel_datatypes.h +++ b/RSPModelLib/include/RSPModel_datatypes.h @@ -55,9 +55,9 @@ typedef struct hob_face { unsigned short indices[4]; T_RGBA vertex_colors[4]; //TODO: convert in R:8_G:8_B:8_A:8 format? Caution with BE/LE conversion T_TEXCOORD tex_coords[4]; -} T_HOB_FACE; +} T_RSPMODEL_FACE; -typedef struct hob_face_group { +typedef struct rspmodel_obj_parts { unsigned int meshdef1_offset; unsigned int face_block_end_offset; @@ -68,11 +68,11 @@ typedef struct hob_face_group { T_VECTOR3 transform; unsigned int face_count; - T_HOB_FACE* faces; + T_RSPMODEL_FACE* faces; unsigned int vertex_count; T_VERTEX* vertices; -} T_HOB_FACE_GROUP; +} T_RSPMODEL_OBJ_PARTS; typedef struct rspmodel_object { char name[16]; @@ -83,7 +83,7 @@ typedef struct rspmodel_object { unsigned int object_part_count; unsigned int face_group_count; - T_HOB_FACE_GROUP* object_parts; + T_RSPMODEL_OBJ_PARTS* object_parts; } T_RSPMODEL_OBJECT; /** diff --git a/RSPModelLib/src/RSPModel.c b/RSPModelLib/src/RSPModel.c index b58ed14..407f1da 100644 --- a/RSPModelLib/src/RSPModel.c +++ b/RSPModelLib/src/RSPModel.c @@ -26,6 +26,8 @@ unsigned short RSPModel_processHOBFile( T_RSPMODEL_HOB* hob, const char* const f T_PROG_OPTIONS canard; canard.god_mode = 1; + canard.debug_mode = 1; + canard.verbose_mode = 1; RSP_ModelLib_ParseHOBFile(filePath, hob, &canard); return RSPLIB_SUCCESS; diff --git a/RSPModelLib/src/hob_parser.c b/RSPModelLib/src/hob_parser.c index c8f934e..2d091a3 100644 --- a/RSPModelLib/src/hob_parser.c +++ b/RSPModelLib/src/hob_parser.c @@ -17,14 +17,17 @@ #include "hob_parser.h" +static unsigned int ExtractObjects(T_RSPMODEL_HOB*, const MEMFILE, const unsigned char); +static unsigned int ExtractObjParts(T_RSPMODEL_OBJECT*, const MEMFILE, const unsigned char); +static unsigned int ExtractObjParts_faces(T_RSPMODEL_OBJ_PARTS*, const MEMFILE, const unsigned char); +static inline unsigned int ExtractObjpart_Face_Colors(T_RSPMODEL_FACE*, const char*); +static inline unsigned int ExtractObjpart_Face_UVMaps(T_RSPMODEL_FACE*, const char*); + unsigned char RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* hob_struct, T_PROG_OPTIONS* p_opts) { unsigned char err = NO_ERROR; long fileSize; FILE* fStream = NULL; - char* memFile = NULL; - unsigned int i,j,k; - unsigned int facesExtraOffset; - int* offset_index = NULL; + MEMFILE memFile = NULL; if (hob_struct != NULL && fileName != NULL) { // Open file @@ -43,6 +46,11 @@ unsigned char RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* ho fread(memFile, fileSize, 1, fStream); fclose(fStream); + // Do the magic! + ExtractObjects(hob_struct, memFile, p_opts->verbose_mode + p_opts->debug_mode + p_opts->god_mode); + + + /* // Retrieve object count from the header hob_struct->obj_count = ((T_HOBFILE_HEADER *)memFile)->obj_count; printf("[INFO] - Object(s) quantity: %d\n", hob_struct->obj_count); @@ -88,7 +96,8 @@ unsigned char RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* ho hob_struct->objects[i].face_group_count = ((T_HOBFILE_FACEGROUP_HEADER *)(memFile + hob_struct->objects[i].object_part_header_offset))->facegroup_count; if (p_opts->verbose_mode) printf("[DBG] > Face groups count: %d\n", hob_struct->objects[i].face_group_count); - if (hob_struct->objects[i].object_part_count != hob_struct->objects[i].face_group_count && (p_opts->verbose_mode)) printf("[DBG] > Object parts / facegroup count are different!\n"); + if (hob_struct->objects[i].object_part_count != hob_struct->objects[i].face_group_count && (p_opts->verbose_mode)) + printf("[DBG] > Object parts / facegroup count are different!\n"); // Get facegroup datas offset_index = calloc(hob_struct->objects[i].object_part_count, sizeof(int)); @@ -354,30 +363,7 @@ unsigned char RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* ho } // Get vertex datas - hob_struct->objects[i].object_parts[j].vertices = calloc(hob_struct->objects[i].object_parts[j].vertex_count, sizeof(T_VERTEX)); - for ( k = 0; k < hob_struct->objects[i].object_parts[j].vertex_count; k++ ) { - hob_struct->objects[i].object_parts[j].vertices[k].x = ((T_HOBFILE_VERTEX *)(memFile - + hob_struct->objects[i].object_parts[j].vertex_block_offset - + sizeof(T_VERTEX) * k))->x; - - hob_struct->objects[i].object_parts[j].vertices[k].y = ((T_HOBFILE_VERTEX *)(memFile - + hob_struct->objects[i].object_parts[j].vertex_block_offset - + sizeof(T_VERTEX) * k))->y; - - hob_struct->objects[i].object_parts[j].vertices[k].z = ((T_HOBFILE_VERTEX *)(memFile - + hob_struct->objects[i].object_parts[j].vertex_block_offset - + sizeof(T_VERTEX) * k))->z; - - hob_struct->objects[i].object_parts[j].vertices[k].w = ((T_HOBFILE_VERTEX *)(memFile - + hob_struct->objects[i].object_parts[j].vertex_block_offset - + sizeof(T_VERTEX) * k))->w; // Always 0??? - - if (p_opts->debug_mode) printf("[DBG] > Found vertex %d: (%d, %d, %d)\n", k, - hob_struct->objects[i].object_parts[j].vertices[k].x, - hob_struct->objects[i].object_parts[j].vertices[k].y, - hob_struct->objects[i].object_parts[j].vertices[k].z - ); - } + ExtractObjpartVertices(&hob_struct->objects[i].object_parts[j], memFile, p_opts->debug_mode); } // Get object part ID, used by animation? bones? @@ -406,6 +392,7 @@ unsigned char RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* ho err = RSPLIB_ERROR_GENERIC; printf("[INFO] Can't process empty file!\n"); } + */ free(memFile); @@ -422,3 +409,334 @@ unsigned char RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* ho return err; } + +/** + * Count objects and extract datas from them. + * + * @param[in|out] pHobStruct Take root hob structure to get the T_RSPMODEL_OBJECT buffer and header datas. + * @param[in] pMemfile + * @param[in] verbose + * + * @return Error code, RSPLIB_SUCCESS when no error. + */ +static unsigned int ExtractObjects(T_RSPMODEL_HOB* pHobStruct, const MEMFILE pMemfile, const unsigned char verbose) { + unsigned int i; + + if (pHobStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL; + + // Retrieve object count from the header + pHobStruct->obj_count = ((T_HOBFILE_HEADER *)pMemfile)->obj_count; + printf("[INFO] - Object(s) quantity: %d\n", pHobStruct->obj_count); + if (pHobStruct->obj_count <= 0) { + printf("[INFO] Can't process empty file!\n"); + return RSPLIB_ERROR_GENERIC; + } + + // Populate HOB structure with object descriptor + pHobStruct->objects = calloc(pHobStruct->obj_count, sizeof(T_RSPMODEL_OBJECT)); + if (pHobStruct->objects == NULL) return RSPLIB_ERROR_MEMORY; + + for ( i = 0; i < pHobStruct->obj_count; i++ ) { + if (verbose == 2) printf("\n-=====================-Begin of Object part-======================-\n"); + + // Get object name + memcpy(pHobStruct->objects[i].name, ((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_name, 16); + + if (verbose == 1) printf("\n"); + printf("[INFO] - Process %s object...\n", pHobStruct->objects[i].name); + + + // Get offsets + pHobStruct->objects[i].face_group_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_offset; + if (verbose == 1) printf("[DBG] > Face group offset: 0x%X\n", pHobStruct->objects[i].face_group_offset); + pHobStruct->objects[i].object_part_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_parts_offset; + if (verbose == 1) printf("[DBG] > Face group header/object parts offset: 0x%X\n", pHobStruct->objects[i].object_part_header_offset); + pHobStruct->objects[i].face_group_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_header_2_offset; + if (verbose == 1) printf("[DBG] > Face group header2 offset: 0x%X\n", pHobStruct->objects[i].face_group_header_offset); + + if (verbose == 3) { + printf("[DBG] > Face group unknown1: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset1); + printf("[DBG] > Face group unknown2: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset2); + printf("[DBG] > Face group unknown3: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset3); + printf("[DBG] > Face group unknown4: %.8f\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknown4); + } + + // Get count and offsets from the facegroup header + pHobStruct->objects[i].object_part_count = ((T_HOBFILE_FACEGROUP_HEADER *)(pMemfile + + pHobStruct->objects[i].object_part_header_offset))->object_part_count; + if (verbose == 1) printf("[DBG] > Object parts count: %d\n", pHobStruct->objects[i].object_part_count); + pHobStruct->objects[i].face_group_count = ((T_HOBFILE_FACEGROUP_HEADER *)(pMemfile + + pHobStruct->objects[i].object_part_header_offset))->facegroup_count; + if (verbose == 1) printf("[DBG] > Face groups count: %d\n", pHobStruct->objects[i].face_group_count); + if (pHobStruct->objects[i].object_part_count != pHobStruct->objects[i].face_group_count && (verbose == 1)) + printf("[DBG] > Object parts / facegroup count are different!\n"); + + // Get facegroup datas + ExtractObjParts(&pHobStruct->objects[i], pMemfile, verbose); + } + + return RSPLIB_SUCCESS; +} + +/** + * Count object's sub-part and extract datas from them. + * + * @param[in|out] pObject Take object structure to get the T_RSPMODEL_OBJ_PARTS buffer and object datas. + * @param[in] pMemfile + * @param[in] verbose + * + * @return Error code, RSPLIB_SUCCESS when no error. + */ +static unsigned int ExtractObjParts(T_RSPMODEL_OBJECT* pObject, const MEMFILE pMemfile, const unsigned char verbose) { + unsigned int i, subpart_offset = 0; + + if (pObject == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL; + + pObject->object_parts = calloc(pObject->object_part_count, sizeof(T_RSPMODEL_OBJ_PARTS)); + if (pObject->object_parts == NULL) return RSPLIB_ERROR_MEMORY; + + for ( i = 0; i < pObject->object_part_count; i++ ) { + if (verbose == 2) printf("\n-----------------------Begin of Mesh part-------------------------\n"); + subpart_offset = ((T_HOBFILE_FACEGROUP_OFFSET *)(pMemfile + pObject->object_part_header_offset + + sizeof(T_HOBFILE_FACEGROUP_HEADER) + sizeof(T_HOBFILE_FACEGROUP_OFFSET) * i))->facegroup_offset; + if (verbose == 1) printf("\n[DBG] > Face group meshdef0 offset: 0x%X\n", subpart_offset); + + // Get meshdef0 datas + if (verbose == 3) printf("[DBG] > meshdef0 offset1: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->offset1); + if (verbose == 3) printf("[DBG] > meshdef0 offset2: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->offset2); + if (verbose == 1) printf("[DBG] > Prev meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->prev_meshdef0_offset); + if (verbose == 1) printf("[DBG] > Next meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->next_meshdef0_offset); + + if (verbose == 3) printf("[DBG] > meshdef0 unknown3: %.8f\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->unknown3); + if (verbose == 3) printf("[DBG] > meshdef0 unknown4: %.8f\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->unknown4); + if (verbose == 3) printf("[DBG] > meshdef0 unknown5: %.8f\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->unknown5); + + // Get meshdef1 (mesh descriptor) offset + pObject->object_parts[i].meshdef1_offset = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->meshdef1_offset_plus_4; + if (verbose == 1) printf("\n[DBG] > Face group meshdef1 offset: 0x%X\n", pObject->object_parts[i].meshdef1_offset); + + if( ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->reserved1 != 0 || + ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->reserved2 != 0 ) { + if (verbose == 3) printf("[DBG] > Face group meshdef0: no 0!\n"); + } + + if (pObject->object_parts[i].meshdef1_offset > 0) { + // Read meshdef1 datas + pObject->object_parts[i].face_block_end_offset = ((T_HOBFILE_MESHDEF1 *)(pMemfile + + pObject->object_parts[i].meshdef1_offset - 4))->facedef_end_offset; + pObject->object_parts[i].vertex_count = ((T_HOBFILE_MESHDEF1 *)(pMemfile + + pObject->object_parts[i].meshdef1_offset - 4))->vertex_count; + pObject->object_parts[i].face_block_offset = ((T_HOBFILE_MESHDEF1 *)(pMemfile + + pObject->object_parts[i].meshdef1_offset - 4))->faceblock_offset; + if (verbose == 1) printf("[DBG] > Faces offset: 0x%X\n", pObject->object_parts[i].face_block_offset); + pObject->object_parts[i].vertex_block_offset = ((T_HOBFILE_MESHDEF1 *)(pMemfile + + pObject->object_parts[i].meshdef1_offset - 4))->vertexblocks_offset; + if (verbose == 1) printf("[DBG] > Vertex offset: 0x%X\n\n", pObject->object_parts[i].vertex_block_offset); + + // Get faces datas + ExtractObjParts_faces(&pObject->object_parts[i], pMemfile, verbose); + } + + // Get object part ID, used by animation? bones? + pObject->object_parts[i].id = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->object_id; + if (verbose == 1) printf("\n[DBG] > Facegroup/object ID: %d\n", pObject->object_parts[i].id); + + // Get the transform matrix, used by at-st and at-at (at this time) + pObject->object_parts[i].transform.x = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->transform_x; + pObject->object_parts[i].transform.y = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->transform_y; + pObject->object_parts[i].transform.z = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->transform_z; + if (verbose == 3) printf("\n[DBG] > Facegroup/object transform matrix: [%.8f %.8f %.8f]\n", + pObject->object_parts[i].transform.x, + pObject->object_parts[i].transform.y, + pObject->object_parts[i].transform.z + ); + + if (verbose == 2) printf("\n-----------------------End of Mesh part---------------------------\n"); + } + + if (verbose == 2) printf("\n-=====================-End of Object part-========================-\n"); + + return RSPLIB_SUCCESS; +} + +/** + * Extract datas from faces in object sub-part. + * + * @param[in|out] pObjParts + * @param[in] pMemfile + * @param[in] verbose + * + * @return Error code, RSPLIB_SUCCESS when no error. + */ +static unsigned int ExtractObjParts_faces(T_RSPMODEL_OBJ_PARTS* pObjParts, const MEMFILE pMemfile, const unsigned char verbose) { + unsigned int i, facesExtraOffset = 0; + + if (pObjParts == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL; + + if( ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjParts->face_block_offset))->reserved1 != 0 || + ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjParts->face_block_offset))->reserved2 != 0 ) { + if (verbose == 3) printf("[DBG] > Face block: uncommon zero header!\n"); + } + if ( ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjParts->face_block_offset))->facesOffset != + pObjParts->face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)) { + if (verbose == 3) printf("[DBG] > Face block: uncommon face data offset position!\n"); + } + + pObjParts->face_count = ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjParts->face_block_offset))->faceCounts; + pObjParts->faces = calloc(pObjParts->face_count, sizeof(T_RSPMODEL_FACE)); + for ( i = 0; i < pObjParts->face_count; i++ ) { + if (verbose == 2) printf("\n----------------------Begin of FaceGroup part----------------------\n"); + + // Get flags + pObjParts->faces[i].flags = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->flags; + + // Get unknown bytes + pObjParts->faces[i].b1 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b1; + pObjParts->faces[i].b2 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b2; + pObjParts->faces[i].b3 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b3; + + pObjParts->faces[i].bsize = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->faceBlockIntSize * 4; // Multiply by 4 to get the bytes exact number + if (((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjParts->face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->headerSeparator != 0) { + if (verbose == 3) printf("[DBG] > Face header: uncommon separator!\n"); + } + + // Get materials index + pObjParts->faces[i].material_index = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->materialIndex; + + // Get vertex indices + memcpy(pObjParts->faces[i].indices, ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->vertexIndices, + sizeof(unsigned short) * 4); + + // Recalculate the dynamic extra bytes offset size - if present + if (pObjParts->faces[i].flags_bits.fHasExtraBytesBeforeColor) facesExtraOffset += 8; + + // Get vertex color - if present + if (pObjParts->faces[i].flags_bits.fHasColor) { + facesExtraOffset += ExtractObjpart_Face_Colors(&pObjParts->faces[i], pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * i + + facesExtraOffset); + } + + // Get UV map - if present + if (pObjParts->faces[i].flags_bits.fHasTexture) { + facesExtraOffset += ExtractObjpart_Face_UVMaps(&pObjParts->faces[i], pMemfile + pObjParts->face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * i + + facesExtraOffset); + } + + if (verbose == 2) { + printf("[DBG] > Face %d details: flags:0x%X b1:%d b2:%d b3%d bsize:%d\n", i, pObjParts->faces[i].flags, + pObjParts->faces[i].b1, pObjParts->faces[i].b2, pObjParts->faces[i].b3, pObjParts->faces[i].bsize); + printf("[DBG] - Type is Quad: %d\n", pObjParts->faces[i].flags_bits.fIsQuad); + printf("[DBG] - Material offset: 0x%X\n", pObjParts->faces[i].material_index); + printf("[DBG] - Vertex indices: %d, %d, %d, %d\n", pObjParts->faces[i].indices[0], pObjParts->faces[i].indices[1], + pObjParts->faces[i].indices[2], pObjParts->faces[i].indices[3]); + printf("[DBG] - Vertex colors: 0x%X, 0x%X, 0x%X, 0x%X\n", pObjParts->faces[i].vertex_colors[0], + pObjParts->faces[i].vertex_colors[1], pObjParts->faces[i].vertex_colors[2], pObjParts->faces[i].vertex_colors[3]); + printf("[DBG] - Vertex UV coord (divided by 4096):\n"); + printf("[DBG] > %.8f(%d), %.8f(%d)\n", + ((double) 1/4096) * pObjParts->faces[i].tex_coords[0].u, + pObjParts->faces[i].tex_coords[0].u, + ((double) 1/4096) * pObjParts->faces[i].tex_coords[0].v, + pObjParts->faces[i].tex_coords[0].v + ); + printf("[DBG] > %.8f(%d), %.8f(%d)\n", + ((double) 1/4096) * pObjParts->faces[i].tex_coords[1].u, + pObjParts->faces[i].tex_coords[1].u, + ((double) 1/4096) * pObjParts->faces[i].tex_coords[1].v, + pObjParts->faces[i].tex_coords[1].v + ); + printf("[DBG] > %.8f(%d), %.8f(%d)\n", + ((double) 1/4096) * pObjParts->faces[i].tex_coords[2].u, + pObjParts->faces[i].tex_coords[2].u, + ((double) 1/4096) * pObjParts->faces[i].tex_coords[2].v, + pObjParts->faces[i].tex_coords[2].v + ); + printf("[DBG] > %.8f(%d), %.8f(%d)\n", + ((double) 1/4096) * pObjParts->faces[i].tex_coords[3].u, + pObjParts->faces[i].tex_coords[3].u, + ((double) 1/4096) * pObjParts->faces[i].tex_coords[3].v, + pObjParts->faces[i].tex_coords[3].v + ); + printf("\n"); + } + + if (verbose == 2) printf("\n-----------------------End of FaceGroup part-----------------------\n"); + } + + // Get vertex datas + pObjParts->vertices = calloc(pObjParts->vertex_count, sizeof(T_VERTEX)); + if (pObjParts->vertices == NULL) return RSPLIB_ERROR_MEMORY; + + for ( i = 0; i < pObjParts->vertex_count; i++ ) { + pObjParts->vertices[i].x = + ((T_HOBFILE_VERTEX *)(pMemfile + pObjParts->vertex_block_offset + sizeof(T_VERTEX) * i))->x; + + pObjParts->vertices[i].y = + ((T_HOBFILE_VERTEX *)(pMemfile + pObjParts->vertex_block_offset + sizeof(T_VERTEX) * i))->y; + + pObjParts->vertices[i].z = + ((T_HOBFILE_VERTEX *)(pMemfile + pObjParts->vertex_block_offset + sizeof(T_VERTEX) * i))->z; + + pObjParts->vertices[i].w = + ((T_HOBFILE_VERTEX *)(pMemfile + pObjParts->vertex_block_offset + sizeof(T_VERTEX) * i))->w; // Always 0??? + + if (verbose == 2) printf("[DBG] > Found vertex %d: (%d, %d, %d)\n", i, + pObjParts->vertices[i].x, pObjParts->vertices[i].y, pObjParts->vertices[i].z + ); + } + + return RSPLIB_SUCCESS; +} + +static inline unsigned int ExtractObjpart_Face_Colors(T_RSPMODEL_FACE* pFace, const char* pFaceMemFileOffset) { + unsigned int dynOffset = 0; + + if (pFace->flags_bits.fSeparateColorVertex) { + pFace->vertex_colors[0] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(pFaceMemFileOffset))->v1_rgba; + pFace->vertex_colors[1] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(pFaceMemFileOffset))->v2_rgba; + pFace->vertex_colors[2] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(pFaceMemFileOffset))->v3_rgba; + if (pFace->flags_bits.fIsQuad) { + pFace->vertex_colors[3] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(pFaceMemFileOffset))->v4_rgba; + dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR); + } else { + dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR) - sizeof(T_RGBA); + } + } else { + pFace->vertex_colors[0] = ((T_HOBFILE_FACES_COLOR *)(pFaceMemFileOffset))->rgba; + pFace->vertex_colors[1] = ((T_HOBFILE_FACES_COLOR *)(pFaceMemFileOffset))->rgba; + pFace->vertex_colors[2] = ((T_HOBFILE_FACES_COLOR *)(pFaceMemFileOffset))->rgba; + pFace->vertex_colors[3] = ((T_HOBFILE_FACES_COLOR *)(pFaceMemFileOffset))->rgba; + dynOffset += sizeof(T_HOBFILE_FACES_COLOR); + } + + return dynOffset; +} + +static inline unsigned int ExtractObjpart_Face_UVMaps(T_RSPMODEL_FACE* pFace, const char* pFaceMemFileOffset) { + unsigned int dynOffset = 0; + + pFace->tex_coords[0] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(pFaceMemFileOffset))->v1_texcoord; + pFace->tex_coords[1] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(pFaceMemFileOffset))->v2_texcoord; + pFace->tex_coords[2] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(pFaceMemFileOffset))->v3_texcoord; + if (pFace->flags_bits.fIsQuad) { + pFace->tex_coords[3] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(pFaceMemFileOffset))->v4_texcoord; + dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE); + } else { + dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE) - sizeof(T_TEXCOORD); + } + + return dynOffset; +} diff --git a/RSPModelLib/src/hob_parser.h b/RSPModelLib/src/hob_parser.h index a2cb907..31094df 100644 --- a/RSPModelLib/src/hob_parser.h +++ b/RSPModelLib/src/hob_parser.h @@ -14,6 +14,8 @@ #ifndef SRC_HOB_PARSER_H_ #define SRC_HOB_PARSER_H_ +typedef char* MEMFILE; + unsigned char RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* hob_struct, T_PROG_OPTIONS* p_opts); #endif /* SRC_HOB_PARSER_H_ */