82d5da7925b0ee67749bb35f91ba77ec1e658fe0
[carveJwlIkooP6JGAAIwe30JlM.git] / world_routes.h
1 #ifndef ROUTES_H
2 #define ROUTES_H
3
4 #include "common.h"
5 #include "model.h"
6 #include "gate.h"
7
8 #include "shaders/vblend.h"
9 #include "shaders/route.h"
10
11 struct subworld_routes
12 {
13 struct route_node
14 {
15 v3f co, right, up, h;
16 u32 next[2];
17
18 u32 is_gate, gate_id, current_refs, ref_count;
19 u32 route_ids[4]; /* Gates can be linked into up to four routes */
20 }
21 *nodes;
22
23 u32 node_count,
24 node_cap;
25
26 struct route
27 {
28 const char *name;
29 v4f colour;
30
31 u32 start;
32 mdl_submesh sm;
33
34 int active;
35 float factive;
36 }
37 *routes;
38
39 u32 route_count,
40 route_cap;
41
42 struct route_gate
43 {
44 teleport_gate gate;
45
46 u32 route_count,
47 node_id;
48 }
49 *gates;
50
51 u32 gate_count,
52 gate_cap;
53
54 u32 active_gate;
55
56 scene scene_lines;
57 };
58
59 static struct subworld_routes *subworld_routes(void);
60
61 /*
62 * TODO list:
63 * when a gate is passed through it needs to trigger into an active state
64 */
65
66 static void debug_sbpath( struct route_node *rna, struct route_node *rnb,
67 u32 colour, float xoffset )
68 {
69 v3f p0, h0, p1, h1, l, p;
70
71 v3_copy( rna->co, p0 );
72 v3_muladds( rna->co, rna->h, 1.0f, h0 );
73 v3_copy( rnb->co, p1 );
74 v3_muladds( rnb->co, rnb->h, -1.0f, h1 );
75
76 v3_muladds( p0, rna->right, xoffset, p0 );
77 v3_muladds( h0, rna->right, xoffset, h0 );
78 v3_muladds( p1, rnb->right, xoffset, p1 );
79 v3_muladds( h1, rnb->right, xoffset, h1 );
80
81 v3_copy( p0, l );
82
83 for( int i=0; i<5; i++ )
84 {
85 float t = (float)(i+1)/5.0f;
86 eval_bezier_time( p0, p1, h0, h1, t, p );
87 vg_line( p, l, colour );
88 v3_copy( p, l );
89 }
90 }
91
92 static void world_routes_activate_gate( u32 id )
93 {
94 struct subworld_routes *r = subworld_routes();
95 struct route_gate *ig = &r->gates[id];
96 struct route_node *pnode = &r->nodes[ig->node_id],
97 *pdest = &r->nodes[pnode->next[0]];
98
99 r->active_gate = id;
100
101 for( int i=0; i<r->route_count; i++ )
102 {
103 struct route *route = &r->routes[i];
104
105 route->active = 0;
106 for( int j=0; j<pdest->ref_count; j++ )
107 {
108 if( pdest->route_ids[j] == i )
109 {
110 route->active = 1;
111 break;
112 }
113 }
114 }
115 }
116
117 static u32 world_routes_get_path( struct route *route, u32 stack[64] )
118 {
119 struct subworld_routes *r = subworld_routes();
120 u32 stack_i[64];
121
122 stack[0] = route->start;
123 stack_i[0] = 0;
124
125 u32 si = 1;
126 int loop_complete = 0;
127
128 while( si )
129 {
130 if( stack_i[si-1] == 2 )
131 {
132 si --;
133 continue;
134 }
135
136 struct route_node *rn = &r->nodes[stack[si-1]];
137 u32 nextid = rn->next[stack_i[si-1]];
138 stack_i[si-1] ++;
139
140 if( nextid != 0xffffffff )
141 {
142 if( nextid == stack[0] )
143 {
144 loop_complete = 1;
145 break;
146 }
147
148 int valid = 1;
149 for( int sj=0; sj<si; sj++ )
150 {
151 if( stack[sj] == nextid )
152 {
153 valid = 0;
154 break;
155 }
156 }
157
158 if( valid )
159 {
160 stack_i[si] = 0;
161 stack[si] = nextid;
162 si ++;
163 continue;
164 }
165 }
166 }
167
168 if( loop_complete )
169 return si;
170
171 return 0;
172 }
173
174 static void world_routes_debug(void)
175 {
176 struct subworld_routes *r = subworld_routes();
177
178 for( int i=0; i<r->node_count; i++ )
179 {
180 struct route_node *rn = &r->nodes[i];
181 vg_line_pt3( rn->co, 1.0f, rn->is_gate? 0xffffff00: 0xff00b2ff );
182 }
183
184 for( int i=0; i<r->route_count; i++ )
185 {
186 struct route *route = &r->routes[i];
187
188 u32 stack[64];
189 u32 si = world_routes_get_path( route, stack );
190
191 u32 colours[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
192 0xff5442f5 };
193
194 u32 cc = colours[i%vg_list_size(colours)];
195
196 for( int sj=0; sj<si; sj++ )
197 {
198 int sk = (sj+1)%si;
199 debug_sbpath( &r->nodes[stack[sj]], &r->nodes[stack[sk]], cc,
200 (float)i );
201 }
202 }
203
204 for( int i=0; i<r->node_count; i++ )
205 {
206 struct route_node *ri = &r->nodes[i],
207 *rj = NULL;
208
209 for( int j=0; j<2; j++ )
210 {
211 if( ri->next[j] != 0xffffffff )
212 {
213 rj = &r->nodes[ri->next[j]];
214 vg_line( ri->co, rj->co, 0x20ffffff );
215 }
216 }
217 }
218 }
219
220 static void world_routes_free(void)
221 {
222 struct subworld_routes *r = subworld_routes();
223
224 free( r->nodes );
225 free( r->routes );
226 free( r->gates );
227 }
228
229 static void world_id_fixup( u32 *uid, mdl_header *mdl )
230 {
231 if( *uid )
232 *uid = mdl_node_from_id( mdl, *uid )->sub_uid;
233 else
234 *uid = 0xffffffff;
235 }
236
237 static void world_routes_gen_meshes(void)
238 {
239 struct subworld_routes *r = subworld_routes();
240 scene_init( &r->scene_lines );
241
242 for( int i=0; i<r->route_count; i++ )
243 {
244 struct route *route = &r->routes[i];
245
246 u32 stack[64];
247 u32 si = world_routes_get_path( route, stack );
248
249 u32 last_valid = 0;
250
251 for( int sj=0; sj<si; sj++ )
252 {
253 int sk=(sj+1)%si;
254
255 struct route_node *rnj = &r->nodes[ stack[sj] ],
256 *rnk = &r->nodes[ stack[sk] ],
257 *rnl;
258
259 if( rnj->is_gate && rnk->is_gate )
260 {
261 last_valid = 0;
262 continue;
263 }
264
265 float base_x0 = (float)rnj->ref_count*-0.5f + (float)rnj->current_refs,
266 base_x1 = (float)rnk->ref_count*-0.5f + (float)rnk->current_refs;
267
268 if( rnk->is_gate )
269 {
270 rnl = &r->nodes[ rnk->next[0] ];
271 base_x1 = (float)rnl->ref_count*-0.5f + (float)rnl->current_refs;
272 }
273
274 if( sk == 0 )
275 {
276 base_x1 -= 1.0f;
277 }
278
279 v3f p0, h0, p1, h1, p, pd;
280
281 v3_copy( rnj->co, p0 );
282 v3_muladds( rnj->co, rnj->h, 1.0f, h0 );
283 v3_copy( rnk->co, p1 );
284 v3_muladds( rnk->co, rnk->h, -1.0f, h1 );
285
286 float t=0.0f;
287 int it = 0;
288
289 for( int it=0; it<256; it ++ )
290 {
291 float const k_sample_dist = 0.02f;
292 eval_bezier_time( p0,p1,h0,h1, t,p );
293 eval_bezier_time( p0,p1,h0,h1, t+k_sample_dist,pd );
294
295 float mod = k_sample_dist / v3_dist( p, pd );
296
297 v3f v0,up, right;
298 v3_muls( rnj->up, 1.0f-t, up );
299 v3_muladds( up, rnk->up, t, up );
300
301 v3_sub( pd,p,v0 );
302 v3_cross( up, v0, right );
303 v3_normalize( right );
304
305 float cur_x = (1.0f-t)*base_x0 + t*base_x1;
306
307 v3f sc, sa, sb, down;
308 v3_muladds( p, right, cur_x, sc );
309 v3_muladds( sc, up, 1.5f, sc );
310 v3_muladds( sc, right, 0.45f, sa );
311 v3_muladds( sc, right, -0.45f, sb );
312 v3_muls( up, -1.0f, down );
313
314 ray_hit ha, hb;
315 ha.dist = 8.0f;
316 hb.dist = 8.0f;
317 if(ray_world( sa, down, &ha ) &&
318 ray_world( sb, down, &hb ))
319 {
320 mdl_vert va, vb;
321
322 v3_muladds( ha.pos, up, 0.06f, va.co );
323 v3_muladds( hb.pos, up, 0.06f, vb.co );
324 v3_copy( up, va.norm );
325 v3_copy( up, vb.norm );
326 v3_zero( va.colour );
327 v3_zero( vb.colour );
328 v2_zero( va.uv );
329 v2_zero( vb.uv );
330
331 scene_push_vert( &r->scene_lines, &va );
332 scene_push_vert( &r->scene_lines, &vb );
333
334 if( last_valid )
335 {
336 /* Connect them with triangles */
337 scene_push_tri( &r->scene_lines, (u32[3]){
338 last_valid+0-2, last_valid+1-2, last_valid+2-2} );
339 scene_push_tri( &r->scene_lines, (u32[3]){
340 last_valid+1-2, last_valid+3-2, last_valid+2-2} );
341 }
342
343 last_valid = r->scene_lines.vertex_count;
344 }
345 else
346 last_valid = 0;
347
348 t += 1.0f*mod;
349
350 if( t >= 1.0f )
351 {
352 /* TODO special case for end of loop, need to add triangles
353 * between first and last rungs */
354 break;
355 }
356 }
357
358 rnj->current_refs ++;
359 }
360
361 scene_copy_slice( &r->scene_lines, &route->sm );
362 }
363
364 scene_upload( &r->scene_lines );
365 scene_free_offline_buffers( &r->scene_lines );
366 }
367
368 static void bind_terrain_textures(void);
369 static void render_world_routes( m4x4f projection, v3f camera )
370 {
371 struct subworld_routes *r = subworld_routes();
372
373 m4x3f identity_matrix;
374 m4x3_identity( identity_matrix );
375
376 shader_route_use();
377 shader_route_uTexGarbage(0);
378 shader_link_standard_ub( _shader_route.id, 2 );
379 bind_terrain_textures();
380
381 shader_route_uPv( projection );
382 shader_route_uMdl( identity_matrix );
383 shader_route_uCamera( camera );
384
385 scene_bind( &r->scene_lines );
386
387 for( int i=0; i<r->route_count; i++ )
388 {
389 struct route *route = &r->routes[i];
390 route->factive = vg_lerpf( route->factive, route->active, 0.01f );
391
392 v4f colour;
393 v3_lerp( (v3f){0.7f,0.7f,0.7f}, route->colour, route->factive, colour );
394 colour[3] = 1.0f;
395
396 shader_route_uColour( colour );
397 mdl_draw_submesh( &route->sm );
398 }
399 }
400
401 static void world_routes_register(void)
402 {
403 shader_route_register();
404 }
405
406 static void world_routes_loadfrom( mdl_header *mdl )
407 {
408 struct subworld_routes *r = subworld_routes();
409 r->nodes = NULL;
410 r->node_count = 0;
411 r->node_cap = 0;
412 r->routes = NULL;
413 r->route_count = 0;
414 r->route_cap = 0;
415 r->gates = NULL;
416 r->gate_count = 0;
417 r->gate_cap = 0;
418
419 for( int i=0; i<mdl->node_count; i++ )
420 {
421 mdl_node *pnode = mdl_node_from_id(mdl,i);
422 m4x3f transform;
423
424 if( pnode->classtype == k_classtype_route_node ||
425 pnode->classtype == k_classtype_gate )
426 {
427 mdl_node_transform( pnode, transform );
428 pnode->sub_uid = r->node_count;
429
430 r->nodes = buffer_reserve( r->nodes, r->node_count, &r->node_cap, 1,
431 sizeof( struct route_node ) );
432
433 struct route_node *rn = &r->nodes[r->node_count];
434
435 v3_copy( transform[0], rn->right );
436 v3_normalize( rn->right );
437 v3_copy( transform[1], rn->up );
438 v3_normalize( rn->up );
439 v3_muls( transform[2], -1.0f, rn->h );
440 v3_copy( transform[3], rn->co );
441 rn->ref_count = 0;
442 rn->current_refs = 0;
443
444 if( pnode->classtype == k_classtype_gate )
445 {
446 r->gates = buffer_reserve( r->gates, r->gate_count, &r->gate_cap,
447 1, sizeof( struct route_gate ) );
448
449 struct classtype_gate *inf = mdl_get_entdata( mdl, pnode );
450
451 /* H is later scaled based on link distance */
452 v3_normalize( rn->h );
453 rn->next[0] = inf->target;
454 rn->next[1] = 0;
455 rn->gate_id = r->gate_count;
456 rn->is_gate = 1;
457
458 /* TODO */
459 if( inf->target )
460 {
461 mdl_node *pother = mdl_node_from_id( mdl, inf->target );
462
463 if( pother->classtype == k_classtype_gate )
464 {
465 struct route_gate *rg = &r->gates[r->gate_count];
466 rg->node_id = r->node_count;
467
468 v3_copy( pnode->co, rg->gate.co[0] );
469 v3_copy( pother->co, rg->gate.co[1] );
470 v4_copy( pnode->q, rg->gate.q[0] );
471 v4_copy( pother->q, rg->gate.q[1] );
472 v2_copy( inf->dims, rg->gate.dims );
473
474 gate_transform_update( &rg->gate );
475
476 r->gate_count ++;
477 }
478 }
479 }
480 else
481 {
482 struct classtype_route_node *inf = mdl_get_entdata( mdl, pnode );
483 rn->next[0] = inf->target;
484 rn->next[1] = inf->target1;
485 rn->is_gate = 0;
486 }
487
488 r->node_count ++;
489 }
490 else if( pnode->classtype == k_classtype_route )
491 {
492 struct classtype_route *inf = mdl_get_entdata( mdl, pnode );
493 r->routes = buffer_reserve( r->routes, r->route_count, &r->route_cap,
494 1, sizeof( struct route ) );
495
496 struct route *route = &r->routes[r->route_count];
497
498 v3_copy( inf->colour, route->colour );
499 route->colour[3] = 1.0f;
500
501 route->name = NULL;
502 route->start = inf->id_start;
503 route->active = 0;
504 route->factive = 0.0f;
505
506 r->route_count ++;
507 }
508 }
509
510 /*
511 * Apply correct system-local ids
512 */
513 for( int i=0; i<r->node_count; i++ )
514 {
515 struct route_node *rn = &r->nodes[i];
516
517 for( int j=0; j<2; j++ )
518 world_id_fixup( &rn->next[j], mdl );
519 }
520
521 for( int i=0; i<r->route_count; i++ )
522 {
523 struct route *route = &r->routes[i];
524 world_id_fixup( &route->start, mdl );
525 }
526
527 /*
528 * Gather references
529 */
530 for( int i=0; i<r->route_count; i++ )
531 {
532 struct route *route = &r->routes[i];
533
534 u32 stack[64];
535 u32 si = world_routes_get_path( route, stack );
536
537 for( int sj=0; sj<si; sj++ )
538 {
539 struct route_node *rn = &r->nodes[ stack[sj] ];
540 rn->route_ids[ rn->ref_count ++ ] = i;
541
542 if( rn->ref_count > 4 )
543 vg_warn( "Too many references on route node %i\n", i );
544 }
545 }
546
547 world_routes_gen_meshes();
548 }
549
550 #endif /* ROUTES_H */