Generator test mode setting

This commit is contained in:
MihailRis 2023-11-15 00:06:28 +03:00
parent ccbfaa3a86
commit 91c06537eb
13 changed files with 67 additions and 105 deletions

View File

@ -1,12 +1,15 @@
#include "png.h"
#include <iostream>
#include <memory>
#include <GL/glew.h>
#include "../graphics/ImageData.h"
#include "../graphics/Texture.h"
#include "../files/files.h"
using std::unique_ptr;
#ifndef _WIN32
#define LIBPNG
#endif
@ -15,41 +18,45 @@
#include <png.h>
int _png_write(const char* filename, uint width, uint height, const ubyte* data, bool alpha) {
int code = 0;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
png_bytep row = NULL;
uint pixsize = alpha ? 4 : 3;
// Open file for writing (binary mode)
FILE* fp = fopen(filename, "wb");
if (fp == NULL) {
fprintf(stderr, "Could not open file %s for writing\n", filename);
code = 1;
goto finalize;
fclose(fp);
return 1;
}
// Initialize write structure
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fprintf(stderr, "Could not allocate write struct\n");
code = 1;
goto finalize;
fclose(fp);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return 1;
}
// Initialize info structure
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
fprintf(stderr, "Could not allocate info struct\n");
code = 1;
goto finalize;
fclose(fp);
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return 1;
}
// Setup Exception handling
if (setjmp(png_jmpbuf(png_ptr))) {
fprintf(stderr, "Error during png creation\n");
code = 1;
goto finalize;
fclose(fp);
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return 1;
}
png_init_io(png_ptr, fp);
@ -65,7 +72,7 @@ int _png_write(const char* filename, uint width, uint height, const ubyte* data,
png_write_info(png_ptr, info_ptr);
row = (png_bytep) malloc(pixsize * width * sizeof(png_byte));
unique_ptr<png_byte[]> row(new png_byte[pixsize * width]);
// Write image data
for (uint y = 0; y < height; y++) {
@ -74,19 +81,16 @@ int _png_write(const char* filename, uint width, uint height, const ubyte* data,
row[x * pixsize + i] = (png_byte)data[(y * width + x) * pixsize + i];
}
}
png_write_row(png_ptr, row);
png_write_row(png_ptr, row.get());
}
// End write
png_write_end(png_ptr, NULL);
finalize:
if (fp != NULL) fclose(fp);
if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
if (row != NULL) free(row);
return code;
fclose(fp);
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return 0;
}
ImageData* _png_load(const char* file){

View File

@ -54,7 +54,7 @@ Engine::Engine(const EngineSettings& settings_) {
std::cout << "-- loading world" << std::endl;
vec3 playerPosition = vec3(0, 64, 0);
Camera* camera = new Camera(playerPosition, radians(90.0f));
World* world = new World("world-1", "world/", 42);
World* world = new World("world-1", "world/", 42, settings);
Player* player = new Player(playerPosition, 4.0f, camera);
level = world->loadLevel(player, settings);
@ -116,7 +116,7 @@ void Engine::mainloop() {
level->chunksController->update(settings.chunks.loadSpeed);
float fovFactor = 18.0f / (float)settings.chunks.loadDistance;
worldRenderer.draw(camera, occlusion, fovFactor, settings.fogCurve);
worldRenderer.draw(camera, occlusion, fovFactor, settings.graphics.fogCurve);
hud.draw();
if (level->player->debug) {
hud.drawDebug( 1 / delta, occlusion);
@ -135,7 +135,7 @@ Engine::~Engine() {
World* world = level->world;
std::cout << "-- saving world" << std::endl;
world->write(level);
world->write(level, !settings.debug.generatorTestMode);
delete level;
delete world;

View File

@ -56,7 +56,8 @@ float bytes2Float(ubyte* src, uint offset){
return *(float*)(&value);
}
WorldFiles::WorldFiles(std::string directory, size_t mainBufferCapacity) : directory(directory){
WorldFiles::WorldFiles(std::string directory, size_t mainBufferCapacity, bool generatorTestMode)
: directory(directory), generatorTestMode(generatorTestMode) {
compressionBuffer = new ubyte[CHUNK_DATA_LEN * 2];
}
@ -161,6 +162,9 @@ ubyte* WorldFiles::getChunk(int x, int y){
}
ubyte* WorldFiles::readChunkData(int x, int y, uint32_t& length){
if (generatorTestMode)
return nullptr;
int regionX = floordiv(x, REGION_SIZE);
int regionY = floordiv(y, REGION_SIZE);
@ -199,6 +203,8 @@ void WorldFiles::write(){
if (!std::filesystem::is_directory(directory)) {
std::filesystem::create_directory(directory);
}
if (generatorTestMode)
return;
for (auto it = regions.begin(); it != regions.end(); it++){
if (it->second.chunksData == nullptr || !it->second.unsaved)
continue;
@ -264,7 +270,6 @@ bool WorldFiles::readPlayer(Player* player) {
return true;
}
void WorldFiles::writeRegion(int x, int y, WorldRegion& entry){
ubyte** region = entry.chunksData;
uint32_t* sizes = entry.compressedSizes;

View File

@ -31,8 +31,9 @@ public:
std::unordered_map<glm::ivec2, WorldRegion> regions;
std::string directory;
ubyte* compressionBuffer;
bool generatorTestMode;
WorldFiles(std::string directory, size_t mainBufferCapacity);
WorldFiles(std::string directory, size_t mainBufferCapacity, bool generatorTestMode);
~WorldFiles();
void put(Chunk* chunk);

View File

@ -1,61 +0,0 @@
#include "settings.h"
#include <memory>
#include <string>
#include "files/files.h"
#include "coders/json.h"
using std::string;
using std::unique_ptr;
void load_settings(EngineSettings& settings, string filename) {
string source = files::read_string(filename);
unique_ptr<json::JObject> obj(json::parse(filename, source));
{
auto& display = settings.display;
obj->num("display-width", display.width);
obj->num("display-height", display.height);
obj->num("display-samples", display.samples);
obj->num("display-swap-interval", display.swapInterval);
}
{
auto& chunks = settings.chunks;
obj->num("chunks-load-distance", chunks.loadDistance);
obj->num("chunks-load-speed", chunks.loadSpeed);
obj->num("chunks-padding", chunks.padding);
}
{
auto& camera = settings.camera;
obj->flag("camera-fov-effects", camera.fovEvents);
obj->flag("camera-shaking", camera.shaking);
}
obj->num("fog-curve", settings.fogCurve);
}
void save_settings(EngineSettings& settings, string filename) {
json::JObject obj;
{
auto& display = settings.display;
obj.put("display-width", display.width);
obj.put("display-height", display.height);
obj.put("display-samples", display.samples);
obj.put("display-swap-interval", display.swapInterval);
}
{
auto& chunks = settings.chunks;
obj.put("chunks-load-distance", chunks.loadDistance);
obj.put("chunks-load-speed", chunks.loadSpeed);
obj.put("chunks-padding", chunks.padding);
}
{
auto& camera = settings.camera;
obj.put("camera-fov-effects", camera.fovEvents);
obj.put("camera-shaking", camera.shaking);
}
obj.put("fog-curve", settings.fogCurve);
files::write_string(filename, json::stringify(&obj, true, " "));
}

View File

@ -34,17 +34,23 @@ struct CameraSettings {
bool shaking = true;
};
struct GraphicsSettings {
/* Fog opacity is calculated as `pow(depth*k, fogCurve)` where k depends on chunksLoadDistance.
Use values in range [1.0 - 2.0] where 1.0 is linear, 2.0 is quadratic */
float fogCurve = 1.6f;
};
struct DebugSettings {
/* Turns off chunks saving/loading */
bool generatorTestMode = false;
};
struct EngineSettings {
DisplaySettings display;
ChunksSettings chunks;
CameraSettings camera;
/* Fog opacity is calculated as `pow(depth*k, fogCurve)` where k depends on chunksLoadDistance.
Use values in range [1.0 - 2.0] where 1.0 is linear, 2.0 is quadratic
*/
float fogCurve = 1.6f;
GraphicsSettings graphics;
DebugSettings debug;
};
#endif // SRC_SETTINGS_H_

View File

@ -31,7 +31,10 @@ toml::Wrapper create_wrapper(EngineSettings& settings) {
camera.add("shaking", &settings.camera.shaking);
toml::Section& graphics = wrapper.add("graphics");
graphics.add("fog-curve", &settings.fogCurve);
graphics.add("fog-curve", &settings.graphics.fogCurve);
toml::Section& debug = wrapper.add("debug");
debug.add("generator-test-mode", &settings.debug.generatorTestMode);
return wrapper;
}

View File

@ -261,7 +261,8 @@ void Chunks::translate(int dx, int dz){
continue;
if (nx < 0 || nz < 0 || nx >= w || nz >= d){
events->trigger(EVT_CHUNK_HIDDEN, chunk.get());
worldFiles->put(chunk.get());
if (worldFiles)
worldFiles->put(chunk.get());
chunksCount--;
continue;
}

View File

@ -42,7 +42,7 @@ void ChunksController::update(int64_t maxDuration) {
int64_t mcstotal = 0;
for (uint i = 0; i < MAX_WORK_PER_FRAME; i++) {
auto start = high_resolution_clock::now();
if (loadVisible(level->world->wfile)) {
if (loadVisible()) {
auto elapsed = high_resolution_clock::now() - start;
int64_t mcs = duration_cast<microseconds>(elapsed).count();
avgDurationMcs = mcs * 0.2 + avgDurationMcs * 0.8;
@ -55,7 +55,7 @@ void ChunksController::update(int64_t maxDuration) {
}
}
bool ChunksController::loadVisible(WorldFiles* worldFiles){
bool ChunksController::loadVisible(){
const int w = chunks->w;
const int d = chunks->d;
const int ox = chunks->ox;
@ -103,7 +103,7 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){
chunk = shared_ptr<Chunk>(new Chunk(nearX+ox, nearZ+oz));
level->chunksStorage->store(chunk);
ubyte* data = worldFiles->getChunk(chunk->x, chunk->z);
ubyte* data = level->world->wfile->getChunk(chunk->x, chunk->z);
if (data) {
chunk->decode(data);
chunk->setLoaded(true);

View File

@ -22,7 +22,7 @@ public:
~ChunksController();
void update(int64_t maxDuration);
bool loadVisible(WorldFiles* worldFiles);
bool loadVisible();
};
#endif /* VOXELS_CHUNKSCONTROLLER_H_ */

View File

@ -20,7 +20,10 @@ Level::Level(World* world, Player* player, ChunksStorage* chunksStorage, LevelEv
uint matrixSize = (settings.chunks.loadDistance+
settings.chunks.padding) * 2;
chunks = new Chunks(matrixSize, matrixSize, 0, 0, world->wfile, events);
chunks = new Chunks(matrixSize, matrixSize,
0, 0,
world->wfile,
events);
lighting = new Lighting(chunks);
chunksController = new ChunksController(this, chunks, lighting, settings.chunks.padding);
playerController = new PlayerController(this, settings);

View File

@ -14,15 +14,15 @@
using std::shared_ptr;
World::World(std::string name, std::string directory, int seed) : name(name), seed(seed) {
wfile = new WorldFiles(directory, REGION_VOL * (CHUNK_DATA_LEN * 2 + 8));
World::World(std::string name, std::string directory, int seed, EngineSettings& settings) : name(name), seed(seed) {
wfile = new WorldFiles(directory, REGION_VOL * (CHUNK_DATA_LEN * 2 + 8), settings.debug.generatorTestMode);
}
World::~World(){
delete wfile;
}
void World::write(Level* level) {
void World::write(Level* level, bool writeChunks) {
Chunks* chunks = level->chunks;
for (size_t i = 0; i < chunks->volume; i++) {

View File

@ -16,10 +16,10 @@ public:
WorldFiles* wfile;
int seed;
World(std::string name, std::string directory, int seed);
World(std::string name, std::string directory, int seed, EngineSettings& settings);
~World();
void write(Level* level);
void write(Level* level, bool writeChunks);
Level* loadLevel(Player* player, EngineSettings& settings);
};