refactor separate framework from game code, add demo3d
This commit is contained in:
parent
19ae869769
commit
40f5cdcaa5
92 changed files with 2665 additions and 6547 deletions
|
|
@ -1,213 +0,0 @@
|
|||
#include "pxl8_bsp_render.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "pxl8_gfx3d.h"
|
||||
#include "pxl8_log.h"
|
||||
#include "pxl8_mem.h"
|
||||
#include "pxl8_mesh.h"
|
||||
|
||||
static inline bool pxl8_bsp_get_edge_vertex(const pxl8_bsp* bsp, i32 surfedge_idx, u32* out_vert_idx) {
|
||||
if (surfedge_idx >= (i32)bsp->num_surfedges) return false;
|
||||
|
||||
i32 edge_idx = bsp->surfedges[surfedge_idx];
|
||||
u32 vertex_index;
|
||||
|
||||
if (edge_idx >= 0) {
|
||||
if ((u32)edge_idx >= bsp->num_edges) return false;
|
||||
vertex_index = 0;
|
||||
} else {
|
||||
edge_idx = -edge_idx;
|
||||
if ((u32)edge_idx >= bsp->num_edges) return false;
|
||||
vertex_index = 1;
|
||||
}
|
||||
|
||||
*out_vert_idx = bsp->edges[edge_idx].vertex[vertex_index];
|
||||
return *out_vert_idx < bsp->num_vertices;
|
||||
}
|
||||
|
||||
static inline bool face_in_frustum(const pxl8_bsp* bsp, u32 face_id, const pxl8_frustum* frustum) {
|
||||
const pxl8_bsp_face* face = &bsp->faces[face_id];
|
||||
return pxl8_frustum_test_aabb(frustum, face->aabb_min, face->aabb_max);
|
||||
}
|
||||
|
||||
static void collect_face_to_mesh(const pxl8_bsp* bsp, const pxl8_bsp_render_state* state,
|
||||
u32 face_id, pxl8_mesh* mesh, u8 ambient) {
|
||||
const pxl8_bsp_face* face = &bsp->faces[face_id];
|
||||
if (face->num_edges < 3) return;
|
||||
|
||||
pxl8_vec3 normal = {0, 1, 0};
|
||||
if (face->plane_id < bsp->num_planes) {
|
||||
normal = bsp->planes[face->plane_id].normal;
|
||||
if (face->side) {
|
||||
normal.x = -normal.x;
|
||||
normal.y = -normal.y;
|
||||
normal.z = -normal.z;
|
||||
}
|
||||
}
|
||||
|
||||
const pxl8_gfx_material* material = NULL;
|
||||
f32 tex_scale = 64.0f;
|
||||
if (state && face->material_id < state->num_materials) {
|
||||
material = &state->materials[face->material_id];
|
||||
}
|
||||
|
||||
pxl8_vec3 u_axis = {1.0f, 0.0f, 0.0f};
|
||||
pxl8_vec3 v_axis = {0.0f, 0.0f, 1.0f};
|
||||
f32 u_offset = 0.0f, v_offset = 0.0f;
|
||||
if (material) {
|
||||
u_offset = material->u_offset;
|
||||
v_offset = material->v_offset;
|
||||
}
|
||||
f32 abs_ny = normal.y < 0 ? -normal.y : normal.y;
|
||||
if (abs_ny > 0.7f) {
|
||||
u_axis = (pxl8_vec3){1.0f, 0.0f, 0.0f};
|
||||
v_axis = (pxl8_vec3){0.0f, 0.0f, 1.0f};
|
||||
} else {
|
||||
f32 abs_nx = normal.x < 0 ? -normal.x : normal.x;
|
||||
f32 abs_nz = normal.z < 0 ? -normal.z : normal.z;
|
||||
if (abs_nx > abs_nz) {
|
||||
u_axis = (pxl8_vec3){0.0f, 0.0f, 1.0f};
|
||||
} else {
|
||||
u_axis = (pxl8_vec3){1.0f, 0.0f, 0.0f};
|
||||
}
|
||||
v_axis = (pxl8_vec3){0.0f, 1.0f, 0.0f};
|
||||
}
|
||||
|
||||
u16 base_idx = (u16)mesh->vertex_count;
|
||||
u32 num_verts = 0;
|
||||
|
||||
for (u32 i = 0; i < face->num_edges && num_verts < 64; i++) {
|
||||
u32 edge_i = face->side ? (face->num_edges - 1 - i) : i;
|
||||
i32 surfedge_idx = face->first_edge + edge_i;
|
||||
u32 vert_idx;
|
||||
|
||||
if (!pxl8_bsp_get_edge_vertex(bsp, surfedge_idx, &vert_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pxl8_vec3 pos = bsp->vertices[vert_idx].position;
|
||||
|
||||
f32 u = (pxl8_vec3_dot(pos, u_axis) + u_offset) / tex_scale;
|
||||
f32 v = (pxl8_vec3_dot(pos, v_axis) + v_offset) / tex_scale;
|
||||
|
||||
u8 light = 255;
|
||||
if (bsp->vertex_lights && vert_idx < bsp->num_vertex_lights) {
|
||||
u32 packed = bsp->vertex_lights[vert_idx];
|
||||
u8 direct = (packed >> 24) & 0xFF;
|
||||
u8 ao = (packed >> 16) & 0xFF;
|
||||
f32 combined = (f32)direct + ((f32)ambient / 255.0f) * (f32)ao;
|
||||
light = (u8)(combined > 255.0f ? 255.0f : combined);
|
||||
}
|
||||
|
||||
pxl8_vertex vtx = {
|
||||
.position = pos,
|
||||
.normal = normal,
|
||||
.u = u,
|
||||
.v = v,
|
||||
.color = 15,
|
||||
.light = light,
|
||||
};
|
||||
pxl8_mesh_push_vertex(mesh, vtx);
|
||||
num_verts++;
|
||||
}
|
||||
|
||||
if (num_verts < 3) return;
|
||||
|
||||
for (u32 i = 1; i < num_verts - 1; i++) {
|
||||
pxl8_mesh_push_triangle(mesh, base_idx, base_idx + i, base_idx + i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_bsp_render_state* pxl8_bsp_render_state_create(u32 num_faces) {
|
||||
pxl8_bsp_render_state* state = pxl8_calloc(1, sizeof(pxl8_bsp_render_state));
|
||||
if (!state) return NULL;
|
||||
|
||||
state->num_faces = num_faces;
|
||||
if (num_faces > 0) {
|
||||
state->render_face_flags = pxl8_calloc(num_faces, 1);
|
||||
if (!state->render_face_flags) {
|
||||
pxl8_free(state);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void pxl8_bsp_render_state_destroy(pxl8_bsp_render_state* state) {
|
||||
if (!state) return;
|
||||
pxl8_free(state->materials);
|
||||
pxl8_free(state->render_face_flags);
|
||||
pxl8_free(state);
|
||||
}
|
||||
|
||||
void pxl8_bsp_render(pxl8_gfx* gfx, const pxl8_bsp* bsp,
|
||||
pxl8_bsp_render_state* state,
|
||||
const pxl8_gfx_draw_opts* opts) {
|
||||
if (!gfx || !bsp || !state || bsp->num_faces == 0) return;
|
||||
if (!state->materials || state->num_materials == 0) return;
|
||||
if (!state->render_face_flags) return;
|
||||
|
||||
const pxl8_frustum* frustum = pxl8_3d_get_frustum(gfx);
|
||||
if (!frustum) return;
|
||||
|
||||
pxl8_mesh* mesh = pxl8_mesh_create(8192, 16384);
|
||||
if (!mesh) return;
|
||||
|
||||
u8 ambient = pxl8_gfx_get_ambient(gfx);
|
||||
pxl8_mat4 identity = pxl8_mat4_identity();
|
||||
|
||||
for (u32 mat = 0; mat < state->num_materials; mat++) {
|
||||
for (u32 face_id = 0; face_id < bsp->num_faces; face_id++) {
|
||||
if (!state->render_face_flags[face_id]) continue;
|
||||
const pxl8_bsp_face* face = &bsp->faces[face_id];
|
||||
if (face->material_id != mat) continue;
|
||||
if (!face_in_frustum(bsp, face_id, frustum)) continue;
|
||||
collect_face_to_mesh(bsp, state, face_id, mesh, ambient);
|
||||
}
|
||||
if (mesh->index_count > 0) {
|
||||
pxl8_gfx_material mat_copy = state->materials[mat];
|
||||
if (state->exterior) mat_copy.double_sided = true;
|
||||
pxl8_3d_draw_mesh(gfx, mesh, &identity, &mat_copy, opts);
|
||||
pxl8_mesh_clear(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_mesh_destroy(mesh);
|
||||
}
|
||||
|
||||
void pxl8_bsp_set_material(pxl8_bsp_render_state* state, u16 material_id, const pxl8_gfx_material* material) {
|
||||
if (!state || !material) return;
|
||||
|
||||
if (material_id >= state->num_materials) {
|
||||
u32 new_count = material_id + 1;
|
||||
pxl8_gfx_material* new_materials = pxl8_realloc(state->materials, new_count * sizeof(pxl8_gfx_material));
|
||||
if (!new_materials) return;
|
||||
|
||||
for (u32 i = state->num_materials; i < new_count; i++) {
|
||||
memset(&new_materials[i], 0, sizeof(pxl8_gfx_material));
|
||||
new_materials[i].u_axis = (pxl8_vec3){1.0f, 0.0f, 0.0f};
|
||||
if (i == 0 || i == 2) {
|
||||
new_materials[i].v_axis = (pxl8_vec3){0.0f, 0.0f, 1.0f};
|
||||
} else {
|
||||
new_materials[i].v_axis = (pxl8_vec3){0.0f, 1.0f, 0.0f};
|
||||
}
|
||||
}
|
||||
|
||||
state->materials = new_materials;
|
||||
state->num_materials = new_count;
|
||||
}
|
||||
|
||||
pxl8_vec3 u_axis = state->materials[material_id].u_axis;
|
||||
pxl8_vec3 v_axis = state->materials[material_id].v_axis;
|
||||
f32 u_offset = state->materials[material_id].u_offset;
|
||||
f32 v_offset = state->materials[material_id].v_offset;
|
||||
|
||||
state->materials[material_id] = *material;
|
||||
|
||||
state->materials[material_id].u_axis = u_axis;
|
||||
state->materials[material_id].v_axis = v_axis;
|
||||
state->materials[material_id].u_offset = u_offset;
|
||||
state->materials[material_id].v_offset = v_offset;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue