main
Dominik Madarász 2024-08-19 11:38:59 +02:00
parent ff7f42aeb9
commit 657d6dcf85
12 changed files with 374328 additions and 1 deletions

2
.gitignore vendored
View File

@ -35,7 +35,7 @@ _fwk
*.dbg
_cache
*.exp
*.obj
./*.obj
*.exe
*.ilk
*.dll

BIN
99-terrain.obj 100644

Binary file not shown.

48
demos/99-terrain.c 100644
View File

@ -0,0 +1,48 @@
#include "v4k.h"
int main() {
window_create(80, WINDOW_MSAA4);
window_title(__FILE__);
// load skybox: launch with --mie for rayleigh/mie scattering
skybox_t sky = skybox(flag("--mie") ? 0 : "cubemaps/stardust", 0);
// terrain model
// model_t mdl = model("terrain_demo.obj", 0);
model_t mdl = model("Mike.fbx", 0);
// camera
camera_t cam = camera();
// scene light
shader_bind(mdl.program);
light_t *l = scene_spawn_light();
light_update(1, l);
skybox_sh_shader(&sky);
// initialise LOD
model_lod(&mdl, 1.0, 1.0, 1);
// demo loop
while (window_swap())
{
// input
if( input_down(KEY_ESC) ) break;
if( input_down(KEY_F5) ) window_reload();
if( input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen() ^ 1 );
// fps camera
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
camera_moveby(&cam, wasdecq);
camera_fps(&cam, mouse.x,mouse.y);
window_cursor( !active );
// draw scene
skybox_render(&sky, cam.proj, cam.view);
model_render(mdl, cam.proj, cam.view, mdl.pivot, 0);
}
}

View File

@ -0,0 +1,12 @@
# Blender 4.0.2 MTL File: 'None'
# www.blender.org
newmtl Material.003
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2

File diff suppressed because it is too large Load Diff

View File

@ -17467,6 +17467,7 @@ API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
API void skybox_destroy(skybox_t *sky);
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
API void skybox_sh_reset(skybox_t *sky);
API void skybox_sh_shader(skybox_t *sky);
API void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength);
API int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
@ -17638,6 +17639,12 @@ typedef struct model_t {
int num_tris;
handle vao, ibo, vbo, vao_instanced;
array(int) lod_collapse_map; // to which neighbor each vertex collapses. ie, [10] -> 7 (used by LODs) @leak
void *lod_verts;
int lod_num_verts;
void *lod_tris;
int lod_num_tris;
unsigned flags;
unsigned billboard;
@ -17663,6 +17670,7 @@ API float model_animate(model_t, float curframe);
API float model_animate_clip(model_t, float curframe, int minframe, int maxframe, bool loop);
API float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float delta);
API aabb model_aabb(model_t, mat44 transform);
API void model_lod(model_t*, float lo_detail, float hi_detail, float morph);
API void model_shading(model_t*, int shading);
API void model_skybox(model_t*, skybox_t sky, bool load_sh);
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
@ -383642,6 +383650,10 @@ void skybox_sh_reset(skybox_t *sky) {
}
}
void skybox_sh_shader(skybox_t *sky) {
shader_vec3v("u_coefficients_sh", 9, sky->cubemap.sh);
}
void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
// Normalize the direction
vec3 norm_dir = norm3(dir);
@ -386010,6 +386022,147 @@ aabb model_aabb(model_t m, mat44 transform) {
return aabb(vec3(0,0,0),vec3(0,0,0));
}
static inline int MapReduce(array(int) collapse_map, int n, int mx) {
while( n >= mx ) n = collapse_map[n];
return n;
}
API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, const int *tri, int *map, int *permutation);
void model_lod(model_t *mdl, float lo_detail, float hi_detail, float morph) {
assert(mdl->num_meshes == 1);
if (array_count(mdl->lod_collapse_map) == 0) {
array(int) permutation = 0;
array_resize(mdl->lod_collapse_map, mdl->num_verts);
array_resize(permutation, mdl->num_verts);
ProgressiveMesh(mdl->num_verts, mdl->stride, (const float *)mdl->verts, mdl->num_tris, (const int *)mdl->tris, mdl->lod_collapse_map, permutation);
// PermuteVertices {
ASSERT(array_count(permutation) == mdl->num_verts);
// rearrange the vertex Array
char *tmp = REALLOC(0, mdl->stride*mdl->num_verts);
char *verts = (char *)mdl->verts;
memcpy(tmp, verts, mdl->stride*mdl->num_verts);
for(int i = 0; i < mdl->num_verts; i++) {
int index = permutation[i];
int src_offset = i * mdl->stride;
int offset = index * mdl->stride;
memcpy(verts + offset, tmp + src_offset, mdl->stride);
}
int *tris = (int *)mdl->tris;
// update the changes in the entries in the triangle Array
for (int i = 0; i < mdl->num_tris*3; i+=3) {
tris[i+0] = permutation[tris[i+0]];
tris[i+1] = permutation[tris[i+1]];
tris[i+2] = permutation[tris[i+2]];
}
// upload modified data
glBindVertexArray(mdl->vao);
glBindBuffer(GL_ARRAY_BUFFER, mdl->vbo);
glBufferData(GL_ARRAY_BUFFER, mdl->num_verts*mdl->stride, mdl->verts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdl->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mdl->num_tris*3*sizeof(int), mdl->tris, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
FREE(tmp);
// } PermuteVertices
array_free(permutation);
}
ASSERT(array_count(mdl->lod_collapse_map));
int max_verts_to_render = hi_detail * mdl->num_verts;
int min_verts_to_render = lo_detail * mdl->num_verts;
if( max_verts_to_render <= 0 || min_verts_to_render <= 0 )
return;
FREE(mdl->lod_verts);
FREE(mdl->lod_tris);
char *verts = (char *)mdl->verts;
int *tris = (int *)mdl->tris;
int max_lod_tris = 0;
//@fixme: optimise
for( unsigned int i = 0; i < mdl->num_tris*3; i+=3 ) {
int p0 = MapReduce(mdl->lod_collapse_map, tris[i+0], max_verts_to_render);
int p1 = MapReduce(mdl->lod_collapse_map, tris[i+1], max_verts_to_render);
int p2 = MapReduce(mdl->lod_collapse_map, tris[i+2], max_verts_to_render);
if(p0==p1 || p0==p2 || p1==p2) continue;
++max_lod_tris;
}
mdl->lod_verts = REALLOC(0, max_lod_tris*3*mdl->stride);
mdl->lod_tris = REALLOC(0, max_lod_tris*3*sizeof(int));
mdl->lod_num_verts = 0;
mdl->lod_num_tris = 0;
struct iqm_vertex *lod_verts = (struct iqm_vertex *)mdl->lod_verts;
int *lod_tris = (int *)mdl->lod_tris;
for( int i = 0; i < mdl->num_tris*3; i+=3 ) {
int p0 = MapReduce(mdl->lod_collapse_map, tris[i+0], max_verts_to_render);
int p1 = MapReduce(mdl->lod_collapse_map, tris[i+1], max_verts_to_render);
int p2 = MapReduce(mdl->lod_collapse_map, tris[i+2], max_verts_to_render);
// @fixme: serious optimization opportunity here,
// by sorting the triangles the following "continue"
// could have been made into a "break" statement.
if(p0==p1 || p0==p2 || p1==p2) continue;
// if we are not currenly morphing between 2 levels of detail
// (i.e. if morph=1.0) then q0,q1, and q2 may not be necessary
int q0 = MapReduce(mdl->lod_collapse_map, p0, min_verts_to_render);
int q1 = MapReduce(mdl->lod_collapse_map, p1, min_verts_to_render);
int q2 = MapReduce(mdl->lod_collapse_map, p2, min_verts_to_render);
struct iqm_vertex v0 = *(struct iqm_vertex *)(verts + (p0*mdl->stride));
struct iqm_vertex v1 = *(struct iqm_vertex *)(verts + (p1*mdl->stride));
struct iqm_vertex v2 = *(struct iqm_vertex *)(verts + (p2*mdl->stride));
lod_verts[mdl->lod_num_verts++] = v0;
lod_verts[mdl->lod_num_verts++] = v1;
lod_verts[mdl->lod_num_verts++] = v2;
int idx = mdl->lod_num_verts;
lod_tris[mdl->lod_num_tris + 0] = idx-3;
lod_tris[mdl->lod_num_tris + 1] = idx-2;
lod_tris[mdl->lod_num_tris + 2] = idx-1;
++mdl->lod_num_tris;
// vec3 v0, v1, v2;
// v0 = mix3(m->in_vertex3[p0], m->in_vertex3[q0], (1-morph));
// v1 = mix3(m->in_vertex3[p1], m->in_vertex3[q1], (1-morph));
// v2 = mix3(m->in_vertex3[p2], m->in_vertex3[q2], (1-morph));
// vec3 normal = norm3(cross3(sub3(v1,v0),sub3(v2,v1)));
// array_push(m->out_vertex3, v0);
// array_push(m->out_vertex3, normal);
// array_push(m->out_vertex3, v1);
// array_push(m->out_vertex3, normal);
// array_push(m->out_vertex3, v2);
// array_push(m->out_vertex3, normal);
// int idx = array_count(m->out_vertex3) / 2;
// array_push(m->out_index3, vec3i(idx-3,idx-2,idx-1));
}
// upload modified data
glBindVertexArray(mdl->vao);
glBindBuffer(GL_ARRAY_BUFFER, mdl->vbo);
glBufferData(GL_ARRAY_BUFFER, mdl->lod_num_verts*mdl->stride, mdl->lod_verts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdl->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mdl->lod_num_tris*3*sizeof(int), mdl->lod_tris, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void model_destroy(model_t m) {
FREE(m.verts);
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {

View File

@ -2037,6 +2037,10 @@ void skybox_sh_reset(skybox_t *sky) {
}
}
void skybox_sh_shader(skybox_t *sky) {
shader_vec3v("u_coefficients_sh", 9, sky->cubemap.sh);
}
void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
// Normalize the direction
vec3 norm_dir = norm3(dir);
@ -4405,6 +4409,147 @@ aabb model_aabb(model_t m, mat44 transform) {
return aabb(vec3(0,0,0),vec3(0,0,0));
}
static inline int MapReduce(array(int) collapse_map, int n, int mx) {
while( n >= mx ) n = collapse_map[n];
return n;
}
API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, const int *tri, int *map, int *permutation);
void model_lod(model_t *mdl, float lo_detail, float hi_detail, float morph) {
assert(mdl->num_meshes == 1);
if (array_count(mdl->lod_collapse_map) == 0) {
array(int) permutation = 0;
array_resize(mdl->lod_collapse_map, mdl->num_verts);
array_resize(permutation, mdl->num_verts);
ProgressiveMesh(mdl->num_verts, mdl->stride, (const float *)mdl->verts, mdl->num_tris, (const int *)mdl->tris, mdl->lod_collapse_map, permutation);
// PermuteVertices {
ASSERT(array_count(permutation) == mdl->num_verts);
// rearrange the vertex Array
char *tmp = REALLOC(0, mdl->stride*mdl->num_verts);
char *verts = (char *)mdl->verts;
memcpy(tmp, verts, mdl->stride*mdl->num_verts);
for(int i = 0; i < mdl->num_verts; i++) {
int index = permutation[i];
int src_offset = i * mdl->stride;
int offset = index * mdl->stride;
memcpy(verts + offset, tmp + src_offset, mdl->stride);
}
int *tris = (int *)mdl->tris;
// update the changes in the entries in the triangle Array
for (int i = 0; i < mdl->num_tris*3; i+=3) {
tris[i+0] = permutation[tris[i+0]];
tris[i+1] = permutation[tris[i+1]];
tris[i+2] = permutation[tris[i+2]];
}
// upload modified data
glBindVertexArray(mdl->vao);
glBindBuffer(GL_ARRAY_BUFFER, mdl->vbo);
glBufferData(GL_ARRAY_BUFFER, mdl->num_verts*mdl->stride, mdl->verts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdl->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mdl->num_tris*3*sizeof(int), mdl->tris, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
FREE(tmp);
// } PermuteVertices
array_free(permutation);
}
ASSERT(array_count(mdl->lod_collapse_map));
int max_verts_to_render = hi_detail * mdl->num_verts;
int min_verts_to_render = lo_detail * mdl->num_verts;
if( max_verts_to_render <= 0 || min_verts_to_render <= 0 )
return;
FREE(mdl->lod_verts);
FREE(mdl->lod_tris);
char *verts = (char *)mdl->verts;
int *tris = (int *)mdl->tris;
int max_lod_tris = 0;
//@fixme: optimise
for( unsigned int i = 0; i < mdl->num_tris*3; i+=3 ) {
int p0 = MapReduce(mdl->lod_collapse_map, tris[i+0], max_verts_to_render);
int p1 = MapReduce(mdl->lod_collapse_map, tris[i+1], max_verts_to_render);
int p2 = MapReduce(mdl->lod_collapse_map, tris[i+2], max_verts_to_render);
if(p0==p1 || p0==p2 || p1==p2) continue;
++max_lod_tris;
}
mdl->lod_verts = REALLOC(0, max_lod_tris*3*mdl->stride);
mdl->lod_tris = REALLOC(0, max_lod_tris*3*sizeof(int));
mdl->lod_num_verts = 0;
mdl->lod_num_tris = 0;
struct iqm_vertex *lod_verts = (struct iqm_vertex *)mdl->lod_verts;
int *lod_tris = (int *)mdl->lod_tris;
for( int i = 0; i < mdl->num_tris*3; i+=3 ) {
int p0 = MapReduce(mdl->lod_collapse_map, tris[i+0], max_verts_to_render);
int p1 = MapReduce(mdl->lod_collapse_map, tris[i+1], max_verts_to_render);
int p2 = MapReduce(mdl->lod_collapse_map, tris[i+2], max_verts_to_render);
// @fixme: serious optimization opportunity here,
// by sorting the triangles the following "continue"
// could have been made into a "break" statement.
if(p0==p1 || p0==p2 || p1==p2) continue;
// if we are not currenly morphing between 2 levels of detail
// (i.e. if morph=1.0) then q0,q1, and q2 may not be necessary
int q0 = MapReduce(mdl->lod_collapse_map, p0, min_verts_to_render);
int q1 = MapReduce(mdl->lod_collapse_map, p1, min_verts_to_render);
int q2 = MapReduce(mdl->lod_collapse_map, p2, min_verts_to_render);
struct iqm_vertex v0 = *(struct iqm_vertex *)(verts + (p0*mdl->stride));
struct iqm_vertex v1 = *(struct iqm_vertex *)(verts + (p1*mdl->stride));
struct iqm_vertex v2 = *(struct iqm_vertex *)(verts + (p2*mdl->stride));
lod_verts[mdl->lod_num_verts++] = v0;
lod_verts[mdl->lod_num_verts++] = v1;
lod_verts[mdl->lod_num_verts++] = v2;
int idx = mdl->lod_num_verts;
lod_tris[mdl->lod_num_tris + 0] = idx-3;
lod_tris[mdl->lod_num_tris + 1] = idx-2;
lod_tris[mdl->lod_num_tris + 2] = idx-1;
++mdl->lod_num_tris;
// vec3 v0, v1, v2;
// v0 = mix3(m->in_vertex3[p0], m->in_vertex3[q0], (1-morph));
// v1 = mix3(m->in_vertex3[p1], m->in_vertex3[q1], (1-morph));
// v2 = mix3(m->in_vertex3[p2], m->in_vertex3[q2], (1-morph));
// vec3 normal = norm3(cross3(sub3(v1,v0),sub3(v2,v1)));
// array_push(m->out_vertex3, v0);
// array_push(m->out_vertex3, normal);
// array_push(m->out_vertex3, v1);
// array_push(m->out_vertex3, normal);
// array_push(m->out_vertex3, v2);
// array_push(m->out_vertex3, normal);
// int idx = array_count(m->out_vertex3) / 2;
// array_push(m->out_index3, vec3i(idx-3,idx-2,idx-1));
}
// upload modified data
glBindVertexArray(mdl->vao);
glBindBuffer(GL_ARRAY_BUFFER, mdl->vbo);
glBufferData(GL_ARRAY_BUFFER, mdl->lod_num_verts*mdl->stride, mdl->lod_verts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdl->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mdl->lod_num_tris*3*sizeof(int), mdl->lod_tris, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void model_destroy(model_t m) {
FREE(m.verts);
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {

View File

@ -500,6 +500,7 @@ API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
API void skybox_destroy(skybox_t *sky);
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
API void skybox_sh_reset(skybox_t *sky);
API void skybox_sh_shader(skybox_t *sky);
API void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength);
API int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
@ -671,6 +672,12 @@ typedef struct model_t {
int num_tris;
handle vao, ibo, vbo, vao_instanced;
array(int) lod_collapse_map; // to which neighbor each vertex collapses. ie, [10] -> 7 (used by LODs) @leak
void *lod_verts;
int lod_num_verts;
void *lod_tris;
int lod_num_tris;
unsigned flags;
unsigned billboard;
@ -696,6 +703,7 @@ API float model_animate(model_t, float curframe);
API float model_animate_clip(model_t, float curframe, int minframe, int maxframe, bool loop);
API float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float delta);
API aabb model_aabb(model_t, mat44 transform);
API void model_lod(model_t*, float lo_detail, float hi_detail, float morph);
API void model_shading(model_t*, int shading);
API void model_skybox(model_t*, skybox_t sky, bool load_sh);
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);

View File

@ -18822,6 +18822,10 @@ void skybox_sh_reset(skybox_t *sky) {
}
}
void skybox_sh_shader(skybox_t *sky) {
shader_vec3v("u_coefficients_sh", 9, sky->cubemap.sh);
}
void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
// Normalize the direction
vec3 norm_dir = norm3(dir);
@ -21190,6 +21194,147 @@ aabb model_aabb(model_t m, mat44 transform) {
return aabb(vec3(0,0,0),vec3(0,0,0));
}
static inline int MapReduce(array(int) collapse_map, int n, int mx) {
while( n >= mx ) n = collapse_map[n];
return n;
}
API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, const int *tri, int *map, int *permutation);
void model_lod(model_t *mdl, float lo_detail, float hi_detail, float morph) {
assert(mdl->num_meshes == 1);
if (array_count(mdl->lod_collapse_map) == 0) {
array(int) permutation = 0;
array_resize(mdl->lod_collapse_map, mdl->num_verts);
array_resize(permutation, mdl->num_verts);
ProgressiveMesh(mdl->num_verts, mdl->stride, (const float *)mdl->verts, mdl->num_tris, (const int *)mdl->tris, mdl->lod_collapse_map, permutation);
// PermuteVertices {
ASSERT(array_count(permutation) == mdl->num_verts);
// rearrange the vertex Array
char *tmp = REALLOC(0, mdl->stride*mdl->num_verts);
char *verts = (char *)mdl->verts;
memcpy(tmp, verts, mdl->stride*mdl->num_verts);
for(int i = 0; i < mdl->num_verts; i++) {
int index = permutation[i];
int src_offset = i * mdl->stride;
int offset = index * mdl->stride;
memcpy(verts + offset, tmp + src_offset, mdl->stride);
}
int *tris = (int *)mdl->tris;
// update the changes in the entries in the triangle Array
for (int i = 0; i < mdl->num_tris*3; i+=3) {
tris[i+0] = permutation[tris[i+0]];
tris[i+1] = permutation[tris[i+1]];
tris[i+2] = permutation[tris[i+2]];
}
// upload modified data
glBindVertexArray(mdl->vao);
glBindBuffer(GL_ARRAY_BUFFER, mdl->vbo);
glBufferData(GL_ARRAY_BUFFER, mdl->num_verts*mdl->stride, mdl->verts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdl->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mdl->num_tris*3*sizeof(int), mdl->tris, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
FREE(tmp);
// } PermuteVertices
array_free(permutation);
}
ASSERT(array_count(mdl->lod_collapse_map));
int max_verts_to_render = hi_detail * mdl->num_verts;
int min_verts_to_render = lo_detail * mdl->num_verts;
if( max_verts_to_render <= 0 || min_verts_to_render <= 0 )
return;
FREE(mdl->lod_verts);
FREE(mdl->lod_tris);
char *verts = (char *)mdl->verts;
int *tris = (int *)mdl->tris;
int max_lod_tris = 0;
//@fixme: optimise
for( unsigned int i = 0; i < mdl->num_tris*3; i+=3 ) {
int p0 = MapReduce(mdl->lod_collapse_map, tris[i+0], max_verts_to_render);
int p1 = MapReduce(mdl->lod_collapse_map, tris[i+1], max_verts_to_render);
int p2 = MapReduce(mdl->lod_collapse_map, tris[i+2], max_verts_to_render);
if(p0==p1 || p0==p2 || p1==p2) continue;
++max_lod_tris;
}
mdl->lod_verts = REALLOC(0, max_lod_tris*3*mdl->stride);
mdl->lod_tris = REALLOC(0, max_lod_tris*3*sizeof(int));
mdl->lod_num_verts = 0;
mdl->lod_num_tris = 0;
struct iqm_vertex *lod_verts = (struct iqm_vertex *)mdl->lod_verts;
int *lod_tris = (int *)mdl->lod_tris;
for( int i = 0; i < mdl->num_tris*3; i+=3 ) {
int p0 = MapReduce(mdl->lod_collapse_map, tris[i+0], max_verts_to_render);
int p1 = MapReduce(mdl->lod_collapse_map, tris[i+1], max_verts_to_render);
int p2 = MapReduce(mdl->lod_collapse_map, tris[i+2], max_verts_to_render);
// @fixme: serious optimization opportunity here,
// by sorting the triangles the following "continue"
// could have been made into a "break" statement.
if(p0==p1 || p0==p2 || p1==p2) continue;
// if we are not currenly morphing between 2 levels of detail
// (i.e. if morph=1.0) then q0,q1, and q2 may not be necessary
int q0 = MapReduce(mdl->lod_collapse_map, p0, min_verts_to_render);
int q1 = MapReduce(mdl->lod_collapse_map, p1, min_verts_to_render);
int q2 = MapReduce(mdl->lod_collapse_map, p2, min_verts_to_render);
struct iqm_vertex v0 = *(struct iqm_vertex *)(verts + (p0*mdl->stride));
struct iqm_vertex v1 = *(struct iqm_vertex *)(verts + (p1*mdl->stride));
struct iqm_vertex v2 = *(struct iqm_vertex *)(verts + (p2*mdl->stride));
lod_verts[mdl->lod_num_verts++] = v0;
lod_verts[mdl->lod_num_verts++] = v1;
lod_verts[mdl->lod_num_verts++] = v2;
int idx = mdl->lod_num_verts;
lod_tris[mdl->lod_num_tris + 0] = idx-3;
lod_tris[mdl->lod_num_tris + 1] = idx-2;
lod_tris[mdl->lod_num_tris + 2] = idx-1;
++mdl->lod_num_tris;
// vec3 v0, v1, v2;
// v0 = mix3(m->in_vertex3[p0], m->in_vertex3[q0], (1-morph));
// v1 = mix3(m->in_vertex3[p1], m->in_vertex3[q1], (1-morph));
// v2 = mix3(m->in_vertex3[p2], m->in_vertex3[q2], (1-morph));
// vec3 normal = norm3(cross3(sub3(v1,v0),sub3(v2,v1)));
// array_push(m->out_vertex3, v0);
// array_push(m->out_vertex3, normal);
// array_push(m->out_vertex3, v1);
// array_push(m->out_vertex3, normal);
// array_push(m->out_vertex3, v2);
// array_push(m->out_vertex3, normal);
// int idx = array_count(m->out_vertex3) / 2;
// array_push(m->out_index3, vec3i(idx-3,idx-2,idx-1));
}
// upload modified data
glBindVertexArray(mdl->vao);
glBindBuffer(GL_ARRAY_BUFFER, mdl->vbo);
glBufferData(GL_ARRAY_BUFFER, mdl->lod_num_verts*mdl->stride, mdl->lod_verts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdl->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mdl->lod_num_tris*3*sizeof(int), mdl->lod_tris, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void model_destroy(model_t m) {
FREE(m.verts);
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {

View File

@ -3534,6 +3534,7 @@ API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
API void skybox_destroy(skybox_t *sky);
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
API void skybox_sh_reset(skybox_t *sky);
API void skybox_sh_shader(skybox_t *sky);
API void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength);
API int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
@ -3705,6 +3706,12 @@ typedef struct model_t {
int num_tris;
handle vao, ibo, vbo, vao_instanced;
array(int) lod_collapse_map; // to which neighbor each vertex collapses. ie, [10] -> 7 (used by LODs) @leak
void *lod_verts;
int lod_num_verts;
void *lod_tris;
int lod_num_tris;
unsigned flags;
unsigned billboard;
@ -3730,6 +3737,7 @@ API float model_animate(model_t, float curframe);
API float model_animate_clip(model_t, float curframe, int minframe, int maxframe, bool loop);
API float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float delta);
API aabb model_aabb(model_t, mat44 transform);
API void model_lod(model_t*, float lo_detail, float hi_detail, float morph);
API void model_shading(model_t*, int shading);
API void model_skybox(model_t*, skybox_t sky, bool load_sh);
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);

1
info.obj 100644
View File

@ -0,0 +1 @@
ff7f42a

BIN
v4k.obj 100644

Binary file not shown.