Actually have a semi working world loader.

This commit is contained in:
2021-04-18 22:06:51 +10:00
parent 7b8afa20a1
commit e0b7313228
20 changed files with 448 additions and 481 deletions

View File

@ -7,6 +7,9 @@
#include "dawngame.h"
primitive_t *primitive;
float i;
game_t * gameInit(platform_t *platform) {
// Create the game
game_t *game = malloc(sizeof(game_t));
@ -19,15 +22,40 @@ game_t * gameInit(platform_t *platform) {
return NULL;
}
// Load the Shader
game->shader = assetShaderLoad("shaders/test.vert", "shaders/test.frag");
// Prepare the camera.
game->camera = cameraCreate();
cameraLookAt(game->camera, 50, 50, 50, 0, 0, 0 );
cameraPerspective(game->camera, 45.0f, 1920.0f/1080.0f, 0.5f, 500.0f);
// Load the world
game->world = worldLoad("testworld/");
// Pass to the main game to handle
return game;
}
uint32_t gameUpdate(game_t *game) {
return engineUpdate(game->engine);
uint32_t result;
// Update the engine.
result = engineUpdate(game->engine);
if(result != 0) return result;
// Prepare for rendering
shaderUse(game->shader);
shaderUseCamera(game->shader, game->camera);
worldRender(game->world, game->shader);
return 0;
}
void gameDispose(game_t *game) {
worldDispose(game->world);
shaderDipose(game->shader);
cameraDispose(game->camera);
engineDispose(game->engine);
free(game);
}

View File

@ -7,11 +7,21 @@
#include <malloc.h>
#include "../engine/engine.h"
#include "../engine/file/asset.h"
#include "../engine/display/shader.h"
#include "../engine/display/camera.h"
#include "world/world.h"
/////////////////////////////// TYPE DEFINITIONS ///////////////////////////////
/** Context about Dawn Game */
typedef struct {
/** The engine context for the game */
engine_t *engine;
/** Rendering items */
camera_t *camera;
shader_t *shader;
world_t *world;
} dawngame_t;
#define GAMETYPE_T dawngame_t

79
src/dawn/world/chunk.c Normal file
View File

@ -0,0 +1,79 @@
#include "chunk.h"
void chunkLoad(world_t *world, chunk_t *chunk,
int32_t x, int32_t y, int32_t z
) {
int32_t tx, ty, tz, i;
tile_t *tile;
tiledef_t *tileDef;
tilesetdiv_t *div;
char *buffer, *seek, *current;
char fileName[128];
// Determine file name of the chunk.
fileName[0] = '\0';
strcat(fileName, world->assetWorldDirectory);
strcat(fileName, "chunks/");
strcat(fileName, "%d_%d_%d.txt");
sprintf(fileName, fileName, x, y, z);
// Load contents of chunk
buffer = assetStringLoad(fileName);
if(buffer == NULL) return;
seek = buffer;
// Determine the size of our primitive.
int32_t indiceCount = 0, verticeCount = 0;
for(i = 0; i < world->tileCount; i++) {
// Get the tile
tile = chunk->tiles + i;
// Now load from the buffer.
current = strtok_r(seek, ";", &seek);
tile->id = current[0] - 48;
if(tile->id == TILE_NULL) continue;
tileDef = world->tilemap->tileDefinitions + tile->id;
if(tileDef->verticeCount == 0 || tileDef->indiceCount == 0) continue;
tile->verticeStart = verticeCount;
tile->indiceStart = indiceCount;
verticeCount += tileDef->verticeCount;
indiceCount += tileDef->indiceCount;
}
// Now we know how big the primitive needs to be!
free(buffer);
if(indiceCount > 0) {
chunk->primitive = primitiveCreate(verticeCount, indiceCount);
}
// For each tile
i = 0;
for(tx = 0; tx < CHUNK_WIDTH; tx++) {
for(ty = 0; ty < CHUNK_HEIGHT; ty++) {
for(tz = 0; tz < CHUNK_DEPTH; tz++) {
// Get tile for position...
tile = chunk->tiles + (i++);
// Should Chunk bother rendering?
if(tile->id == TILE_NULL) continue;
tileDef = world->tilemap->tileDefinitions + tile->id;
if(tileDef->verticeCount == 0 || tileDef->indiceCount == 0) continue;
// Render the tile's primitive
tileRender(world, chunk, tile, tileDef, tx, ty, tz);
}
}
}
}
void chunkUnload(world_t *world, chunk_t *chunk) {
// Unload the primitive
primitiveDispose(chunk->primitive);
chunk->primitive = NULL;
// Load chunks to zero. TODO: Necessary?
memset(chunk->tiles, TILE_NULL, world->count);
}

31
src/dawn/world/chunk.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
#include <string.h>
#include "worldtypes.h"
#include "tile.h"
#include "../../engine/file/asset.h"
#include "../../engine/util/string.h"
#define CHUNK_WIDTH 16
#define CHUNK_HEIGHT 16
#define CHUNK_DEPTH 8
/**
* Loads a given chunk.
*
* @param list World to load the chunk for.
* @param chunk The chunk to load.
* @param x X of the chunk.
* @param y Y of the chunk.
* @param z Z of the chunk.
*/
void chunkLoad(world_t *world, chunk_t *chunk,
int32_t x, int32_t y, int32_t z
);
/**
* Unload a given chunk.
*
* @param world World that the chunk belongs to.
* @param chunk Chunk to unload.
*/
void chunkUnload(world_t *world, chunk_t *chunk);

38
src/dawn/world/tile.c Normal file
View File

@ -0,0 +1,38 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "tile.h"
tilemap_t * tileMapCreate(int32_t columns, int32_t rows) {
tilemap_t *tilemap = malloc(sizeof(tilemap_t));
if(tilemap == NULL) return NULL;
tilemap->tileDefinitions = calloc(columns * rows, sizeof(tiledef_t));
if(!tilemap->tileDefinitions) {
free(tilemap);
return NULL;
}
return tilemap;
}
void tileMapDispose(tilemap_t *tilemap) {
free(tilemap->tileDefinitions);
free(tilemap);
}
void tileRender(world_t *world, chunk_t *chunk,
tile_t *tile, tiledef_t *tileDef, int32_t x, int32_t y, int32_t z
) {
if(tile->id == 1) {
tilesetdiv_t *div = world->tileset->divisions + tile->id;
quadBuffer(chunk->primitive, z,
x, y, div->x0, div->y0,
x+1, y+1, div->x1, div->y1,
tile->verticeStart, tile->indiceStart
);
}
}

49
src/dawn/world/tile.h Normal file
View File

@ -0,0 +1,49 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include <malloc.h>
#include "worldtypes.h"
#include "../../engine/display/tileset.h"
#include "../../engine/display/primitives/quad.h"
#include "../../engine/display/primitives/cube.h"
#define TILE_NULL 0
#define TILE_FLAG_DYNAMIC (tileflag_t)1
/**
* Creates a tilemap from a tileset.
*
* @param columns Count of columns in the tilemap.
* @param rows Count of rows in the tilemap.
* @returns The tilemap.
*/
tilemap_t * tileMapCreate(int32_t columns, int32_t rows);
/**
* Destroys a previously created tilemap.
*
* @param tilemap Tilemap to dispose.
*/
void tileMapDispose(tilemap_t *tilemap);
/**
* Rendedrs a given chunk tile.
*
* @param world The world that the chunk belongs to.
* @param chunk The chunk to render against.
* @param tile The tile to render.
* @param tileDef The tile's definition information.
* @param x The X Coordinate of the tile (chunk space).
* @param y The Y Coordinate of the tile (chunk space).
* @param z The Z Coordinate of the tile (chunk space).
*/
void tileRender(world_t *world, chunk_t *chunk,
tile_t *tile, tiledef_t *tileDef, int32_t x, int32_t y, int32_t z
);

229
src/dawn/world/world.c Normal file
View File

@ -0,0 +1,229 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "world.h"
world_t * worldLoad(char *assetWorldDirectory) {
// Define our local variables
char file [128];
char *reading, *version, *textureFilename, *temp;
world_t *world;
chunk_t *chunk;
int32_t i, x, y, z;
// Load the world file.
file[0] = '\0';
strcat(file, assetWorldDirectory);
strcat(file, "world.txt");
char *worldData = assetStringLoad(file);
if(worldData == NULL) return NULL;
// Create the world
world = malloc(sizeof(world_t));
world->assetWorldDirectory = assetWorldDirectory;
// Now begin parsing, first we need to know which version of the file format
// we are using.
reading = worldData;
version = strtok_r(reading, ";", &reading);
// Now load the tileset texture filename
textureFilename = strtok_r(reading, ";", &reading);
// Load tileset texture.
file[0] = '\0';
strcat(file, assetWorldDirectory);
strcat(file, textureFilename);
world->texture = assetTextureLoad(file);
// Finished actual loading.
free(worldData);
// Create the tileset
world->tileset = tilesetCreate(
world->texture->width/16, world->texture->height/16,
world->texture->width, world->texture->height,
0, 0, 0, 0
);
// Create the Tilemap
world->tilemap = tileMapCreate(world->tileset->columns, world->tileset->rows);
(world->tilemap->tileDefinitions + 1)->indiceCount = 6;
(world->tilemap->tileDefinitions + 1)->verticeCount = 4;
// Prepare the chunk lists
world->x = 0, world->y = 0, world->z = 0;
world->count = WORLD_WIDTH * WORLD_HEIGHT * WORLD_DEPTH;
world->tileCount = CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH;
//Create chunks
world->chunks = malloc(world->count * sizeof(chunk_t));
world->chunkList = malloc(world->count * sizeof(chunk_t *));
// Load initial chunks, ZYX order is important here.
i = 0;
for(z = 0; z < WORLD_DEPTH; z++) {
for(y = 0; y < WORLD_HEIGHT; y++) {
for(x = 0; x < WORLD_WIDTH; x++) {
chunk = world->chunks + i;
world->chunkList[i] = chunk;
// Load initial coordinates
chunk->x = x;
chunk->y = y;
chunk->z = z;
chunk->primitive = NULL;
// Init the chunk.
chunk->tiles = calloc(world->tileCount, sizeof(tile_t));
chunkLoad(world, chunk, x, y, z);
i++;
}
}
}
return world;
}
void worldRender(world_t *world, shader_t *shader) {
int32_t i, j, tx, ty, tz;
float x, y, z;
chunk_t *chunk;
tile_t *tile;
tiledef_t *tileDef;
shaderUseTexture(shader, world->texture);
for(i = 0; i < world->count; i++) {
chunk = world->chunks + i;
if(chunk->primitive == NULL) continue;
x = (chunk->x * CHUNK_WIDTH);
y = (chunk->y * CHUNK_HEIGHT);
z = (chunk->z * CHUNK_DEPTH);
// Re-render every single tile in the chunk.
// j = 0;
// for(tx = 0; tx < CHUNK_WIDTH; tx++) {
// for(ty = 0; ty < CHUNK_HEIGHT; ty++) {
// for(tz = 0; tz < CHUNK_DEPTH; tz++) {
// // Get tile for position...
// tile = chunk->tiles + (j++);
// // Should Tile bother rendering?
// if(tile->id == TILE_NULL) continue;
// tileDef = list->tilemap->tileDefinitions + tile->id;
// if(tileDef->verticeCount == 0 || tileDef->indiceCount == 0) continue;
// tileRender(list, chunk, tile, tileDef, tx, ty, tz);
// }
// }
// }
shaderUsePosition(shader, x, y, z, 0, 0, 0);
primitiveDraw(chunk->primitive, 0, chunk->primitive->indiceCount);
}
}
void worldDispose(world_t *world) {
int32_t i;
chunk_t *chunk;
// Unload the chunks
for(i = 0; i < world->count; i++) {
chunk = world->chunks + i;
chunkUnload(world, chunk);
free(chunk->tiles);
}
free(world->chunks);
textureDispose(world->texture);
tilesetDispose(world->tileset);
tileMapDispose(world->tilemap);
free(world);
}
void worldShift(world_t *world, int32_t x, int32_t y, int32_t z) {
int32_t i,
/** New List Coordinates */
lx, ly, lz,
/** New Local Chunk Coordinates */
nx, ny, nz,
/** New Absolute Chunk Coordinates */
ax, ay, az,
/** New Chunk Index */
ni,
/** Precalculated width * height */
wh
;
chunk_t *chunk;
chunk_t **chunkList;
// Calculate the new chunklist coordinates
lx = world->x + x;
ly = world->y + y;
lz = world->z + z;
// Precalc width * height.
wh = WORLD_WIDTH * WORLD_HEIGHT;
chunkList = malloc(world->count * sizeof(chunk_t *));
for(i = 0; i < world->count; i++) {
chunk = world->chunkList[i];
// Calculate the new local positions for the chunk.
nx = mathMod(chunk->x - world->x - x, WORLD_WIDTH);
ny = mathMod(chunk->y - world->y - y, WORLD_HEIGHT);
nz = mathMod(chunk->z - world->z - z, WORLD_DEPTH);
// Load the chunk if we need to. We also use this to calculate new absolutes
if(
(ax = lx + nx) != chunk->x ||
(ly + ny) != chunk->y ||
(lz + nz) != chunk->z
) {
// Calculate those things that may have not been done within the if
ay = ly + ny;
az = lz + nz;
// Load new chunk.
chunkUnload(world, chunk);
chunkLoad(world, chunk, ax, ay, az);
// Update the absolute coordinates.
chunk->x = ax;
chunk->y = ay;
chunk->z = az;
}
// Now, based off those new local positions, calculate the new index.
ni = (
nx +
(ny * WORLD_WIDTH) +
(nz * wh)
);
chunkList[ni] = chunk;
}
// Update Absolutes.
world->x = lx;
world->y = ly;
world->z = lz;
// Now copy that array over.
memcpy(world->chunkList, chunkList, sizeof(chunk_t *) * world->count);
free(chunkList);
}
void worldAlign(world_t *world, int32_t x, int32_t y, int32_t z) {
int32_t lx, ly, lz;
lx = x - world->x;
ly = y - world->y;
lz = z - world->z;
worldShift(world, lx, ly, lz);
}

68
src/dawn/world/world.h Normal file
View File

@ -0,0 +1,68 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <malloc.h>
#include <stdint.h>
#include "worldtypes.h"
#include "tile.h"
#include "chunk.h"
#include "../../engine/display/shader.h"
#include "../../engine/display/primitive.h"
#include "../../engine/display/tileset.h"
#include "../../engine/display/texture.h"
#include "../../engine/file/asset.h"
#include "../../engine/util/string.h"
#include "../../engine/util/math.h"
#define WORLD_WIDTH 1
#define WORLD_HEIGHT WORLD_WIDTH
#define WORLD_DEPTH WORLD_HEIGHT
#define CHUNK_WIDTH 16
#define CHUNK_HEIGHT 16
#define CHUNK_DEPTH 8
/**
* Create a world object.
*
* @returns The newly created world.
*/
world_t * worldLoad(char *fileName);
/**
* Render a world object to the graphics device.
*
* @param world The world to render.
* @param shader The shader to render to.
*/
void worldRender(world_t *world, shader_t *shader);
/**
* Cleans up a previously created world.
*
* @param world World to cleanup.
*/
void worldDispose(world_t *world);
/**
* Shift the world chunk list along a set of axis (in absolute space).
*
* @param world World to shift.
* @param x X movement to shift chunk along.
* @param y Y movement to shift chunk along.
* @param z Z movement to shift chunk along.
*/
void worldShift(world_t *world, int32_t x, int32_t y, int32_t z);
/**
* Align the world chunk list (in absolute space).
*
* @param world World to align.
* @param x X movement to shift chunk along.
* @param y Y movement to shift chunk along.
* @param z Z movement to shift chunk along.
*/
void worldAlign(world_t *world, int32_t x, int32_t y, int32_t z);

View File

@ -0,0 +1,45 @@
#pragma once
#include <stdint.h>
#include <malloc.h>
#include "../../engine/display/primitive.h"
#include "../../engine/display/texture.h"
#include "../../engine/display/tileset.h"
typedef uint8_t tileflag_t;
typedef uint8_t tileid_t;
typedef struct {
tileid_t id;
void *data;
int32_t indiceStart, verticeStart;
} tile_t;
typedef struct {
tileflag_t flags;
int32_t indiceCount, verticeCount;
} tiledef_t;
typedef struct {
tiledef_t *tileDefinitions;
} tilemap_t;
typedef struct chunk_t {
int32_t x, y, z;
tile_t *tiles;
primitive_t *primitive;
} chunk_t;
typedef struct {
char *assetWorldDirectory;
texture_t *texture;
tileset_t *tileset;
tilemap_t *tilemap;
int32_t x, y, z;
int32_t count;
int32_t tileCount;
chunk_t **chunkList;
chunk_t *chunks;
} world_t;