Tiles
This commit is contained in:
@@ -85,19 +85,30 @@ errorret_t assetChunkLoaderSync(assetloading_t *loading) {
|
||||
memoryCopy(out->tiles, data + offset, tileSize);
|
||||
offset += tileSize;
|
||||
|
||||
out->vertCount = endianLittleToHost32(*(uint32_t *)(data + offset));
|
||||
offset += sizeof(uint32_t);
|
||||
|
||||
out->meshCount = data[offset];
|
||||
offset += sizeof(uint8_t);
|
||||
assertTrue(
|
||||
out->vertCount <= CHUNK_VERTEX_COUNT,
|
||||
"Chunk vertex count exceeds maximum."
|
||||
out->meshCount <= CHUNK_MESH_COUNT_MAX,
|
||||
"Chunk mesh count exceeds maximum."
|
||||
);
|
||||
|
||||
memoryCopy(
|
||||
out->vertices,
|
||||
data + offset,
|
||||
out->vertCount * sizeof(meshvertex_t)
|
||||
);
|
||||
uint32_t poolOffset = 0;
|
||||
for(uint8_t m = 0; m < out->meshCount; m++) {
|
||||
uint32_t vertCount = endianLittleToHost32(*(uint32_t *)(data + offset));
|
||||
offset += sizeof(uint32_t);
|
||||
assertTrue(
|
||||
poolOffset + vertCount <= CHUNK_VERTEX_COUNT,
|
||||
"Chunk vertex data exceeds pool."
|
||||
);
|
||||
out->meshVertCounts[m] = vertCount;
|
||||
memoryCopy(
|
||||
&out->vertices[poolOffset],
|
||||
data + offset,
|
||||
vertCount * sizeof(meshvertex_t)
|
||||
);
|
||||
offset += vertCount * sizeof(meshvertex_t);
|
||||
poolOffset += vertCount;
|
||||
}
|
||||
|
||||
memoryFree(data);
|
||||
loading->loading.chunk.data = NULL;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "asset/assetfile.h"
|
||||
#include "rpg/overworld/chunk.h"
|
||||
|
||||
#define ASSET_CHUNK_FILE_VERSION 1
|
||||
#define ASSET_CHUNK_FILE_VERSION 2
|
||||
|
||||
typedef struct assetloading_s assetloading_t;
|
||||
typedef struct assetentry_s assetentry_t;
|
||||
@@ -33,7 +33,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
tile_t tiles[CHUNK_TILE_COUNT];
|
||||
uint32_t vertCount;
|
||||
uint8_t meshCount;
|
||||
uint32_t meshVertCounts[CHUNK_MESH_COUNT_MAX];
|
||||
meshvertex_t vertices[CHUNK_VERTEX_COUNT];
|
||||
} assetchunkoutput_t;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
@@ -8,24 +8,22 @@
|
||||
#pragma once
|
||||
#include "rpg/overworld/tile.h"
|
||||
#include "worldpos.h"
|
||||
#include "display/mesh/quad.h"
|
||||
#include "display/mesh/mesh.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
|
||||
// #define CHUNK_MESH_COUNT_MAX 3
|
||||
#define CHUNK_VERTEX_COUNT (QUAD_VERTEX_COUNT * CHUNK_WIDTH * CHUNK_HEIGHT * 2)
|
||||
#define CHUNK_MESH_COUNT_MAX 10
|
||||
#define CHUNK_VERTEX_COUNT 8192
|
||||
#define CHUNK_ENTITY_COUNT_MAX 10
|
||||
|
||||
typedef struct chunk_s {
|
||||
chunkpos_t position;
|
||||
tile_t tiles[CHUNK_TILE_COUNT];
|
||||
|
||||
uint8_t meshCount;
|
||||
uint32_t meshVertCounts[CHUNK_MESH_COUNT_MAX];
|
||||
meshvertex_t vertices[CHUNK_VERTEX_COUNT];
|
||||
uint32_t vertCount;
|
||||
mesh_t mesh;
|
||||
|
||||
// uint8_t meshCount;
|
||||
// meshvertex_t vertices[CHUNK_VERTEX_COUNT_MAX];
|
||||
// mesh_t meshes[CHUNK_MESH_COUNT_MAX];
|
||||
mesh_t meshes[CHUNK_MESH_COUNT_MAX];
|
||||
|
||||
uint8_t entities[CHUNK_ENTITY_COUNT_MAX];
|
||||
} chunk_t;
|
||||
|
||||
|
||||
@@ -20,12 +20,14 @@ errorret_t mapInit() {
|
||||
// Setup chunk meshes
|
||||
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
||||
chunk_t *chunk = &MAP.chunks[i];
|
||||
errorChain(meshInit(
|
||||
&chunk->mesh,
|
||||
MESH_PRIMITIVE_TYPE_TRIANGLES,
|
||||
CHUNK_VERTEX_COUNT,
|
||||
chunk->vertices
|
||||
));
|
||||
for(uint8_t j = 0; j < CHUNK_MESH_COUNT_MAX; j++) {
|
||||
errorChain(meshInit(
|
||||
&chunk->meshes[j],
|
||||
MESH_PRIMITIVE_TYPE_TRIANGLES,
|
||||
CHUNK_VERTEX_COUNT,
|
||||
chunk->vertices
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Perform "initial load"
|
||||
@@ -196,7 +198,9 @@ void mapUpdate() {
|
||||
errorret_t mapDispose() {
|
||||
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
||||
mapChunkUnload(&MAP.chunks[i]);
|
||||
errorChain(meshDispose(&MAP.chunks[i].mesh));
|
||||
for(uint8_t j = 0; j < CHUNK_MESH_COUNT_MAX; j++) {
|
||||
errorChain(meshDispose(&MAP.chunks[i].meshes[j]));
|
||||
}
|
||||
}
|
||||
errorOk();
|
||||
}
|
||||
@@ -216,14 +220,14 @@ void mapChunkUnload(chunk_t* chunk) {
|
||||
entity->type = ENTITY_TYPE_NULL;
|
||||
}
|
||||
}
|
||||
chunk->vertCount = 0;
|
||||
chunk->meshCount = 0;
|
||||
}
|
||||
|
||||
errorret_t mapChunkLoad(chunk_t* chunk) {
|
||||
if(!mapIsLoaded()) errorThrow("No map loaded");
|
||||
|
||||
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
|
||||
chunk->vertCount = 0;
|
||||
chunk->meshCount = 0;
|
||||
|
||||
char_t name[64];
|
||||
stringFormat(
|
||||
@@ -248,19 +252,26 @@ errorret_t mapChunkLoad(chunk_t* chunk) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
memoryCopy(chunk->tiles, entry->data.chunk.tiles, sizeof(chunk->tiles));
|
||||
memoryCopy(
|
||||
chunk->tiles, entry->data.chunk.tiles, sizeof(chunk->tiles)
|
||||
chunk->vertices, entry->data.chunk.vertices, sizeof(chunk->vertices)
|
||||
);
|
||||
chunk->vertCount = entry->data.chunk.vertCount;
|
||||
memoryCopy(
|
||||
chunk->vertices,
|
||||
entry->data.chunk.vertices,
|
||||
chunk->vertCount * sizeof(meshvertex_t)
|
||||
chunk->meshVertCounts,
|
||||
entry->data.chunk.meshVertCounts,
|
||||
sizeof(chunk->meshVertCounts)
|
||||
);
|
||||
uint8_t meshCount = entry->data.chunk.meshCount;
|
||||
assetUnlockEntry(entry);
|
||||
|
||||
if(chunk->vertCount == 0) errorOk();
|
||||
errorChain(meshFlush(&chunk->mesh, 0, chunk->vertCount));
|
||||
if(meshCount == 0) errorOk();
|
||||
chunk->meshCount = meshCount;
|
||||
for(uint8_t m = 0; m < meshCount; m++) {
|
||||
if(chunk->meshVertCounts[m] == 0) continue;
|
||||
errorChain(meshFlush(
|
||||
&chunk->meshes[m], 0, (int32_t)chunk->meshVertCounts[m]
|
||||
));
|
||||
}
|
||||
errorOk();
|
||||
}
|
||||
|
||||
|
||||
@@ -97,31 +97,7 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) {
|
||||
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, eye));
|
||||
|
||||
// Chunks
|
||||
{
|
||||
shadermaterial_t chunkMaterial = {
|
||||
.unlit = {
|
||||
.color = COLOR_WHITE,
|
||||
.texture = &TEXTURE_CHUNK
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t i = 0;
|
||||
for(uint8_t x = 0; x < MAP_CHUNK_WIDTH; x++) {
|
||||
for(uint8_t y = 0; y < MAP_CHUNK_HEIGHT; y++) {
|
||||
for(uint8_t z = 0; z < MAP_CHUNK_DEPTH; z++) {
|
||||
chunk_t *chunk = &MAP.chunks[i];
|
||||
if(chunk->vertCount == 0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
errorChain(shaderSetMaterial(&SHADER_UNLIT, &chunkMaterial));
|
||||
errorChain(meshDraw(&chunk->mesh, 0, chunk->vertCount));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
errorChain(sceneOverworldDrawChunks());
|
||||
|
||||
// Entities
|
||||
{
|
||||
@@ -156,6 +132,46 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) {
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t sceneOverworldDrawChunks() {
|
||||
shadermaterial_t chunkMaterial = {
|
||||
.unlit = {
|
||||
.color = COLOR_WHITE,
|
||||
.texture = &TEXTURE_CHUNK
|
||||
}
|
||||
};
|
||||
|
||||
// Pass 1: draw all base meshes with the shared chunk texture (no mid-loop
|
||||
// texture swaps).
|
||||
errorChain(shaderSetMaterial(&SHADER_UNLIT, &chunkMaterial));
|
||||
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
||||
chunk_t *chunk = &MAP.chunks[i];
|
||||
if(chunk->meshCount == 0) continue;
|
||||
if(chunk->meshVertCounts[0] == 0) continue;
|
||||
errorChain(meshDraw(
|
||||
&chunk->meshes[0], 0, (int32_t)chunk->meshVertCounts[0]
|
||||
));
|
||||
}
|
||||
|
||||
// Pass 2: draw each chunk's additional meshes (indices 1..meshCount-1).
|
||||
// Vertices are packed sequentially in the pool, so accumulate the offset.
|
||||
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
||||
chunk_t *chunk = &MAP.chunks[i];
|
||||
uint32_t vertOffset = chunk->meshVertCounts[0];
|
||||
for(uint8_t m = 1; m < chunk->meshCount; m++) {
|
||||
if(chunk->meshVertCounts[m] > 0) {
|
||||
errorChain(meshDraw(
|
||||
&chunk->meshes[m],
|
||||
(int32_t)vertOffset,
|
||||
(int32_t)chunk->meshVertCounts[m]
|
||||
));
|
||||
}
|
||||
vertOffset += chunk->meshVertCounts[m];
|
||||
}
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t sceneOverworldDispose(scenedata_t *sceneData) {
|
||||
assertNotNull(sceneData, "Scene data cannot be null");
|
||||
|
||||
|
||||
@@ -28,9 +28,17 @@ errorret_t sceneOverworldInit(scenedata_t *sceneData);
|
||||
*/
|
||||
errorret_t sceneOverworldUpdate(scenedata_t *sceneData);
|
||||
|
||||
/**
|
||||
* Draws all loaded chunks in two passes: base meshes first (shared texture,
|
||||
* no binds between chunks), then each chunk's additional meshes.
|
||||
*
|
||||
* @return An error if drawing failed, or errorOk() on success.
|
||||
*/
|
||||
errorret_t sceneOverworldDrawChunks();
|
||||
|
||||
/**
|
||||
* Renders the overworld scene.
|
||||
*
|
||||
*
|
||||
* @param sceneData The scene data used for this scene.
|
||||
* @return An error if the render failed, or errorOk() if it succeeded.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user