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