174 lines
5.3 KiB
C
174 lines
5.3 KiB
C
/**
|
|
* @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;
|
|
}
|