From 6538d63bbe4c4d5efb08bd207498ef57a6657e4d Mon Sep 17 00:00:00 2001 From: hgn Date: Sun, 4 Feb 2024 09:49:37 +0000 Subject: [PATCH] trail rendering basics --- skaterift.c | 7 +++ skaterift.h | 8 ++- trail.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++ trail.h | 43 ++++++++++++++ 4 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 trail.c create mode 100644 trail.h diff --git a/skaterift.c b/skaterift.c index bc0bd3c..82aa54c 100644 --- a/skaterift.c +++ b/skaterift.c @@ -59,6 +59,8 @@ #include "player_effects.c" #include "freecam.c" #include "testing.c" +#include "trail.h" +#include "trail.c" static int k_tools_mode = 0; @@ -198,6 +200,7 @@ static void skaterift_load_player_content(void){ particle_alloc( &particles_grind, 300 ); particle_alloc( &particles_env, 200 ); + trail_alloc( &trails_test, 200 ); player_load_animation_reference( "models/ch_none.mdl" ); player_model_load( &localplayer.fallback_model, "models/ch_none.mdl" ); @@ -513,6 +516,10 @@ static void render_scene(void){ particle_system_prerender( &particles_env ); particle_system_render( &particles_env, &skaterift.cam ); + trail_system_update( &trails_test, vg.time_delta, + localplayer.rb.co, localplayer.rb.to_world[1], 1.0f ); + trail_system_debug( &trails_test ); + /* * render transition */ diff --git a/skaterift.h b/skaterift.h index a21e6ab..ebab767 100644 --- a/skaterift.h +++ b/skaterift.h @@ -11,6 +11,7 @@ #include "vg/vg.h" #include "world.h" #include "addon.h" +#include "trail.h" enum skaterift_rt { k_skaterift_rt_workshop_preview, @@ -69,10 +70,15 @@ struct{ audio_channel *aud_air; const char *hub_world; + + struct trail_system test_trail; } static skaterift = { .op = k_async_op_clientloading, .time_rate = 1.0f, .demo_mode = 1, - .hub_world = "maps/dev_hub" + .hub_world = "maps/dev_hub", + .test_trail = { + .max = 80 + } }; /* Skaterift api */ diff --git a/trail.c b/trail.c new file mode 100644 index 0000000..bf23b1c --- /dev/null +++ b/trail.c @@ -0,0 +1,159 @@ +#pragma once +#include "trail.h" + +static void trail_system_update( trail_system *sys, f32 dt, + v3f co, v3f normal, f32 alpha ){ + /* update existing points and clip dead ones */ + bool clip_allowed = 1; + for( i32 i=0; icount; i ++ ){ + i32 i0 = sys->head - sys->count + i; + if( i0 < 0 ) i0 += sys->max; + + trail_point *p0 = &sys->array[i0]; + p0->alpha -= dt/sys->lifetime; + + if( clip_allowed ){ + if( p0->alpha <= 0.0f ) + sys->count --; + else + clip_allowed = 0; + } + } + + bool add_point = 1; + i32 index_current = sys->head; + if( sys->count >= 2 ) index_current = sys->head -1; + + i32 index_prev = index_current -1; + + if( index_current < 0 ) index_current += sys->max; + if( index_prev < 0 ) index_prev += sys->max; + + /* always enforced non-zero distance */ + if( sys->count >= 1 ){ + if( v3_dist2( sys->array[index_prev].co, co ) < 0.001f*0.001f ) + return; + } + + /* copy new info in */ + trail_point *p_current = &sys->array[index_current]; + v3_copy( co, p_current->co ); + v3_copy( normal, p_current->normal ); + p_current->alpha = alpha; + + /* update direction */ + if( sys->count >= 2 ){ + trail_point *p_prev = &sys->array[index_prev]; + + v3f dir; + v3_sub( co, p_prev->co, dir ); + v3_normalize( dir ); + v3_cross( dir, normal, p_current->right ); + v3_copy( p_current->right, p_prev->right ); + + /* decide if to prevent split based on user min-distance */ + if( v3_dist2( p_prev->co, co ) < sys->min_dist*sys->min_dist ) + add_point = 0; + } + else + v3_zero( p_current->right ); + + if( add_point ){ + sys->head ++; + + if( sys->head == sys->max ) + sys->head = 0; + + /* undesirable effect: will remove active points if out of space! */ + if( sys->count < sys->max ) + sys->count ++; + + index_current = sys->head; + } + + p_current = &sys->array[index_current]; + v3_copy( co, p_current->co ); + v3_copy( normal, p_current->normal ); + p_current->alpha = alpha; + v3_zero( p_current->right ); +} + +static void trail_system_debug( trail_system *sys ){ + for( i32 i=0; icount; i ++ ){ + i32 i0 = sys->head - sys->count + i; + if( i0 < 0 ) i0 += sys->max; + + trail_point *p0 = &sys->array[i0]; + vg_line_point( p0->co, 0.04f, 0xff000000 | (u32)(p0->alpha*255.0f) ); + vg_line_arrow( p0->co, p0->right, 0.3f, VG__GREEN ); + + if( i == sys->count-1 ) break; + + i32 i1 = i0+1; + if( i1 == sys->max ) i1 = 0; + + trail_point *p1 = &sys->array[i1]; + vg_line( p0->co, p1->co, VG__RED ); + } +} + +struct trail_init_args { + trail_system *sys; +}; + +static void async_trail_init( void *payload, u32 size ){ + struct trail_init_args *args = payload; + trail_system *sys = args->sys; + + glGenVertexArrays( 1, &sys->vao ); + glGenBuffers( 1, &sys->vbo ); + glBindVertexArray( sys->vao ); + + size_t stride = sizeof(trail_vert); + + glBindBuffer( GL_ARRAY_BUFFER, sys->vbo ); + glBufferData( GL_ARRAY_BUFFER, sys->max*stride*2, NULL, GL_DYNAMIC_DRAW ); + + /* 0: coordinates */ + glVertexAttribPointer( 0, 4, GL_FLOAT, GL_FALSE, stride, (void*)0 ); + glEnableVertexAttribArray( 0 ); + + VG_CHECK_GL_ERR(); +} + +static void trail_alloc( trail_system *sys, u32 max ){ + size_t stride = sizeof(trail_vert); + sys->max = max; + sys->array = vg_linear_alloc( vg_mem.rtmemory, max*sizeof(trail_point) ); + sys->vertices = vg_linear_alloc( vg_mem.rtmemory, max*stride*2 ); + + vg_async_item *call = vg_async_alloc( sizeof(struct trail_init_args) ); + + struct trail_init_args *init = call->payload; + init->sys = sys; + vg_async_dispatch( call, async_trail_init ); +} + +static void trail_system_prerender( trail_system *sys ){ +#if 0 + glBindVertexArray( sys->vao ); + + size_t stride = sizeof(trail_vert); + glBindBuffer( GL_ARRAY_BUFFER, sys->vbo ); + glBufferSubData( GL_ARRAY_BUFFER, 0, sys->alive*stride*4, sys->vertices ); +#endif +} + +static void trail_system_render( trail_system *sys, camera *cam ){ +#if 0 + glDisable( GL_CULL_FACE ); + glEnable( GL_DEPTH_TEST ); + + shader_trail_use(); + shader_trail_uPv( cam->mtx.pv ); + shader_trail_uPvPrev( cam->mtx_prev.pv ); + + glBindVertexArray( sys->vao ); + glDrawElements( GL_TRIANGLES, sys->alive*6, GL_UNSIGNED_SHORT, NULL ); +#endif +} diff --git a/trail.h b/trail.h new file mode 100644 index 0000000..dc90fc9 --- /dev/null +++ b/trail.h @@ -0,0 +1,43 @@ +#ifndef TRAIL_H +#define TRAIL_H + +#include "skaterift.h" + +typedef struct trail_system trail_system; +typedef struct trail_point trail_point; +typedef struct trail_vert trail_vert; + +struct trail_system { + struct trail_point { + v3f co, normal, right; + f32 alpha; + } + *array; + +#pragma pack(push,1) + struct trail_vert { + v4f co; /* xyz: position, w: alpha */ + } + *vertices; +#pragma pack(pop) + + i32 head, count, max; + GLuint vao, vbo; + + /* render settings */ + f32 width, lifetime, min_dist; +} +static trails_test = { + .width = 0.25f, + .lifetime = 5.0f, + .min_dist = 0.5f +}; + +static void trail_alloc( trail_system *sys, u32 max ); +static void trail_system_update( trail_system *sys, f32 dt, + v3f co, v3f normal, f32 alpha ); +static void trail_system_debug( trail_system *sys ); +static void trail_system_prerender( trail_system *sys ); +static void trail_system_render( trail_system *sys, camera *cam ); + +#endif /* TRAIL_H */ -- 2.25.1