stuff
[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 node_id;
47
48 double time_passed; /* When did we last pass this gate? */
49 u32 passed_version; /* Incremented on every reset */
50 }
51 *gates;
52
53 u32 gate_count,
54 gate_cap;
55
56 u32 active_gate,
57 current_run_version;
58
59 scene scene_lines;
60 };
61
62 static struct subworld_routes *subworld_routes(void);
63
64 static void debug_sbpath( struct route_node *rna, struct route_node *rnb,
65 u32 colour, float xoffset )
66 {
67 v3f p0, h0, p1, h1, l, p;
68
69 v3_copy( rna->co, p0 );
70 v3_muladds( rna->co, rna->h, 1.0f, h0 );
71 v3_copy( rnb->co, p1 );
72 v3_muladds( rnb->co, rnb->h, -1.0f, h1 );
73
74 v3_muladds( p0, rna->right, xoffset, p0 );
75 v3_muladds( h0, rna->right, xoffset, h0 );
76 v3_muladds( p1, rnb->right, xoffset, p1 );
77 v3_muladds( h1, rnb->right, xoffset, h1 );
78
79 v3_copy( p0, l );
80
81 for( int i=0; i<5; i++ )
82 {
83 float t = (float)(i+1)/5.0f;
84 eval_bezier_time( p0, p1, h0, h1, t, p );
85 vg_line( p, l, colour );
86 v3_copy( p, l );
87 }
88 }
89
90 static u32 world_routes_get_path( u32 starter, u32 stack[64] )
91 {
92 struct subworld_routes *r = subworld_routes();
93 u32 stack_i[64];
94
95 stack[0] = starter;
96 stack_i[0] = 0;
97
98 u32 si = 1;
99 int loop_complete = 0;
100
101 while( si )
102 {
103 if( stack_i[si-1] == 2 )
104 {
105 si --;
106 continue;
107 }
108
109 struct route_node *rn = &r->nodes[stack[si-1]];
110 u32 nextid = rn->next[stack_i[si-1]];
111 stack_i[si-1] ++;
112
113 if( nextid != 0xffffffff )
114 {
115 if( nextid == stack[0] )
116 {
117 loop_complete = 1;
118 break;
119 }
120
121 int valid = 1;
122 for( int sj=0; sj<si; sj++ )
123 {
124 if( stack[sj] == nextid )
125 {
126 valid = 0;
127 break;
128 }
129 }
130
131 if( valid )
132 {
133 stack_i[si] = 0;
134 stack[si] = nextid;
135 si ++;
136 continue;
137 }
138 }
139 }
140
141 if( loop_complete )
142 return si;
143
144 return 0;
145 }
146
147 static void world_routes_verify_run( u32 route, double new_pass_time )
148 {
149 struct subworld_routes *r = subworld_routes();
150 if( r->current_run_version == 0 ) return;
151
152 u32 stack[64];
153 u32 si = world_routes_get_path( r->routes[route].start, stack );
154
155 /*
156 * we only care about gates that ref gates, so shuffle down the array
157 */
158 u32 sj = 0;
159 for( u32 i=0; i<si; i++ )
160 if( r->nodes[stack[i]].is_gate && r->nodes[stack[(i+1)%si]].is_gate )
161 stack[sj ++] = r->nodes[stack[i]].gate_id;
162
163 /*
164 * run versions & times must always ASCEND apart from exactly once, where
165 * the tail connects to the head
166 */
167
168 vg_info("Verifying run (%u)\n", route);
169
170 u32 descend_allowance = 1;
171 double lap_time = 0.0;
172
173 for( u32 i=0; i<sj; i++ )
174 {
175 struct route_gate *pa = &r->gates[stack[i]],
176 *pb = &r->gates[stack[(i+1) % sj]];
177
178 vg_info( " pa: %u, pb: %u\n", pa->passed_version, pb->passed_version );
179
180 int version_inorder = 0;
181 double diff = 0.0;
182
183 if( pb->passed_version == pa->passed_version+1 )
184 {
185 version_inorder = 1;
186 diff = pb->time_passed - pa->time_passed;
187 }
188 else if( pb->passed_version == pa->passed_version+1-sj &&
189 pa->passed_version+1 == r->current_run_version )
190 {
191 version_inorder = 1;
192 diff = new_pass_time - pa->time_passed;
193 }
194
195 if( !version_inorder )
196 return;
197
198 lap_time += diff;
199 }
200
201 /* We've now verified the run was completed correctly */
202 vg_success( "Lap time set. route %u: %lf\n", route, lap_time );
203 }
204
205 static void world_routes_activate_gate( u32 id )
206 {
207 struct subworld_routes *r = subworld_routes();
208 struct route_gate *ig = &r->gates[id];
209 struct route_node *pnode = &r->nodes[ig->node_id],
210 *pdest = &r->nodes[pnode->next[0]];
211
212 r->active_gate = id;
213
214 for( u32 i=0; i<r->route_count; i++ )
215 {
216 struct route *route = &r->routes[i];
217
218 route->active = 0;
219 for( u32 j=0; j<pdest->ref_count; j++ )
220 {
221 if( pdest->route_ids[j] == i )
222 {
223 world_routes_verify_run( i, vg_time );
224 route->active = 1;
225 break;
226 }
227 }
228 }
229
230 ig->time_passed = vg_time;
231 ig->passed_version = r->current_run_version;
232 r->current_run_version ++;
233 }
234
235 static void world_routes_debug(void)
236 {
237 struct subworld_routes *r = subworld_routes();
238
239 for( int i=0; i<r->node_count; i++ )
240 {
241 struct route_node *rn = &r->nodes[i];
242 vg_line_pt3( rn->co, 1.0f, rn->is_gate? 0xffffff00: 0xff00b2ff );
243 }
244
245 for( int i=0; i<r->route_count; i++ )
246 {
247 struct route *route = &r->routes[i];
248
249 u32 stack[64];
250 u32 si = world_routes_get_path( route->start, stack );
251
252 u32 colours[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
253 0xff5442f5 };
254
255 u32 cc = colours[i%vg_list_size(colours)];
256
257 for( int sj=0; sj<si; sj++ )
258 {
259 int sk = (sj+1)%si;
260 debug_sbpath( &r->nodes[stack[sj]], &r->nodes[stack[sk]], cc,
261 (float)i );
262 }
263 }
264
265 for( int i=0; i<r->node_count; i++ )
266 {
267 struct route_node *ri = &r->nodes[i],
268 *rj = NULL;
269
270 for( int j=0; j<2; j++ )
271 {
272 if( ri->next[j] != 0xffffffff )
273 {
274 rj = &r->nodes[ri->next[j]];
275 vg_line( ri->co, rj->co, 0x20ffffff );
276 }
277 }
278 }
279 }
280
281 static void world_routes_free(void)
282 {
283 struct subworld_routes *r = subworld_routes();
284
285 free( r->nodes );
286 free( r->routes );
287 free( r->gates );
288 }
289
290 static void world_id_fixup( u32 *uid, mdl_header *mdl )
291 {
292 if( *uid )
293 *uid = mdl_node_from_id( mdl, *uid )->sub_uid;
294 else
295 *uid = 0xffffffff;
296 }
297
298 static void world_routes_gen_meshes(void)
299 {
300 struct subworld_routes *r = subworld_routes();
301 scene_init( &r->scene_lines );
302
303 for( int i=0; i<r->route_count; i++ )
304 {
305 struct route *route = &r->routes[i];
306
307 u32 stack[64];
308 u32 si = world_routes_get_path( route->start, stack );
309
310 u32 last_valid = 0;
311
312 for( int sj=0; sj<si; sj++ )
313 {
314 int sk=(sj+1)%si;
315
316 struct route_node *rnj = &r->nodes[ stack[sj] ],
317 *rnk = &r->nodes[ stack[sk] ],
318 *rnl;
319
320 if( rnj->is_gate && rnk->is_gate )
321 {
322 last_valid = 0;
323 continue;
324 }
325
326 float base_x0 = (float)rnj->ref_count*-0.5f + (float)rnj->current_refs,
327 base_x1 = (float)rnk->ref_count*-0.5f + (float)rnk->current_refs;
328
329 if( rnk->is_gate )
330 {
331 rnl = &r->nodes[ rnk->next[0] ];
332 base_x1 = (float)rnl->ref_count*-0.5f + (float)rnl->current_refs;
333 }
334
335 if( sk == 0 )
336 {
337 base_x1 -= 1.0f;
338 }
339
340 v3f p0, h0, p1, h1, p, pd;
341
342 v3_copy( rnj->co, p0 );
343 v3_muladds( rnj->co, rnj->h, 1.0f, h0 );
344 v3_copy( rnk->co, p1 );
345 v3_muladds( rnk->co, rnk->h, -1.0f, h1 );
346
347 float t=0.0f;
348 int it = 0;
349
350 for( int it=0; it<256; it ++ )
351 {
352 float const k_sample_dist = 0.02f;
353 eval_bezier_time( p0,p1,h0,h1, t,p );
354 eval_bezier_time( p0,p1,h0,h1, t+k_sample_dist,pd );
355
356 float mod = k_sample_dist / v3_dist( p, pd );
357
358 v3f v0,up, right;
359 v3_muls( rnj->up, 1.0f-t, up );
360 v3_muladds( up, rnk->up, t, up );
361
362 v3_sub( pd,p,v0 );
363 v3_cross( up, v0, right );
364 v3_normalize( right );
365
366 float cur_x = (1.0f-t)*base_x0 + t*base_x1;
367
368 v3f sc, sa, sb, down;
369 v3_muladds( p, right, cur_x, sc );
370 v3_muladds( sc, up, 1.5f, sc );
371 v3_muladds( sc, right, 0.45f, sa );
372 v3_muladds( sc, right, -0.45f, sb );
373 v3_muls( up, -1.0f, down );
374
375 ray_hit ha, hb;
376 ha.dist = 8.0f;
377 hb.dist = 8.0f;
378 if(ray_world( sa, down, &ha ) &&
379 ray_world( sb, down, &hb ))
380 {
381 mdl_vert va, vb;
382
383 v3_muladds( ha.pos, up, 0.06f, va.co );
384 v3_muladds( hb.pos, up, 0.06f, vb.co );
385 v3_copy( up, va.norm );
386 v3_copy( up, vb.norm );
387 v3_zero( va.colour );
388 v3_zero( vb.colour );
389 v2_zero( va.uv );
390 v2_zero( vb.uv );
391
392 scene_push_vert( &r->scene_lines, &va );
393 scene_push_vert( &r->scene_lines, &vb );
394
395 if( last_valid )
396 {
397 /* Connect them with triangles */
398 scene_push_tri( &r->scene_lines, (u32[3]){
399 last_valid+0-2, last_valid+1-2, last_valid+2-2} );
400 scene_push_tri( &r->scene_lines, (u32[3]){
401 last_valid+1-2, last_valid+3-2, last_valid+2-2} );
402 }
403
404 last_valid = r->scene_lines.vertex_count;
405 }
406 else
407 last_valid = 0;
408
409 t += 1.0f*mod;
410
411 if( t >= 1.0f )
412 {
413 /* TODO special case for end of loop, need to add triangles
414 * between first and last rungs */
415 break;
416 }
417 }
418
419 rnj->current_refs ++;
420 }
421
422 scene_copy_slice( &r->scene_lines, &route->sm );
423 }
424
425 scene_upload( &r->scene_lines );
426 scene_free_offline_buffers( &r->scene_lines );
427 }
428
429 static void bind_terrain_textures(void);
430 static void render_world_routes( m4x4f projection, v3f camera )
431 {
432 struct subworld_routes *r = subworld_routes();
433
434 m4x3f identity_matrix;
435 m4x3_identity( identity_matrix );
436
437 shader_route_use();
438 shader_route_uTexGarbage(0);
439 shader_link_standard_ub( _shader_route.id, 2 );
440 bind_terrain_textures();
441
442 shader_route_uPv( projection );
443 shader_route_uMdl( identity_matrix );
444 shader_route_uCamera( camera );
445
446 scene_bind( &r->scene_lines );
447
448 for( int i=0; i<r->route_count; i++ )
449 {
450 struct route *route = &r->routes[i];
451 route->factive = vg_lerpf( route->factive, route->active, 0.01f );
452
453 v4f colour;
454 v3_lerp( (v3f){0.7f,0.7f,0.7f}, route->colour, route->factive, colour );
455 colour[3] = 1.0f;
456
457 shader_route_uColour( colour );
458 mdl_draw_submesh( &route->sm );
459 }
460 }
461
462 static void world_routes_register(void)
463 {
464 shader_route_register();
465 }
466
467 static void world_routes_loadfrom( mdl_header *mdl )
468 {
469 struct subworld_routes *r = subworld_routes();
470 r->nodes = NULL;
471 r->node_count = 0;
472 r->node_cap = 0;
473 r->routes = NULL;
474 r->route_count = 0;
475 r->route_cap = 0;
476 r->gates = NULL;
477 r->gate_count = 0;
478 r->gate_cap = 0;
479
480 for( int i=0; i<mdl->node_count; i++ )
481 {
482 mdl_node *pnode = mdl_node_from_id(mdl,i);
483 m4x3f transform;
484
485 if( pnode->classtype == k_classtype_route_node ||
486 pnode->classtype == k_classtype_gate )
487 {
488 mdl_node_transform( pnode, transform );
489 pnode->sub_uid = r->node_count;
490
491 r->nodes = buffer_reserve( r->nodes, r->node_count, &r->node_cap, 1,
492 sizeof( struct route_node ) );
493
494 struct route_node *rn = &r->nodes[r->node_count];
495
496 v3_copy( transform[0], rn->right );
497 v3_normalize( rn->right );
498 v3_copy( transform[1], rn->up );
499 v3_normalize( rn->up );
500 v3_muls( transform[2], -1.0f, rn->h );
501 v3_copy( transform[3], rn->co );
502 rn->ref_count = 0;
503 rn->current_refs = 0;
504
505 if( pnode->classtype == k_classtype_gate )
506 {
507 r->gates = buffer_reserve( r->gates, r->gate_count, &r->gate_cap,
508 1, sizeof( struct route_gate ) );
509
510 struct classtype_gate *inf = mdl_get_entdata( mdl, pnode );
511
512 /* H is later scaled based on link distance */
513 v3_normalize( rn->h );
514 rn->next[0] = inf->target;
515 rn->next[1] = 0;
516 rn->gate_id = r->gate_count;
517 rn->is_gate = 1;
518
519 /* TODO */
520 if( inf->target )
521 {
522 mdl_node *pother = mdl_node_from_id( mdl, inf->target );
523
524 if( pother->classtype == k_classtype_gate )
525 {
526 struct route_gate *rg = &r->gates[r->gate_count];
527 rg->node_id = r->node_count;
528 rg->passed_version = 0;
529 rg->time_passed = 0.0;
530
531 v3_copy( pnode->co, rg->gate.co[0] );
532 v3_copy( pother->co, rg->gate.co[1] );
533 v4_copy( pnode->q, rg->gate.q[0] );
534 v4_copy( pother->q, rg->gate.q[1] );
535 v2_copy( inf->dims, rg->gate.dims );
536
537 gate_transform_update( &rg->gate );
538
539 r->gate_count ++;
540 }
541 }
542 }
543 else
544 {
545 struct classtype_route_node *inf = mdl_get_entdata( mdl, pnode );
546 rn->next[0] = inf->target;
547 rn->next[1] = inf->target1;
548 rn->is_gate = 0;
549 }
550
551 r->node_count ++;
552 }
553 else if( pnode->classtype == k_classtype_route )
554 {
555 struct classtype_route *inf = mdl_get_entdata( mdl, pnode );
556 r->routes = buffer_reserve( r->routes, r->route_count, &r->route_cap,
557 1, sizeof( struct route ) );
558
559 struct route *route = &r->routes[r->route_count];
560
561 v3_copy( inf->colour, route->colour );
562 route->colour[3] = 1.0f;
563
564 route->name = NULL;
565 route->start = inf->id_start;
566 route->active = 0;
567 route->factive = 0.0f;
568
569 r->route_count ++;
570 }
571 }
572
573 /*
574 * Apply correct system-local ids
575 */
576 for( int i=0; i<r->node_count; i++ )
577 {
578 struct route_node *rn = &r->nodes[i];
579
580 for( int j=0; j<2; j++ )
581 world_id_fixup( &rn->next[j], mdl );
582 }
583
584 for( int i=0; i<r->route_count; i++ )
585 {
586 struct route *route = &r->routes[i];
587 world_id_fixup( &route->start, mdl );
588 }
589
590 /*
591 * Gather references
592 */
593 for( int i=0; i<r->route_count; i++ )
594 {
595 struct route *route = &r->routes[i];
596
597 u32 stack[64];
598 u32 si = world_routes_get_path( route->start, stack );
599
600 for( int sj=0; sj<si; sj++ )
601 {
602 struct route_node *rn = &r->nodes[ stack[sj] ];
603 rn->route_ids[ rn->ref_count ++ ] = i;
604
605 if( rn->ref_count > 4 )
606 vg_warn( "Too many references on route node %i\n", i );
607 }
608 }
609
610 world_routes_gen_meshes();
611 }
612
613 #endif /* ROUTES_H */