Add texture mtl exporting pre-release #17
@ -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
2
Jenkinsfile
vendored
@ -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 {
|
||||
|
@ -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]);
|
||||
}
|
||||
|
122
RSEModel/src/lib_interface.c
Normal file
122
RSEModel/src/lib_interface.c
Normal 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
|
||||
}
|
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 "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_ */
|
@ -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