save timing version in replay frame
[carveJwlIkooP6JGAAIwe30JlM.git] / trail.c
1 #pragma once
2 #include "trail.h"
3 #include "shaders/particle.h"
4 #include "shaders/trail.h"
5
6 static void trail_increment( trail_system *sys ){
7 sys->head ++;
8
9 if( sys->head == sys->max )
10 sys->head = 0;
11
12 /* undesirable effect: will remove active points if out of space! */
13 if( sys->count < sys->max )
14 sys->count ++;
15 }
16
17 static void trail_system_update( trail_system *sys, f32 dt,
18 v3f co, v3f normal, f32 alpha ){
19 /* update existing points and clip dead ones */
20 bool clip_allowed = 1;
21 for( i32 i=0; i<sys->count; i ++ ){
22 i32 i0 = sys->head - sys->count + i;
23 if( i0 < 0 ) i0 += sys->max;
24
25 trail_point *p0 = &sys->array[i0];
26 p0->alpha -= dt/sys->lifetime;
27
28 if( clip_allowed ){
29 if( p0->alpha <= 0.0f )
30 sys->count --;
31 else
32 clip_allowed = 0;
33 }
34 }
35
36 i32 icur = sys->head -1,
37 iprev = sys->head -2,
38 ihead = sys->head;
39
40 if( icur < 0 ) icur += sys->max;
41 if( iprev < 0 ) iprev += sys->max;
42
43 trail_point *pcur = &sys->array[ icur ],
44 *pprev = &sys->array[ iprev ],
45 *phead = &sys->array[ ihead ],
46 *pdest = NULL;
47 v3f dir;
48
49 f32 k_min = 0.001f;
50
51 if( sys->count == 0 ){
52 trail_increment( sys );
53 v3_copy( (v3f){0,0,-1}, dir );
54 pdest = phead;
55 }
56 else if( sys->count == 1 ){
57 if( v3_dist2( pcur->co, co ) < k_min*k_min )
58 return;
59
60 trail_increment( sys );
61 pdest = phead;
62 v3_sub( co, pcur->co, dir );
63 }
64 else {
65 if( v3_dist2( pprev->co, co ) < k_min*k_min )
66 return;
67
68 if( v3_dist2( pprev->co, co ) > sys->min_dist*sys->min_dist ){
69 trail_increment( sys );
70 pdest = phead;
71 }
72 else
73 pdest = pcur;
74
75 v3_sub( co, pprev->co, dir );
76 }
77
78 v3_cross( dir, normal, pdest->right );
79 v3_normalize( pdest->right );
80 v3_copy( co, pdest->co );
81 v3_copy( normal, pdest->normal );
82 pdest->alpha = alpha;
83 }
84
85 static void trail_system_debug( trail_system *sys ){
86 for( i32 i=0; i<sys->count; i ++ ){
87 i32 i0 = sys->head - sys->count + i;
88 if( i0 < 0 ) i0 += sys->max;
89
90 trail_point *p0 = &sys->array[i0];
91 vg_line_point( p0->co, 0.04f, 0xff000000 | (u32)(p0->alpha*255.0f) );
92 vg_line_arrow( p0->co, p0->right, 0.3f, VG__GREEN );
93
94 if( i == sys->count-1 ) break;
95
96 i32 i1 = i0+1;
97 if( i1 == sys->max ) i1 = 0;
98
99 trail_point *p1 = &sys->array[i1];
100 vg_line( p0->co, p1->co, VG__RED );
101 }
102 }
103
104 struct trail_init_args {
105 trail_system *sys;
106 };
107
108 static void async_trail_init( void *payload, u32 size ){
109 struct trail_init_args *args = payload;
110 trail_system *sys = args->sys;
111
112 glGenVertexArrays( 1, &sys->vao );
113 glGenBuffers( 1, &sys->vbo );
114 glBindVertexArray( sys->vao );
115
116 size_t stride = sizeof(trail_vert);
117
118 glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
119 glBufferData( GL_ARRAY_BUFFER, sys->max*stride*2, NULL, GL_DYNAMIC_DRAW );
120
121 /* 0: coordinates */
122 glVertexAttribPointer( 0, 4, GL_FLOAT, GL_FALSE, stride, (void*)0 );
123 glEnableVertexAttribArray( 0 );
124
125 VG_CHECK_GL_ERR();
126 }
127
128 static void trail_alloc( trail_system *sys, u32 max ){
129 size_t stride = sizeof(trail_vert);
130 sys->max = max;
131 sys->array = vg_linear_alloc( vg_mem.rtmemory, max*sizeof(trail_point) );
132 sys->vertices = vg_linear_alloc( vg_mem.rtmemory, max*stride*2 );
133
134 vg_async_item *call = vg_async_alloc( sizeof(struct trail_init_args) );
135
136 struct trail_init_args *init = call->payload;
137 init->sys = sys;
138 vg_async_dispatch( call, async_trail_init );
139 }
140
141 static void trail_system_prerender( trail_system *sys ){
142 if( sys->count < 2 ) return;
143
144 for( i32 i=0; i<sys->count; i ++ ){
145 i32 i0 = sys->head - sys->count + i;
146 if( i0 < 0 ) i0 += sys->max;
147
148 trail_point *p0 = &sys->array[i0];
149 trail_vert *v0 = &sys->vertices[i*2+0],
150 *v1 = &sys->vertices[i*2+1];
151
152 v3_muladds( p0->co, p0->right, -sys->width, v0->co );
153 v3_muladds( p0->co, p0->right, sys->width, v1->co );
154 v0->co[3] = p0->alpha;
155 v1->co[3] = p0->alpha;
156 }
157
158 glBindVertexArray( sys->vao );
159
160 size_t stride = sizeof(trail_vert);
161 glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
162 glBufferSubData( GL_ARRAY_BUFFER, 0, sys->count*stride*2, sys->vertices );
163 }
164
165 static void trail_system_render( trail_system *sys, camera *cam ){
166 if( sys->count < 2 ) return;
167 glDisable( GL_CULL_FACE );
168 glEnable( GL_DEPTH_TEST );
169
170 shader_trail_use();
171 shader_trail_uPv( cam->mtx.pv );
172 shader_trail_uPvPrev( cam->mtx_prev.pv );
173 shader_trail_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
174
175 glBindVertexArray( sys->vao );
176 glDrawArrays( GL_TRIANGLE_STRIP, 0, sys->count*2 );
177 }
178
179 static void trail_init( void ){
180 shader_trail_register();
181 }