From 493477bf0d76669bcd3703ca4c5a994e0b754447 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Mon, 5 Apr 2021 13:58:17 +1000 Subject: [PATCH] Built tileset logic --- src/engine/display/primitives/quad.c | 14 +++--- src/engine/display/primitives/quad.h | 7 ++- src/engine/display/spritebatch.c | 8 ++-- src/engine/display/spritebatch.h | 2 +- src/engine/display/tileset.c | 68 ++++++++++++++++++++++++++++ src/engine/display/tileset.h | 62 +++++++++++++++++++++++++ src/engine/engine.c | 9 +++- src/engine/util/math.h | 6 +-- src/engine/world/chunk.c | 37 +++++++-------- src/engine/world/chunk.h | 17 +++++-- src/engine/world/chunklist.c | 6 +-- src/engine/world/world.c | 2 +- 12 files changed, 193 insertions(+), 45 deletions(-) create mode 100644 src/engine/display/tileset.c create mode 100644 src/engine/display/tileset.h diff --git a/src/engine/display/primitives/quad.c b/src/engine/display/primitives/quad.c index 28821cdd..5c2938da 100644 --- a/src/engine/display/primitives/quad.c +++ b/src/engine/display/primitives/quad.c @@ -7,7 +7,7 @@ #include "quad.h" -void quadBuffer(primitive_t *primitive, +void quadBuffer(primitive_t *primitive, float z, float x0, float y0, float u0, float v0, float x1, float y1, float u1, float v1, int32_t verticeStart, int32_t indiceStart @@ -15,16 +15,16 @@ void quadBuffer(primitive_t *primitive, vertice_t *vertices = malloc(sizeof(vertice_t) * QUAD_VERTICE_COUNT); indice_t *indices = malloc(sizeof(indice_t) * QUAD_INDICE_COUNT); - vertices[0].x = x0, vertices[0].y = y0, vertices[0].z = 0; + vertices[0].x = x0, vertices[0].y = y0, vertices[0].z = z; vertices[0].u = u0, vertices[0].v = v0; - vertices[1].x = x1, vertices[1].y = y0, vertices[1].z = 0; + vertices[1].x = x1, vertices[1].y = y0, vertices[1].z = z; vertices[1].u = u1, vertices[1].v = v0; - vertices[2].x = x0, vertices[2].y = y1, vertices[2].z = 0; + vertices[2].x = x0, vertices[2].y = y1, vertices[2].z = z; vertices[2].u = u0, vertices[2].v = v1; - vertices[3].x = x1, vertices[3].y = y1, vertices[3].z = 0; + vertices[3].x = x1, vertices[3].y = y1, vertices[3].z = z; vertices[3].u = u1, vertices[3].v = v1; indices[0] = (indice_t)(verticeStart + 0); @@ -42,13 +42,13 @@ void quadBuffer(primitive_t *primitive, free(indices); } -primitive_t * quadCreate( +primitive_t * quadCreate(float z, float x0, float y0, float u0, float v0, float x1, float y1, float u1, float v1 ) { primitive_t *primitive = primitiveCreate(4, 6); - quadBuffer(primitive, + quadBuffer(primitive, z, x0, y0, u0, v0, x1, y1, u1, v1, 0, 0 diff --git a/src/engine/display/primitives/quad.h b/src/engine/display/primitives/quad.h index fbd5e807..67dea4d2 100644 --- a/src/engine/display/primitives/quad.h +++ b/src/engine/display/primitives/quad.h @@ -13,6 +13,8 @@ /** * Buffers the vertices of a quad onto a primitive. * + * @param primitive The primitive to buffer to. + * @param z The Z axis coordinate of the quad. * @param x0 The X lower coordinate. * @param y0 The Y lower coordinate. * @param u0 The X lower texture coordinate. @@ -24,7 +26,7 @@ * @param verticeStart Start vertice to buffer to. * @param indiceStart Start indice to buffer to. */ -void quadBuffer(primitive_t *primitive, +void quadBuffer(primitive_t *primitive, float z, float x0, float y0, float u0, float v0, float x1, float y1, float u1, float v1, int32_t verticeStart, int32_t indiceStart @@ -33,6 +35,7 @@ void quadBuffer(primitive_t *primitive, /** * Creates a new quad primitive. * + * @param z The Z axis coordinate of the quad. * @param x0 The X lower coordinate. * @param y0 The Y lower coordinate. * @param u0 The X lower texture coordinate. @@ -43,7 +46,7 @@ void quadBuffer(primitive_t *primitive, * @param v1 The Y higher texture coordinate. * @return The quad primitive. */ -primitive_t * quadCreate( +primitive_t * quadCreate(float z, float x0, float y0, float u0, float v0, float x1, float y1, float u1, float v1 ); \ No newline at end of file diff --git a/src/engine/display/spritebatch.c b/src/engine/display/spritebatch.c index 883faed7..ee14042a 100644 --- a/src/engine/display/spritebatch.c +++ b/src/engine/display/spritebatch.c @@ -26,16 +26,16 @@ spritebatch_t * spriteBatchCreate(int32_t maxSprites) { } void spriteBatchQuad(spritebatch_t *spriteBatch, int32_t index, - float x, float y, float width, float height, + float x, float y, float z, float width, float height, float u0, float v0, float u1, float v1 ) { if(index == -1) { index = spriteBatch->currentSprite++; } else { - spriteBatch->currentSprite = max(index, spriteBatch->currentSprite); + spriteBatch->currentSprite = mathMax(index, spriteBatch->currentSprite); } - quadBuffer(spriteBatch->primitive, + quadBuffer(spriteBatch->primitive, z, x, y, u0, v0, x+width, y+height, u1, v1, index*QUAD_VERTICE_COUNT, index*QUAD_INDICE_COUNT @@ -54,6 +54,6 @@ void spriteBatchDraw(spritebatch_t *spriteBatch, int32_t index, int32_t count) { } void spriteBatchDispose(spritebatch_t *spriteBatch) { - primitiveDispose(spriteBatch); + primitiveDispose(spriteBatch->primitive); free(spriteBatch); } \ No newline at end of file diff --git a/src/engine/display/spritebatch.h b/src/engine/display/spritebatch.h index 3f255f27..89e5df4d 100644 --- a/src/engine/display/spritebatch.h +++ b/src/engine/display/spritebatch.h @@ -43,7 +43,7 @@ spritebatch_t * spriteBatchCreate(int32_t maxSprites); * @param v1 Texture V coordinate (max). */ void spriteBatchQuad(spritebatch_t *spriteBatch, int32_t index, - float x, float y, float width, float height, + float x, float y, float z, float width, float height, float u0, float v0, float u1, float v1 ); diff --git a/src/engine/display/tileset.c b/src/engine/display/tileset.c new file mode 100644 index 00000000..904f4b57 --- /dev/null +++ b/src/engine/display/tileset.c @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "tileset.h" + +tileset_t * tilesetCreate( + int32_t columns, int32_t rows, + int32_t gapX, int32_t gapY, + int32_t borderX, int32_t borderY, + int32_t width, int32_t height +) { + tileset_t *tileset; + float divX, divY, tdivX; + int32_t x, y, i, j, count; + + + tileset = malloc(sizeof(tileset_t)); + + if(tileset == NULL) return NULL; + + count = rows * columns; + tileset->divisions = malloc(sizeof(tilesetdiv_t) * count); + if(tileset->divisions == NULL) { + free(tileset); + return NULL; + } + + tileset->columns = columns; + tileset->rows = rows; + + // Calculate division sizes (pixels) + divX = (width - (borderX * 2) - (gapX * (columns - 1))) / columns; + divY = (height - (borderY * 2) - (gapY * (rows - 1))) / rows; + + // Calculate the division sizes (units) + divX = divX / width; + divY = divY / height; + + // Calculate the divisions + i = -1; + for(y = 0; y < rows; y++) { + for(x = 0; x < columns; x++) { + tileset->divisions[++i].x0 = borderX + (divX * x) + (gapX * x); + tileset->divisions[i].y0 = borderY + (divY * y) + (gapY * y); + tileset->divisions[i].x1 = tileset->divisions[i].x0 + divX; + tileset->divisions[i].y1 = tileset->divisions[i].y0 + divY; + } + } + + return tileset; +} + +tilesetdiv_t tilesetGetDivision(tileset_t *tileset, + int32_t column, int32_t row +) { + return tileset->divisions[ + (column % tileset->columns) + (row * tileset->columns) + ]; +} + +void tilesetDispose(tileset_t *tileset) { + free(tileset->divisions); + free(tileset); +} \ No newline at end of file diff --git a/src/engine/display/tileset.h b/src/engine/display/tileset.h new file mode 100644 index 00000000..bcf9d85f --- /dev/null +++ b/src/engine/display/tileset.h @@ -0,0 +1,62 @@ +// Copyright (c) 2021 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include +#include + +/** Division of a texture */ +typedef struct { + float x0, y0, x1, y1; +} tilesetdiv_t; + +/** Definition of a Tileset */ +typedef struct { + /** Count of X/Y divisions */ + int32_t columns, rows; + + /** Division information */ + tilesetdiv_t *divisions; +} tileset_t; + + +/** + * Create a tileset. Tilesets will be pre-divided to save performance later. + * + * @param columns Count of columns. + * @param rows Count of rows. + * @param gapX Space between each column. + * @param gapY Space between each row. + * @param borderX Space around the edge of the tileset. + * @param borderY Space around the edge of the tileset. + * @param width Width of the tileset. + * @param height Height of the tileset. + * @returns The tileset. + */ +tileset_t * tilesetCreate( + int32_t columns, int32_t rows, + int32_t gapX, int32_t gapY, + int32_t borderX, int32_t borderY, + int32_t width, int32_t height +); + +/** + * Retreive the division for a given tileset coordinate. + * + * @param tileset Tileset to retreive from. + * @param column X axis of the tileset. + * @param row Y axis of the tileset. + * @returns The Tileset division. + */ +tilesetdiv_t tilesetGetDivision(tileset_t *tileset, + int32_t column, int32_t row +); + +/** + * Cleans a previously created tileset + * + * @param tileset Cleanup the tileset. + */ +void tilesetDispose(tileset_t *tileset); \ No newline at end of file diff --git a/src/engine/engine.c b/src/engine/engine.c index bafe1181..7df15eea 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -12,6 +12,8 @@ shader_t *shader; world_t *world; spritebatch_t *batch; +int i; + engine_t * engineInit(platform_t *platform, char *name, uint32_t inputCount) { // Create the engine instance. engine_t *engine = malloc(sizeof(engine_t)); @@ -38,13 +40,14 @@ engine_t * engineInit(platform_t *platform, char *name, uint32_t inputCount) { shader = assetShaderLoad("shaders/test.vert", "shaders/test.frag"); camera = cameraCreate(); cameraLookAt(camera, - 5, 5, 5, + 30, 30, 30, 0, 0, 0 ); cameraPerspective(camera, 45.0f, 1920.0f/1080.0f, 0.5f, 100.0f); shaderUseCamera(shader, camera); world = worldCreate(); + i = 0; return engine; } @@ -55,6 +58,10 @@ uint32_t engineUpdate(engine_t *engine) { worldRender(world, shader); + if((++i % 10000) == 0) { + chunkListShift(world->chunkList, 0, 0, 1); + } + inputUpdate(engine->input); return 0; } diff --git a/src/engine/util/math.h b/src/engine/util/math.h index 22508725..b32a0852 100644 --- a/src/engine/util/math.h +++ b/src/engine/util/math.h @@ -5,6 +5,6 @@ #pragma once -#define mod(a,b) (a%b+b)%b -#define max(a,b) (ab?b:a) \ No newline at end of file +#define mathMod(a,b) (a%b+b)%b +#define mathMax(a,b) (ab?b:a) \ No newline at end of file diff --git a/src/engine/world/chunk.c b/src/engine/world/chunk.c index 348e6292..8d14350a 100644 --- a/src/engine/world/chunk.c +++ b/src/engine/world/chunk.c @@ -8,38 +8,39 @@ #include "chunk.h" void chunkCreate(chunk_t *chunk) { - int32_t count, x, y, z, i; + int32_t count, x, y, i; count = CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH; - chunk->primitive = primitiveCreate(count * 4, count * 6); - - i = 0; - for(z = 0; z < CHUNK_DEPTH; z++) { - for(y = 0; y < CHUNK_HEIGHT; y++) { - for(x = 0; x < CHUNK_WIDTH; x++) { - quadBuffer(chunk->primitive, - x, y, 0, 0, - x+1, y+1, 1, 1, - i*4, i*6 - ); - i++; - } - } - } + chunk->batch = spriteBatchCreate(count); + chunk->tiles = malloc(sizeof(tile_t) * count); } void chunkRender(chunk_t *chunk, shader_t *shader) { + // Coordinates of the chunk. float x, y, z; x = (chunk->x * CHUNK_WIDTH); y = (chunk->y * CHUNK_HEIGHT); z = (chunk->z * CHUNK_DEPTH); - shaderUsePosition(shader, x*2, y*2, z*2, 0, 0, 0); - primitiveDraw(chunk->primitive, 0, chunk->primitive->indiceCount); + // Render the batch. + shaderUsePosition(shader, x, y, z, 0, 0, 0); + spriteBatchDraw(chunk->batch, 0, -1); } void chunkLoad(chunk_t *chunk, int32_t x, int32_t y, int32_t z) { + int32_t tx, ty, tz; + spriteBatchFlush(chunk->batch); + + // for(tx = 0; tx < CHUNK_WIDTH; tx++) { + // for(ty = 0; ty < CHUNK_HEIGHT; ty++) { + // for(tz = 0; tz < CHUNK_DEPTH; tz++) { + // spriteBatchQuad(chunk->batch, -1, + // x, y, z, 1, 1, 0, 0, 1, 1 + // ); + // } + // } + // } } void chunkUnload(chunk_t *chunk) { diff --git a/src/engine/world/chunk.h b/src/engine/world/chunk.h index e7ea6f2b..82205a18 100644 --- a/src/engine/world/chunk.h +++ b/src/engine/world/chunk.h @@ -7,7 +7,7 @@ #include #include "../display/primitive.h" #include "../display/shader.h" -#include "../display/primitives/quad.h" +#include "../display/spritebatch.h" #define CHUNK_WIDTH 3 #define CHUNK_HEIGHT CHUNK_WIDTH @@ -16,9 +16,14 @@ typedef uint8_t tile_t; typedef struct { + /** Absolute X Y Z chunklist coordinates */ int32_t x, y, z; + + /** Tiles within the chunk */ tile_t *tiles; - primitive_t *primitive; + + /** Sprite Batch for holding static tiles */ + spritebatch_t *batch; } chunk_t; @@ -29,8 +34,6 @@ typedef struct { */ void chunkCreate(chunk_t *chunk); -void chunkRender(chunk_t *chunk, shader_t *shader); - /** * Loads a given chunk into the memory specified. * @@ -46,4 +49,8 @@ void chunkLoad(chunk_t *chunk, int32_t x, int32_t y, int32_t z); * * @param chunk Chunk to unload. */ -void chunkUnload(chunk_t *chunk); \ No newline at end of file +void chunkUnload(chunk_t *chunk); + + + +void chunkRender(chunk_t *chunk, shader_t *shader); \ No newline at end of file diff --git a/src/engine/world/chunklist.c b/src/engine/world/chunklist.c index 98b05865..a64ca831 100644 --- a/src/engine/world/chunklist.c +++ b/src/engine/world/chunklist.c @@ -90,9 +90,9 @@ void chunkListShift(chunklist_t *list, int32_t x, int32_t y, int32_t z) { chunk = list->chunkList[i]; // Calculate the new local positions for the chunk. - nx = mod(chunk->x - list->x - x, list->width); - ny = mod(chunk->y - list->y - y, list->height); - nz = mod(chunk->z - list->z - z, list->depth); + nx = mathMod(chunk->x - list->x - x, list->width); + ny = mathMod(chunk->y - list->y - y, list->height); + nz = mathMod(chunk->z - list->z - z, list->depth); // Load the chunk if we need to. We also use this to calculate new absolutes if( diff --git a/src/engine/world/world.c b/src/engine/world/world.c index 7813083a..73cf20e5 100644 --- a/src/engine/world/world.c +++ b/src/engine/world/world.c @@ -11,7 +11,7 @@ world_t * worldCreate() { world_t *world = malloc(sizeof(world_t)); if(world == NULL) return NULL; - world->chunkList = chunkListCreate(3, 3, 1); + world->chunkList = chunkListCreate(3, 3, 3); if(world->chunkList == NULL) { free(world); return NULL;