Add texture mtl exporting pre-release
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.
This commit is contained in:
parent
eafb0680fe
commit
fc53d11d15
@ -20,6 +20,7 @@
|
||||
#include <RSPModel.h>
|
||||
#include <RSPModel_errordefs.h>
|
||||
#include "model_export.h"
|
||||
#include "lib_interface.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -36,15 +37,19 @@ static void dispHelp();
|
||||
* - MAIN -
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
T_PROG_OPTIONS _opts;
|
||||
T_PROG_OPTIONS _opts = {0};
|
||||
unsigned char p;
|
||||
unsigned int status = RSPLIB_SUCCESS;
|
||||
|
||||
// Hello world!
|
||||
printf("\n*~[ Rogue Squadron Extractor (RSE) - RSPModelLib v%s ]~*\n", RSPModel_getVersion());
|
||||
printf("\n*~[ Rogue Squadron Extractor (RSE) - RSPModelLib v%s ]~*\n\n", RSPModel_getVersion());
|
||||
|
||||
// Try linking to externals modules
|
||||
linkTextureLib(&_opts);
|
||||
|
||||
// Check for arguments
|
||||
if (argc < 2) {
|
||||
printf("\n[ERR] No input file/commands specified!\n");
|
||||
printf("[ERR] No input file/commands specified!\n");
|
||||
dispHelp();
|
||||
return RSPLIB_ERROR_ARGS_NULL;
|
||||
}
|
||||
@ -54,7 +59,11 @@ int main(int argc, char *argv[]) {
|
||||
if ( p == RSPLIB_ERROR_GENERIC ) return RSPLIB_SUCCESS;
|
||||
else if ( p != RSPLIB_SUCCESS ) return p;
|
||||
|
||||
return mainProcess(argc, argv, &_opts);
|
||||
status = mainProcess(argc, argv, &_opts);
|
||||
|
||||
unlinkTextureLib();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -66,7 +75,9 @@ static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS
|
||||
unsigned short file_index;
|
||||
RSPMODEL_PARAMETERS libParams;
|
||||
T_RSPMODEL_HOB* hobStruct = NULL;
|
||||
int i;
|
||||
char hmt_filename[1024];
|
||||
void* hmtStruct = NULL;
|
||||
unsigned int i;
|
||||
|
||||
libParams.raw = p_opts->raw & 0x7;
|
||||
|
||||
@ -84,6 +95,14 @@ static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS
|
||||
RSPModel_freeHOB(hobStruct);
|
||||
return RSPLIB_ERROR_PROCESS;
|
||||
}
|
||||
|
||||
// If Texture module loaded, process HMT file for mtl naming (doesn't extract texture!)
|
||||
if (p_opts->texture_module) {
|
||||
hmtStruct = RSPTexture_createHMT();
|
||||
strncpy(hmt_filename, args_value[file_index], strlen(args_value[file_index]) - 3);
|
||||
strncat(hmt_filename, "HMT", strlen(args_value[file_index]));
|
||||
RSPTexture_processHMTFile(hmtStruct, hmt_filename, 0);
|
||||
}
|
||||
} else return RSPLIB_ERROR_MEMORY;
|
||||
|
||||
if (hobStruct->obj_count > 0) {
|
||||
@ -91,12 +110,14 @@ static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS
|
||||
if (p_opts->output_dir) createSubDir(args_value[file_index]);
|
||||
|
||||
for ( i = 0; i < hobStruct->obj_count; i++ ) {
|
||||
if (exportOBJModel(&(hobStruct->objects[i]), args_value[file_index], p_opts) == RSPLIB_SUCCESS)
|
||||
if (exportOBJModel(&(hobStruct->objects[i]), args_value[file_index], hmtStruct, p_opts) == RSPLIB_SUCCESS)
|
||||
printf("[INFO] Successfully exported %s object in OBJ format.\n", hobStruct->objects[i].name);
|
||||
else
|
||||
printf("[ERR] Failed to export %s object in OBJ format!\n", hobStruct->objects[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
RSPTexture_freeHMT(hmtStruct);
|
||||
}
|
||||
|
||||
RSPModel_freeHOB(hobStruct);
|
||||
@ -109,7 +130,6 @@ static unsigned short checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, cha
|
||||
int i;
|
||||
|
||||
// Set default options
|
||||
opt_ptr->raw = 0;
|
||||
opt_ptr->output_dir = 1;
|
||||
|
||||
if (p_arg_nbr > 1) {
|
||||
@ -135,8 +155,12 @@ static unsigned short checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, cha
|
||||
opt_ptr->output_dir = 0;
|
||||
printf("[OPTN] Export to current directory.\n");
|
||||
} else if (strcmp(p_args[i], "-mtl") == 0) {
|
||||
opt_ptr->export_mtl = 1;
|
||||
printf("[OPTN] Export materials datas.\n");
|
||||
if (opt_ptr->texture_module) {
|
||||
opt_ptr->export_mtl = 1;
|
||||
printf("[OPTN] Export materials datas.\n");
|
||||
} else {
|
||||
printf("[OPTN] Can't export materials datas, RSPTextureLib not found or incorrect version!\n");
|
||||
}
|
||||
} else {
|
||||
printf("[ERR] Unknown option: %s\n", p_args[i]);
|
||||
}
|
||||
|
121
RSEModel/src/lib_interface.c
Normal file
121
RSEModel/src/lib_interface.c
Normal file
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* @file lib_interface.c
|
||||
* @date 01/09/2022
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief Interface functions to external RSP libraries.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#if defined(_WIN32)
|
||||
#include <libloaderapi.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#include "options.h"
|
||||
#include "lib_interface.h"
|
||||
|
||||
|
||||
/*
|
||||
* Global handler declaration
|
||||
*/
|
||||
static void* hRSPTextureLib = NULL;
|
||||
__RSPTexture_getVersion RSPTexture_getVersion;
|
||||
__RSPTexture_createHMT RSPTexture_createHMT;
|
||||
__RSPTexture_processHMTFile RSPTexture_processHMTFile;
|
||||
__RSPTexture_getMaterialFromID RSPTexture_getMaterialFromID;
|
||||
__RSPTexture_getMaterialName RSPTexture_getMaterialName;
|
||||
__RSPTexture_getMaterialOpacity RSPTexture_getMaterialOpacity;
|
||||
__RSPTexture_getMaterialAmbient RSPTexture_getMaterialAmbient;
|
||||
__RSPTexture_freeHMT RSPTexture_freeHMT;
|
||||
|
||||
|
||||
/**
|
||||
* Link functions proxies against RSPTextureLib dll/so.
|
||||
* @param opt_ptr Table of parameters to record module loading status.
|
||||
*/
|
||||
void* linkTextureLib(T_PROG_OPTIONS* opt_ptr) {
|
||||
if (hRSPTextureLib == NULL) {
|
||||
#if defined(_WIN32)
|
||||
hRSPTextureLib = LoadLibraryA(RSPTEXTURE_OSLIBFILE);
|
||||
if (hRSPTextureLib) {
|
||||
RSPTexture_getVersion = (__RSPTexture_getVersion)GetProcAddress(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_VERSION);
|
||||
RSPTexture_createHMT = (__RSPTexture_createHMT)GetProcAddress(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_NEW_HMT);
|
||||
RSPTexture_processHMTFile = (__RSPTexture_processHMTFile)GetProcAddress(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_PROC_HMT);
|
||||
RSPTexture_getMaterialFromID = (__RSPTexture_getMaterialFromID)GetProcAddress(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_MAT);
|
||||
RSPTexture_getMaterialName = (__RSPTexture_getMaterialName)GetProcAddress(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_NAME);
|
||||
RSPTexture_getMaterialOpacity = (__RSPTexture_getMaterialOpacity)GetProcAddress(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_OPACITY);
|
||||
RSPTexture_getMaterialAmbient = (__RSPTexture_getMaterialAmbient)GetProcAddress(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_AMBIENT);
|
||||
RSPTexture_freeHMT = (__RSPTexture_freeHMT)GetProcAddress(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_FREE_HMT);
|
||||
|
||||
if (RSPTexture_getVersion && RSPTexture_createHMT && RSPTexture_processHMTFile
|
||||
&& RSPTexture_getMaterialFromID && RSPTexture_freeHMT && RSPTexture_getMaterialName
|
||||
&& RSPTexture_getMaterialOpacity && RSPTexture_getMaterialAmbient) {
|
||||
opt_ptr->texture_module = 1;
|
||||
printf("[INFO] Loaded RSPTextureLib v%s\n", RSPTexture_getVersion());
|
||||
} else {
|
||||
printf("[INFO] RSPTextureLib linking failure. Maybe incorrect version or file corrupted?\n");
|
||||
}
|
||||
} else {
|
||||
printf("[INFO] RSPTextureLib not found.\n");
|
||||
}
|
||||
#else
|
||||
hRSPTextureLib = dlopen(RSPTEXTURE_OSLIBFILE, RTLD_LAZY | RTLD_DEEPBIND);
|
||||
if (hRSPTextureLib) {
|
||||
RSPTexture_getVersion = dlsym(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_VERSION);
|
||||
RSPTexture_createHMT = dlsym(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_NEW_HMT);
|
||||
RSPTexture_processHMTFile = dlsym(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_PROC_HMT);
|
||||
RSPTexture_getMaterialFromID = dlsym(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_MAT);
|
||||
RSPTexture_getMaterialName = dlsym(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_NAME);
|
||||
RSPTexture_getMaterialOpacity = dlsym(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_OPACITY);
|
||||
RSPTexture_getMaterialAmbient = dlsym(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_GET_AMBIENT);
|
||||
RSPTexture_freeHMT = dlsym(
|
||||
hRSPTextureLib, RSPTEXTURE_FUNCNAME_FREE_HMT);
|
||||
|
||||
if (RSPTexture_getVersion && RSPTexture_createHMT && RSPTexture_processHMTFile
|
||||
&& RSPTexture_getMaterialFromID && RSPTexture_freeHMT && RSPTexture_getMaterialName
|
||||
&& RSPTexture_getMaterialOpacity && RSPTexture_getMaterialAmbient) {
|
||||
opt_ptr->texture_module = 1;
|
||||
printf("[INFO] Loaded RSPTextureLib v%s\n", RSPTexture_getVersion());
|
||||
} else {
|
||||
printf("[INFO] RSPTextureLib linking failure. Maybe incorrect version or file corrupted?\n");
|
||||
}
|
||||
} else {
|
||||
printf("[INFO] RSPTextureLib not found.\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return hRSPTextureLib;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release libraries from dynamic loader.
|
||||
*/
|
||||
void unlinkTextureLib(void) {
|
||||
if (hRSPTextureLib == NULL) return;
|
||||
|
||||
#if defined(_WIN32)
|
||||
//FreeLibraryAndExitThread(hRSPTextureLib, 0);
|
||||
FreeLibrary(hRSPTextureLib);
|
||||
#else
|
||||
dlclose(hRSPTextureLib);
|
||||
#endif
|
||||
}
|
67
RSEModel/src/lib_interface.h
Normal file
67
RSEModel/src/lib_interface.h
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @file lib_interface.h
|
||||
* @date 01/09/2022
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief Interface functions to external RSP libraries.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "options.h"
|
||||
|
||||
|
||||
#ifndef RSEMODEL_LIB_INTERFACE_H_
|
||||
#define RSEMODEL_LIB_INTERFACE_H_
|
||||
|
||||
#define RSPTEXTURE_VERSION "20"
|
||||
#define RSPTEXTURE_LIBFILE "libRSPTexture" RSPTEXTURE_VERSION
|
||||
#if defined(_WIN32)
|
||||
#define RSPTEXTURE_OSLIBFILE RSPTEXTURE_LIBFILE ".dll"
|
||||
#else
|
||||
#define RSPTEXTURE_OSLIBFILE RSPTEXTURE_LIBFILE ".so"
|
||||
#endif
|
||||
|
||||
#define RSPTEXTURE_FUNCNAME_GET_VERSION "RSPTexture_getVersion"
|
||||
#define RSPTEXTURE_FUNCNAME_NEW_HMT "RSPTexture_createHMT"
|
||||
#define RSPTEXTURE_FUNCNAME_PROC_HMT "RSPTexture_processHMTFile"
|
||||
#define RSPTEXTURE_FUNCNAME_GET_MAT "RSPTexture_getMaterialFromID"
|
||||
#define RSPTEXTURE_FUNCNAME_GET_NAME "RSPTexture_getMaterialName"
|
||||
#define RSPTEXTURE_FUNCNAME_GET_OPACITY "RSPTexture_getMaterialOpacity"
|
||||
#define RSPTEXTURE_FUNCNAME_GET_AMBIENT "RSPTexture_getMaterialAmbient"
|
||||
#define RSPTEXTURE_FUNCNAME_FREE_HMT "RSPTexture_freeHMT"
|
||||
|
||||
/* External libraries functions signatures */
|
||||
typedef char* (*__RSPTexture_getVersion)(void);
|
||||
typedef void* (*__RSPTexture_createHMT)(void);
|
||||
typedef unsigned short (*__RSPTexture_processHMTFile)(
|
||||
void* hmtStruct,
|
||||
const char* const filePath,
|
||||
const unsigned char params
|
||||
);
|
||||
typedef void* (*__RSPTexture_getMaterialFromID)(
|
||||
const void* hmtStruct,
|
||||
const unsigned short mat_id
|
||||
);
|
||||
typedef char* (*__RSPTexture_getMaterialName)(const void* material);
|
||||
typedef float (*__RSPTexture_getMaterialOpacity)(const void* material);
|
||||
typedef float (*__RSPTexture_getMaterialAmbient)(const void* material);
|
||||
typedef void (*__RSPTexture_freeHMT)(void* hmtStruct);
|
||||
|
||||
|
||||
/* External libraries proxies functions */
|
||||
extern __RSPTexture_getVersion RSPTexture_getVersion;
|
||||
extern __RSPTexture_createHMT RSPTexture_createHMT;
|
||||
extern __RSPTexture_processHMTFile RSPTexture_processHMTFile;
|
||||
extern __RSPTexture_getMaterialFromID RSPTexture_getMaterialFromID;
|
||||
extern __RSPTexture_getMaterialName RSPTexture_getMaterialName;
|
||||
extern __RSPTexture_getMaterialOpacity RSPTexture_getMaterialOpacity;
|
||||
extern __RSPTexture_getMaterialAmbient RSPTexture_getMaterialAmbient;
|
||||
extern __RSPTexture_freeHMT RSPTexture_freeHMT;
|
||||
|
||||
|
||||
/* Linker functions declarations */
|
||||
void* linkTextureLib(T_PROG_OPTIONS* opt_ptr);
|
||||
void unlinkTextureLib(void);
|
||||
|
||||
|
||||
#endif /* RSEMODEL_LIB_INTERFACE_H_ */
|
@ -14,18 +14,21 @@
|
||||
#include <RSPModel_datatypes.h>
|
||||
#include <RSPModel_errordefs.h>
|
||||
#include "obj/obj.h"
|
||||
#include "lib_interface.h"
|
||||
#include "model_export.h"
|
||||
|
||||
|
||||
unsigned char exportOBJModel(T_RSPMODEL_OBJECT* hob_objects, const char *out_path, T_PROG_OPTIONS* p_opts) {
|
||||
unsigned char exportOBJModel(T_RSPMODEL_OBJECT* hob_objects, const char *out_path, void* hmt_struct, T_PROG_OPTIONS* p_opts) {
|
||||
char export_path[1024];
|
||||
char objExport_name[128];
|
||||
char mtlExport_name[128];
|
||||
char material_name[64];
|
||||
obj* objConstruct = NULL;
|
||||
unsigned int i,j;
|
||||
void* material = NULL;
|
||||
unsigned int i,j,k,a;
|
||||
unsigned int poly_count = 0;
|
||||
int surfID = 0, materialID = 0, tmpVertex = 0, tmpIndex = 0;
|
||||
int indexOffset = 0; // Used to compensate reset of indices between face group
|
||||
float vertexBuff[3] = {0}, textureBuff[2] = {0};
|
||||
float vertexBuff[3] = {0}, textureBuff[2] = {0}, materialAmbient[4] = {0};
|
||||
int indicesBuff[3] = {0};
|
||||
|
||||
if (hob_objects == NULL || out_path == NULL)
|
||||
@ -41,74 +44,106 @@ unsigned char exportOBJModel(T_RSPMODEL_OBJECT* hob_objects, const char *out_pat
|
||||
|
||||
objConstruct = obj_create(NULL);
|
||||
|
||||
// Build face/surface material group
|
||||
//TODO: should be deconstructed in sub-functions
|
||||
// For each objects sub-part, create it's faces and surfaces/materials datas
|
||||
for ( i = 0; i < hob_objects->object_part_count; i++) {
|
||||
surfID = obj_add_surf(objConstruct);
|
||||
materialID = obj_add_mtrl(objConstruct);
|
||||
|
||||
// Build vertex container
|
||||
for ( j = 0; j < hob_objects->object_parts[i].vertex_count; j++ ) {
|
||||
tmpVertex = obj_add_vert(objConstruct);
|
||||
|
||||
vertexBuff[0] = ((float)1/1024) * -hob_objects->object_parts[i].vertices[j].x; // Invert X to fix mirror display
|
||||
vertexBuff[1] = ((float)1/1024) * -hob_objects->object_parts[i].vertices[j].y; // Invert Y to render upside up
|
||||
vertexBuff[2] = ((float)1/1024) * hob_objects->object_parts[i].vertices[j].z;
|
||||
obj_set_vert_v(objConstruct, tmpVertex, vertexBuff);
|
||||
}
|
||||
|
||||
// Build indices container and UV mapping
|
||||
// Build faces datas: vertices, indices table, materials and UV mapping
|
||||
for ( j = 0; j < hob_objects->object_parts[i].face_count; j++ ) {
|
||||
tmpIndex = obj_add_poly(objConstruct, surfID);
|
||||
|
||||
indicesBuff[0] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[0];
|
||||
indicesBuff[1] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[1];
|
||||
indicesBuff[2] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[2];
|
||||
obj_set_poly(objConstruct, surfID, tmpIndex, indicesBuff);
|
||||
// Construct materials list - add new when first loop or mt_index change
|
||||
if (j == 0 || ( hob_objects->object_parts[i].faces[j].mt_index != hob_objects->object_parts[i].faces[j-1].mt_index )) {
|
||||
surfID = obj_add_surf(objConstruct);
|
||||
|
||||
if (hob_objects->object_parts[i].faces[j].flags_bits.fHasTexture) {
|
||||
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[0].u;
|
||||
textureBuff[1] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[0].v;
|
||||
obj_set_vert_t(objConstruct, indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[0], textureBuff);
|
||||
if (p_opts->texture_module) {
|
||||
materialID = obj_add_mtrl(objConstruct);
|
||||
|
||||
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[1].u;
|
||||
textureBuff[1] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[1].v;
|
||||
obj_set_vert_t(objConstruct, indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[1], textureBuff);
|
||||
// Set material properties for face group
|
||||
material = RSPTexture_getMaterialFromID(hmt_struct, hob_objects->object_parts[i].faces[j].mt_index);
|
||||
obj_set_mtrl_name(objConstruct, materialID, RSPTexture_getMaterialName(material));
|
||||
materialAmbient[0] = RSPTexture_getMaterialOpacity(material);
|
||||
materialAmbient[1] = materialAmbient[0];
|
||||
materialAmbient[2] = materialAmbient[0];
|
||||
materialAmbient[3] = materialAmbient[0];
|
||||
//obj_set_mtrl_c(objConstruct, materialID, OBJ_KA, materialAmbient);
|
||||
obj_set_mtrl_c(objConstruct, materialID, OBJ_KD, materialAmbient);
|
||||
//obj_set_mtrl_c(objConstruct, materialID, OBJ_KS, materialAmbient);
|
||||
|
||||
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[2].u;
|
||||
textureBuff[1] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[2].v;
|
||||
obj_set_vert_t(objConstruct, indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[2], textureBuff);
|
||||
// Add image file name if textured
|
||||
if (hob_objects->object_parts[i].faces[j].flags_bits.fHasTexture) {
|
||||
snprintf(material_name, 64, "%s.png", RSPTexture_getMaterialName(material));
|
||||
//obj_set_mtrl_map(objConstruct, materialID, OBJ_KA, material_name);
|
||||
obj_set_mtrl_map(objConstruct, materialID, OBJ_KD, material_name);
|
||||
//obj_set_mtrl_map(objConstruct, materialID, OBJ_KS, material_name);
|
||||
}
|
||||
|
||||
// Link material to surface
|
||||
obj_set_surf(objConstruct, surfID, materialID);
|
||||
}
|
||||
}
|
||||
|
||||
// Add vertex corresponding to indices
|
||||
for ( k = 0; k < 3; k++ ) {
|
||||
tmpVertex = obj_add_vert(objConstruct);
|
||||
a = hob_objects->object_parts[i].faces[j].indices[k];
|
||||
|
||||
vertexBuff[0] = ((float)1/1024) * -hob_objects->object_parts[i].vertices[a].x; // Invert X to fix mirror display
|
||||
vertexBuff[1] = ((float)1/1024) * -hob_objects->object_parts[i].vertices[a].y; // Invert Y to render upside up
|
||||
vertexBuff[2] = ((float)1/1024) * hob_objects->object_parts[i].vertices[a].z;
|
||||
obj_set_vert_v(objConstruct, tmpVertex, vertexBuff);
|
||||
|
||||
if (hob_objects->object_parts[i].faces[j].flags_bits.fHasTexture) {
|
||||
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[k].u;
|
||||
textureBuff[1] = -((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[k].v + 1;
|
||||
obj_set_vert_t(objConstruct, tmpVertex, textureBuff);
|
||||
}
|
||||
}
|
||||
// Build indices table for this face
|
||||
tmpIndex = obj_add_poly(objConstruct, surfID);
|
||||
indicesBuff[0] = 3 * poly_count;
|
||||
indicesBuff[1] = 3 * poly_count + 1;
|
||||
indicesBuff[2] = 3 * poly_count + 2;
|
||||
poly_count++;
|
||||
obj_set_poly(objConstruct, surfID, tmpIndex, indicesBuff);
|
||||
|
||||
// Process 2 triangles if face is Quad
|
||||
if (hob_objects->object_parts[i].faces[j].flags_bits.fIsQuad) {
|
||||
tmpIndex = obj_add_poly(objConstruct, surfID);
|
||||
for ( k = 0; k < 3; k++ ) {
|
||||
tmpVertex = obj_add_vert(objConstruct);
|
||||
a = hob_objects->object_parts[i].faces[j].indices[(k + 2) & 0x3]; // TODO: can't be written properly?
|
||||
|
||||
indicesBuff[0] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[0];
|
||||
indicesBuff[1] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[2];
|
||||
indicesBuff[2] = indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[3];
|
||||
obj_set_poly(objConstruct, surfID, tmpIndex, indicesBuff);
|
||||
vertexBuff[0] = ((float)1/1024) * -hob_objects->object_parts[i].vertices[a].x; // Invert X to fix mirror display
|
||||
vertexBuff[1] = ((float)1/1024) * -hob_objects->object_parts[i].vertices[a].y; // Invert Y to render upside up
|
||||
vertexBuff[2] = ((float)1/1024) * hob_objects->object_parts[i].vertices[a].z;
|
||||
obj_set_vert_v(objConstruct, tmpVertex, vertexBuff);
|
||||
|
||||
if (hob_objects->object_parts[i].faces[j].flags_bits.fHasTexture) {
|
||||
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[3].u;
|
||||
textureBuff[1] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[3].v;
|
||||
obj_set_vert_t(objConstruct, indexOffset + (int)hob_objects->object_parts[i].faces[j].indices[3], textureBuff);
|
||||
if (hob_objects->object_parts[i].faces[j].flags_bits.fHasTexture) {
|
||||
textureBuff[0] = ((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[(k + 2) & 0x3].u;
|
||||
textureBuff[1] = -((float)1/4096) * hob_objects->object_parts[i].faces[j].tex_coords[(k + 2) & 0x3].v + 1;
|
||||
obj_set_vert_t(objConstruct, tmpVertex, textureBuff);
|
||||
}
|
||||
}
|
||||
// Build indices table for this face
|
||||
tmpIndex = obj_add_poly(objConstruct, surfID);
|
||||
indicesBuff[0] = 3 * poly_count;
|
||||
indicesBuff[1] = 3 * poly_count + 1;
|
||||
indicesBuff[2] = 3 * poly_count + 2;
|
||||
poly_count++;
|
||||
obj_set_poly(objConstruct, surfID, tmpIndex, indicesBuff);
|
||||
}
|
||||
}
|
||||
|
||||
indexOffset = obj_num_vert(objConstruct);
|
||||
}
|
||||
|
||||
if (p_opts->export_mtl) {
|
||||
if (p_opts->output_dir)
|
||||
obj_write(objConstruct, objExport_name, mtlExport_name, export_path, 8);
|
||||
obj_write(objConstruct, objExport_name, mtlExport_name, export_path, 6);
|
||||
else
|
||||
obj_write(objConstruct, objExport_name, mtlExport_name, NULL, 8);
|
||||
obj_write(objConstruct, objExport_name, mtlExport_name, NULL, 6);
|
||||
} else {
|
||||
if (p_opts->output_dir)
|
||||
obj_write(objConstruct, objExport_name, NULL, export_path, 8);
|
||||
obj_write(objConstruct, objExport_name, NULL, export_path, 6);
|
||||
else
|
||||
obj_write(objConstruct, objExport_name, NULL, NULL, 8);
|
||||
obj_write(objConstruct, objExport_name, NULL, NULL, 6);
|
||||
}
|
||||
|
||||
obj_delete(objConstruct);
|
||||
|
@ -10,13 +10,6 @@
|
||||
#ifndef MODEL_EXPORT_H_
|
||||
#define MODEL_EXPORT_H_
|
||||
|
||||
|
||||
typedef struct t_material {
|
||||
unsigned short hasTexture;
|
||||
unsigned short bpp;
|
||||
unsigned int gl_tex_id;
|
||||
} T_MATERIAL;
|
||||
|
||||
unsigned char exportOBJModel(T_RSPMODEL_OBJECT* hob_objects, const char *out_path, T_PROG_OPTIONS* p_opts);
|
||||
unsigned char exportOBJModel(T_RSPMODEL_OBJECT* hob_objects, const char *out_path, void* hmt_struct, T_PROG_OPTIONS* p_opts);
|
||||
|
||||
#endif /* MODEL_EXPORT_H_ */
|
||||
|
@ -17,10 +17,12 @@ typedef union u_prog_options {
|
||||
unsigned char debug_mode:1; //!< Output all values of faces, indices and vertices and others "heavy" things.
|
||||
unsigned char god_mode:1; //!< Dev only. Output experimental values.
|
||||
|
||||
unsigned char texture_module:1; //!< Set if RSPTextureLib module is present and loaded.
|
||||
|
||||
unsigned char output_dir:1; //!< Export extracted datas to a sub-directory.
|
||||
unsigned char export_mtl:1; //!< Export materials datas with object.
|
||||
|
||||
unsigned short reserved0:11; //!< For future use.
|
||||
unsigned short reserved0:10; //!< For future use.
|
||||
|
||||
unsigned short input_files_cnt; //!< Internal files counters.
|
||||
};
|
||||
|
@ -51,7 +51,7 @@ typedef struct vertex { short x,y,z,w; } T_VERTEX;
|
||||
#endif
|
||||
|
||||
#ifndef T_TEXCOORD
|
||||
typedef struct tex_coord { unsigned short u,v; } T_TEXCOORD;
|
||||
typedef struct tex_coord { short u,v; } T_TEXCOORD;
|
||||
#endif
|
||||
|
||||
typedef struct face_flags {
|
||||
|
@ -152,6 +152,10 @@ static unsigned short ExtractObjects(T_RSPMODEL_HOB* pHobStruct, const MEMFILE p
|
||||
+ 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");
|
||||
|
||||
@ -210,6 +214,7 @@ static unsigned short ExtractObjParts(T_RSPMODEL_OBJECT* pObject, const MEMFILE
|
||||
+ 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);
|
||||
@ -269,7 +274,7 @@ static unsigned short ExtractObjParts_faces(T_RSPMODEL_OBJ_PARTS* pObjPart, cons
|
||||
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 FaceGroup part----------------------\n");
|
||||
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
|
||||
@ -355,7 +360,7 @@ static unsigned short ExtractObjParts_faces(T_RSPMODEL_OBJ_PARTS* pObjPart, cons
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (pParams->debug_mode) printf("\n-----------------------End of FaceGroup part-----------------------\n");
|
||||
if (pParams->debug_mode) printf("\n-----------------------End of Face part-----------------------\n");
|
||||
}
|
||||
|
||||
// Get vertex datas
|
||||
|
@ -33,6 +33,17 @@
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* - Global HOB file structure-
|
||||
* +------------------+--------------------------------------+----------------------------------------+
|
||||
* | T_HOBFILE_HEADER | obj_count * T_HOBFILE_OBJ_DESCRIPTOR | obj_count * T_HOBFILE_FACEGROUP_HEADER |
|
||||
* +------------------+--------------------------------------+----------------------------------------+
|
||||
*
|
||||
* - Facegroup sub-structure -
|
||||
* +----------------------------+------------------------------------------------+
|
||||
* | T_HOBFILE_FACEGROUP_HEADER | object_part_count * T_HOBFILE_FACEGROUP_OFFSET |
|
||||
* +----------------------------+------------------------------------------------+
|
||||
*/
|
||||
typedef struct PACK hobfile_header {
|
||||
unsigned int obj_count;
|
||||
unsigned int vertices_offset;
|
||||
@ -169,7 +180,7 @@ typedef struct PACK hobfile_faceblock {
|
||||
|
||||
typedef struct PACK hobfile_faces_header {
|
||||
unsigned int flags;
|
||||
unsigned char b1;
|
||||
unsigned char b1; // 74 = transparent / 75 = opaque
|
||||
unsigned char b2;
|
||||
unsigned char b3;
|
||||
unsigned char faceBlockIntSize; // Bytes size divided by 4, count as number of UInt32 type.
|
||||
|
246
RSPModelLib/src/hob_struct2.h
Normal file
246
RSPModelLib/src/hob_struct2.h
Normal file
@ -0,0 +1,246 @@
|
||||
/**
|
||||
* @file hob_struct.h
|
||||
* @date 26/07/2022
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief HOB file mapping definition.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RSPMODELLIB_HOB_STRUCT_H_
|
||||
#define RSPMODELLIB_HOB_STRUCT_H_
|
||||
|
||||
|
||||
/*
|
||||
* long = 64bits???
|
||||
* int = 32bits
|
||||
* short = 16bits
|
||||
* car = 8bits
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define PACK
|
||||
#elif defined(__GNUC__)
|
||||
#define PACK __attribute__((packed))
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declaration of Memory Mapped Structure
|
||||
// Caution: the place of variable is important for correct mapping!
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* - Global HOB file structure-
|
||||
* +------------------+--------------------------------------+----------------------------------------+
|
||||
* | T_HOBFILE_HEADER | obj_count * T_HOBFILE_OBJ_DESCRIPTOR | obj_count * T_HOBFILE_FACEGROUP_HEADER | -->
|
||||
* +------------------+--------------------------------------+----------------------------------------+
|
||||
*
|
||||
* - Facegroup sub-structure -
|
||||
* +------------------------------+--------------------------------------------------+
|
||||
* --> | T_HOBFILE_FACEGROUP_HEADER_1 | object_part_count * T_HOBFILE_FACEGROUP_OFFSET_1 |
|
||||
* +------------------------------+--------------------------------------------------+
|
||||
*
|
||||
* - Facegroup sub-structure 2 -
|
||||
* +------------------------------+------------------------------------------------------------------------+--------------------------------------------------------+
|
||||
* | T_HOBFILE_FACEGROUP_HEADER_2 | ( object_part_count + facegroup_count ) * T_HOBFILE_FACEGROUP_OFFSET_2 | ( object_part_count - 1 ) * T_HOBFILE_FACEGROUP_NAMEID | + padding
|
||||
* +------------------------------+------------------------------------------------------------------------+--------------------------------------------------------+
|
||||
*/
|
||||
typedef struct PACK hobfile_header {
|
||||
unsigned int obj_count;
|
||||
unsigned int vertices_offset;
|
||||
} T_HOBFILE_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_obj_header {
|
||||
unsigned char object_name[16]; // Name of the object
|
||||
|
||||
unsigned int facegroup_start_offset; // First facegroup datas offset. Look in T_HOBFILE_FACEGROUP_HEADER for all offsets of facegroups of the current object.
|
||||
unsigned int object_parts_offset; // Object parts descriptor offset
|
||||
unsigned int object_parts_offset2; // Facegroup descriptor offset (subpart of Object parts descriptor)
|
||||
|
||||
unsigned int opt_offset1; // Optional offset - empty on last obj_header - point to after end mask ffffff of current bloc
|
||||
unsigned int opt_offset2; // Optional offset - empty on last obj_header - point to after the previous opt_offset1
|
||||
unsigned int reserved1; // Always zeros ?
|
||||
|
||||
unsigned int subparts_namelist_offset; // Point to an array of string value (8 chars) + ID (2 chars - 1 to obj_parts-1). Seem like name of articulation points (some have name like "node_86").
|
||||
unsigned int effects_offset; // Empty in gun_turret and no datas after, xwing have 0x5006. worddevastator should have the answer...
|
||||
unsigned int properties_offset; // Offset to different string (a_b/zf/zt/zb/etc.) Animation datas ? Empty with 6x float in train_hob
|
||||
|
||||
float unknown4; // Probably scale: 1.0F/1.125F
|
||||
|
||||
unsigned int reserved4; // 12B of zeros
|
||||
unsigned int reserved5;
|
||||
unsigned int reserved6;
|
||||
|
||||
float unknown5; //Scale? ~20.0F
|
||||
float unknown6; //Scale? ~77-418.0F
|
||||
|
||||
float reserved7; //Translation matrix? Center of object?
|
||||
float reserved8;
|
||||
float reserved9;
|
||||
|
||||
unsigned int footer_offset; //To redefine, seem to be a copy of following bounding box? Maybe there are 2 box: render and collision?
|
||||
|
||||
float bbox_start_x; // Bounding box start vector
|
||||
float bbox_start_y;
|
||||
float bbox_start_z;
|
||||
|
||||
float bbox_end_x; // Bounding box start vector
|
||||
float bbox_end_y;
|
||||
float bbox_end_z;
|
||||
} T_HOBFILE_OBJ_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_header_1 {
|
||||
unsigned short object_part_count;
|
||||
unsigned short facegroup_count;
|
||||
} T_HOBFILE_FACEGROUP_HEADER_1;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_offset_1 {
|
||||
unsigned int unknown0; // Flags?
|
||||
unsigned int facegroup_offset;
|
||||
} T_HOBFILE_FACEGROUP_OFFSET_1;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_header_2 {
|
||||
unsigned short object_part_count;
|
||||
unsigned short facegroup_count;
|
||||
} T_HOBFILE_FACEGROUP_HEADER_2;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_offset_2 {
|
||||
unsigned int unknownOffset0;
|
||||
} T_HOBFILE_FACEGROUP_OFFSET_2;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_nameid {
|
||||
unsigned char name[8];
|
||||
unsigned short id;
|
||||
} T_HOBFILE_FACEGROUP_NAMEID;
|
||||
|
||||
typedef struct PACK hobfile_meshdef0 {
|
||||
unsigned int offset1;
|
||||
unsigned int offset2;
|
||||
unsigned int prev_meshdef0_offset;
|
||||
unsigned int next_meshdef0_offset;
|
||||
unsigned int meshdef1_offset_plus_4;
|
||||
|
||||
unsigned int reserved1; // 8B of zeros
|
||||
unsigned int reserved2;
|
||||
|
||||
float unknown3;
|
||||
|
||||
unsigned int reserved3; // 12B of zeros
|
||||
unsigned int reserved4;
|
||||
unsigned int reserved5;
|
||||
|
||||
float unknown4;
|
||||
|
||||
unsigned int reserved6; // 12B of zeros
|
||||
unsigned int reserved7;
|
||||
unsigned int reserved8;
|
||||
|
||||
float unknown5;
|
||||
|
||||
unsigned int reserved9; // 12B of zeros
|
||||
unsigned int reserved10;
|
||||
unsigned int reserved11;
|
||||
|
||||
unsigned int object_id;
|
||||
|
||||
float unknown12; // Can be a vector???
|
||||
float unknown13;
|
||||
float unknown14;
|
||||
|
||||
float unknown15; // Can be a vector???
|
||||
float unknown16;
|
||||
float unknown17;
|
||||
|
||||
float unknown18; // Can be a matrix???
|
||||
float unknown19;
|
||||
float unknown20;
|
||||
float unknown21;
|
||||
|
||||
float transform_x;
|
||||
float transform_y;
|
||||
float transform_z;
|
||||
} T_HOBFILE_MESHDEF0;
|
||||
|
||||
typedef struct PACK hobfile_meshdef1 {
|
||||
unsigned int facedef_end_offset;
|
||||
|
||||
unsigned int reserved1; // 20B of zeros
|
||||
unsigned int reserved2;
|
||||
unsigned int reserved3;
|
||||
unsigned int reserved4;
|
||||
unsigned int reserved5;
|
||||
|
||||
unsigned int vertex_count;
|
||||
unsigned int unknown1;
|
||||
unsigned int reserved6;
|
||||
unsigned int faceblock_offset;
|
||||
unsigned int vertexblocks_offset;
|
||||
|
||||
unsigned int reserved7; // 52B of zeros
|
||||
unsigned int reserved8;
|
||||
unsigned int reserved9;
|
||||
unsigned int reserved10;
|
||||
unsigned int reserved11;
|
||||
unsigned int reserved12;
|
||||
unsigned int reserved13;
|
||||
unsigned int reserved14;
|
||||
unsigned int reserved15;
|
||||
unsigned int reserved16;
|
||||
unsigned int reserved17;
|
||||
unsigned int reserved18;
|
||||
unsigned int reserved19;
|
||||
} T_HOBFILE_MESHDEF1;
|
||||
|
||||
typedef struct PACK hobfile_faceblock {
|
||||
unsigned int reserved1; // 8B of zeros
|
||||
unsigned int reserved2;
|
||||
|
||||
unsigned int facesOffset;
|
||||
unsigned int faceCounts;
|
||||
} T_HOBFILE_FACEBLOCK;
|
||||
|
||||
typedef struct PACK hobfile_faces_header {
|
||||
unsigned int flags;
|
||||
unsigned char b1; // 74 = transparent / 75 = opaque
|
||||
unsigned char b2;
|
||||
unsigned char b3;
|
||||
unsigned char faceBlockIntSize; // Bytes size divided by 4, count as number of UInt32 type.
|
||||
unsigned short headerSeparator;
|
||||
unsigned short materialIndex;
|
||||
unsigned short vertexIndices[4]; // Relative to facegroup, the last value is equal to 0 when it's triangle shape.
|
||||
} T_HOBFILE_FACES_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_vertex_color {
|
||||
T_RGBA v1_rgba;
|
||||
T_RGBA v2_rgba;
|
||||
T_RGBA v3_rgba;
|
||||
T_RGBA v4_rgba; // Used with quad type face
|
||||
} T_HOBFILE_FACES_VERTEX_COLOR;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_color {
|
||||
T_RGBA rgba;
|
||||
} T_HOBFILE_FACES_COLOR;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_vertex_texture {
|
||||
T_TEXCOORD v1_texcoord; // Should be divided (no shifting) by 4096 to get 0...1 range
|
||||
T_TEXCOORD v2_texcoord;
|
||||
T_TEXCOORD v3_texcoord;
|
||||
T_TEXCOORD v4_texcoord; // Used with quad type face
|
||||
} T_HOBFILE_FACES_VERTEX_TEXTURE;
|
||||
|
||||
typedef struct PACK hobfile_vertex {
|
||||
short x;
|
||||
short y;
|
||||
short z;
|
||||
short w;
|
||||
} T_HOBFILE_VERTEX;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#endif /* RSPMODELLIB_HOB_STRUCT_H_ */
|
Loading…
x
Reference in New Issue
Block a user