New library version of the RS parser #7

Merged
JackCarterSmith merged 4 commits from develop into master 2022-08-24 18:54:17 +02:00
34 changed files with 3967 additions and 3198 deletions

3
.gitignore vendored
View File

@ -15,7 +15,8 @@
# Precompiled Headers # Precompiled Headers
*.gch *.gch
*.pch *.pch
src/config.h RSPTerrainLib/src/config.h
RSETerrain/src/config.h
# Libraries # Libraries
*.lib *.lib

6
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "src/rlk"] [submodule "RSETerrain/src/obj"]
path = src/rlk path = RSETerrain/src/obj
url = https://github.com/rlk/obj.git url = https://git.jcsmith.fr/jackcartersmith/obj.git

View File

@ -14,72 +14,65 @@ if(DEFINED ENV{MS_COMPATIBLE})
set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries
endif() endif()
include(CheckIncludeFile)
include(CheckCSourceCompiles)
add_definitions(-DCONF_NO_GL) # Used for obj-lib to not compile GL part
#add_definitions(-DNO_PNG_SUPPORT) # Can be used to disable code support for PNG exporting
# Project definition # Project definition
if(DEFINED ENV{CI}) # Jenkins CI integration mode if(DEFINED ENV{CI}) # Jenkins CI integration mode
project(rse-terrain VERSION $ENV{CI_VERSION}.$ENV{CI_BUILD_NUMBER} DESCRIPTION "RogueSquadron Extractor - Terrain" LANGUAGES C) project(rse-terrain VERSION $ENV{CI_VERSION}.$ENV{CI_BUILD_NUMBER} DESCRIPTION "RogueSquadron Extractor - Terrain" LANGUAGES C)
set(RSE_TER_NAME $ENV{CI_OUTPUT_NAME}-${PROJECT_VERSION}) set(RSE_TERRAIN_NAME $ENV{CI_OUTPUT_NAME})
else() # Standalone project mode, should not be used for release. else() # Standalone project mode, should not be used for release.
project(rse-terrain VERSION 1.0.0 DESCRIPTION "RogueSquadron Extractor - Terrain" LANGUAGES C) project(rse-terrain VERSION 2.0.0 DESCRIPTION "RogueSquadron Extractor - Terrain" LANGUAGES C)
set(RSE_TER_NAME RSE_Terrain-${PROJECT_VERSION}) set(RSE_TERRAIN_NAME RSETerrain)
endif() endif()
set(RSP_TERRAIN_LIB_NAME RSPTerrain${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
# Compilation option
option(RSPTERRAIN_SHARED "Build shared lib" ON)
# Push compile infos to source # Push compile infos to source
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/config.h @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/RSPTerrainLib/src/config.h @ONLY)
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/RSETerrain/src/config.h @ONLY)
# Import needed packages and references their include path # The project is divided in two parts:
find_package(ZLIB 1.2.12 REQUIRED) # - RSPTerrainLib is the parser library for terrain type data, it's take hmp file as input and output extracted datas.
include_directories(${ZLIB_INCLUDE_DIR}) # It is intended to be used by others apps like rendering engine or others.
find_package(PNG 1.6.37 REQUIRED) # - RSETerrain is the standalone application of the library, take hmp file in argument and output OBJ/MTL file.
include_directories(${PNG_INCLUDE_DIR}) # Artists or users can directly use this program to retrieve data in common datas format.
#find_package(GLEW REQUIRED) # Enable when GL rendering is ready set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
#include_directories(${GLEW_INCLUDE_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
add_subdirectory(RSPTerrainLib)
# Define src/headers files add_subdirectory(RSETerrain)
FILE(GLOB_RECURSE RSE_TER_SOURCES src/*.c)
FILE(GLOB_RECURSE RSE_TER_HEADERS src/*.h)
SOURCE_GROUP("Source Files" FILES ${RSE_TER_SOURCES})
SOURCE_GROUP("Header Files" FILES ${RSE_TER_HEADERS})
# Building instructions for RSE-Terrain
if(DEFINED ENV{RSE-WS})
set(CMAKE_BUILD_TYPE DEBUG)
endif()
#include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(rse-terrain ${RSE_TER_SOURCES} ${RSE_TER_HEADERS}) # Set the inputs for the compiler (srcs&hrds)
set_property(TARGET rse-terrain PROPERTY C_STANDARD 90)
set_target_properties(rse-terrain PROPERTIES OUTPUT_NAME ${RSE_TER_NAME}) # Define the executable file name
# Link externals libraries to the linker
if(MSVC)
# msvc does not append 'lib' - do it here to have consistent name
#set_target_properties(rse-terrain PROPERTIES PREFIX "lib")
set_target_properties(rse-terrain PROPERTIES IMPORT_PREFIX "lib")
target_link_libraries(rse-terrain ${ZLIB_LIBRARIES} ${PNG_LIBRARIES} ${GLEW_LIBRARIES})
else()
target_link_libraries(rse-terrain ${ZLIB_LIBRARIES} ${PNG_LIBRARIES} ${GLEW_LIBRARIES} m)
endif()
# GPG signature custom command # GPG signature custom command
#add_custom_command( #add_custom_command(
# OUTPUT "" # OUTPUT ""
# COMMAND gpg --batch --detach-sign # COMMAND gpg --batch --detach-sign
# -o ${RSE_TER_NAME}_${CI_SYS_TARGET}.gpg # -o ${RSE_MOD_NAME}_${CI_SYS_TARGET}.gpg
# ${RSE_TER_NAME} # ${RSE_MOD_NAME}
# DEPENDS ${RSE_TER_NAME} # DEPENDS ${RSE_MOD_NAME}
# VERBATIM # VERBATIM
#) #)
# Install project executable # Install project executable
install(TARGETS rse-terrain set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
RUNTIME DESTINATION bin set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
if(RSPTERRAIN_SHARED)
set(RSE_TERRAIN_TARGETS_LIST rse-terrain rsp-terrain-lib rsp-terrain-libstatic)
else()
set(RSE_TERRAIN_TARGETS_LIST rse-terrain rsp-terrain-libstatic)
endif()
install(TARGETS ${RSE_TERRAIN_TARGETS_LIST}
RUNTIME DESTINATION ${INSTALL_BIN_DIR}
LIBRARY DESTINATION ${INSTALL_LIB_DIR}
ARCHIVE DESTINATION ${INSTALL_LIB_DIR}
) )
# Install library includes
install(FILES ${RSP_PUBLIC_HRDS} DESTINATION ${INSTALL_INC_DIR})
# Install dependancies
install(FILES ${PROJECT_BINARY_DIR}/bin/glew32.dll ${PROJECT_BINARY_DIR}/bin/libpng16.dll ${PROJECT_BINARY_DIR}/bin/zlib1.dll
DESTINATION ${INSTALL_BIN_DIR})

25
Jenkinsfile vendored
View File

@ -4,8 +4,8 @@ pipeline {
skipDefaultCheckout(true) skipDefaultCheckout(true)
} }
environment { environment {
CI_OUTPUT_NAME = "RSE_Terrain" CI_OUTPUT_NAME = "RSETerrain"
CI_VERSION = "1.0.0" CI_VERSION = "2.0.0"
CI_BUILD_NUMBER = "$BUILD_NUMBER" CI_BUILD_NUMBER = "$BUILD_NUMBER"
} }
stages { stages {
@ -23,7 +23,7 @@ pipeline {
checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RSE-Terrain'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RSE-Terrain.git']]]) checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RSE-Terrain'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RSE-Terrain.git']]])
sh 'git submodule update --init --recursive' sh 'git submodule update --init --recursive'
dir("build") { dir("build") {
rtConanRun(clientId: "conan", command: "install .. --build missing") rtConanRun(clientId: "conan", command: "install .. --build=missing")
} }
cmakeBuild buildDir: 'build', installation: 'latest', steps: [[args: 'all']] cmakeBuild buildDir: 'build', installation: 'latest', steps: [[args: 'all']]
} }
@ -33,9 +33,9 @@ pipeline {
checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RSE-Terrain'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RSE-Terrain.git']]]) checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RSE-Terrain'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RSE-Terrain.git']]])
sh 'git submodule update --init --recursive' sh 'git submodule update --init --recursive'
dir("build") { dir("build") {
rtConanRun(clientId: "conan", command: "install .. --profile windows --build missing") rtConanRun(clientId: "conan", command: "install .. --profile=windows --build=missing")
} }
cmakeBuild buildDir: 'build', cmakeArgs: '-DGNU_HOST=x86_64-w64-mingw32 -DCMAKE_TOOLCHAIN_FILE=../mingw_cross_toolchain.cmake', installation: 'latest', steps: [[args: 'all']] cmakeBuild buildDir: 'build', cmakeArgs: '-DGNU_HOST=x86_64-w64-mingw32 -DCMAKE_TOOLCHAIN_FILE=../cmake/mingw_cross_toolchain.cmake', installation: 'latest', steps: [[args: 'all']]
} }
} }
) )
@ -44,24 +44,23 @@ pipeline {
stage('Deploy') { stage('Deploy') {
steps { steps {
dir("zip_linux") { dir("zip_linux") {
sh 'cp ../linux/build/${CI_OUTPUT_NAME}-${CI_VERSION}.${BUILD_NUMBER}* .' sh 'cp -R ../linux/build/bin ../linux/build/lib ../linux/RSPTerrainLib/include .'
} }
dir("zip_win") { dir("zip_win") {
sh 'cp ../windows/build/${CI_OUTPUT_NAME}-${CI_VERSION}.${BUILD_NUMBER}* ../windows/build/*.dll .' sh 'cp -R ../windows/build/bin ../windows/build/lib ../windows/RSPTerrainLib/include .'
} }
zip archive: false, dir: 'zip_linux', exclude: '', glob: '', zipFile: 'x64.zip' zip archive: false, dir: 'zip_linux', exclude: '', glob: '', zipFile: 'linux_x64.zip'
sh 'mv x64.zip ${CI_OUTPUT_NAME}-${CI_VERSION}.${BUILD_NUMBER}_x64.zip' sh 'mv linux_x64.zip ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_Linux_x86_64.zip'
zip archive: false, dir: 'zip_win', exclude: '', glob: '', zipFile: 'mingw64.zip' zip archive: false, dir: 'zip_win', exclude: '', glob: '', zipFile: 'mingw64.zip'
sh 'mv mingw64.zip ${CI_OUTPUT_NAME}-${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip' sh 'mv mingw64.zip ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip'
archiveArtifacts(artifacts: '*.zip') archiveArtifacts(artifacts: '*.zip')
fingerprint(targets: '*.zip') fingerprint(targets: '*.zip')
} }
} }
stage('Sign') { stage('Sign') {
steps { steps {
sh 'ls -l' sh 'gpg --batch --detach-sign -o ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_Linux_x86_64.zip.gpg ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_Linux_x86_64.zip'
sh 'gpg --batch --detach-sign -o ${CI_OUTPUT_NAME}-${CI_VERSION}.${BUILD_NUMBER}_x64.zip.gpg ${CI_OUTPUT_NAME}-${CI_VERSION}.${BUILD_NUMBER}_x64.zip' sh 'gpg --batch --detach-sign -o ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip.gpg ${CI_OUTPUT_NAME}_${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip'
sh 'gpg --batch --detach-sign -o ${CI_OUTPUT_NAME}-${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip.gpg ${CI_OUTPUT_NAME}-${CI_VERSION}.${BUILD_NUMBER}_mingw64.zip'
archiveArtifacts(artifacts: '*.gpg') archiveArtifacts(artifacts: '*.gpg')
fingerprint(targets: '*.gpg') fingerprint(targets: '*.gpg')
} }

73
LICENSE-glew Normal file
View File

@ -0,0 +1,73 @@
The OpenGL Extension Wrangler Library
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
Copyright (C) 2002, Lev Povalahev
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
Mesa 3-D graphics library
Version: 7.0
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Copyright (c) 2007 The Khronos Group Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and/or associated documentation files (the
"Materials"), to deal in the Materials without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Materials, and to
permit persons to whom the Materials are furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Materials.
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

View File

@ -23,12 +23,11 @@ This module can do:
- Add textures to terrain. - Add textures to terrain.
- Adding LOD method to optimize datas manipulation and rendering. - Adding LOD method to optimize datas manipulation and rendering.
- Rewrite OBJ lib...
- Discover all last unknowns fields, etc. - Discover all last unknowns fields, etc.
### Using ### Using
`RSE-Terrain_"version" [options] <hob files...>` or you can simply drag&drop HOB files on it. `RSETerrain [options] <hob files...>` or you can simply drag&drop HOB files on it.
A futur main program can extract all HOB files directly from DAT file. A futur main program can extract all HOB files directly from DAT file.
Due to issue with copyrights, I can't provide samples... You need to extract HOB files yourself. Due to issue with copyrights, I can't provide samples... You need to extract HOB files yourself.
@ -44,12 +43,10 @@ Due to issue with copyrights, I can't provide samples... You need to extract HOB
### Dependencies ### Dependencies
- obj-lib: as obj file exporter. (https://github.com/rlk/obj) - obj-lib: as obj file exporter. (https://git.jcsmith.fr/jackcartersmith/obj)
### Compiling ### Compiling
:mega: **MSVC compatibility is in progress. Not working for now but you can try to fix error by yourself.**
You can compile on both Windows (MinGW) or native Linux system thanks to CMake, you only need to adjust your dependencies on Windows or use Conan packages manager (https://conan.io). You can compile on both Windows (MinGW) or native Linux system thanks to CMake, you only need to adjust your dependencies on Windows or use Conan packages manager (https://conan.io).
zlib-dev (zlib1g-dev) and libpng16-dev distrib packages can be used on debian/ubuntu. zlib-dev (zlib1g-dev) and libpng16-dev distrib packages can be used on debian/ubuntu.
@ -80,7 +77,7 @@ We can also use cross-compilation (after installing `mingw64` and `cmake` packag
```shell ```shell
mkdir build && cd build mkdir build && cd build
cmake -DGNU_HOST=x86_64-w64-mingw32 \ cmake -DGNU_HOST=x86_64-w64-mingw32 \
-DCMAKE_TOOLCHAIN_FILE=../mingw_cross_toolchain.cmake \ -DCMAKE_TOOLCHAIN_FILE=../cmake/mingw_cross_toolchain.cmake \
-D"ZLIB_INCLUDE_DIR=zlib/1.2.11/include" \ -D"ZLIB_INCLUDE_DIR=zlib/1.2.11/include" \
-D"ZLIB_LIBRARY=zlib/1.2.11/lib/libzlib.dll.a" \ -D"ZLIB_LIBRARY=zlib/1.2.11/lib/libzlib.dll.a" \
-D"PNG_PNG_INCLUDE_DIR=libpng/1.6.37/include" \ -D"PNG_PNG_INCLUDE_DIR=libpng/1.6.37/include" \

49
RSETerrain/CMakeLists.txt Normal file
View File

@ -0,0 +1,49 @@
# CMakeLists.txt
####################################################
# Written by JackCarterSmith, 2022
# This code is released under the RSE license.
####################################################
# General configuration
include(CheckIncludeFile)
include(CheckCSourceCompiles)
add_definitions(-DCONF_NO_GL) # Used for obj-lib to not compile GL part
# Import needed packages and references their include path
find_package(ZLIB 1.2.12 REQUIRED)
include_directories(${ZLIB_INCLUDE_DIR})
find_package(PNG 1.6.37 REQUIRED)
include_directories(${PNG_INCLUDE_DIR})
#find_package(GLEW REQUIRED) # Enable when GL rendering is ready
#include_directories(${GLEW_INCLUDE_DIR})
# Define src/headers files
file(GLOB_RECURSE RSE_TERRAIN_SOURCES ./src/*.c)
source_group("Source Files" FILES ${RSE_TERRAIN_SOURCES})
# Building instructions for RSE-Terrain
if(DEFINED ENV{CI})
set(CMAKE_BUILD_TYPE RELEASE)
endif()
# Declare standalone application
add_executable(rse-terrain ${RSE_TERRAIN_SOURCES})
set_property(TARGET rse-terrain PROPERTY C_STANDARD 90)
#target_include_directories(rse-terrain PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
set_target_properties(rse-terrain PROPERTIES OUTPUT_NAME ${RSE_TERRAIN_NAME})
# Link externals libraries to the linker
if(MSVC)
# msvc does not append 'lib' - do it here to have consistent name
set_target_properties(rse-terrain PROPERTIES IMPORT_PREFIX "lib")
target_link_libraries(rse-terrain PRIVATE rsp-terrain-libstatic ${ZLIB_LIBRARIES} ${PNG_LIBRARIES} ${GLEW_LIBRARIES})
else()
target_link_libraries(rse-terrain PRIVATE rsp-terrain-libstatic ${ZLIB_LIBRARIES} ${PNG_LIBRARIES} ${GLEW_LIBRARIES} m)
endif()

215
RSETerrain/src/RSETerrain.c Normal file
View File

@ -0,0 +1,215 @@
/**
* @file RSETerrain.c
* @date 23/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief HMP model 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);
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);
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);
return RSPLIB_ERROR_MEMORY;
}
//#endif
RSPTerrain_freeHMP(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");
}

1
RSETerrain/src/obj Submodule

@ -0,0 +1 @@
Subproject commit 59191c204ab030aabc34cf758efefdaf2de65401

View File

@ -1,34 +1,31 @@
/** /**
* \file options.h * @file options.h
* \date 29/07/2022 * @date 29/07/2022
* \author JackCarterSmith * @author JackCarterSmith
* \copyright GPL-v3.0 * @copyright GPL-v3.0
* \brief Shared options structure definition and declaration. * @brief Shared options structure definition and declaration.
*
*/ */
#ifndef OPTIONS_H_ #ifndef OPTIONS_H_
#define OPTIONS_H_ #define OPTIONS_H_
// Number of height values to take for computing terrain (default: 4) // Scale value for vertex grid constructor (default: 0.1) TODO: user input as argument?
#define TERRAIN_TILE_SAMPLING 4
// Scale value for vertex grid constructor (default: 0.1)
#define TERRAIN_MESH_SCALE 0.1 #define TERRAIN_MESH_SCALE 0.1
/// Options structure /// Options structure
typedef union u_prog_options { typedef union u_prog_options {
struct { struct {
unsigned char verbose_mode:1; //!< Output simple details about ID and other "light" things. unsigned char verbose_mode:1; //!< Output simple details about ID and other "light" things.
unsigned char output_dir:1; //!< Export extracted datas to a sub-directory.
unsigned char inverted_HM: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 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 god_mode:1; //!< Dev only. Output experimental values.
unsigned char reserved1:6; //!< For future use. unsigned char output_dir:1; //!< Export extracted datas to a sub-directory.
unsigned char inverted_Z:1; //!< Reverse Z axis in tilesmap parsing.
unsigned char negative_HM:1; //!< Enable negative heightmap output.
unsigned char export_mtl:1; //!< Export materials datas with object.
unsigned short reserved0:10; //!< For future use.
unsigned short input_files_cnt; //!< Internal files counters. unsigned short input_files_cnt; //!< Internal files counters.
}; };

View File

@ -0,0 +1,173 @@
/**
* @file terrain_export.c
* @date 23/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Export datas to heightmap PNG and Waveform OBJ format.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "options.h"
#include <RSPTerrain_datatypes.h>
#include <RSPTerrain_errordefs.h>
#include <zlib.h>
#include <png.h>
#include "obj/obj.h"
#include "terrain_export.h"
unsigned char exportHeightmapPNG(const T_RSPTERRAIN_HEIGHTMAP* heightmap, const char *out_path, T_PROG_OPTIONS* p_opts) {
char export_path[1024];
FILE *_png_f = NULL;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x,z;
png_byte **row_ptrs = NULL;
//int pixel_size = 3;
//int depth = 8; //bit par color channel (RGB)
if (heightmap == NULL || out_path == NULL)
return RSPLIB_ERROR_ARGS_NULL;
#ifdef _WIN32
if (p_opts->output_dir)
snprintf(export_path, 1024, "%s-out\\heightmap.png", out_path);
else
snprintf(export_path, 1024, "%s-heightmap.png", out_path);
#else
if (p_opts->output_dir)
snprintf(export_path, 1024, "%s-out/heightmap.png", out_path);
else
snprintf(export_path, 1024, "%s-heightmap.png", out_path);
#endif
// Open export file and add PNG header
_png_f = fopen(export_path, "wb");
if (_png_f == NULL) return RSPLIB_ERROR_MEMORY;
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(_png_f);
return RSPLIB_ERROR_MEMORY;
}
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
fclose(_png_f);
return RSPLIB_ERROR_MEMORY;
}
// Set image attributes
png_set_IHDR(png_ptr, info_ptr, heightmap->width * RSPTERRAINLIB_TILE_SAMPLING, heightmap->height * RSPTERRAINLIB_TILE_SAMPLING, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// Store PNG datas in buffer
row_ptrs = png_malloc(png_ptr, heightmap->height * RSPTERRAINLIB_TILE_SAMPLING * sizeof(png_byte *));
for ( z = 0; z < heightmap->height * RSPTERRAINLIB_TILE_SAMPLING; z++ ) {
png_byte *row = png_malloc(png_ptr, heightmap->width * RSPTERRAINLIB_TILE_SAMPLING * sizeof(unsigned char) * 3);
row_ptrs[z] = row;
for ( x = 0; x < heightmap->width * RSPTERRAINLIB_TILE_SAMPLING; x++ ) {
*row++ = heightmap->heightmap[x][z];
*row++ = heightmap->heightmap[x][z];
*row++ = heightmap->heightmap[x][z];
}
}
// Write pixels datas
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);
// Clean up
for ( z = 0; z < heightmap->height * RSPTERRAINLIB_TILE_SAMPLING; z++ ) {
png_free(png_ptr, row_ptrs[z]);
}
png_free(png_ptr, row_ptrs);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(_png_f);
return RSPLIB_SUCCESS;
}
unsigned char exportHeightmapOBJ(const T_RSPTERRAIN_MESH* terrain_mesh, const char *out_path, T_PROG_OPTIONS* p_opts) {
char export_path[1024];
char objExport_name[128];
char mtlExport_name[128];
obj* objConstruct = NULL;
unsigned int i,j;
int surfID = 0;
float vertexBuff[3] = {0};
int indicesBuff[3] = {0};
if (terrain_mesh == NULL || out_path == NULL)
return RSPLIB_ERROR_ARGS_NULL;
#ifdef _WIN32
if (p_opts->output_dir) {
snprintf(export_path, 1024, "%s-out\\", out_path);
snprintf(objExport_name, 128, "heightmap.obj");
snprintf(mtlExport_name, 128, "heightmap.mtl");
} else {
snprintf(objExport_name, 128, "%s-heightmap.obj", out_path);
snprintf(mtlExport_name, 128, "%s-heightmap.mtl", out_path);
}
#else
if (p_opts->output_dir) {
snprintf(export_path, 1024, "%s-out/", out_path);
snprintf(objExport_name, 128, "heightmap.obj");
snprintf(mtlExport_name, 128, "heightmap.mtl");
} else {
snprintf(objExport_name, 128, "%s-heightmap.obj", out_path);
snprintf(mtlExport_name, 128, "%s-heightmap.mtl", out_path);
}
#endif
objConstruct = obj_create(NULL);
// Build face/surface material group
surfID = obj_add_surf(objConstruct);
obj_add_mtrl(objConstruct);
// Build vertex container
for ( i = 0; i < terrain_mesh->vertices_count; i++ ) {
vertexBuff[0] = terrain_mesh->verticesmap[i].x;
vertexBuff[1] = terrain_mesh->verticesmap[i].y;
vertexBuff[2] = terrain_mesh->verticesmap[i].z;
obj_set_vert_v(objConstruct, obj_add_vert(objConstruct), vertexBuff);
}
// Build indices container
// Each tile contains 2 triangles, build both of them.
// 1-2 2
// |/ /|
// 3 3-4
for ( j = 0; j < terrain_mesh->height - 1; j++ ) {
for ( i = 0; i < terrain_mesh->width - 1; i++ ) {
indicesBuff[0] = j * terrain_mesh->width + i;
indicesBuff[1] = indicesBuff[0] + 1;
indicesBuff[2] = indicesBuff[0] + terrain_mesh->width;
obj_set_poly(objConstruct, surfID, obj_add_poly(objConstruct, surfID), indicesBuff);
indicesBuff[0] = indicesBuff[1];
indicesBuff[1] = indicesBuff[2] + 1;
//indicesBuff[2] = indicesBuff[0] + stride;
obj_set_poly(objConstruct, surfID, obj_add_poly(objConstruct, surfID), indicesBuff);
}
}
if (p_opts->export_mtl) {
if (p_opts->output_dir)
obj_write(objConstruct, objExport_name, mtlExport_name, export_path, 8);
else
obj_write(objConstruct, objExport_name, mtlExport_name, NULL, 8);
} else {
if (p_opts->output_dir)
obj_write(objConstruct, objExport_name, NULL, export_path, 8);
else
obj_write(objConstruct, objExport_name, NULL, NULL, 8);
}
obj_delete(objConstruct);
return NO_ERROR;
}

View File

@ -0,0 +1,16 @@
/**
* @file terrain_export.h
* @date 23/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Export datas to heightmap PNG and Waveform OBJ format.
*
*/
#ifndef TERRAIN_EXPORT_H_
#define TERRAIN_EXPORT_H_
unsigned char exportHeightmapPNG(const T_RSPTERRAIN_HEIGHTMAP* heightmap, const char* out_path, T_PROG_OPTIONS* p_opts);
unsigned char exportHeightmapOBJ(const T_RSPTERRAIN_MESH* terrain_mesh, const char *out_path, T_PROG_OPTIONS* p_opts);
#endif /* TERRAIN_EXPORT_H_ */

View File

@ -0,0 +1,67 @@
# CMakeLists.txt
####################################################
# Written by JackCarterSmith, 2022
# This code is released under the RSE license.
####################################################
# General library configuration
if(DEFINED ENV{MS_COMPATIBLE})
set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries
endif()
include(CheckIncludeFile)
include(CheckCSourceCompiles)
# Define src/headers files
file(GLOB_RECURSE RSP_TERRAIN_SOURCES ./src/*.c)
source_group("Source Files" FILES ${RSP_TERRAIN_SOURCES})
file(GLOB RSP_PUBLIC_HRDS ./include/*.h)
set(RSP_PUBLIC_HRDS ${RSP_PUBLIC_HRDS} PARENT_SCOPE)
# Building instructions for RSP-Terrain library
if(DEFINED ENV{CI})
set(CMAKE_BUILD_TYPE RELEASE)
endif()
# Declare the shared library instance
if(RSPTERRAIN_SHARED)
add_library(rsp-terrain-lib SHARED ${RSP_TERRAIN_SOURCES})
set_property(TARGET rsp-terrain-lib PROPERTY C_STANDARD 90)
target_include_directories(rsp-terrain-lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
set_target_properties(rsp-terrain-lib PROPERTIES OUTPUT_NAME ${RSP_TERRAIN_LIB_NAME})
set_target_properties(rsp-terrain-lib PROPERTIES DEFINE_SYMBOL RSPTERRAIN_DLL)
if(MSVC)
# msvc does not append 'lib' - do it here to have consistent name
set_target_properties(rsp-terrain-lib PROPERTIES PREFIX "lib")
set_target_properties(rsp-terrain-lib PROPERTIES IMPORT_PREFIX "lib")
endif()
endif()
# Declare the static library instance
add_library(rsp-terrain-libstatic STATIC ${RSP_TERRAIN_SOURCES})
set_property(TARGET rsp-terrain-libstatic PROPERTY C_STANDARD 90)
target_include_directories(rsp-terrain-libstatic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
if(NOT MSVC)
set_target_properties(rsp-terrain-libstatic PROPERTIES OUTPUT_NAME "${RSP_TERRAIN_LIB_NAME}")
set_target_properties(rsp-terrain-libstatic PROPERTIES CLEAN_DIRECT_OUTPUT 1)
else()
set_target_properties(rsp-terrain-libstatic PROPERTIES OUTPUT_NAME "${RSP_TERRAIN_LIB_NAME}_static")
set_target_properties(rsp-terrain-libstatic PROPERTIES CLEAN_DIRECT_OUTPUT 1)
endif()
if(MSVC)
# msvc does not append 'lib' - do it here to have consistent name
set_target_properties(rsp-terrain-libstatic PROPERTIES PREFIX "lib")
set_target_properties(rsp-terrain-libstatic PROPERTIES IMPORT_PREFIX "lib")
endif()

View File

@ -0,0 +1,166 @@
/**
* @file RSPTerrain.h
* @date 22/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Rogue Squadron Parser terrain library, used to decode decode datas
* from original game file and access them through public interface.
*
*/
#include "RSPTerrain_datatypes.h"
#ifndef RSPTERRAINLIB_H_
#define RSPTERRAINLIB_H_
#if defined(_MSC_VER)
# define RSPTERRAIN_ABI_EXPORT __declspec(dllexport)
# define RSPTERRAIN_ABI_IMPORT __declspec(dllimport)
#elif __GNUC__ >= 4
# define RSPTERRAIN_ABI_EXPORT __attribute__ ((visibility("default")))
# define RSPTERRAIN_ABI_IMPORT __attribute__ ((visibility("default")))
#else
# define RSPTERRAIN_ABI_EXPORT
# define RSPTERRAIN_ABI_IMPORT
#endif
#if defined(RSPTERRAIN_DLL)
# if defined(WIN32)
# if defined(RSPTERRAIN_DLLBUILD)
# define RSPTERRAIN_EXTERN extern RSPTERRAIN_ABI_EXPORT
# else
# define RSPTERRAIN_EXTERN extern RSPTERRAIN_ABI_IMPORT
# endif
# endif
#endif
#ifndef RSPTERRAIN_EXTERN
# define RSPTERRAIN_EXTERN extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
///////////////////////////////////////////////////////////////////////////////
// Library's functions declaration
///////////////////////////////////////////////////////////////////////////////
/**
* @brief Get the current library version.
* @return Char array of the version, escape char included.
*/
RSPTERRAIN_EXTERN char* RSPTerrain_getVersion( void );
/**
* @brief Run terrain parser for the specified file in file system.
* @details Model library can process HMP file from file system. It's a easy
* approach using this library for debugging purpose.
*
* @param[out] hmpStruct HMP terrain structure to be filled with parsed datas.
* @param[in] filePath Path to the HMP file in system.
* @param[in] params Parser options. See RSPTERRAIN_PARAMETERS.
*
* @return Error status, return RSPLIB_SUCCESS in nominal case.
*/
RSPTERRAIN_EXTERN unsigned short RSPTerrain_processHMPFile(
T_RSPTERRAIN_HMP* hmpStruct, const char* const filePath,
const RSPTERRAIN_PARAMETERS params
);
/**
* @brief Run terrain parser for the specified file in memory.
* @details Model library can process HMP file directly stored in RAM memory,
* you must load the file beforehand through a malloc/memcpy call.
* @warning No controls routines are implemented to verify file length!
*
* @param[out] hmpStruct HMP terrain structure to be filled with parsed datas.
* @param[in] memFilePtr Pointer to the beginning of the file in memory.
* @param[in] memFileSize Size of the file in bytes.
* @param[in] params Parser options. See RSPTERRAIN_PARAMETERS.
*
* @return Error status, return RSPLIB_SUCCESS in nominal case.
*/
RSPTERRAIN_EXTERN unsigned short RSPTerrain_processHMPFileMemory(
T_RSPTERRAIN_HMP* hmpStruct, const void* const memFilePtr, const long memFileSize,
const RSPTERRAIN_PARAMETERS params
);
/**
* @brief Convert terrain tilesmap into fullframe heightmap.
* @details Height values are placed in a two dim array for easy access.
*
* @param[out] heightmap 2D array type heightmap structure.
* @param[in] hmpStruct HMP terrain datas from previously parsed HMP file.
*
* @return Error status, return RSPLIB_SUCCESS in nominal case.
*/
RSPTERRAIN_EXTERN unsigned short RSPTerrain_terrainToHeightmap(
T_RSPTERRAIN_HEIGHTMAP* heightmap, const T_RSPTERRAIN_HMP* hmpStruct
);
/**
* @brief Convert terrain tilesmap into vertices mesh for 3D purpose.
* @details Vertex have a X,Y,Z format. Vertices are placed in a row.
*
* @param[out] mesh Mesh of vertices heightmap type.
* @param[in] hmpStruct HMP terrain datas from previously parsed HMP file.
* @param[in] scale X/Z map mesh scale factor (default: 0.1).
*
* @return Error status, return RSPLIB_SUCCESS in nominal case.
*/
RSPTERRAIN_EXTERN unsigned short RSPTerrain_terrainToMesh(
T_RSPTERRAIN_MESH* mesh, const T_RSPTERRAIN_HMP* hmpStruct, const float scale
);
/**
* @brief Convert terrain to GL compatible format.
* @note Only available if GL module as specified at compilation.
*
* @param[out] glTerrainObj GL structure.
* @param[in] hmpStruct HMP terrain datas from previously parsed HMP file.
*
* @return Error status, return RSPLIB_SUCCESS in nominal case.
*/
RSPTERRAIN_EXTERN unsigned short RSPTerrain_terrainToGL(
void* glTerrainObj, const T_RSPTERRAIN_HMP* hmpStruct
);
/**
* @brief Convert terrain to Direct3D compatible format.
* @note Only available if D3D module as specified at compilation.
*
* @param[out] D3DTerrainObj Direct3D structure.
* @param[in] hmpStruct HMP terrain datas from previously parsed HMP file.
*
* @return Error status, return RSPLIB_SUCCESS in nominal case.
*/
RSPTERRAIN_EXTERN unsigned short RSPTerrain_terrainToD3D(
void* D3DTerrainObj, const T_RSPTERRAIN_HMP* hmpStruct
);
/**
* @brief Clean HMP object and it's childrens from memory.
* @param[in] hmpStruct Pointer to data to be cleaned up.
*/
RSPTERRAIN_EXTERN void RSPTerrain_freeHMP( T_RSPTERRAIN_HMP* hmpStruct );
/**
* @brief Clean heightmap object and it's childrens from memory.
* @param[in] heightmap Pointer to data to be cleaned up.
*/
RSPTERRAIN_EXTERN void RSPTerrain_freeHeightmap( T_RSPTERRAIN_HEIGHTMAP* heightmap );
/**
* @brief Clean mesh object and it's childrens from memory.
* @param[in] mesh Pointer to data to be cleaned up.
*/
RSPTERRAIN_EXTERN void RSPTerrain_freeMesh( T_RSPTERRAIN_MESH* mesh );
#ifdef __cplusplus
}
#endif
#endif /* RSPTERRAINLIB_H_ */

View File

@ -0,0 +1,100 @@
/**
* @file RSPTerrain_datatypes.h
* @date 11/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief RSP Terrain workflow structures definitions
*
*/
#ifndef RSPTERRAINLIB_DATATYPES_H_
#define RSPTERRAINLIB_DATATYPES_H_
#ifdef __cplusplus
extern "C" {
#endif
// Number of height values to take for computing terrain (default: 4)
#define RSPTERRAINLIB_TILE_SAMPLING 4
#if (RSPTERRAINLIB_TILE_SAMPLING > 5 || RSPTERRAINLIB_TILE_SAMPLING < 1)
#error "RSPTERRAINLIB_TILE_SAMPLING must be within the range of 1-5."
#endif
///////////////////////////////////////////////////////////////////////////////
// Configuration structure
///////////////////////////////////////////////////////////////////////////////
typedef union u_rspterrain_parameters {
struct {
unsigned char verbose_mode:1; //!< Output simple details about ID and other "light" things.
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 reserved0:1; //!< For future use.
unsigned char invertZ:1; //!< Invert Z axis on tilesmap output.
unsigned char negative:1; //!< Enable negative tilesmap output.
unsigned char reserved1:2; //!< For future use.
};
unsigned char raw; //!< Raw options access for bit-masking or memory copy/compare.
} RSPTERRAIN_PARAMETERS ;
////////////////////////////////////////////////////////////////////////////////
// Lib's structure definitions
////////////////////////////////////////////////////////////////////////////////
#ifndef MEMFILE
typedef char* MEMFILE;
#endif
#ifndef HEIGHTMAP_T
typedef unsigned char** HEIGHTMAP_T;
#endif
#ifndef T_VECTOR3
typedef struct vector3 { float x,y,z; } T_VECTOR3;
#endif
#ifndef T_VERTEX
typedef T_VECTOR3 T_VERTEX;
#endif
typedef struct rspterrain_heightmap {
unsigned short width;
unsigned short height;
HEIGHTMAP_T heightmap;
} T_RSPTERRAIN_HEIGHTMAP ;
typedef struct rspterrain_mesh {
unsigned short width;
unsigned short height;
unsigned int vertices_count;
T_VERTEX* verticesmap;
} T_RSPTERRAIN_MESH ;
typedef struct rspterrain_tile {
unsigned short texmap_id;
unsigned char low_height;
unsigned char high_height;
unsigned char height_values[5][5];
} T_RSPTERRAIN_TILE;
typedef struct rspterrain_obj {
unsigned short width;
unsigned short height;
float height_scale;
unsigned short tiles_count;
T_RSPTERRAIN_TILE* tilesmap;
} T_RSPTERRAIN_HMP ;
#ifdef __cplusplus
}
#endif
#endif /* RSPTERRAINLIB_DATATYPES_H_ */

View File

@ -0,0 +1,45 @@
/**
* @file RSPTerrain_errordefs.h
* @date 22/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Errors type definition file. Used mostly by methods in this project.
*
*/
#include <stdlib.h>
#ifndef RSPLIB_ERRORS_H_
#define RSPLIB_ERRORS_H_
#ifdef __cplusplus
extern "C" {
#endif
///////////////////////////////////////////////////////////////////////////////
// Errors types definitions
///////////////////////////////////////////////////////////////////////////////
#ifndef NO_ERROR
#define NO_ERROR 0 // In case of dual declaration by GCC
#endif
#define RSPLIB_SUCCESS NO_ERROR //!< All is running good!
#define RSPLIB_ERROR_GENERIC 1 //!< Misuse of the program
#define RSPLIB_ERROR_MEMORY 2 //!< Memory de/allocation failure
#define RSPLIB_ERROR_IO 3 //!< File system access failure
#define RSPLIB_ERROR_PROCESS 4 //!< Internal processing failure
#define RSPLIB_ERROR_ARGS_NULL 16 //!< Method not NULL input expected
#define RSPLIB_ERROR_ARGS_RANGE 17 //!< Method input out of expected range
#define RSPLIB_ERROR_MOD_DISABLED 64 //!< A necessary module hasn't been activated during compilation time
#define RSPLIB_ERROR_REALITY_BRK -1 //!< This error can only appear in alternate reality
#ifdef __cplusplus
}
#endif
#endif /* RSPLIB_ERRORS_H_ */

View File

@ -0,0 +1,95 @@
/**
* @file RSPTerrain.c
* @date 22/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief HMP terrain datas parser and export to Waveform OBJ format and greyscale PNG heightmap.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "RSPTerrain_errordefs.h"
#include "RSPTerrain_datatypes.h"
#include "hmp_parser.h"
#include "data_builders.h"
#include "RSPTerrain.h"
char* RSPTerrain_getVersion( void ) {
return PRG_VERSION;
}
unsigned short RSPTerrain_processHMPFile( T_RSPTERRAIN_HMP* hmpStruct, const char* const filePath,
const RSPTERRAIN_PARAMETERS params ) {
if ( hmpStruct == NULL || filePath == NULL ) return RSPLIB_ERROR_ARGS_NULL;
return RSP_TerrainLib_ParseHMPFile(filePath, hmpStruct, &params);
}
unsigned short RSPTerrain_processHMPFileMemory( T_RSPTERRAIN_HMP* hmpStruct, const void* const memFilePtr,
const long memFileSize, const RSPTERRAIN_PARAMETERS params ) {
if ( hmpStruct == NULL || memFilePtr == NULL ) return RSPLIB_ERROR_ARGS_NULL;
return RSP_TerrainLib_ParseHMPMemFile((MEMFILE)memFilePtr, hmpStruct, &params);
}
unsigned short RSPTerrain_terrainToHeightmap( T_RSPTERRAIN_HEIGHTMAP* heightmap, const T_RSPTERRAIN_HMP* hmpStruct ) {
if ( hmpStruct == NULL ) return RSPLIB_ERROR_ARGS_NULL;
return RSP_TerrainLib_ConstructHeightmap(heightmap, hmpStruct);
}
unsigned short RSPTerrain_terrainToMesh( T_RSPTERRAIN_MESH* mesh, const T_RSPTERRAIN_HMP* hmpStruct, const float scale ) {
if ( hmpStruct == NULL ) return RSPLIB_ERROR_ARGS_NULL;
return RSP_TerrainLib_ConstructMesh(mesh, hmpStruct, scale);
}
unsigned short RSPTerrain_terrainToGL( void* glTerrainObj, const T_RSPTERRAIN_HMP* hmpStruct ) {
#ifndef GL_SUPPORT
return RSPLIB_ERROR_MOD_DISABLED;
#endif
return RSPLIB_SUCCESS;
}
unsigned short RSPTerrain_terrainToD3D( void* D3DTerrainObj, const T_RSPTERRAIN_HMP* hmpStruct ) {
#ifndef D3D_SUPPORT
return RSPLIB_ERROR_MOD_DISABLED;
#endif
return RSPLIB_SUCCESS;
}
void RSPTerrain_freeHMP(T_RSPTERRAIN_HMP* hmpStruct) {
if (hmpStruct == NULL) return;
if (hmpStruct->tilesmap) free(hmpStruct->tilesmap);
free(hmpStruct);
}
void RSPTerrain_freeHeightmap(T_RSPTERRAIN_HEIGHTMAP* heightmap) {
unsigned int i;
if (heightmap == NULL) return;
for ( i = 0; i < heightmap->width * RSPTERRAINLIB_TILE_SAMPLING; i++ )
if (heightmap->heightmap[i]) free(heightmap->heightmap[i]);
free(heightmap);
}
void RSPTerrain_freeMesh(T_RSPTERRAIN_MESH* mesh) {
if (mesh == NULL) return;
if (mesh->verticesmap) free(mesh->verticesmap);
free(mesh);
}

View File

@ -0,0 +1,96 @@
/**
* @file data_builders.c
* @date 23/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Construct converted datas structure from extracted raw HMP.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "RSPTerrain_errordefs.h"
#include "RSPTerrain_datatypes.h"
#include "data_builders.h"
unsigned short RSP_TerrainLib_ConstructHeightmap(T_RSPTERRAIN_HEIGHTMAP* pHeightMap, const T_RSPTERRAIN_HMP* pHmpStruct) {
unsigned int i,j,k,l;
pHeightMap->height = pHmpStruct->height;
pHeightMap->width = pHmpStruct->width;
// Build 2D array heightmap
pHeightMap->heightmap = (HEIGHTMAP_T)malloc(pHmpStruct->width * RSPTERRAINLIB_TILE_SAMPLING * sizeof(unsigned char *));
for ( i = 0; i < pHmpStruct->width * RSPTERRAINLIB_TILE_SAMPLING; i++ ) {
pHeightMap->heightmap[i] = (unsigned char *)malloc(pHmpStruct->height * RSPTERRAINLIB_TILE_SAMPLING * sizeof(unsigned char));
}
if (pHeightMap->heightmap) {
// Select tile
for ( i = 0; i < pHmpStruct->width; i++ ) {
for ( j = 0; j < pHmpStruct->height; j++ ) {
// Get the 5x5 bytes height values for this tile
for ( k = 0; k < RSPTERRAINLIB_TILE_SAMPLING; k++ ) {
for ( l = 0; l < RSPTERRAINLIB_TILE_SAMPLING; l++ ) {
pHeightMap->heightmap[i*RSPTERRAINLIB_TILE_SAMPLING+k][j*RSPTERRAINLIB_TILE_SAMPLING+l] = pHmpStruct->tilesmap[i * pHmpStruct->height + j].height_values[l][k];
}
}
}
}
} else return RSPLIB_ERROR_MEMORY;
return RSPLIB_SUCCESS;
}
unsigned short RSP_TerrainLib_ConstructMesh(T_RSPTERRAIN_MESH* pMesh, const T_RSPTERRAIN_HMP* pHmpStruct, const float meshScale) {
unsigned int i,j,k,m,n;
int vertices_width, vertices_height;
float tmp_x,tmp_z;
if (pMesh == NULL || pHmpStruct == NULL) return RSPLIB_ERROR_ARGS_NULL;
if (pHmpStruct->tilesmap == NULL) return RSPLIB_ERROR_ARGS_NULL;
vertices_width = pHmpStruct->width * RSPTERRAINLIB_TILE_SAMPLING;
vertices_height = pHmpStruct->height * RSPTERRAINLIB_TILE_SAMPLING;
pMesh->height = vertices_height;
pMesh->width = vertices_width;
pMesh->vertices_count = vertices_width * vertices_height;
// Build vertex list of the terrain
pMesh->verticesmap = (T_VERTEX *)malloc(pMesh->vertices_count * sizeof(T_VERTEX));
if (pMesh->verticesmap) {
// Select tile
for ( j = 0; j < pHmpStruct->height; j++ ) {
for ( i = 0; i < pHmpStruct->width; i++ ) {
k = i * RSPTERRAINLIB_TILE_SAMPLING + j * RSPTERRAINLIB_TILE_SAMPLING * vertices_width;
for ( n = 0; n < RSPTERRAINLIB_TILE_SAMPLING; n++ ) {
for ( m = 0; m < RSPTERRAINLIB_TILE_SAMPLING; m++ ) {
// Terrain center defined as mesh center -- sould not be used for game application
tmp_x = -(vertices_width / 2);
tmp_x = meshScale * (tmp_x + i * RSPTERRAINLIB_TILE_SAMPLING + m);
pMesh->verticesmap[k + n*vertices_width + m].x = tmp_x;
tmp_z = -(vertices_height / 2);
tmp_z = meshScale * (tmp_z + j * RSPTERRAINLIB_TILE_SAMPLING + n);
pMesh->verticesmap[k + n*vertices_width + m].z = tmp_z;
// Convert read scale to display scale, don't known the real operation in game
pMesh->verticesmap[k + n*vertices_width + m].y = pHmpStruct->tilesmap[j * pHmpStruct->height + i].height_values[m][n] * (pHmpStruct->height_scale * 2.0 / 10.0);
}
}
}
}
} else return RSPLIB_ERROR_MEMORY;
return RSPLIB_SUCCESS;
}

View File

@ -0,0 +1,18 @@
/**
* @file data_builders.h
* @date 23/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Construct converted datas structure from extracted raw HMP.
*
*/
#include "RSPTerrain_datatypes.h"
#ifndef RSPTERRAINLIB_DATA_BUILDERS_H_
#define RSPTERRAINLIB_DATA_BUILDERS_H_
unsigned short RSP_TerrainLib_ConstructHeightmap(T_RSPTERRAIN_HEIGHTMAP*, const T_RSPTERRAIN_HMP*);
unsigned short RSP_TerrainLib_ConstructMesh(T_RSPTERRAIN_MESH*, const T_RSPTERRAIN_HMP*, const float);
#endif /* RSPTERRAINLIB_DATA_BUILDERS_H_ */

View File

@ -0,0 +1,196 @@
/**
* @file hmp_parser.c
* @date 22/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Process HMP file structure and extract its datas.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "RSPTerrain_errordefs.h"
#include "RSPTerrain_datatypes.h"
#include "hmp_struct.h"
#include "hmp_parser.h"
////////////////////////////////////////////////////////////////////////////////
// Private functions declarations
////////////////////////////////////////////////////////////////////////////////
static unsigned short extractTerrainHMP(T_RSPTERRAIN_HMP*, const MEMFILE, const RSPTERRAIN_PARAMETERS*);
static unsigned short resolveTilesMap(T_RSPTERRAIN_HMP* pHmpStruct, const T_TILE_INDICES* tiles_indices,
const T_HMPFILE_TILE* tiles, const RSPTERRAIN_PARAMETERS* pParams);
////////////////////////////////////////////////////////////////////////////////
// Public functions definition
////////////////////////////////////////////////////////////////////////////////
unsigned short RSP_TerrainLib_ParseHMPMemFile(const MEMFILE pMemFile, T_RSPTERRAIN_HMP* hmpStruct, const RSPTERRAIN_PARAMETERS* pParams) {
unsigned char err = RSPLIB_SUCCESS;
if (hmpStruct != NULL && pMemFile != NULL) {
// Do the magic!
err = extractTerrainHMP(hmpStruct, pMemFile, pParams);
} else err = RSPLIB_ERROR_ARGS_NULL;
return err;
}
unsigned short RSP_TerrainLib_ParseHMPFile(const char* fileName, T_RSPTERRAIN_HMP* hmpStruct, const RSPTERRAIN_PARAMETERS* pParams) {
unsigned char err = RSPLIB_SUCCESS;
long fileSize;
FILE* fStream = NULL;
MEMFILE memFile = NULL;
if (hmpStruct != 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 (pParams->verbose_mode) printf("[DBG] > Input file size: %ld bytes\n", fileSize);
memFile = malloc(fileSize + 1);
if (memFile != NULL) {
// Copy file in RAM
fread(memFile, fileSize, 1, fStream);
fclose(fStream);
// Do the magic!
err = extractTerrainHMP(hmpStruct, memFile, pParams);
free(memFile);
} else {
fclose(fStream);
err = RSPLIB_ERROR_MEMORY;
if (pParams->verbose_mode) printf("[ERR] Can't allocate enough memory for file processing!\n");
}
} else {
err = RSPLIB_ERROR_IO;
if (pParams->verbose_mode) printf("[ERR] Input file %s not found!\n", fileName);
}
} else err = RSPLIB_ERROR_ARGS_NULL;
return err;
}
////////////////////////////////////////////////////////////////////////////////
// Private functions definition
////////////////////////////////////////////////////////////////////////////////
/**
* @brief Extract datas from terrain HMP in memory.
*
* @param[out] pHmpStruct Take T_RSPTERRAIN_HMP structure to fill with parsed datas.
* @param[in] pMemfile Pointer to an in-memory file location.
* @param[in] pParams Program option, used to tune parser features.
*
* @return Error code, RSPLIB_SUCCESS when no error.
*/
static unsigned short extractTerrainHMP(T_RSPTERRAIN_HMP* pHmpStruct, const MEMFILE pMemfile, const RSPTERRAIN_PARAMETERS* pParams) {
unsigned short errorCode = RSPLIB_SUCCESS;
T_TILE_INDICES* tiles_indices = NULL;
T_HMPFILE_TILE* tiles = NULL;
unsigned int tiles_offset = 0;
if (pHmpStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
// Get header infos
pHmpStruct->height_scale = ((T_HMPFILE_HEADER *)pMemfile)->height_scale;
tiles_offset = ((T_HMPFILE_HEADER *)pMemfile)->tiles_start_offset;
pHmpStruct->tiles_count = ((T_HMPFILE_HEADER *)pMemfile)->tiles_count;
pHmpStruct->width = ((T_HMPFILE_HEADER *)pMemfile)->width_BLK;
pHmpStruct->height = ((T_HMPFILE_HEADER *)pMemfile)->height_BLK;
if (pParams->verbose_mode) {
printf("[DBG] > Height scale: %.8f\n", pHmpStruct->height_scale);
printf("[DBG] > Tiles count: %d\n", pHmpStruct->tiles_count);
printf("[DBG] > Tiles offset: 0x%X\n", tiles_offset);
printf("[DBG] > Terrain size: %dx%d\n", pHmpStruct->width, pHmpStruct->height);
printf("\n");
}
if (pParams->god_mode) {
printf("[DBG] > Unknown0: %d\n", ((T_HMPFILE_HEADER *)pHmpStruct)->unknown0);
printf("[DBG] > Unknown1: %d\n", ((T_HMPFILE_HEADER *)pHmpStruct)->unknown1);
printf("\n");
}
// Get tiles indices
tiles_indices = (T_TILE_INDICES *)malloc(pHmpStruct->width * pHmpStruct->height * sizeof(T_TILE_INDICES));
memcpy(tiles_indices,
pMemfile + sizeof(T_HMPFILE_HEADER),
pHmpStruct->width * pHmpStruct->height * sizeof(unsigned short));
// Get tiles datas
tiles = (T_HMPFILE_TILE *)malloc(pHmpStruct->tiles_count * sizeof(T_HMPFILE_TILE));
memcpy(tiles,
pMemfile + tiles_offset,
((T_HMPFILE_HEADER *)pMemfile)->tiles_count * sizeof(T_HMPFILE_TILE));
if (tiles && tiles_indices) {
// Reconstruct tiles map from tiles datas and tiles indices
errorCode = resolveTilesMap(pHmpStruct, tiles_indices, tiles, pParams);
} else errorCode = RSPLIB_ERROR_MEMORY;
if (tiles) free(tiles);
if (tiles_indices) free(tiles_indices);
return errorCode;
}
/**
* @brief Recreate original tilesmap using index and tiles in memory.
*
* @param[in|out] pHmpStruct Take T_RSPTERRAIN_HMP structure to fill with parsed datas.
* @param[in] tiles_indices Tiles indices list.
* @param[in] tiles Tiles datas list.
* @param[in] pParams Program option, used to tune parser features.
*
* @return Error code, RSPLIB_SUCCESS when no error.
*/
static unsigned short resolveTilesMap(T_RSPTERRAIN_HMP* pHmpStruct, const T_TILE_INDICES* tiles_indices,
const T_HMPFILE_TILE* tiles, const RSPTERRAIN_PARAMETERS* pParams) {
T_TILE_INDICES tiles_idx;
unsigned int i,j,k,l,remap_index;
// Build tilesmap array to contain height values
pHmpStruct->tilesmap = malloc(pHmpStruct->width * pHmpStruct->height * sizeof(T_RSPTERRAIN_TILE));
if (pHmpStruct->tilesmap == NULL) return RSPLIB_ERROR_MEMORY;
// Fetch tile from ID
for ( i = 0; i < pHmpStruct->height; i++ ) {
for ( j = 0; j < pHmpStruct->width; j++ ) {
remap_index = pParams->invertZ ? i * pHmpStruct->height + (pHmpStruct->width-1 - j) : i * pHmpStruct->height + j;
tiles_idx = tiles_indices[i * pHmpStruct->height + j];
// Get tiles pseudodatas
pHmpStruct->tilesmap[remap_index].texmap_id = tiles[tiles_idx].texmap_id;
pHmpStruct->tilesmap[remap_index].low_height = tiles[tiles_idx].low_height;
pHmpStruct->tilesmap[remap_index].high_height = tiles[tiles_idx].high_height;
// Get the 5x5 bytes height values for this tile
for ( k = 0; k < 5; k++ ) {
for ( l = 0; l < 5; l++ ) {
if (pParams->invertZ)
pHmpStruct->tilesmap[remap_index].height_values[4-l][k] = pParams->negative ? tiles[tiles_idx].height_values[k][l] + 128 : 255 - (tiles[tiles_idx].height_values[k][l] + 128);
else
pHmpStruct->tilesmap[remap_index].height_values[l][k] = pParams->negative ? tiles[tiles_idx].height_values[k][l] + 128 : 255 - (tiles[tiles_idx].height_values[k][l] + 128);
}
}
}
}
return RSPLIB_SUCCESS;
}

View File

@ -0,0 +1,51 @@
/**
* @file hmp_parser.h
* @date 22/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief Process HMP file structure and extract its datas.
*
*/
#include "RSPTerrain_datatypes.h"
#ifndef RSPTERRAINLIB_HMP_PARSER_H_
#define RSPTERRAINLIB_HMP_PARSER_H_
/**
* @brief Process HMP file stored in memory.
* @details Parser will directly extract tiles count and information stored in
* HMP file and store them in T_RSPTERRAIN_HMP structure.
* @note Unmanaged mode
*
* @param[in] pMemFile Pointer to an in-memory HOB file location.
* @param[out] hmpStruct Allocated empty T_RSPTERRAIN_HMP structure instance to
* be filled with HMP datas.
* @param[in] pParams Parser options. See RSPTERRAIN_PARAMETERS.
*
* @return Processing error code, RSPLIB_SUCCESS if no error.
*/
unsigned short RSP_TerrainLib_ParseHMPMemFile(const MEMFILE pMemFile,
T_RSPTERRAIN_HMP* hmpStruct, const RSPTERRAIN_PARAMETERS* pParams);
/**
* @brief Process HMP file in file system.
* @details HMP file is dumped in memory before parsing in order to enhance
* performance during parser operation and in optic to protect data
* stored in the original file (read-only).
* Parser will extract tiles count and information stored in HMP file
* and store them in T_RSPTERRAIN_HMP structure.
* @note Managed mode
*
* @param[in] fileName String value of file name/path.
* @param[out] hmpStruct Allocated empty T_RSPTERRAIN_HMP structure instance to
* be filled with HMP datas.
* @param[in] pParams Parser options. See RSPTERRAIN_PARAMETERS.
*
* @return Processing error code, RSPLIB_SUCCESS if no error.
*/
unsigned short RSP_TerrainLib_ParseHMPFile(const char* fileName,
T_RSPTERRAIN_HMP* hmpStruct, const RSPTERRAIN_PARAMETERS* pParams);
#endif /* RSPTERRAINLIB_HMP_PARSER_H_ */

View File

@ -1,19 +1,21 @@
/* /**
* hmp_struct.h * @file hmp_struct.h
* @date 22/08/2022
* @author JackCarterSmith
* @copyright GPL-v3.0
* @brief HMP file mapping definition.
* *
* Created on: 31 juil. 2022
* Author: JackCarterSmith
*/ */
#ifndef SRC_HMP_STRUCT_H_ #ifndef RSPTERRAINLIB_HMP_STRUCT_H_
#define SRC_HMP_STRUCT_H_ #define RSPTERRAINLIB_HMP_STRUCT_H_
/* /*
* long = 64bits??? (8 Bytes) * long = 64bits??? (8 Bytes)
* int = 32bits (4 Bytes) * int = 32bits (4 Bytes)
* short = 16bits (2 Bytes) * short = 16bits (2 Bytes)
* car = 8bits (1 Bytes) * char = 8bits (1 Bytes)
*/ */
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -22,24 +24,6 @@
#define PACK __attribute__((packed)) #define PACK __attribute__((packed))
#endif #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;
unsigned int verticesmap_size;
T_VERTEX* verticesmap;
} T_TERRAIN ;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Declaration of Memory Mapped Structure // Declaration of Memory Mapped Structure
// Caution: the place of variable is important for correct mapping! // Caution: the place of variable is important for correct mapping!
@ -84,4 +68,4 @@ typedef struct PACK hmpfile_tile {
#pragma pack(pop) #pragma pack(pop)
#endif #endif
#endif /* SRC_HMP_STRUCT_H_ */ #endif /* RSPTERRAINLIB_HMP_STRUCT_H_ */

View File

@ -13,4 +13,4 @@ libpng:shared=True
glew:shared=True glew:shared=True
[imports] [imports]
bin, *.dll -> . bin, *.dll -> ./bin

6
config.h.in Normal file
View File

@ -0,0 +1,6 @@
#ifndef CONFIG_H_
#define CONFIG_H_
#define PRG_VERSION "@PROJECT_VERSION@"
#endif /* CONFIG_H_ */

View File

@ -32,13 +32,13 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places. # title of most generated pages and in a few other places.
# The default value is: My Project. # The default value is: My Project.
PROJECT_NAME = HMT-Extractor PROJECT_NAME = RSE-Terrain
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 1.0 PROJECT_NUMBER = 2.0.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a

View File

@ -1,168 +0,0 @@
/**
* \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 <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 "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]);
#ifndef NO_PNG_SUPPORT
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");
#endif
if (exportHeightmapOBJ(terrainStruct, args_value[file_index], p_opts) != NO_ERROR)
printf("[ERR] Failed to export terrain in OBJ format!\n");
else
printf("[INFO] Successfully exported terrain in OBJ format.\n");
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;
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->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], "-subdir") == 0) {
opt_ptr->output_dir = 0;
printf("[OPTN] Export to sub-directory.\n");
} else if (strcmp(p_args[i], "-neg") == 0) {
opt_ptr->inverted_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 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(" -subdir Export output to a sub-directory\n");
printf(" -neg Negative heightmap output\n");
printf("\n");
printf("Usage: RSE-Terrain_%s [options] <hmp_file>\n", VERSION);
printf("\n");
}

View File

@ -1 +0,0 @@
#define VERSION "@PROJECT_VERSION@"

View File

@ -1,28 +0,0 @@
/*
* 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_ */

View File

@ -1,156 +0,0 @@
/**
* \file hmp_export.c
* \date 02/08/2022
* \author JackCarterSmith
* \copyright GPL-v3.0
* \brief Export datas to heightmap PNG and Waveform OBJ format.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef NO_PNG_SUPPORT
#include <zlib.h>
#include <png.h>
#endif
#include "rlk/obj.h"
#include "errors_types.h"
#include "options.h"
#include "hmp_struct.h"
#include "hmp_export.h"
#ifndef NO_PNG_SUPPORT
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,z;
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 * TERRAIN_TILE_SAMPLING, terrain->height * TERRAIN_TILE_SAMPLING, 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 * TERRAIN_TILE_SAMPLING * sizeof(png_byte *));
for ( z = 0; z < terrain->height * TERRAIN_TILE_SAMPLING; z++ ) {
png_byte *row = png_malloc(png_ptr, terrain->width * TERRAIN_TILE_SAMPLING * sizeof(unsigned char) * 3);
row_ptrs[z] = row;
for ( x = 0; x < terrain->width * TERRAIN_TILE_SAMPLING; x++ ) {
*row++ = terrain->heightmap[x][z];
*row++ = terrain->heightmap[x][z];
*row++ = terrain->heightmap[x][z];
}
}
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 ( z = 0; z < terrain->height * TERRAIN_TILE_SAMPLING; z++ ) {
png_free(png_ptr, row_ptrs[z]);
}
png_free(png_ptr, row_ptrs);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(_png_f);
return NO_ERROR;
}
#endif
unsigned char exportHeightmapOBJ(const T_TERRAIN* terrain_struct, const char *out_path, T_PROG_OPTIONS* p_opts) {
char objExport_path[128];
char mtlExport_path[128];
obj* objConstruct = NULL;
unsigned int i,j,stride;
int surfID = 0;
float vertexBuff[3] = {0};
int indicesBuff[3] = {0};
if (terrain_struct == NULL || out_path == NULL)
return ERROR_ARGS_NULL;
strcpy(objExport_path, out_path);
if (p_opts->output_dir) {
#ifdef _WIN32
strcat(objExport_path, "-out\\");
#else
strcat(objExport_path, "-out/");
#endif
strcat(objExport_path, "heightmap");
} else {
strcat(objExport_path, "-heightmap");
}
strcpy(mtlExport_path, objExport_path);
strcat(objExport_path, ".obj\0");
strcat(mtlExport_path, ".mtl\0");
objConstruct = obj_create(NULL);
// Build face/surface material group
surfID = obj_add_surf(objConstruct);
obj_add_mtrl(objConstruct);
// Build vertex container
for ( i = 0; i < terrain_struct->verticesmap_size; i++ ) {
vertexBuff[0] = terrain_struct->verticesmap[i].x;
vertexBuff[1] = terrain_struct->verticesmap[i].y;
vertexBuff[2] = terrain_struct->verticesmap[i].z;
obj_set_vert_v(objConstruct, obj_add_vert(objConstruct), vertexBuff);
}
// Build indices container
// Each tile contains 2 triangles, build both of them.
// 1-2 2
// |/ /|
// 3 3-4
stride = terrain_struct->width * TERRAIN_TILE_SAMPLING;
for ( j = 0; j < terrain_struct->width * TERRAIN_TILE_SAMPLING - 1; j++ ) {
for ( i = 0; i < terrain_struct->width * TERRAIN_TILE_SAMPLING - 1; i++ ) {
indicesBuff[0] = j * stride + i + 1 - 1; //TODO: -1 needed to compensate the obj constructor. Really need to rewrite my own...
indicesBuff[1] = indicesBuff[0] + 1;
indicesBuff[2] = indicesBuff[0] + stride;
obj_set_poly(objConstruct, surfID, obj_add_poly(objConstruct, surfID), indicesBuff);
indicesBuff[0] = indicesBuff[1];
indicesBuff[1] = indicesBuff[2] + 1;
//indicesBuff[2] = indicesBuff[0] + stride;
obj_set_poly(objConstruct, surfID, obj_add_poly(objConstruct, surfID), indicesBuff);
}
}
obj_write(objConstruct, objExport_path, NULL, 8);
obj_delete(objConstruct);
return NO_ERROR;
}

View File

@ -1,17 +0,0 @@
/**
* \file hmp_export.h
* \date 02/08/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_
#ifndef NO_PNG_SUPPORT
unsigned char exportHeightmapPNG(const T_TERRAIN* terrain, const char* out_path, T_PROG_OPTIONS* p_opts);
#endif
unsigned char exportHeightmapOBJ(const T_TERRAIN* terrain_struct, const char *out_path, T_PROG_OPTIONS* p_opts);
#endif /* SRC_HMP_EXPORT_H_ */

View File

@ -1,180 +0,0 @@
/**
* \file hmp_parser.c
* \date 31/07/2022
* \author JackCarterSmith
* \copyright GPL-v3.0
* \brief Decode terrain file (hmp) structure.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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);
static void processHeighmapToVertices(T_TERRAIN* terrain, const float h_scale);
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("[DBG] > Terrain size: %dx%d\n", hmp_struct->width, hmp_struct->height);
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->inverted_HM);
// Convert tiles datas to terrain vertices
processHeighmapToVertices(hmp_struct, y_scale);
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 * TERRAIN_TILE_SAMPLING; i++ )
free(terrain->heightmap[i]);
free(terrain->heightmap);
free(terrain->verticesmap);
free(terrain);
}
static void processTilesToHeightmap(T_TERRAIN* terrain, const T_TILE_INDICES* tiles_indices, const T_HMPFILE_TILE* tiles, const unsigned char inv_output) {
T_TILE_INDICES tiles_idx;
unsigned int i,j,k,l;
unsigned int heightmap_size_w = terrain->width * TERRAIN_TILE_SAMPLING;
unsigned int heightmap_size_h = terrain->height * TERRAIN_TILE_SAMPLING;
// 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 < TERRAIN_TILE_SAMPLING; k++ ) {
for ( l = 0; l < TERRAIN_TILE_SAMPLING; l++ ) {
if (inv_output) {
// Invert Z to set 0,0 origin at bottom left of terrain
terrain->heightmap[i*TERRAIN_TILE_SAMPLING+k][(heightmap_size_h-1) - (j*TERRAIN_TILE_SAMPLING+l)] =
tiles[tiles_idx].height_values[l][k] + 128;
//terrain->heightmap[i*TERRAIN_TILE_SAMPLING+k][j*TERRAIN_TILE_SAMPLING+l] =
// tiles[tiles_idx].height_values[l][k] + 128;
} else {
// Invert Z to set 0,0 origin at bottom left of terrain
terrain->heightmap[i*TERRAIN_TILE_SAMPLING+k][(heightmap_size_h-1) - (j*TERRAIN_TILE_SAMPLING+l)] =
255 - (tiles[tiles_idx].height_values[l][k] + 128);
//terrain->heightmap[i*TERRAIN_TILE_SAMPLING+k][j*TERRAIN_TILE_SAMPLING+l] =
// 255 - (tiles[tiles_idx].height_values[l][k] + 128);
}
}
}
}
}
}
static void processHeighmapToVertices(T_TERRAIN* terrain, const float h_scale) {
unsigned int i,j,k;
float w_half,h_half,_h_scale;
if (terrain->heightmap == NULL) return;
terrain->verticesmap_size = terrain->width * TERRAIN_TILE_SAMPLING * terrain->height * TERRAIN_TILE_SAMPLING;
w_half = terrain->width * 2; // Terrain center defined as mesh center -- sould not be used for game application
h_half = terrain->height * 2;
_h_scale = h_scale * 2.0 / 10.0; // Convert read scale to display scale, don't known the real operation in game
// Build vertex list of the terrain
terrain->verticesmap = (T_VERTEX *)malloc(terrain->verticesmap_size * sizeof(T_VERTEX));
for ( j = 0; j < terrain->height * TERRAIN_TILE_SAMPLING; j++ ) {
for ( i = 0; i < terrain->width * TERRAIN_TILE_SAMPLING; i++ ) {
k = j * terrain->width * TERRAIN_TILE_SAMPLING + i;
terrain->verticesmap[k].x = TERRAIN_MESH_SCALE * (-w_half + i);
terrain->verticesmap[k].z = TERRAIN_MESH_SCALE * (-h_half + j);
terrain->verticesmap[k].y = terrain->heightmap[i][j] * _h_scale;
}
}
}

View File

@ -1,18 +0,0 @@
/**
* \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_ */

@ -1 +0,0 @@
Subproject commit 48a6916526d043691bb3f9e38676fbc99995da10