Insert material processing in workflow Tests and experiments with unknown values Reviewed material resolution The first approach of model constructor optimize vertices/indices numbers but doesn't support correctly texture coordinates. Raw approach output good result but need advanced functions in obj lib to efficiently store vertices, textures coord and indices together.
448 lines
22 KiB
C
448 lines
22 KiB
C
/**
|
|
* @file hob_parser.c
|
|
* @date 18/08/2022
|
|
* @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_ParseHOBMemFile(const MEMFILE pMemFile, T_RSPMODEL_HOB* hobStruct, 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_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* hobStruct, const RSPMODEL_PARAMETERS* pParams) {
|
|
unsigned char err = RSPLIB_SUCCESS;
|
|
long fileSize;
|
|
FILE* fStream = NULL;
|
|
MEMFILE memFile = NULL;
|
|
|
|
if (hobStruct != 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);
|
|
|
|
memFile = malloc(fileSize + 1);
|
|
if (memFile != NULL) {
|
|
// Copy file in RAM
|
|
fread(memFile, fileSize, 1, fStream);
|
|
fclose(fStream);
|
|
|
|
// Do the magic!
|
|
err = ExtractObjects(hobStruct, memFile, pParams);
|
|
|
|
free(memFile);
|
|
|
|
} 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;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// 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 = ((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 (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");
|
|
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 (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 && (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_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_VERTEX) * i))->x;
|
|
|
|
pObjPart->vertices[i].y =
|
|
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_VERTEX) * i))->y;
|
|
|
|
pObjPart->vertices[i].z =
|
|
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_VERTEX) * i))->z;
|
|
|
|
pObjPart->vertices[i].w =
|
|
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_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_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_TEXCOORD);
|
|
}
|
|
|
|
return dynOffset;
|
|
}
|