diff --git a/.gitignore b/.gitignore index 25478cc..0f2e944 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,8 @@ # Precompiled Headers *.gch *.pch -RSPTerrainLib/src/config.h -RSETerrain/src/config.h +RSPTextureLib/src/config.h +RSETexture/src/config.h # Libraries *.lib diff --git a/CMakeLists.txt b/CMakeLists.txt index cf1ceb5..152d9d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ if(DEFINED ENV{CI}) # Jenkins CI integration mode project(rse-texture VERSION $ENV{CI_VERSION}.$ENV{CI_BUILD_NUMBER} DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C) set(RSE_TEXTURE_NAME $ENV{CI_OUTPUT_NAME}) else() # Standalone project mode, should not be used for release. - project(rse-texture VERSION 2.0.0 DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C) + project(rse-texture VERSION 2.1.0 DESCRIPTION "RogueSquadron Extractor - Texture" LANGUAGES C) set(RSE_TEXTURE_NAME RSETexture) endif() set(RSP_TEXTURE_LIB_NAME RSPTexture${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR}) diff --git a/Jenkinsfile b/Jenkinsfile index 594a860..5ac09a1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,7 +5,7 @@ pipeline { } environment { CI_OUTPUT_NAME = "RSETexture" - CI_VERSION = "2.0.1" + CI_VERSION = "2.1.0" CI_BUILD_NUMBER = "$BUILD_NUMBER" } stages { diff --git a/RSPTextureLib/include/RSPTexture.h b/RSPTextureLib/include/RSPTexture.h index f208531..f7544f4 100644 --- a/RSPTextureLib/include/RSPTexture.h +++ b/RSPTextureLib/include/RSPTexture.h @@ -54,6 +54,8 @@ extern "C" { */ RSPTEXTURE_EXTERN char* RSPTexture_getVersion( void ); +RSPTEXTURE_EXTERN T_RSPTEXTURE_HMT* RSPTexture_createHMT( void ); + /** * @brief Run texture parser for the specified file in file system. * @details Texture library can process HMT file from file system. It's a easy @@ -88,6 +90,26 @@ RSPTEXTURE_EXTERN unsigned short RSPTexture_processHMTFileMemory( const RSPTEXTURE_PARAMETERS params ); +/** + * @brief Parse HMT materials for specific ID. + * @pre HMT structure should be processed with RSPTexture_processHMTFile() + * or RSPTexture_processHMTMemFile() before. + * + * @param[in] pHmt HMT texture structure to be analyzed. + * @param[in] mat_id ID of the material. + * + * @return Pointer to T_RSPTEXTURE_MATERIAL if found or NULL otherwise. + */ +RSPTEXTURE_EXTERN T_RSPTEXTURE_MATERIAL* RSPTexture_getMaterialFromID( + const T_RSPTEXTURE_HMT* pHmt, const unsigned short mat_id + ); + +RSPTEXTURE_EXTERN char* RSPTexture_getMaterialName( const T_RSPTEXTURE_MATERIAL* mat ); + +RSPTEXTURE_EXTERN float RSPTexture_getMaterialOpacity( const T_RSPTEXTURE_MATERIAL* mat ); + +RSPTEXTURE_EXTERN float RSPTexture_getMaterialAmbient( const T_RSPTEXTURE_MATERIAL* mat ); + /** * @brief Clean HMT object and it's childrens from memory. * @param[in] hmtStruct Pointer to data to be cleaned up. diff --git a/RSPTextureLib/include/RSPTexture_datatypes.h b/RSPTextureLib/include/RSPTexture_datatypes.h index 0c0dce7..2477a4e 100644 --- a/RSPTextureLib/include/RSPTexture_datatypes.h +++ b/RSPTextureLib/include/RSPTexture_datatypes.h @@ -44,15 +44,13 @@ typedef struct r8g8b8 { unsigned char r,g,b; } T_R8G8B8; typedef struct r8g8b8a8 { unsigned char r,g,b,a; } T_R8G8B8A8; #endif +typedef enum e_mat_type { + RSPTEX_MAT_TYPE_TEXTURED = 1, + RSPTEX_MAT_TYPE_SOLID = 2 +} RSPTEX_MAT_TYPE; + typedef unsigned char T_SAMPLE; -typedef struct rsptexture_material { - unsigned char name[17]; // 16 + 1 string ending \0 - unsigned short type; - - unsigned short texture_index; //TODO: pointer to a T_RSPTEXTURE_TEXTURE element? -} T_RSPTEXTURE_MATERIAL; - typedef struct rsptexture_texture { unsigned char name[17]; // 16 + 1 string ending \0 unsigned short width; @@ -61,15 +59,22 @@ typedef struct rsptexture_texture { unsigned char type; unsigned char sample_bits; unsigned int palette_entries; - T_R8G8B8A8 alpha_color; - unsigned int palette_offset; //TODO: useless? - unsigned int pixels_offset; //TODO: useless? - T_R8G8B8A8* pixels; } T_RSPTEXTURE_TEXTURE; +typedef struct rsptexture_material { + unsigned short id; + unsigned char name[17]; // 16 + 1 string ending \0 + RSPTEX_MAT_TYPE type; + + float opacity; //TODO: temporary, need to be defined + float ambient; //TODO: temporary, need to be defined + + T_RSPTEXTURE_TEXTURE* texture; +} T_RSPTEXTURE_MATERIAL; + typedef struct rsptexture_hmt { unsigned int materials_count; unsigned int textures_count; diff --git a/RSPTextureLib/src/RSPTexture.c b/RSPTextureLib/src/RSPTexture.c index e32518e..f207b73 100644 --- a/RSPTextureLib/src/RSPTexture.c +++ b/RSPTextureLib/src/RSPTexture.c @@ -1,6 +1,6 @@ /** * @file RSPTexture.c - * @date 25/08/2022 + * @date 31/08/2022 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief HMT textures datas parser and export to PNG format. @@ -17,10 +17,20 @@ #include "RSPTexture.h" +/* + * Libs interface + */ inline char* RSPTexture_getVersion( void ) { return PRG_VERSION; } +/* + * HMT parser + */ +T_RSPTEXTURE_HMT* RSPTexture_createHMT( void ) { + return calloc(1, sizeof(T_RSPTEXTURE_HMT)); +} + unsigned short RSPTexture_processHMTFile( T_RSPTEXTURE_HMT* hmtStruct, const char* const filePath, const RSPTEXTURE_PARAMETERS params ) { @@ -37,7 +47,35 @@ unsigned short RSPTexture_processHMTFileMemory( T_RSPTEXTURE_HMT* hmtStruct, con return RSP_TextureLib_ParseHMTMemFile((MEMFILE)memFilePtr, hmtStruct, ¶ms); } -void RSPTexture_freeHMT(T_RSPTEXTURE_HMT* hmtStruct) { +/* + * Material utilities + */ +T_RSPTEXTURE_MATERIAL* RSPTexture_getMaterialFromID( const T_RSPTEXTURE_HMT* pHmt, const unsigned short mat_id ) { + if ( pHmt == NULL ) return NULL; + if ( pHmt->materials == NULL ) return NULL; + + return &(pHmt->materials[mat_id]); +} + +char* RSPTexture_getMaterialName( const T_RSPTEXTURE_MATERIAL* mat ) { + if ( mat == NULL ) return NULL; + + return (char*)mat->name; +} + +float RSPTexture_getMaterialOpacity( const T_RSPTEXTURE_MATERIAL* mat ) { + if ( mat == NULL ) return 1.0; + + return mat->opacity; +} + +float RSPTexture_getMaterialAmbient( const T_RSPTEXTURE_MATERIAL* mat ) { + if ( mat == NULL ) return 1.0; + + return mat->ambient; +} + +void RSPTexture_freeHMT( T_RSPTEXTURE_HMT* hmtStruct ) { unsigned int i; if (hmtStruct == NULL) return; diff --git a/RSPTextureLib/src/config.h b/RSPTextureLib/src/config.h deleted file mode 100644 index 9b62256..0000000 --- a/RSPTextureLib/src/config.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef CONFIG_H_ -#define CONFIG_H_ - -#define PRG_VERSION "2.0.0" - -#endif /* CONFIG_H_ */ diff --git a/RSPTextureLib/src/hmt_parser.c b/RSPTextureLib/src/hmt_parser.c index 51f33cc..21afbc2 100644 --- a/RSPTextureLib/src/hmt_parser.c +++ b/RSPTextureLib/src/hmt_parser.c @@ -117,14 +117,15 @@ static unsigned short ExtractTextureHMT(T_RSPTEXTURE_HMT* pHmtStruct, const MEMF if (pParams->verbose_mode) printf("[DBG] > Texture offset: 0x%X\n", pHmtStruct->texture_offset); printf("\n"); - // Get materials if any - if (pHmtStruct->materials_count > 0) - errorCode |= ExtractMaterials(pHmtStruct, pMemfile, pParams); - // Get textures if any if (pHmtStruct->textures_count > 0) errorCode |= ExtractTextures(pHmtStruct, pMemfile, pParams); + // Get materials if any and link them to texture + if (pHmtStruct->materials_count > 0) + errorCode |= ExtractMaterials(pHmtStruct, pMemfile, pParams); + + return errorCode; } @@ -156,19 +157,35 @@ static unsigned short ExtractMaterials(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMe // Get material datas pHmt->materials[i].type = ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->type; - pHmt->materials[i].texture_index = ((T_HMTFILE_MATERIAL *)(pMemfile + - sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->texture_index; // Texture index is only for texture "type" (1) + pHmt->materials[i].id = ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->texture_index; + // If material is textured, the linked texture correspond to tex_index in textures array. + if (pHmt->materials[i].type == RSPTEX_MAT_TYPE_TEXTURED) pHmt->materials[i].texture = pHmt->textures + pHmt->materials[i].id; + else pHmt->materials[i].texture = NULL; + pHmt->materials[i].opacity = ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved1; + pHmt->materials[i].ambient = ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved0; if (pParams->verbose_mode) { printf("[INFO] > Material name: %s\n", pHmt->materials[i].name); printf("[INFO] > Material type: %d\n", pHmt->materials[i].type); - printf("[INFO] > Material text. index: %d (valid if type == 1)\n", pHmt->materials[i].texture_index); + printf("[INFO] > Material id: %d\n", pHmt->materials[i].id); + printf("[INFO] > Material text. index: %d\n", i); + if (pHmt->materials[i].type == RSPTEX_MAT_TYPE_TEXTURED) + printf("[INFO] > Linked texture name: %s (should correspond to material name)\n", pHmt->materials[i].texture->name); } + + /* + * Unassigned generic material datas : + * - Transparent + * - Ambient (global) + * - Diffuse (environnement) + * - Specular (self) + */ if (pParams->debug_mode) { - printf("[DBG] > Material reserved0: %.8f\n", ((T_HMTFILE_MATERIAL *)(pMemfile + - sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved0); - printf("[DBG] > Material reserved1: %.8f\n", ((T_HMTFILE_MATERIAL *)(pMemfile + - sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved1); + printf("[DBG] > Material reserved0: %.8f\n", pHmt->materials[i].ambient); + printf("[DBG] > Material reserved1: %.8f\n", pHmt->materials[i].opacity); printf("[DBG] > Material reserved2 (zero): 0x%X\n", ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved2); printf("[DBG] > Material reserved3 (0xA): 0x%X\n", ((T_HMTFILE_MATERIAL *)(pMemfile + @@ -193,6 +210,7 @@ static unsigned short ExtractMaterials(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMe static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMemfile, const RSPTEXTURE_PARAMETERS* pParams) { T_R8G8B8* _palette = NULL; T_SAMPLE* _samples = NULL; + unsigned int palette_offset, pixels_offset; unsigned int i; if (pHmt == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL; @@ -245,9 +263,9 @@ static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMem sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.transparent_color, sizeof(T_R8G8B8A8)); // Get texture datas offsets - pHmt->textures[i].pixels_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + pixels_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->pixels_offset; - pHmt->textures[i].palette_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + palette_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->palette_offset; // Get texture name @@ -268,8 +286,8 @@ static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMem printf("[DBG] > Texture unknown0: 0x%X\n", ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.unknown0); if (((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.reserved0 != 1) printf("[DBG] > Texture: Always 1 different.\n"); - printf("[DBG] > Texture palette offset: 0x%X\n", pHmt->textures[i].palette_offset); - printf("[DBG] > Texture pixels offset: 0x%X\n", pHmt->textures[i].pixels_offset); + printf("[DBG] > Texture palette offset: 0x%X\n", palette_offset); + printf("[DBG] > Texture pixels offset: 0x%X\n", pixels_offset); } // Retrieve palette datas from HMT file @@ -278,7 +296,7 @@ static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMem case 256: _palette = (T_R8G8B8 *)realloc(_palette, sizeof(T_R8G8B8) * pHmt->textures[i].palette_entries); if (_palette) - memcpy(_palette, pMemfile + pHmt->textures[i].palette_offset, sizeof(T_R8G8B8) * pHmt->textures[i].palette_entries); + memcpy(_palette, pMemfile + palette_offset, sizeof(T_R8G8B8) * pHmt->textures[i].palette_entries); else return RSPLIB_ERROR_MEMORY; break; default: @@ -289,7 +307,7 @@ static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMem //TODO: better approach? _samples = (T_SAMPLE *)realloc(_samples, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / 8); if (_samples) { - memcpy(_samples, pMemfile + pHmt->textures[i].pixels_offset, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / 8); + memcpy(_samples, pMemfile + pixels_offset, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / 8); //if (pHmt->textures[i].type == 2) memcpy(pHmt->textures[i].samples, pMemfile + pHmt->textures[i].pixels_offset, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / (8 * 4)); //TODO: manage texture type 2 } else return RSPLIB_ERROR_MEMORY; diff --git a/RSPTextureLib/src/hmt_struct.h b/RSPTextureLib/src/hmt_struct.h index 2a4cf18..3fb0b20 100644 --- a/RSPTextureLib/src/hmt_struct.h +++ b/RSPTextureLib/src/hmt_struct.h @@ -46,10 +46,10 @@ typedef struct PACK hmtfile_material { unsigned short type; // 1 - Material with texture / 2 - Material without texture unsigned short texture_index; - float reserved0; // misc. - float reserved1; // Always 1.0f + float reserved0; // misc. Diffuse? Transparent? + float reserved1; // Always 1.0f Ambient? - unsigned int reserved2; // Zero + unsigned int reserved2; // Zero Specular? unsigned int reserved3; // 0x0A unsigned char name[16];