165 lines
4.2 KiB
C
165 lines
4.2 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "scene/scene.h"
|
|
#include "console/console.h"
|
|
#include "assert/assert.h"
|
|
|
|
#include "display/shader/shader.h"
|
|
#include "display/screen/screen.h"
|
|
#include "display/shader/shaderunlit.h"
|
|
#include "display/spritebatch/spritebatch.h"
|
|
#include "display/texture/texture.h"
|
|
|
|
#include "rpg/overworld/map.h"
|
|
#include "rpg/entity/entity.h"
|
|
#include "rpg/rpgcamera.h"
|
|
|
|
#define TEXTURE_CHUNK_SIZE 16
|
|
|
|
static texture_t TEXTURE_CHUNK;
|
|
static color_t TEXTURE_CHUNK_PIXELS[TEXTURE_CHUNK_SIZE * TEXTURE_CHUNK_SIZE];
|
|
|
|
errorret_t sceneOverworldInit(scenedata_t *sceneData) {
|
|
assertNotNull(sceneData, "Scene data cannot be null");
|
|
|
|
for(uint32_t i = 0; i < TEXTURE_CHUNK_SIZE * TEXTURE_CHUNK_SIZE; i++) {
|
|
uint8_t r = (uint8_t)((i & 7) * 36);
|
|
uint8_t g = (uint8_t)(((i >> 3) & 7) * 36);
|
|
uint8_t b = (uint8_t)((i >> 6) * 85);
|
|
TEXTURE_CHUNK_PIXELS[i] = color4b(r, g, b, 255);
|
|
}
|
|
errorChain(textureInit(
|
|
&TEXTURE_CHUNK,
|
|
TEXTURE_CHUNK_SIZE, TEXTURE_CHUNK_SIZE,
|
|
TEXTURE_FORMAT_RGBA,
|
|
(texturedata_t){ .rgbaColors = TEXTURE_CHUNK_PIXELS }
|
|
));
|
|
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t sceneOverworldUpdate(scenedata_t *sceneData) {
|
|
assertNotNull(sceneData, "Scene data cannot be null");
|
|
|
|
|
|
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t sceneOverworldRender(scenedata_t *sceneData) {
|
|
assertNotNull(sceneData, "Scene data cannot be null");
|
|
|
|
mat4 proj, model, eye;
|
|
|
|
|
|
errorChain(shaderBind(&SHADER_UNLIT));
|
|
|
|
// Model
|
|
glm_mat4_identity(model);
|
|
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model));
|
|
|
|
// Camera projection
|
|
float_t fov = glm_rad(45.0f);
|
|
glm_perspective(
|
|
fov,
|
|
SCREEN.aspect,
|
|
0.1f,
|
|
100.0f,
|
|
proj
|
|
);
|
|
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj));
|
|
|
|
// Camera Eye
|
|
float_t pixelsPerUnit = TILE_SIZE_PIXELS;
|
|
float_t worldH = (float_t)SCREEN.height / pixelsPerUnit;
|
|
float_t z = (worldH * 0.5f) / tanf(fov * 0.5f);
|
|
vec3 worldPosVec;
|
|
rpgCameraGetPosition(worldPosVec);
|
|
float_t offset = -24.0f * (worldH / TILE_SIZE_PIXELS);
|
|
|
|
glm_vec3_add(worldPosVec, (vec3){ 0.5f, 0.5f, 0.5f }, worldPosVec);
|
|
|
|
glm_lookat(
|
|
(vec3){
|
|
worldPosVec[0],
|
|
worldPosVec[1] + offset,
|
|
worldPosVec[2] + z
|
|
},
|
|
worldPosVec,
|
|
(vec3){ 0, 1, 0 }, // up
|
|
eye
|
|
);
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Entities
|
|
{
|
|
for(uint8_t i = 0; i < ENTITY_COUNT; i++) {
|
|
entity_t *ent = &ENTITIES[i];
|
|
if(ent->type == ENTITY_TYPE_NULL) continue;
|
|
|
|
spritebatchsprite_t sprite;
|
|
glm_vec3_copy(ent->renderPosition, sprite.min);
|
|
glm_vec3_copy(ent->renderPosition, sprite.max);
|
|
glm_vec3_add(sprite.max, (vec3){ 1, 1, 0 }, sprite.max);
|
|
glm_vec2_copy((vec2){ 0, 0 }, sprite.uvMin);
|
|
glm_vec2_copy((vec2){ 1, 1 }, sprite.uvMax);
|
|
|
|
color_t color;
|
|
switch(ent->direction) {
|
|
case ENTITY_DIR_NORTH: color = COLOR_YELLOW; break;
|
|
case ENTITY_DIR_EAST: color = COLOR_RED; break;
|
|
case ENTITY_DIR_SOUTH: color = COLOR_GREEN; break;
|
|
case ENTITY_DIR_WEST: color = COLOR_BLUE; break;
|
|
default: color = COLOR_CYAN; break;
|
|
}
|
|
|
|
shadermaterial_t material = {
|
|
.unlit = { .color = color, .texture = NULL }
|
|
};
|
|
spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, material);
|
|
spriteBatchFlush();
|
|
}
|
|
}
|
|
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t sceneOverworldDispose(scenedata_t *sceneData) {
|
|
assertNotNull(sceneData, "Scene data cannot be null");
|
|
|
|
errorChain(textureDispose(&TEXTURE_CHUNK));
|
|
|
|
errorOk();
|
|
} |