lods wip
parent
ff7f42aeb9
commit
657d6dcf85
|
@ -35,7 +35,7 @@ _fwk
|
||||||
*.dbg
|
*.dbg
|
||||||
_cache
|
_cache
|
||||||
*.exp
|
*.exp
|
||||||
*.obj
|
./*.obj
|
||||||
*.exe
|
*.exe
|
||||||
*.ilk
|
*.ilk
|
||||||
*.dll
|
*.dll
|
||||||
|
|
Binary file not shown.
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
@ -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_destroy(skybox_t *sky);
|
||||||
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
|
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
|
||||||
API void skybox_sh_reset(skybox_t *sky);
|
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 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
|
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;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
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 flags;
|
||||||
unsigned billboard;
|
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_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 float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float delta);
|
||||||
API aabb model_aabb(model_t, mat44 transform);
|
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_shading(model_t*, int shading);
|
||||||
API void model_skybox(model_t*, skybox_t sky, bool load_sh);
|
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);
|
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) {
|
void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
|
||||||
// Normalize the direction
|
// Normalize the direction
|
||||||
vec3 norm_dir = norm3(dir);
|
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));
|
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) {
|
void model_destroy(model_t m) {
|
||||||
FREE(m.verts);
|
FREE(m.verts);
|
||||||
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {
|
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {
|
||||||
|
|
|
@ -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) {
|
void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
|
||||||
// Normalize the direction
|
// Normalize the direction
|
||||||
vec3 norm_dir = norm3(dir);
|
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));
|
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) {
|
void model_destroy(model_t m) {
|
||||||
FREE(m.verts);
|
FREE(m.verts);
|
||||||
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {
|
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {
|
||||||
|
|
|
@ -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_destroy(skybox_t *sky);
|
||||||
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
|
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
|
||||||
API void skybox_sh_reset(skybox_t *sky);
|
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 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
|
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;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
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 flags;
|
||||||
unsigned billboard;
|
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_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 float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float delta);
|
||||||
API aabb model_aabb(model_t, mat44 transform);
|
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_shading(model_t*, int shading);
|
||||||
API void model_skybox(model_t*, skybox_t sky, bool load_sh);
|
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);
|
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
||||||
|
|
145
engine/v4k.c
145
engine/v4k.c
|
@ -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) {
|
void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
|
||||||
// Normalize the direction
|
// Normalize the direction
|
||||||
vec3 norm_dir = norm3(dir);
|
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));
|
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) {
|
void model_destroy(model_t m) {
|
||||||
FREE(m.verts);
|
FREE(m.verts);
|
||||||
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {
|
for( int i = 0, end = array_count(m.texture_names); i < end; ++i ) {
|
||||||
|
|
|
@ -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_destroy(skybox_t *sky);
|
||||||
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
|
API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity);
|
||||||
API void skybox_sh_reset(skybox_t *sky);
|
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 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
|
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;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
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 flags;
|
||||||
unsigned billboard;
|
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_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 float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float delta);
|
||||||
API aabb model_aabb(model_t, mat44 transform);
|
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_shading(model_t*, int shading);
|
||||||
API void model_skybox(model_t*, skybox_t sky, bool load_sh);
|
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);
|
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
||||||
|
|
Loading…
Reference in New Issue