RSE-Terrain/RSETerrain/src/RSETerrain.c
JackCarterSmith ebfd3faeaa
All checks were successful
JCS-Prod/RSE-Terrain/pipeline/head This commit looks good
Fix HMP deallocation
2023-02-05 15:26:49 +01:00

220 lines
6.5 KiB
C

/**
* @file RSETerrain.c
* @date 23/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief HMP terrain parser and export to Waveform OBJ format and grey-scale PNG heightmap.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "options.h"
#include <RSPTerrain.h>
#include <RSPTerrain_errordefs.h>
#include "terrain_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 short 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*~[ Rogue Squadron Extractor (RSE) - RSPTerrainLib v%s ]~*\n", RSPTerrain_getVersion());
// Check for arguments
if (argc < 2) {
printf("\n[ERR] No input file/commands specified!\n");
dispHelp();
return RSPLIB_ERROR_ARGS_NULL;
}
// Create options for programs according to user's arguments.
p = checkInputArgs(&_opts, argc, argv);
if ( p == RSPLIB_ERROR_GENERIC ) return RSPLIB_SUCCESS;
else if ( p != RSPLIB_SUCCESS ) 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;
RSPTERRAIN_PARAMETERS libParams;
T_RSPTERRAIN_HMP* hmpStruct = NULL;
T_RSPTERRAIN_HEIGHTMAP* terrainHM = NULL;
T_RSPTERRAIN_MESH* terrainMesh = NULL;
libParams.raw = p_opts->raw & 0x7;
libParams.negative = p_opts->negative_HM; // Invert it by default to correspond to in-game rendering
libParams.invertZ = !p_opts->inverted_Z; // Invert it by default to correspond to in-game rendering
// 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]);
// Allocate T_RSPTERRAIN_HMP structure to store extracted datas.
hmpStruct = calloc(1, sizeof(T_RSPTERRAIN_HMP));
if (hmpStruct) {
// Parse data from HMP file and put in T_RSPTERRAIN_HMP structure.
if (RSPTerrain_processHMPFile(hmpStruct, args_value[file_index], libParams) != RSPLIB_SUCCESS) {
printf("[ERR] Failed to parse datas from %s\n", args_value[file_index]);
RSPTerrain_freeHMP(hmpStruct);
free(hmpStruct);
return RSPLIB_ERROR_PROCESS;
}
} else return RSPLIB_ERROR_MEMORY;
// Create output folders structure.
if (p_opts->output_dir) createSubDir(args_value[file_index]);
// Allocate terrain full heighmap format
terrainHM = calloc(1, sizeof(T_RSPTERRAIN_HEIGHTMAP));
if (terrainHM) {
if (RSPTerrain_terrainToHeightmap(terrainHM, hmpStruct) == RSPLIB_SUCCESS) {
// Export terrain as a PNG greyscale heightmap
if (exportHeightmapPNG(terrainHM, args_value[file_index], p_opts) == RSPLIB_SUCCESS)
printf("[INFO] Successfully exported heightmap to PNG format.\n");
else
printf("[ERR] Failed to export heightmap to PNG format!\n");
} else {
printf("[ERR] Failed to process tilesmap to heightmap!\n");
}
RSPTerrain_freeHeightmap(terrainHM);
} else {
RSPTerrain_freeHMP(hmpStruct);
free(hmpStruct);
return RSPLIB_ERROR_MEMORY;
}
// Allocate mesh object for 3D terrain generation
//#ifndef TEXTURE_MODULE TODO: Next version: detect presence of external library to manage texture handling...
terrainMesh = calloc(1, sizeof(T_RSPTERRAIN_MESH));
if (terrainMesh) {
if (RSPTerrain_terrainToMesh(terrainMesh, hmpStruct, TERRAIN_MESH_SCALE) == RSPLIB_SUCCESS) {
// Export terrain as a blank OBJ terrain
if (exportHeightmapOBJ(terrainMesh, args_value[file_index], p_opts) == RSPLIB_SUCCESS)
printf("[INFO] Successfully exported terrain in OBJ format.\n");
else
printf("[ERR] Failed to export terrain in OBJ format!\n");
} else {
printf("[ERR] Failed to process tilesmap to mesh!\n");
}
RSPTerrain_freeMesh(terrainMesh);
} else {
RSPTerrain_freeHMP(hmpStruct);
free(hmpStruct);
return RSPLIB_ERROR_MEMORY;
}
//#endif
RSPTerrain_freeHMP(hmpStruct);
free(hmpStruct);
}
return RSPLIB_SUCCESS;
}
static unsigned short 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;
opt_ptr->export_mtl = 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 RSPLIB_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->verbose_mode = 1;
opt_ptr->debug_mode = 1;
printf("[OPTN] Debug enabled.\n");
} else if (strcmp(p_args[i], "-vvv") == 0) {
opt_ptr->verbose_mode = 1;
opt_ptr->debug_mode = 1;
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], "-no-mtl") == 0) {
opt_ptr->export_mtl = 0;
printf("[OPTN] Export to current directory.\n");
} else if (strcmp(p_args[i], "-invZ") == 0) {
opt_ptr->inverted_Z = 1;
printf("[OPTN] Invert Z axis.\n");
} else if (strcmp(p_args[i], "-neg") == 0) {
opt_ptr->negative_HM = 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 RSPLIB_SUCCESS;
}
return RSPLIB_ERROR_ARGS_NULL;
}
static void createSubDir(char *dirName) {
if (dirName == NULL) return;
char _dir[1024];
snprintf(_dir, 1024, "%s-out", dirName);
#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(" -no-mtl Disable texture exporting\n");
printf(" -invZ Invert Z axis when parsing\n");
printf(" -neg Negative heightmap output\n");
printf("\n");
printf("Usage: RSE-Terrain [options] <hmp_file>\n");
printf("\n");
}