From a7bf7303efb6b04958cb5805106e89b843b4ee3a Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Sun, 31 Jul 2022 21:02:57 +0200 Subject: [PATCH] HMP parser and PNG exporter --- .gitmodules | 3 + CMakeLists.txt | 4 +- src/Image_Exporter.c | 72 ----------------- src/Image_Exporter.h | 12 --- src/Map-Extractor.c | 133 -------------------------------- src/Map-Extractor.h | 26 ------- src/Terrain-Extractor.c | 167 ++++++++++++++++++++++++++++++++++++++++ src/errors_types.h | 28 +++++++ src/hmp_export.c | 91 ++++++++++++++++++++++ src/hmp_export.h | 14 ++++ src/hmp_parser.c | 137 ++++++++++++++++++++++++++++++++ src/hmp_parser.h | 18 +++++ src/hmp_struct.h | 85 ++++++++++++++++++++ src/options.h | 34 +++++++- src/rlk | 1 + 15 files changed, 576 insertions(+), 249 deletions(-) create mode 100644 .gitmodules delete mode 100644 src/Image_Exporter.c delete mode 100644 src/Image_Exporter.h delete mode 100644 src/Map-Extractor.c delete mode 100644 src/Map-Extractor.h create mode 100644 src/Terrain-Extractor.c create mode 100644 src/errors_types.h create mode 100644 src/hmp_export.c create mode 100644 src/hmp_export.h create mode 100644 src/hmp_parser.c create mode 100644 src/hmp_parser.h create mode 100644 src/hmp_struct.h create mode 160000 src/rlk diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..cc9feb4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/rlk"] + path = src/rlk + url = https://github.com/rlk/obj.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fa2850..950991e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,8 +27,8 @@ find_package(ZLIB 1.2.11 EXACT REQUIRED) include_directories(${ZLIB_INCLUDE_DIR}) find_package(PNG 1.6.37 EXACT REQUIRED) include_directories(${PNG_INCLUDE_DIR}) -#find_package(GLEW REQUIRED) -#include_directories(${GLEW_INCLUDE_DIR}) +find_package(GLEW REQUIRED) +include_directories(${GLEW_INCLUDE_DIR}) # define src/headers files diff --git a/src/Image_Exporter.c b/src/Image_Exporter.c deleted file mode 100644 index dd43284..0000000 --- a/src/Image_Exporter.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "Image_Exporter.h" - - -int saveToPNG(RS_IMAGE *img, char *tex_path, char *hmt_fileName) { - if (tex_path == NULL || img == NULL) return EXIT_FAILURE; - char export_path[128]; - FILE *_png_f = NULL; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - size_t x,y; - png_byte **row_ptrs = NULL; - PIXEL_A *pixel = NULL; - //int pixel_size = 3; - //int depth = 8; //bit par color channel (RGB) - - if (_options & OUTPUT_DIR) { - strcpy(export_path, hmt_fileName); - #ifdef _WIN32 - strcat(export_path, "-out\\"); - #else - strcat(export_path, "-out/"); - #endif - strcat(export_path, tex_path); - } else { - strcpy(export_path, tex_path); - } - strcat(export_path, ".png"); - _png_f = fopen(export_path, "wb"); - if (_png_f == NULL) return EXIT_FAILURE; - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) { - fclose(_png_f); - return EXIT_FAILURE; - } - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - fclose(_png_f); - return EXIT_FAILURE; - } - - // Set image attributes - png_set_IHDR(png_ptr, info_ptr, img->width, img->height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - // Init PNG datas - row_ptrs = png_malloc(png_ptr, img->height * sizeof(png_byte *)); - for (y=0; yheight; y++) { - png_byte *row = png_malloc(png_ptr, img->width*sizeof(PIXEL_A)); - row_ptrs[y] = row; - for (x=0; xwidth; x++) { - pixel = pixelAt(img, x , y); - if(pixel == NULL) return EXIT_FAILURE; - - *row++ = pixel->_red; - *row++ = pixel->_green; - *row++ = pixel->_blue; - *row++ = pixel->_alpha; - } - } - - png_init_io(png_ptr, _png_f); - png_set_rows(png_ptr, info_ptr, row_ptrs); - png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - for (y=0; yheight; y++) { - png_free(png_ptr, row_ptrs[y]); - } - png_free(png_ptr, row_ptrs); - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(_png_f); - - return EXIT_SUCCESS; -} diff --git a/src/Image_Exporter.h b/src/Image_Exporter.h deleted file mode 100644 index d0ff59f..0000000 --- a/src/Image_Exporter.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef IMAGE_EXPORTER_H_ -#define IMAGE_EXPORTER_H_ - -#include "options.h" -#include "RS_images.h" -#include -#include - - -int saveToPNG(RS_IMAGE *img, char *tex_name, char *hmt_fileName); - -#endif diff --git a/src/Map-Extractor.c b/src/Map-Extractor.c deleted file mode 100644 index 796a06d..0000000 --- a/src/Map-Extractor.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - ================================================================================ - Name : Map-Extractor.c - Author : JackCarterSmith - License : GPL-v3.0 - Description : DAT textures extractor to PNG format with enhanced function in C - ================================================================================ - */ - -#include "Map-Extractor.h" - - -int _options; // Global options settings variable - -int main(int argc, char *argv[]) { - // Init buffer vars - HMT_FILE *hmt_fdatas = NULL; - int file_index; - - printf("\n*** RogueSquadron Extractor (RSE) - MAP module - v%s ***\n", VERSION); - - // Check if filenames arguments exist - if (argc < 2) { - printf("\n[ERR] No input file/commands specified!\n"); - dispHelp(); - return EXIT_FAILURE; //TODO: implement own error codes system - } - _options = checkArgs(argv, argc); // Analyse program arguments - if (_options == -1) return EXIT_SUCCESS; - - // Do the work - for (file_index=(_options >> 8) & 0xFF; file_index 1) { - for (i=1; itexture_count > 0) { - if (_options & OUTPUT_DIR) createSubDir(filename); - for (i=0; itexture_count; i++) { - switch (hmt_f->textures_list[i].image.type_) { - case 0: - case 1: - case 3: - case 4: - case 5: - if (saveToPNG(&(hmt_f->textures_list[i].image), hmt_f->textures_list[i].name, filename)) { - printf("[ERR] Failed saving image file: %s\n", hmt_f->textures_list[i].name); - return EXIT_FAILURE; - } else printf("[INFO] Saved image file: %s\n", hmt_f->textures_list[i].name); - break; - default: - printf("[WARN] Can't export %s ! Image type %d not currently supported! (WIP)\n", hmt_f->textures_list[i].name, hmt_f->textures_list[i].image.type_); - } - - } - } - - return EXIT_SUCCESS; -} - -void dispHelp() { - printf("\n"); - printf("Options:\n -h Print this message\n -v Activate verbose console output\n -no-subdir Extract textures inside current folder\n"); - printf("\n"); - printf("Usage: RSE-Texture_%s [options] \n", VERSION); - printf("\n"); -} diff --git a/src/Map-Extractor.h b/src/Map-Extractor.h deleted file mode 100644 index 1311701..0000000 --- a/src/Map-Extractor.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef MAP_EXTRACTOR_H_ -#define MAP_EXTRACTOR_H_ - -#include -#include -#include -#if defined(_WIN32) - #include -#else - #include - #include -#endif -#include "config.h" -#include "options.h" -#include "HMT_Parser.h" -#include "RS_images.h" -#include "Image_Exporter.h" - - -void createSubDir(char *dirName); -int checkArgs(char *args[], int arg_nbr); -HMT_FILE *extractDatasFromHMT(char* hmt_filename); -int exportTextures(HMT_FILE *hmt_f, char *filename); -void dispHelp(); - -#endif diff --git a/src/Terrain-Extractor.c b/src/Terrain-Extractor.c new file mode 100644 index 0000000..420a60f --- /dev/null +++ b/src/Terrain-Extractor.c @@ -0,0 +1,167 @@ +/** + * \file Terrain-Extractor.c + * \date 31/07/2022 + * \author JackCarterSmith + * \copyright GPL-v3.0 + * \brief Terrain file (hmp) parser with option to export to both Waveform OBJ format and grey-scale PNG heightmap. + */ + +#include +#include +#include +#if defined(_WIN32) + #include +#else + #include + #include +#endif +#include "errors_types.h" +#include "config.h" +#include "options.h" +#include "hmp_struct.h" +#include "hmp_parser.h" +#include "hmp_export.h" + + +/* + * Internal functions declarations + */ + +static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* opt_ptr); +static void createSubDir(char *dirName); +static unsigned char checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]); +static void dispHelp(); + + +/* + * - MAIN - + */ +int main(int argc, char *argv[]) { + T_PROG_OPTIONS _opts; + unsigned char p; + + // Hello world! + printf("\n*** RogueSquadron Extractor (RSE) - TERRAIN module - v%s ***\n", VERSION); + + // Check for arguments + if (argc < 2) { + printf("\n[ERR] No input file/commands specified!\n"); + dispHelp(); + return ERROR_ARGS_NULL; + } + + // Create options for programs according to user's arguments. + p = checkInputArgs(&_opts, argc, argv); + if ( p == ERROR_GENERIC ) return NO_ERROR; + else if ( p != NO_ERROR ) return p; + + return mainProcess(argc, argv, &_opts); +} + + +/* + * Private functions definition + */ + +static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* p_opts) { + unsigned short file_index; + T_TERRAIN* terrainStruct = NULL; + + // Manage multiple inputs files + for ( file_index = p_opts->input_files_cnt; file_index < args_cnt; file_index++) + { + printf("\n=============================================\n[INFO] - Parsing file: %s ...\n", args_value[file_index]); + terrainStruct = calloc(1, sizeof(T_TERRAIN)); + // Parse data from HOB file and put in T_HOB structure. + if (parseHMPFile(args_value[file_index], terrainStruct, p_opts) != NO_ERROR) { + printf("[ERR] Failed to parse datas from %s\n", args_value[file_index]); + free(terrainStruct); + return ERROR_PROCESS; + } + + if (p_opts->output_dir) createSubDir(args_value[file_index]); + + if (exportHeightmapPNG(terrainStruct, args_value[file_index], p_opts) != NO_ERROR) + printf("[ERR] Failed to export heightmap to PNG format!\n"); + else + printf("[INFO] Successfully exported heightmap to PNG format.\n"); + /* + for ( i = 0; i < hobStruct->obj_count; i++ ) { + if (exportOBJModel(&(hobStruct->objects[i]), args_value[file_index], p_opts) != NO_ERROR) + printf("[ERR] Failed to export %s object in OBJ format!\n", hobStruct->objects[i].name); + else + printf("[INFO] Successfully exported %s object in OBJ format.\n", hobStruct->objects[i].name); + } + */ + + cleanUpResources(terrainStruct); + } + + return NO_ERROR; +} + +static unsigned char checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]) { + char test[256]; + int i; + + // Set default options + opt_ptr->raw = 0; + opt_ptr->output_dir = 1; + + if (p_arg_nbr > 1) { + for ( i = 1; i < p_arg_nbr; i++) { + strcpy(test, p_args[i]); + if (p_args[i][0] != '-') break; + if (strcmp(p_args[i], "-h") == 0) { + dispHelp(); + return ERROR_GENERIC; + } else if (strcmp(p_args[i], "-v") == 0) { + opt_ptr->verbose_mode = 1; + printf("[OPTN] Verbose enabled.\n"); + } else if (strcmp(p_args[i], "-vv") == 0) { + opt_ptr->debug_mode = 1; + printf("[OPTN] Debug enabled.\n"); + } else if (strcmp(p_args[i], "-vvv") == 0) { + opt_ptr->god_mode = 1; + printf("[OPTN] God damn it!\n"); + } else if (strcmp(p_args[i], "-no-subdir") == 0) { + opt_ptr->output_dir = 0; + printf("[OPTN] Export to current directory.\n"); + } else if (strcmp(p_args[i], "-neg") == 0) { + opt_ptr->neg_heightmap = 1; + printf("[OPTN] Negative heightmap output mode.\n"); + } else { + printf("[ERR] Unknown option: %s\n", p_args[i]); + } + } + + opt_ptr->input_files_cnt = i; + return NO_ERROR; + } + + return ERROR_ARGS_NULL; +} + +static void createSubDir(char *dirName) { + if (dirName == NULL) return; + char _dir[260]; //TODO: Change directory management + strcpy(_dir, dirName); + strcat(_dir, "-out"); + + #ifdef _WIN32 + CreateDirectory(_dir, NULL); + #else + mkdir(_dir, 0755); + #endif +} + +static void dispHelp() { + printf("\n"); + printf("Options:\n -h Print this message\n"); + printf(" -v -vv Activate verbose console output\n"); + printf(" -no-subdir Export models inside current folder\n"); + printf(" -neg Negative heightmap output\n"); + printf("\n"); + printf("Usage: RSE-Terrain_%s [options] \n", VERSION); + printf("\n"); +} diff --git a/src/errors_types.h b/src/errors_types.h new file mode 100644 index 0000000..6d101ab --- /dev/null +++ b/src/errors_types.h @@ -0,0 +1,28 @@ +/* + * errors_types.h + * + * Created on: 26 juil. 2022 + * Author: JackCarterSmith + */ + +//#include "error.h" //TODO: use it as base for error ID + + +#ifndef SRC_ERRORS_TYPES_H_ +#define SRC_ERRORS_TYPES_H_ + +#ifdef NO_ERROR +#undef NO_ERROR +#endif +#define NO_ERROR 0 +#define ERROR_GENERIC 1 +#define ERROR_MEMORY 2 +#define ERROR_IO 3 +#define ERROR_PROCESS 4 + +#define ERROR_ARGS_NULL 10 +#define ERROR_ARGS_RANGE 11 + +#define ERROR_REALITY_BROKED -1 + +#endif /* SRC_ERRORS_TYPES_H_ */ diff --git a/src/hmp_export.c b/src/hmp_export.c new file mode 100644 index 0000000..3faaa55 --- /dev/null +++ b/src/hmp_export.c @@ -0,0 +1,91 @@ +/** + * \file hmp_export.c + * \date 31/07/2022 + * \author JackCarterSmith + * \copyright GPL-v3.0 + * \brief Export datas to heightmap PNG and Waveform OBJ format. + */ + +#include +#include +#include +#include +#include +#include "errors_types.h" +#include "options.h" +#include "hmp_struct.h" +#include "hmp_export.h" + + +unsigned char exportHeightmapPNG(const T_TERRAIN* terrain, const char *out_path, T_PROG_OPTIONS* p_opts) { + if (out_path == NULL || terrain == NULL) return ERROR_ARGS_NULL; + char export_path[128]; + FILE *_png_f = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + size_t x,y; + png_byte **row_ptrs = NULL; + //int pixel_size = 3; + //int depth = 8; //bit par color channel (RGB) + + strcpy(export_path, out_path); + if (p_opts->output_dir) { + #ifdef _WIN32 + strcat(export_path, "-out\\"); + #else + strcat(export_path, "-out/"); + #endif + strcat(export_path, "heightmap.png"); + } else { + strcat(export_path, "-heightmap.png"); + } + + _png_f = fopen(export_path, "wb"); + if (_png_f == NULL) return ERROR_MEMORY; + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + fclose(_png_f); + return ERROR_MEMORY; + } + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + fclose(_png_f); + return ERROR_MEMORY; + } + + // Set image attributes + png_set_IHDR(png_ptr, info_ptr, terrain->width * TILE_HEIGHT_TUNE, terrain->height * TILE_HEIGHT_TUNE, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // Store PNG datas + row_ptrs = png_malloc(png_ptr, terrain->height * TILE_HEIGHT_TUNE * sizeof(png_byte *)); + for ( y = 0; y < terrain->height * TILE_HEIGHT_TUNE; y++ ) { + png_byte *row = png_malloc(png_ptr, terrain->width * TILE_HEIGHT_TUNE * sizeof(unsigned char) * 3); + row_ptrs[y] = row; + for ( x = 0; x < terrain->width * TILE_HEIGHT_TUNE; x++ ) { + // Invert Y to display 0,0 origin at bottom left of image + *row++ = terrain->heightmap[x][terrain->height * TILE_HEIGHT_TUNE - 1 - y]; + *row++ = terrain->heightmap[x][terrain->height * TILE_HEIGHT_TUNE - 1 - y]; + *row++ = terrain->heightmap[x][terrain->height * TILE_HEIGHT_TUNE - 1 - y]; + + // Normal one struc + /* + *row++ = terrain->heightmap[x][y]; + *row++ = terrain->heightmap[x][y]; + *row++ = terrain->heightmap[x][y]; + */ + } + } + + png_init_io(png_ptr, _png_f); + png_set_rows(png_ptr, info_ptr, row_ptrs); + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + for ( y = 0; y < terrain->height * TILE_HEIGHT_TUNE; y++ ) { + png_free(png_ptr, row_ptrs[y]); + } + png_free(png_ptr, row_ptrs); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(_png_f); + + return EXIT_SUCCESS; +} diff --git a/src/hmp_export.h b/src/hmp_export.h new file mode 100644 index 0000000..162c7d5 --- /dev/null +++ b/src/hmp_export.h @@ -0,0 +1,14 @@ +/** + * \file hmp_export.h + * \date 31/07/2022 + * \author JackCarterSmith + * \copyright GPL-v3.0 + * \brief Export datas to heightmap PNG and Waveform OBJ format. + */ + +#ifndef SRC_HMP_EXPORT_H_ +#define SRC_HMP_EXPORT_H_ + +unsigned char exportHeightmapPNG(const T_TERRAIN* terrain, const char* out_path, T_PROG_OPTIONS* p_opts); + +#endif /* SRC_HMP_EXPORT_H_ */ diff --git a/src/hmp_parser.c b/src/hmp_parser.c new file mode 100644 index 0000000..20dbcb6 --- /dev/null +++ b/src/hmp_parser.c @@ -0,0 +1,137 @@ +/** + * \file hmp_parser.c + * \date 31/07/2022 + * \author JackCarterSmith + * \copyright GPL-v3.0 + * \brief Decode terrain file (hmp) structure. + */ + +#include +#include +#include +#include "errors_types.h" +#include "options.h" +#include "hmp_struct.h" +#include "hmp_parser.h" + + +static void processTilesToHeightmap(T_TERRAIN* terrain, const T_TILE_INDICES* tiles_indices, + const T_HMPFILE_TILE* tiles, const unsigned char negativeOutput); + +unsigned char parseHMPFile(const char* fileName, T_TERRAIN* hmp_struct, T_PROG_OPTIONS* p_opts) { + unsigned char err = NO_ERROR; + long fileSize; + FILE* fStream = NULL; + char* memFile = NULL; + + float y_scale = 1.0; + unsigned int tiles_offset = 0; + T_TILE_INDICES* tiles_indices = NULL; + T_HMPFILE_TILE* tiles = NULL; + + if (hmp_struct != NULL && fileName != NULL) { + // Open file + fStream = fopen(fileName, "rb"); + + if (fStream != NULL) { + // Determine file size in bytes + fseek(fStream, 0, SEEK_END); + fileSize = ftell(fStream); + fseek(fStream, 0, SEEK_SET); + if (p_opts->verbose_mode) printf("[DBG] > Input file size: %ld bytes\n\n", fileSize); + + memFile = malloc(fileSize + 1); + if (memFile != NULL) { + // Copy file in RAM + fread(memFile, fileSize, 1, fStream); + fclose(fStream); + + // Get header infos + y_scale = ((T_HMPFILE_HEADER *)memFile)->height_scale; + tiles_offset = ((T_HMPFILE_HEADER *)memFile)->tiles_start_offset; + hmp_struct->width = ((T_HMPFILE_HEADER *)memFile)->width_BLK; + hmp_struct->height = ((T_HMPFILE_HEADER *)memFile)->height_BLK; + + if (p_opts->verbose_mode) { + printf("[DBG] > Height scale: %.8f\n", y_scale); + printf("[DBG] > Tiles count: %d\n", ((T_HMPFILE_HEADER *)memFile)->tiles_count); + printf("[DBG] > Tiles offset: 0x%X\n", tiles_offset); + printf("\n"); + } + if (p_opts->god_mode) { + printf("[DBG] > Unknown0: %d\n", ((T_HMPFILE_HEADER *)memFile)->unknown0); + printf("[DBG] > Unknown1: %d\n", ((T_HMPFILE_HEADER *)memFile)->unknown1); + printf("\n"); + } + + // Get tiles indices + tiles_indices = malloc(hmp_struct->width * hmp_struct->height * sizeof(unsigned short)); + memcpy(tiles_indices, memFile + sizeof(T_HMPFILE_HEADER), + hmp_struct->width * hmp_struct->height * sizeof(unsigned short)); + + // Get tiles datas + tiles = malloc(((T_HMPFILE_HEADER *)memFile)->tiles_count * sizeof(T_HMPFILE_TILE)); + memcpy(tiles, memFile + tiles_offset, ((T_HMPFILE_HEADER *)memFile)->tiles_count * sizeof(T_HMPFILE_TILE)); + + // Convert tiles datas to raw heightmap + processTilesToHeightmap(hmp_struct, tiles_indices, tiles, p_opts->neg_heightmap); + free(tiles); + + free(tiles_indices); + free(memFile); + + } else { + fclose(fStream); + err = ERROR_MEMORY; + printf("[ERR] Can't allocate enough memory for file processing!\n"); + } + } else { + err = ERROR_IO; + printf("[ERR] Input file %s not found!\n", fileName); + } + } else err = ERROR_ARGS_NULL; + + return err; +} + +void cleanUpResources(T_TERRAIN* terrain) { + unsigned int i; + + if (terrain == NULL) return; + + for ( i = 0; i < terrain->width * TILE_HEIGHT_TUNE; i++ ) + free(terrain->heightmap[i]); + + free(terrain->heightmap); + free(terrain); +} + +static void processTilesToHeightmap(T_TERRAIN* terrain, const T_TILE_INDICES* tiles_indices, const T_HMPFILE_TILE* tiles, const unsigned char negativeOutput) { + T_TILE_INDICES tiles_idx; + unsigned int i,j,k,l; + unsigned int heightmap_size_w = terrain->width * TILE_HEIGHT_TUNE; + unsigned int heightmap_size_h = terrain->height * TILE_HEIGHT_TUNE; + + // Build 2D array to contain height values + terrain->heightmap = (unsigned char **)malloc(heightmap_size_w * sizeof(unsigned char *)); + for ( i = 0; i < heightmap_size_w; i++ ) { + terrain->heightmap[i] = (unsigned char *)malloc(heightmap_size_h * sizeof(unsigned char)); + } + + // Select tile + for ( i = 0; i < terrain->width; i++ ) { + for ( j = 0; j < terrain->height; j++ ) { + tiles_idx = tiles_indices[j * terrain->width + i]; + + // Get the 5x5 bytes height values for this tile + for ( k = 0; k < TILE_HEIGHT_TUNE; k++ ) { + for ( l = 0; l < TILE_HEIGHT_TUNE; l++ ) { + if (negativeOutput) + terrain->heightmap[i*TILE_HEIGHT_TUNE+k][j*TILE_HEIGHT_TUNE+l] = 255 - (tiles[tiles_idx].height_values[l][k] + 128); + else + terrain->heightmap[i*TILE_HEIGHT_TUNE+k][j*TILE_HEIGHT_TUNE+l] = tiles[tiles_idx].height_values[l][k] + 128; + } + } + } + } +} diff --git a/src/hmp_parser.h b/src/hmp_parser.h new file mode 100644 index 0000000..3cfbba6 --- /dev/null +++ b/src/hmp_parser.h @@ -0,0 +1,18 @@ +/** + * \file hmp_parser.h + * \date 31/07/2022 + * \author JackCarterSmith + * \copyright GPL-v3.0 + * \brief Decode terrain file (hmp) structure. + */ + +#include "hmp_struct.h" + + +#ifndef SRC_HOB_PARSER_H_ +#define SRC_HOB_PARSER_H_ + +unsigned char parseHMPFile(const char* fileName, T_TERRAIN* hmp_struct, T_PROG_OPTIONS* p_opts); +void cleanUpResources(T_TERRAIN* terrain); + +#endif /* SRC_HOB_PARSER_H_ */ diff --git a/src/hmp_struct.h b/src/hmp_struct.h new file mode 100644 index 0000000..b82fe79 --- /dev/null +++ b/src/hmp_struct.h @@ -0,0 +1,85 @@ +/* + * hmp_struct.h + * + * Created on: 31 juil. 2022 + * Author: JackCarterSmith + */ + +#ifndef SRC_HMP_STRUCT_H_ +#define SRC_HMP_STRUCT_H_ + + +/* + * long = 64bits??? (8 Bytes) + * int = 32bits (4 Bytes) + * short = 16bits (2 Bytes) + * car = 8bits (1 Bytes) + */ + +#if defined(_MSC_VER) +#define PACK +#elif defined(__GNUC__) +#define PACK __attribute__((packed)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// HMP file structure +/////////////////////////////////////////////////////////////////////////////// + +typedef struct vector3 { float x,y,z; } T_VECTOR3; +typedef T_VECTOR3 T_VERTEX; + +typedef struct terrain { + unsigned short width; // Dimension of the height/vertices map + unsigned short height; + + unsigned char** heightmap; + T_VERTEX* verticesmap; +} T_TERRAIN ; + + +/////////////////////////////////////////////////////////////////////////////// +// Declaration of Memory Mapped Structure +// Caution: the place of variable is important for correct mapping! +/////////////////////////////////////////////////////////////////////////////// + +#if defined(_MSC_VER) +#pragma pack(push, 1) +#endif + +typedef struct PACK hmpfile_header { + unsigned int reserved0; //12B of zeros + unsigned int reserved1; + unsigned int reserved2; + + float reserved3; // Always 0x3F000000 + float height_scale; + float reserved4; // Always 0x3F000000 + + unsigned short tiles_count; + unsigned short unknown0; + + unsigned int tiles_start_offset; + unsigned int unknown1; // Offset to some datas? + + unsigned short width_BLK; + unsigned short height_BLK; +} T_HMPFILE_HEADER; + +typedef unsigned short T_TILE_INDICES; + +typedef struct PACK hmpfile_tile { + unsigned short texmap_id; + + unsigned char unknown0; + unsigned char low_height; // LOD application? Clipping? Terrain render quadrants? + unsigned char high_height; + + unsigned char height_values[5][5]; // first and last row/column overlap with a neighboring tile, "glue" for tiles, need to be identical to avoid "hill" effect +} T_HMPFILE_TILE; + +#if defined(_MSC_VER) +#pragma pack(pop) +#endif + +#endif /* SRC_HMP_STRUCT_H_ */ diff --git a/src/options.h b/src/options.h index 904c2d3..5376a2c 100644 --- a/src/options.h +++ b/src/options.h @@ -1,9 +1,35 @@ +/** + * \file options.h + * \date 29/07/2022 + * \author JackCarterSmith + * \copyright GPL-v3.0 + * \brief Shared options structure definition and declaration. + */ + #ifndef OPTIONS_H_ #define OPTIONS_H_ -#define VERBOSE_ENABLED 0x0001 -#define OUTPUT_DIR 0x0002 +// Number of height values to take for computing terrain (default: 4) +#define TILE_HEIGHT_TUNE 4 -extern int _options; +/// Options structure +typedef union u_prog_options { + struct { + unsigned char verbose_mode:1; //!< Output simple details about ID and other "light" things. -#endif + unsigned char output_dir:1; //!< Export extracted datas to a sub-directory. + unsigned char neg_heightmap:1; //!< Enable negative heightmap output. + + unsigned char reserved0:6; //!< For future use. + + 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 reserved1:6; //!< For future use. + + unsigned short input_files_cnt; //!< Internal files counters. + }; + unsigned int raw; //!< Raw options access for bit-masking or memory copy/compare. +} T_PROG_OPTIONS ; + +#endif /* OPTIONS_H_ */ diff --git a/src/rlk b/src/rlk new file mode 160000 index 0000000..48a6916 --- /dev/null +++ b/src/rlk @@ -0,0 +1 @@ +Subproject commit 48a6916526d043691bb3f9e38676fbc99995da10