This commit is contained in:
2026-06-27 08:50:55 -05:00
parent 2a85c9503f
commit f17b0bfcfb
9 changed files with 390 additions and 65 deletions
+21 -10
View File
@@ -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;
+9 -11
View File
@@ -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;
+27 -16
View File
@@ -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();
}
+41 -25
View File
@@ -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");
+9 -1
View File
@@ -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.
*/