4 static void trail_system_update( trail_system
*sys
, f32 dt
,
5 v3f co
, v3f normal
, f32 alpha
){
6 /* update existing points and clip dead ones */
8 for( i32 i
=0; i
<sys
->count
; i
++ ){
9 i32 i0
= sys
->head
- sys
->count
+ i
;
10 if( i0
< 0 ) i0
+= sys
->max
;
12 trail_point
*p0
= &sys
->array
[i0
];
13 p0
->alpha
-= dt
/sys
->lifetime
;
16 if( p0
->alpha
<= 0.0f
)
24 i32 index_current
= sys
->head
;
25 if( sys
->count
>= 2 ) index_current
= sys
->head
-1;
27 i32 index_prev
= index_current
-1;
29 if( index_current
< 0 ) index_current
+= sys
->max
;
30 if( index_prev
< 0 ) index_prev
+= sys
->max
;
32 /* always enforced non-zero distance */
33 if( sys
->count
>= 1 ){
34 if( v3_dist2( sys
->array
[index_prev
].co
, co
) < 0.001f
*0.001f
)
38 /* copy new info in */
39 trail_point
*p_current
= &sys
->array
[index_current
];
40 v3_copy( co
, p_current
->co
);
41 v3_copy( normal
, p_current
->normal
);
42 p_current
->alpha
= alpha
;
44 /* update direction */
45 if( sys
->count
>= 2 ){
46 trail_point
*p_prev
= &sys
->array
[index_prev
];
49 v3_sub( co
, p_prev
->co
, dir
);
51 v3_cross( dir
, normal
, p_current
->right
);
52 v3_copy( p_current
->right
, p_prev
->right
);
54 /* decide if to prevent split based on user min-distance */
55 if( v3_dist2( p_prev
->co
, co
) < sys
->min_dist
*sys
->min_dist
)
59 v3_zero( p_current
->right
);
64 if( sys
->head
== sys
->max
)
67 /* undesirable effect: will remove active points if out of space! */
68 if( sys
->count
< sys
->max
)
71 index_current
= sys
->head
;
74 p_current
= &sys
->array
[index_current
];
75 v3_copy( co
, p_current
->co
);
76 v3_copy( normal
, p_current
->normal
);
77 p_current
->alpha
= alpha
;
78 v3_zero( p_current
->right
);
81 static void trail_system_debug( trail_system
*sys
){
82 for( i32 i
=0; i
<sys
->count
; i
++ ){
83 i32 i0
= sys
->head
- sys
->count
+ i
;
84 if( i0
< 0 ) i0
+= sys
->max
;
86 trail_point
*p0
= &sys
->array
[i0
];
87 vg_line_point( p0
->co
, 0.04f
, 0xff000000 | (u32
)(p0
->alpha
*255.0f
) );
88 vg_line_arrow( p0
->co
, p0
->right
, 0.3f
, VG__GREEN
);
90 if( i
== sys
->count
-1 ) break;
93 if( i1
== sys
->max
) i1
= 0;
95 trail_point
*p1
= &sys
->array
[i1
];
96 vg_line( p0
->co
, p1
->co
, VG__RED
);
100 struct trail_init_args
{
104 static void async_trail_init( void *payload
, u32 size
){
105 struct trail_init_args
*args
= payload
;
106 trail_system
*sys
= args
->sys
;
108 glGenVertexArrays( 1, &sys
->vao
);
109 glGenBuffers( 1, &sys
->vbo
);
110 glBindVertexArray( sys
->vao
);
112 size_t stride
= sizeof(trail_vert
);
114 glBindBuffer( GL_ARRAY_BUFFER
, sys
->vbo
);
115 glBufferData( GL_ARRAY_BUFFER
, sys
->max
*stride
*2, NULL
, GL_DYNAMIC_DRAW
);
118 glVertexAttribPointer( 0, 4, GL_FLOAT
, GL_FALSE
, stride
, (void*)0 );
119 glEnableVertexAttribArray( 0 );
124 static void trail_alloc( trail_system
*sys
, u32 max
){
125 size_t stride
= sizeof(trail_vert
);
127 sys
->array
= vg_linear_alloc( vg_mem
.rtmemory
, max
*sizeof(trail_point
) );
128 sys
->vertices
= vg_linear_alloc( vg_mem
.rtmemory
, max
*stride
*2 );
130 vg_async_item
*call
= vg_async_alloc( sizeof(struct trail_init_args
) );
132 struct trail_init_args
*init
= call
->payload
;
134 vg_async_dispatch( call
, async_trail_init
);
137 static void trail_system_prerender( trail_system
*sys
){
139 glBindVertexArray( sys
->vao
);
141 size_t stride
= sizeof(trail_vert
);
142 glBindBuffer( GL_ARRAY_BUFFER
, sys
->vbo
);
143 glBufferSubData( GL_ARRAY_BUFFER
, 0, sys
->alive
*stride
*4, sys
->vertices
);
147 static void trail_system_render( trail_system
*sys
, camera
*cam
){
149 glDisable( GL_CULL_FACE
);
150 glEnable( GL_DEPTH_TEST
);
153 shader_trail_uPv( cam
->mtx
.pv
);
154 shader_trail_uPvPrev( cam
->mtx_prev
.pv
);
156 glBindVertexArray( sys
->vao
);
157 glDrawElements( GL_TRIANGLES
, sys
->alive
*6, GL_UNSIGNED_SHORT
, NULL
);