Add texture mtl exporting pre-release #17

Merged
JackCarterSmith merged 4 commits from external-lib into master 2022-09-07 21:17:31 +02:00
12 changed files with 592 additions and 72 deletions

View File

@ -20,7 +20,7 @@ if(DEFINED ENV{CI}) # Jenkins CI integration mode
project(rse-model VERSION $ENV{CI_VERSION}.$ENV{CI_BUILD_NUMBER} DESCRIPTION "RogueSquadron Extractor - Model" LANGUAGES C)
set(RSE_MODEL_NAME $ENV{CI_OUTPUT_NAME})
else() # Standalone project mode, should not be used for release.
project(rse-model VERSION 2.1.0 DESCRIPTION "RogueSquadron Extractor - Model" LANGUAGES C)
project(rse-model VERSION 2.2.0 DESCRIPTION "RogueSquadron Extractor - Model" LANGUAGES C)
set(RSE_MODEL_NAME RSEModel)
endif()
set(RSP_MODEL_LIB_NAME RSPModel${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR})

2
Jenkinsfile vendored
View File

@ -5,7 +5,7 @@ pipeline {
}
environment {
CI_OUTPUT_NAME = "RSEModel"
CI_VERSION = "2.1.1"
CI_VERSION = "2.2.0"
CI_BUILD_NUMBER = "$BUILD_NUMBER"
}
stages {

View File

@ -12,14 +12,21 @@
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#include <io.h>
#define F_OK 0
#define access _access
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include "options.h"
#include <RSPModel.h>
#include <RSPModel_errordefs.h>
#include "model_export.h"
#include "lib_interface.h"
#define MAX_STR_VAR 1024
/*
@ -36,15 +43,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 +65,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 +81,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[MAX_STR_VAR] = {0};
void* hmtStruct = NULL;
unsigned int i;
libParams.raw = p_opts->raw & 0x7;
@ -84,6 +101,23 @@ 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) {
if (strlen(args_value[file_index]) >= MAX_STR_VAR) return RSPLIB_ERROR_GENERIC;
strncpy(hmt_filename, args_value[file_index], strlen(args_value[file_index]) - 3);
hmt_filename[strlen(args_value[file_index]) - 1] = 0; //C6053 fix
strncat(hmt_filename, "HMT", strlen(args_value[file_index]));
if (access(hmt_filename, F_OK) == 0) {
hmtStruct = RSPTexture_createHMT();
RSPTexture_processHMTFile(hmtStruct, hmt_filename, 0);
} else {
printf("[ERR] HMT file '%s' not found for mtl processing!\n", hmt_filename);
return RSPLIB_ERROR_GENERIC;
}
}
} else return RSPLIB_ERROR_MEMORY;
if (hobStruct->obj_count > 0) {
@ -91,12 +125,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 +145,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 +170,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]);
}

View File

@ -0,0 +1,122 @@
/**
* @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 <windows.h>
#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
}

View 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 "21"
#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_ */

View File

@ -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);

View File

@ -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_ */

View File

@ -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.
};

View File

@ -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 {

View File

@ -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

View File

@ -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.

View 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_ */