All checks were successful
JCS-Prod/RSE-Model/pipeline/head This commit looks good
Removed logging in library by default
450 lines
22 KiB
C
450 lines
22 KiB
C
/**
|
|
* @file hob_parser.c
|
|
* @date 18/01/2023
|
|
* @author JackCarterSmith
|
|
* @copyright GPL-v3.0
|
|
* @brief Process HOB file structure and extract its datas.
|
|
*
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "RSPModel_errordefs.h"
|
|
#include "RSPModel_datatypes.h"
|
|
#include "hob_struct.h"
|
|
#include "hob_parser.h"
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Private functions declarations
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static unsigned short ExtractObjects(T_RSPMODEL_HOB*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
|
static unsigned short ExtractObjParts(T_RSPMODEL_OBJECT*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
|
static unsigned short ExtractObjParts_faces(T_RSPMODEL_OBJ_PARTS*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
|
static unsigned short ExtractObjpart_Face_Colors(T_RSPMODEL_FACE*, const char*);
|
|
static unsigned short ExtractObjpart_Face_UVMaps(T_RSPMODEL_FACE*, const char*);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Public functions definition
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
unsigned short RSP_ModelLib_ProcessHOBMemFile(T_RSPMODEL_HOB* hobStruct, const MEMFILE pMemFile, const RSPMODEL_PARAMETERS* pParams) {
|
|
unsigned char err = RSPLIB_SUCCESS;
|
|
|
|
if (hobStruct != NULL && pMemFile != NULL) {
|
|
// Do the magic!
|
|
err = ExtractObjects(hobStruct, pMemFile, pParams);
|
|
} else err = RSPLIB_ERROR_ARGS_NULL;
|
|
|
|
return err;
|
|
}
|
|
|
|
unsigned short RSP_ModelLib_LoadHOBFile(MEMFILE* newMemFile, const char* fileName, const RSPMODEL_PARAMETERS* pParams) {
|
|
unsigned char err = RSPLIB_SUCCESS;
|
|
long fileSize;
|
|
FILE* fStream = NULL;
|
|
|
|
if (newMemFile != 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 (pParams->verbose_mode) printf("[DBG] > Input file size: %ld bytes\n", fileSize);
|
|
|
|
*newMemFile = malloc(fileSize + 1);
|
|
if (*newMemFile != NULL) {
|
|
// Copy file in RAM
|
|
fread(*newMemFile, fileSize, 1, fStream);
|
|
fclose(fStream);
|
|
} else {
|
|
fclose(fStream);
|
|
err = RSPLIB_ERROR_MEMORY;
|
|
if (pParams->verbose_mode) printf("[ERR] Can't allocate enough memory for file processing!\n");
|
|
}
|
|
} else {
|
|
err = RSPLIB_ERROR_IO;
|
|
if (pParams->verbose_mode) printf("[ERR] Input file %s not found!\n", fileName);
|
|
}
|
|
} else err = RSPLIB_ERROR_ARGS_NULL;
|
|
|
|
return err;
|
|
}
|
|
|
|
unsigned short RSP_ModelLib_FreeHOBFile(const MEMFILE* memFile) {
|
|
unsigned char err = RSPLIB_SUCCESS;
|
|
|
|
if (memFile != NULL && *memFile != NULL) {
|
|
free(*memFile);
|
|
} else err = RSPLIB_ERROR_ARGS_NULL;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Private functions definition
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @brief 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 Pointer to an in-memory file location.
|
|
* @param[in] pParams Program option, used to tune parser features.
|
|
*
|
|
* @return Error code, RSPLIB_SUCCESS when no error.
|
|
*/
|
|
static unsigned short ExtractObjects(T_RSPMODEL_HOB* pHobStruct, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
|
unsigned int i;
|
|
|
|
if (pHobStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
|
|
|
// Retrieve object count from the header
|
|
pHobStruct->obj_count = RSP_ModelLib_getObjectsCount(pMemfile);
|
|
if (pParams->verbose_mode) printf("[INFO] - Object(s) quantity: %d\n", pHobStruct->obj_count);
|
|
if (pHobStruct->obj_count <= 0) {
|
|
if (pParams->verbose_mode) 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 (pParams->debug_mode) 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 (pParams->verbose_mode) printf("\n[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 (pParams->verbose_mode) 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 (pParams->verbose_mode) 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 (pParams->verbose_mode) printf("[DBG] > Face group header2 offset: 0x%X\n", pHobStruct->objects[i].face_group_header_offset);
|
|
|
|
if (pParams->god_mode) {
|
|
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 (pParams->verbose_mode) 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 (pParams->verbose_mode) printf("[DBG] > Face groups count: %d\n", pHobStruct->objects[i].face_group_count);
|
|
//TODO: Caution with obj/facegrp count difference. What is facegroup count???
|
|
/*
|
|
* Seem "object" are independant structure like xwing, turret, etc.
|
|
* Facegroup is more like part of previous object, like wing-left, turret-barrel, etc.
|
|
*/
|
|
if (pHobStruct->objects[i].object_part_count != pHobStruct->objects[i].face_group_count)
|
|
if (pParams->verbose_mode) printf("[DBG] > Object parts / facegroup count are different!\n");
|
|
|
|
// Get facegroup datas
|
|
ExtractObjParts(&pHobStruct->objects[i], pMemfile, pParams);
|
|
}
|
|
|
|
return RSPLIB_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief 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 Pointer to an in-memory file location.
|
|
* @param[in] pParams Program option, used to tune parser features.
|
|
*
|
|
* @return Error code, RSPLIB_SUCCESS when no error.
|
|
*/
|
|
static unsigned short ExtractObjParts(T_RSPMODEL_OBJECT* pObject, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
|
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 (pParams->debug_mode) 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 (pParams->verbose_mode) printf("\n[DBG] > Face group meshdef0 offset: 0x%X\n", subpart_offset);
|
|
|
|
// Get meshdef0 datas
|
|
if (pParams->god_mode) printf("[DBG] > meshdef0 offset1: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->offset1);
|
|
if (pParams->god_mode) printf("[DBG] > meshdef0 offset2: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->offset2);
|
|
if (pParams->verbose_mode) printf("[DBG] > Prev meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->prev_meshdef0_offset);
|
|
if (pParams->verbose_mode) printf("[DBG] > Next meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->next_meshdef0_offset);
|
|
|
|
if (pParams->god_mode) printf("[DBG] > meshdef0 unknown3: %.8f\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->unknown3);
|
|
if (pParams->god_mode) printf("[DBG] > meshdef0 unknown4: %.8f\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->unknown4);
|
|
if (pParams->god_mode) 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 (pParams->verbose_mode) 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 (pParams->god_mode) 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;
|
|
if (pParams->verbose_mode) printf("[DBG] > Vertex count: %d\n", pObject->object_parts[i].vertex_count);
|
|
pObject->object_parts[i].face_block_offset = ((T_HOBFILE_MESHDEF1 *)(pMemfile
|
|
+ pObject->object_parts[i].meshdef1_offset - 4))->faceblock_offset;
|
|
if (pParams->verbose_mode) 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 (pParams->verbose_mode) 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, pParams);
|
|
}
|
|
|
|
// Get object part ID, used by animation? bones?
|
|
pObject->object_parts[i].id = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->object_id;
|
|
if (pParams->verbose_mode) 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 (pParams->god_mode) 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 (pParams->debug_mode) printf("\n-----------------------End of Mesh part---------------------------\n");
|
|
}
|
|
|
|
if (pParams->debug_mode) printf("\n-=====================-End of Object part-========================-\n");
|
|
|
|
return RSPLIB_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Extract datas from faces from object sub-part.
|
|
*
|
|
* @param[in|out] pObjPart Take object sub-part structure to get the T_RSPMODEL_FACE buffer and object sub-part datas.
|
|
* @param[in] pMemfile Pointer to an in-memory file location.
|
|
* @param[in] pParams Program option, used to tune parser features.
|
|
*
|
|
* @return Error code, RSPLIB_SUCCESS when no error.
|
|
*/
|
|
static unsigned short ExtractObjParts_faces(T_RSPMODEL_OBJ_PARTS* pObjPart, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
|
unsigned int i, facesExtraOffset = 0;
|
|
|
|
if (pObjPart == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
|
|
|
if( ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjPart->face_block_offset))->reserved1 != 0 ||
|
|
((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjPart->face_block_offset))->reserved2 != 0 ) {
|
|
if (pParams->god_mode) printf("[DBG] > Face block: uncommon zero header!\n");
|
|
}
|
|
if ( ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjPart->face_block_offset))->facesOffset !=
|
|
pObjPart->face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)) {
|
|
if (pParams->god_mode) printf("[DBG] > Face block: uncommon face data offset position!\n");
|
|
}
|
|
|
|
pObjPart->face_count = ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjPart->face_block_offset))->faceCounts;
|
|
pObjPart->faces = calloc(pObjPart->face_count, sizeof(T_RSPMODEL_FACE));
|
|
for ( i = 0; i < pObjPart->face_count; i++ ) {
|
|
if (pParams->debug_mode) printf("\n----------------------Begin of Face part----------------------\n");
|
|
|
|
// Get flags
|
|
pObjPart->faces[i].flags = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
|
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->flags;
|
|
|
|
// Get unknown bytes
|
|
pObjPart->faces[i].b1 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
|
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b1;
|
|
pObjPart->faces[i].b2 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
|
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b2;
|
|
pObjPart->faces[i].b3 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
|
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b3;
|
|
|
|
pObjPart->faces[i].bsize = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->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 + pObjPart->face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)
|
|
+ sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->headerSeparator != 0) {
|
|
if (pParams->god_mode) printf("[DBG] > Face header: uncommon separator!\n");
|
|
}
|
|
|
|
// Get materials index
|
|
pObjPart->faces[i].mt_index = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
|
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->materialIndex;
|
|
|
|
// Get vertex indices
|
|
memcpy(pObjPart->faces[i].indices, ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->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 (pObjPart->faces[i].flags_bits.fHasExtraBytesBeforeColor) facesExtraOffset += 8;
|
|
|
|
// Get vertex color - if present
|
|
if (pObjPart->faces[i].flags_bits.fHasColor) {
|
|
facesExtraOffset += ExtractObjpart_Face_Colors(&pObjPart->faces[i], pMemfile + pObjPart->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 (pObjPart->faces[i].flags_bits.fHasTexture) {
|
|
facesExtraOffset += ExtractObjpart_Face_UVMaps(&pObjPart->faces[i], pMemfile + pObjPart->face_block_offset
|
|
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * i
|
|
+ facesExtraOffset);
|
|
}
|
|
|
|
if (pParams->debug_mode) {
|
|
printf("[DBG] > Face %d details: flags:0x%X b1:%d b2:%d b3%d bsize:%d\n", i, pObjPart->faces[i].flags,
|
|
pObjPart->faces[i].b1, pObjPart->faces[i].b2, pObjPart->faces[i].b3, pObjPart->faces[i].bsize);
|
|
printf("[DBG] - Type is Quad: %d\n", pObjPart->faces[i].flags_bits.fIsQuad);
|
|
printf("[DBG] - Have color: %d\n", pObjPart->faces[i].flags_bits.fHasColor);
|
|
printf("[DBG] - Have texture: %d\n", pObjPart->faces[i].flags_bits.fHasTexture);
|
|
printf("[DBG] - Material/texture index: %d\n", pObjPart->faces[i].mt_index);
|
|
printf("[DBG] - Vertex indices: %d, %d, %d, %d\n", pObjPart->faces[i].indices[0], pObjPart->faces[i].indices[1],
|
|
pObjPart->faces[i].indices[2], pObjPart->faces[i].indices[3]);
|
|
printf("[DBG] - Vertex colors: 0x%X, 0x%X, 0x%X, 0x%X\n", pObjPart->faces[i].vertex_colors[0],
|
|
pObjPart->faces[i].vertex_colors[1], pObjPart->faces[i].vertex_colors[2], pObjPart->faces[i].vertex_colors[3]);
|
|
printf("[DBG] - Vertex UV coord (divided by 4096):\n");
|
|
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
|
((double) 1/4096) * pObjPart->faces[i].tex_coords[0].u,
|
|
pObjPart->faces[i].tex_coords[0].u,
|
|
((double) 1/4096) * pObjPart->faces[i].tex_coords[0].v,
|
|
pObjPart->faces[i].tex_coords[0].v
|
|
);
|
|
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
|
((double) 1/4096) * pObjPart->faces[i].tex_coords[1].u,
|
|
pObjPart->faces[i].tex_coords[1].u,
|
|
((double) 1/4096) * pObjPart->faces[i].tex_coords[1].v,
|
|
pObjPart->faces[i].tex_coords[1].v
|
|
);
|
|
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
|
((double) 1/4096) * pObjPart->faces[i].tex_coords[2].u,
|
|
pObjPart->faces[i].tex_coords[2].u,
|
|
((double) 1/4096) * pObjPart->faces[i].tex_coords[2].v,
|
|
pObjPart->faces[i].tex_coords[2].v
|
|
);
|
|
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
|
((double) 1/4096) * pObjPart->faces[i].tex_coords[3].u,
|
|
pObjPart->faces[i].tex_coords[3].u,
|
|
((double) 1/4096) * pObjPart->faces[i].tex_coords[3].v,
|
|
pObjPart->faces[i].tex_coords[3].v
|
|
);
|
|
printf("\n");
|
|
}
|
|
|
|
if (pParams->debug_mode) printf("\n-----------------------End of Face part-----------------------\n");
|
|
}
|
|
|
|
// Get vertex datas
|
|
pObjPart->vertices = calloc(pObjPart->vertex_count, sizeof(T_RSPMODEL_VERTEX));
|
|
if (pObjPart->vertices == NULL) return RSPLIB_ERROR_MEMORY;
|
|
|
|
for ( i = 0; i < pObjPart->vertex_count; i++ ) {
|
|
pObjPart->vertices[i].x =
|
|
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_RSPMODEL_VERTEX) * i))->x;
|
|
|
|
pObjPart->vertices[i].y =
|
|
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_RSPMODEL_VERTEX) * i))->y;
|
|
|
|
pObjPart->vertices[i].z =
|
|
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_RSPMODEL_VERTEX) * i))->z;
|
|
|
|
pObjPart->vertices[i].w =
|
|
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_RSPMODEL_VERTEX) * i))->w; // Always 0???
|
|
|
|
if (pParams->debug_mode) printf("[DBG] > Found vertex %d: (%d, %d, %d)\n", i,
|
|
pObjPart->vertices[i].x, pObjPart->vertices[i].y, pObjPart->vertices[i].z
|
|
);
|
|
}
|
|
|
|
return RSPLIB_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Extract colors from HOB's face to T_RSPMODEL_FACE instance.
|
|
*
|
|
* @param pFace[out] Pointer to an empty instance of T_RSPMODEL_FACE.
|
|
* @param pFaceMemFileOffset[in] Pointer to the in-memory location of face HOB datas.
|
|
* @warning Access to an unallocated memory location using this function result in an ACCESS_VIOLATION.
|
|
*
|
|
* @return The size of processed data. Used to count new offset between each face in object sub-part.
|
|
*/
|
|
static unsigned short 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_RSPMODEL_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;
|
|
}
|
|
|
|
/**
|
|
* @brief Extract UV maps from HOB's face to T_RSPMODEL_FACE instance.
|
|
*
|
|
* @param pFace[out] Pointer to an empty instance of T_RSPMODEL_FACE.
|
|
* @param pFaceMemFileOffset[in] Pointer to the in-memory location of face HOB datas.
|
|
* @warning Access to an unallocated memory location using this function result in an ACCESS_VIOLATION.
|
|
*
|
|
* @return The size of processed data. Used to count new offset between each face in object sub-part.
|
|
*/
|
|
static unsigned short 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_RSPMODEL_TEXCOORD);
|
|
}
|
|
|
|
return dynOffset;
|
|
}
|