/** * \file hob_parser.c * \date 26/07/2022 * \author JackCarterSmith * \copyright GPL-v3.0 * \brief Decode HOB file structure. */ #include #include #include #include "errors_types.h" #include "options.h" #include "hob_struct.h" #include "hob_parser.h" unsigned char RSP_ModelLib_ParseHOBFile(const char* fileName, T_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; if (hob_struct != NULL && fileName != NULL) { // Open file fStream = fopen(fileName, "rb"); if (fStream != NULL) { // Determine file size in bytes fseek(fStream, 0, SEEK_END); fileSize = ftell(fStream); fseek(fStream, 0, SEEK_SET); if (p_opts->verbose_mode) printf("[DBG] > Input file size: %ld bytes\n", fileSize); memFile = malloc(fileSize + 1); if (memFile != NULL) { // Copy file in RAM fread(memFile, fileSize, 1, fStream); fclose(fStream); // 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); if (hob_struct->obj_count > 0) { // Populate HOB structure with object descriptor hob_struct->objects = calloc(hob_struct->obj_count, sizeof(T_HOB_OBJECT)); for ( i = 0; i < hob_struct->obj_count; i++ ) { if (p_opts->debug_mode) printf("\n-=====================-Begin of Object part-======================-\n"); // Get object name memcpy(hob_struct->objects[i].name, ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_name, 16); if (p_opts->verbose_mode) printf("\n"); printf("[INFO] - Process %s object...\n", hob_struct->objects[i].name); // Get offsets hob_struct->objects[i].face_group_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_offset; if (p_opts->verbose_mode) printf("[DBG] > Face group offset: 0x%X\n", hob_struct->objects[i].face_group_offset); hob_struct->objects[i].object_part_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_parts_offset; if (p_opts->verbose_mode) printf("[DBG] > Face group header/object parts offset: 0x%X\n", hob_struct->objects[i].object_part_header_offset); hob_struct->objects[i].face_group_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_header_2_offset; if (p_opts->verbose_mode) printf("[DBG] > Face group header2 offset: 0x%X\n", hob_struct->objects[i].face_group_header_offset); if (p_opts->god_mode) { printf("[DBG] > Face group unknown1: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset1); printf("[DBG] > Face group unknown2: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset2); printf("[DBG] > Face group unknown3: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset3); printf("[DBG] > Face group unknown4: %.8f\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknown4); } // Get count and offsets from the facegroup header hob_struct->objects[i].object_part_count = ((T_HOBFILE_FACEGROUP_HEADER *)(memFile + hob_struct->objects[i].object_part_header_offset))->object_part_count; if (p_opts->verbose_mode) printf("[DBG] > Object parts count: %d\n", hob_struct->objects[i].object_part_count); 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"); // Get facegroup datas offset_index = calloc(hob_struct->objects[i].object_part_count, sizeof(int)); hob_struct->objects[i].object_parts = calloc(hob_struct->objects[i].object_part_count, sizeof(T_HOB_FACE_GROUP)); for ( j = 0; j < hob_struct->objects[i].object_part_count; j++ ) { if (p_opts->debug_mode) printf("\n-----------------------Begin of Mesh part-------------------------\n"); offset_index[j] = ((T_HOBFILE_FACEGROUP_OFFSET *)(memFile + hob_struct->objects[i].object_part_header_offset + sizeof(T_HOBFILE_FACEGROUP_HEADER) + sizeof(T_HOBFILE_FACEGROUP_OFFSET) * j))->facegroup_offset; if (p_opts->verbose_mode) printf("\n[DBG] > Face group meshdef0 offset: 0x%X\n", offset_index[j]); // Get meshdef0 datas if (p_opts->god_mode) printf("[DBG] > meshdef0 offset1: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->offset1); if (p_opts->god_mode) printf("[DBG] > meshdef0 offset2: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->offset2); if (p_opts->verbose_mode) printf("[DBG] > Prev meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->prev_meshdef0_offset); if (p_opts->verbose_mode) printf("[DBG] > Next meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->next_meshdef0_offset); if (p_opts->god_mode) printf("[DBG] > meshdef0 unknown3: %.8f\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->unknown3); if (p_opts->god_mode) printf("[DBG] > meshdef0 unknown4: %.8f\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->unknown4); if (p_opts->god_mode) printf("[DBG] > meshdef0 unknown5: %.8f\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->unknown5); // Get meshdef1 (mesh descriptor) offset hob_struct->objects[i].object_parts[j].meshdef1_offset = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->meshdef1_offset_plus_4; if (p_opts->verbose_mode) printf("\n[DBG] > Face group meshdef1 offset: 0x%X\n", hob_struct->objects[i].object_parts[j].meshdef1_offset); if( ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->reserved1 != 0 || ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->reserved2 != 0 ) { if (p_opts->god_mode) printf("[DBG] > Face group meshdef0: no 0!\n"); } if (hob_struct->objects[i].object_parts[j].meshdef1_offset > 0) { // Read meshdef1 datas hob_struct->objects[i].object_parts[j].face_block_end_offset = ((T_HOBFILE_MESHDEF1 *)(memFile + hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->facedef_end_offset; hob_struct->objects[i].object_parts[j].vertex_count = ((T_HOBFILE_MESHDEF1 *)(memFile + hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->vertex_count; hob_struct->objects[i].object_parts[j].face_block_offset = ((T_HOBFILE_MESHDEF1 *)(memFile + hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->faceblock_offset; if (p_opts->verbose_mode) printf("[DBG] > Faces offset: 0x%X\n", hob_struct->objects[i].object_parts[j].face_block_offset); hob_struct->objects[i].object_parts[j].vertex_block_offset = ((T_HOBFILE_MESHDEF1 *)(memFile + hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->vertexblocks_offset; if (p_opts->verbose_mode) printf("[DBG] > Vertex offset: 0x%X\n\n", hob_struct->objects[i].object_parts[j].vertex_block_offset); // Get face datas if( ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->reserved1 != 0 || ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->reserved2 != 0 ) { if (p_opts->god_mode) printf("[DBG] > Face block: uncommon zero header!\n"); } if ( ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->facesOffset != hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)) { if (p_opts->god_mode) printf("[DBG] > Face block: uncommon face data offset position!\n"); } hob_struct->objects[i].object_parts[j].face_count = ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->faceCounts; hob_struct->objects[i].object_parts[j].faces = calloc(hob_struct->objects[i].object_parts[j].face_count, sizeof(T_HOB_FACE)); facesExtraOffset = 0; for ( k = 0; k < hob_struct->objects[i].object_parts[j].face_count; k++ ) { if (p_opts->debug_mode) printf("\n----------------------Begin of FaceGroup part----------------------\n"); // Get flags hob_struct->objects[i].object_parts[j].faces[k].flags = ((T_HOBFILE_FACES_HEADER *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->flags; // Get unknown bytes hob_struct->objects[i].object_parts[j].faces[k].b1 = ((T_HOBFILE_FACES_HEADER *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->b1; hob_struct->objects[i].object_parts[j].faces[k].b2 = ((T_HOBFILE_FACES_HEADER *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->b2; hob_struct->objects[i].object_parts[j].faces[k].b3 = ((T_HOBFILE_FACES_HEADER *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->b3; hob_struct->objects[i].object_parts[j].faces[k].bsize = ((T_HOBFILE_FACES_HEADER *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->faceBlockIntSize * 4; // Multiply by 4 to get the bytes exact number if (((T_HOBFILE_FACES_HEADER *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->headerSeparator != 0) { if (p_opts->god_mode) printf("[DBG] > Face header: uncommon separator!\n"); } // Get materials index hob_struct->objects[i].object_parts[j].faces[k].material_index = ((T_HOBFILE_FACES_HEADER *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->materialIndex; // Get vertex indices memcpy(hob_struct->objects[i].object_parts[j].faces[k].indices, ((T_HOBFILE_FACES_HEADER *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->vertexIndices, sizeof(unsigned short) * 4); // Recalculate the dynamic extra bytes offset size - if present if (hob_struct->objects[i].object_parts[j].faces[k].flags_bits.fHasExtraBytesBeforeColor) facesExtraOffset += 8; // Get vertex color - if present if (hob_struct->objects[i].object_parts[j].faces[k].flags_bits.fHasColor) { if (hob_struct->objects[i].object_parts[j].faces[k].flags_bits.fSeparateColorVertex) { hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[0] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->v1_rgba; hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[1] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->v2_rgba; hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[2] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->v3_rgba; if (hob_struct->objects[i].object_parts[j].faces[k].flags_bits.fIsQuad) { hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[3] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->v4_rgba; facesExtraOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR); } else { facesExtraOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR) - sizeof(T_RGBA); } } else { hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[0] = ((T_HOBFILE_FACES_COLOR *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->rgba; hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[1] = ((T_HOBFILE_FACES_COLOR *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->rgba; hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[2] = ((T_HOBFILE_FACES_COLOR *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->rgba; hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[3] = ((T_HOBFILE_FACES_COLOR *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->rgba; facesExtraOffset += sizeof(T_HOBFILE_FACES_COLOR); } } // Get UV map - if present if (hob_struct->objects[i].object_parts[j].faces[k].flags_bits.fHasTexture) { hob_struct->objects[i].object_parts[j].faces[k].tex_coords[0] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->v1_texcoord; hob_struct->objects[i].object_parts[j].faces[k].tex_coords[1] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->v2_texcoord; hob_struct->objects[i].object_parts[j].faces[k].tex_coords[2] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->v3_texcoord; if (hob_struct->objects[i].object_parts[j].faces[k].flags_bits.fIsQuad) { hob_struct->objects[i].object_parts[j].faces[k].tex_coords[3] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * k + facesExtraOffset))->v4_texcoord; facesExtraOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE); } else { facesExtraOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE) - sizeof(T_TEXCOORD); } } if (p_opts->debug_mode) { printf("[DBG] > Face %d details: flags:0x%X b1:%d b2:%d b3%d bsize:%d\n", k, hob_struct->objects[i].object_parts[j].faces[k].flags, hob_struct->objects[i].object_parts[j].faces[k].b1, hob_struct->objects[i].object_parts[j].faces[k].b2, hob_struct->objects[i].object_parts[j].faces[k].b3, hob_struct->objects[i].object_parts[j].faces[k].bsize ); printf("[DBG] - Type is Quad: %d\n", hob_struct->objects[i].object_parts[j].faces[k].flags_bits.fIsQuad); printf("[DBG] - Material offset: 0x%X\n", hob_struct->objects[i].object_parts[j].faces[k].material_index); printf("[DBG] - Vertex indices: %d, %d, %d, %d\n", hob_struct->objects[i].object_parts[j].faces[k].indices[0], hob_struct->objects[i].object_parts[j].faces[k].indices[1], hob_struct->objects[i].object_parts[j].faces[k].indices[2], hob_struct->objects[i].object_parts[j].faces[k].indices[3] ); printf("[DBG] - Vertex colors: 0x%X, 0x%X, 0x%X, 0x%X\n", hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[0], hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[1], hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[2], hob_struct->objects[i].object_parts[j].faces[k].vertex_colors[3] ); printf("[DBG] - Vertex UV coord (divided by 4096):\n"); printf("[DBG] > %.8f(%d), %.8f(%d)\n", ((double) 1/4096) * hob_struct->objects[i].object_parts[j].faces[k].tex_coords[0].u, hob_struct->objects[i].object_parts[j].faces[k].tex_coords[0].u, ((double) 1/4096) * hob_struct->objects[i].object_parts[j].faces[k].tex_coords[0].v, hob_struct->objects[i].object_parts[j].faces[k].tex_coords[0].v ); printf("[DBG] > %.8f(%d), %.8f(%d)\n", ((double) 1/4096) * hob_struct->objects[i].object_parts[j].faces[k].tex_coords[1].u, hob_struct->objects[i].object_parts[j].faces[k].tex_coords[1].u, ((double) 1/4096) * hob_struct->objects[i].object_parts[j].faces[k].tex_coords[1].v, hob_struct->objects[i].object_parts[j].faces[k].tex_coords[1].v ); printf("[DBG] > %.8f(%d), %.8f(%d)\n", ((double) 1/4096) * hob_struct->objects[i].object_parts[j].faces[k].tex_coords[2].u, hob_struct->objects[i].object_parts[j].faces[k].tex_coords[2].u, ((double) 1/4096) * hob_struct->objects[i].object_parts[j].faces[k].tex_coords[2].v, hob_struct->objects[i].object_parts[j].faces[k].tex_coords[2].v ); printf("[DBG] > %.8f(%d), %.8f(%d)\n", ((double) 1/4096) * hob_struct->objects[i].object_parts[j].faces[k].tex_coords[3].u, hob_struct->objects[i].object_parts[j].faces[k].tex_coords[3].u, ((double) 1/4096) * hob_struct->objects[i].object_parts[j].faces[k].tex_coords[3].v, hob_struct->objects[i].object_parts[j].faces[k].tex_coords[3].v ); printf("\n"); } if (p_opts->debug_mode) printf("\n-----------------------End of FaceGroup part-----------------------\n"); } // 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 ); } } // Get object part ID, used by animation? bones? hob_struct->objects[i].object_parts[j].id = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->object_id; if (p_opts->verbose_mode) printf("\n[DBG] > Facegroup/object ID: %d\n", hob_struct->objects[i].object_parts[j].id); // Get the transform matrix, used by at-st and at-at (at this time) hob_struct->objects[i].object_parts[j].transform.x = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_x; hob_struct->objects[i].object_parts[j].transform.y = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_y; hob_struct->objects[i].object_parts[j].transform.z = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_z; if (p_opts->god_mode) printf("\n[DBG] > Facegroup/object transform matrix: [%.8f %.8f %.8f]\n", hob_struct->objects[i].object_parts[j].transform.x, hob_struct->objects[i].object_parts[j].transform.y, hob_struct->objects[i].object_parts[j].transform.z ); if (p_opts->debug_mode) printf("\n-----------------------End of Mesh part---------------------------\n"); } if (p_opts->debug_mode) printf("\n-=====================-End of Object part-========================-\n"); } free(offset_index); } else { err = ERROR_GENERIC; printf("[INFO] Can't process empty file!\n"); } free(memFile); } else { fclose(fStream); err = ERROR_MEMORY; if (p_opts->verbose_mode) printf("[ERR] Can't allocate enough memory for file processing!\n"); } } else { err = ERROR_IO; if (p_opts->verbose_mode) printf("[ERR] Input file %s not found!\n", fileName); } } else err = ERROR_ARGS_NULL; return err; }