8 #include "shaders/vblend.h"
9 #include "shaders/route.h"
11 enum route_special_type
13 k_route_special_type_gate
= 1,
14 k_route_special_type_collector
= 2
17 struct subworld_routes
24 u32 special_type
, special_id
, current_refs
, ref_count
;
25 u32 route_ids
[4]; /* Gates can be linked into up to four routes */
56 u32 version
; /* Incremented on every teleport */
63 struct route_collector
65 struct route_timing timing
;
80 static struct subworld_routes
*subworld_routes(void);
82 static void debug_sbpath( struct route_node
*rna
, struct route_node
*rnb
,
83 u32 colour
, float xoffset
)
85 v3f p0
, h0
, p1
, h1
, l
, p
;
87 v3_copy( rna
->co
, p0
);
88 v3_muladds( rna
->co
, rna
->h
, 1.0f
, h0
);
89 v3_copy( rnb
->co
, p1
);
90 v3_muladds( rnb
->co
, rnb
->h
, -1.0f
, h1
);
92 v3_muladds( p0
, rna
->right
, xoffset
, p0
);
93 v3_muladds( h0
, rna
->right
, xoffset
, h0
);
94 v3_muladds( p1
, rnb
->right
, xoffset
, p1
);
95 v3_muladds( h1
, rnb
->right
, xoffset
, h1
);
99 for( int i
=0; i
<5; i
++ )
101 float t
= (float)(i
+1)/5.0f
;
102 eval_bezier_time( p0
, p1
, h0
, h1
, t
, p
);
103 vg_line( p
, l
, colour
);
109 * Get a list of node ids in stack, and return how many there is
111 static u32
world_routes_get_path( u32 starter
, u32 stack
[64] )
113 struct subworld_routes
*r
= subworld_routes();
120 int loop_complete
= 0;
124 if( stack_i
[si
-1] == 2 )
130 struct route_node
*rn
= &r
->nodes
[stack
[si
-1]];
131 u32 nextid
= rn
->next
[stack_i
[si
-1]];
134 if( nextid
!= 0xffffffff )
136 if( nextid
== stack
[0] )
143 for( int sj
=0; sj
<si
; sj
++ )
145 if( stack
[sj
] == nextid
)
169 * Will scan the whole run for two things;
170 * 1: we set a new record for the total, complete loop around the course
171 * 2: the time of each segment will be recorded into the data buffer
172 * (not implemented: TODO)
174 static void world_routes_verify_run( u32 route
)
176 struct subworld_routes
*r
= subworld_routes();
179 u32 si
= world_routes_get_path( r
->routes
[route
].start
, stack
);
182 * we only care about gates that ref gates, so shuffle down the array
184 struct route_timing
*timings
[64];
185 u32 sj
= 0, maxv
= 0, begin
= 0;
186 for( u32 i
=0; i
<si
; i
++ )
188 if( r
->nodes
[stack
[i
]].special_type
== k_route_special_type_collector
)
189 timings
[sj
++] = &r
->collectors
[r
->nodes
[stack
[i
]].special_id
].timing
;
190 else if( r
->nodes
[stack
[i
]].special_type
== k_route_special_type_gate
)
191 timings
[sj
++] = &r
->gates
[r
->nodes
[stack
[i
]].special_id
].timing
;
194 for( u32 i
=0; i
<sj
; i
++ )
196 if( timings
[i
]->version
> maxv
)
198 maxv
= timings
[i
]->version
;
203 vg_info( "== begin verification (%u) ==\n", route
);
204 vg_info( " current version: %u\n", r
->current_run_version
);
207 if( timings
[begin
]->version
== r
->current_run_version
)
210 double lap_time
= 0.0;
212 for( u32 i
=0; i
<sj
; i
++ )
214 u32 j
= (sj
+begin
-i
-1) % sj
,
221 /* j1v should equal jv+1 */
222 if( timings
[j1
]->version
== timings
[j
]->version
+1 )
224 diff
= timings
[j1
]->time
- timings
[j
]->time
;
232 vg_success( " [ %u %f ] %f\n", timings
[j1
]->time
,
233 timings
[j1
]->version
, diff
);
235 vg_warn( " [ %u %f ]\n", timings
[j1
]->time
, timings
[j1
]->version
);
239 vg_success( " NEW LAP TIME: %f\n", lap_time
);
241 vg_info( " ctime: %f\n", lap_time
);
245 * When going through a gate this is called for bookkeeping purposes
247 static void world_routes_activate_gate( u32 id
)
249 struct subworld_routes
*r
= subworld_routes();
250 struct route_gate
*rg
= &r
->gates
[id
];
251 struct route_node
*pnode
= &r
->nodes
[rg
->node_id
],
252 *pdest
= &r
->nodes
[pnode
->next
[0]];
254 struct route_collector
*rc
= &r
->collectors
[ pdest
->special_id
];
257 rg
->timing
.version
= r
->current_run_version
;
258 rg
->timing
.time
= vg_time
;
259 for( u32 i
=0; i
<r
->route_count
; i
++ )
261 struct route
*route
= &r
->routes
[i
];
264 for( u32 j
=0; j
<pdest
->ref_count
; j
++ )
266 if( pdest
->route_ids
[j
] == i
)
268 world_routes_verify_run( i
);
275 r
->current_run_version
++;
277 rc
->timing
.version
= r
->current_run_version
;
278 rc
->timing
.time
= vg_time
;
279 r
->current_run_version
++;
282 static void world_routes_debug(void)
284 struct subworld_routes
*r
= subworld_routes();
286 for( int i
=0; i
<r
->node_count
; i
++ )
288 struct route_node
*rn
= &r
->nodes
[i
];
289 vg_line_pt3( rn
->co
, 1.0f
, rn
->special_type
? 0xffffff00: 0xff00b2ff );
292 for( int i
=0; i
<r
->route_count
; i
++ )
294 struct route
*route
= &r
->routes
[i
];
297 u32 si
= world_routes_get_path( route
->start
, stack
);
299 u32 colours
[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
302 u32 cc
= colours
[i
%vg_list_size(colours
)];
304 for( int sj
=0; sj
<si
; sj
++ )
307 debug_sbpath( &r
->nodes
[stack
[sj
]], &r
->nodes
[stack
[sk
]], cc
,
312 for( int i
=0; i
<r
->node_count
; i
++ )
314 struct route_node
*ri
= &r
->nodes
[i
],
317 for( int j
=0; j
<2; j
++ )
319 if( ri
->next
[j
] != 0xffffffff )
321 rj
= &r
->nodes
[ri
->next
[j
]];
322 vg_line( ri
->co
, rj
->co
, 0x20ffffff );
328 static void world_routes_free(void)
330 struct subworld_routes
*r
= subworld_routes();
337 static void world_id_fixup( u32
*uid
, mdl_header
*mdl
)
340 *uid
= mdl_node_from_id( mdl
, *uid
)->sub_uid
;
346 * Create the strips of colour that run through the world along course paths
348 static void world_routes_gen_meshes(void)
350 struct subworld_routes
*r
= subworld_routes();
351 scene_init( &r
->scene_lines
);
353 for( int i
=0; i
<r
->route_count
; i
++ )
355 struct route
*route
= &r
->routes
[i
];
358 u32 si
= world_routes_get_path( route
->start
, stack
);
362 for( int sj
=0; sj
<si
; sj
++ )
366 struct route_node
*rnj
= &r
->nodes
[ stack
[sj
] ],
367 *rnk
= &r
->nodes
[ stack
[sk
] ],
370 if( rnj
->special_type
&& rnk
->special_type
)
376 float base_x0
= (float)rnj
->ref_count
*-0.5f
+ (float)rnj
->current_refs
,
377 base_x1
= (float)rnk
->ref_count
*-0.5f
+ (float)rnk
->current_refs
;
379 if( rnk
->special_type
)
381 rnl
= &r
->nodes
[ rnk
->next
[0] ];
382 base_x1
= (float)rnl
->ref_count
*-0.5f
+ (float)rnl
->current_refs
;
390 v3f p0
, h0
, p1
, h1
, p
, pd
;
392 v3_copy( rnj
->co
, p0
);
393 v3_muladds( rnj
->co
, rnj
->h
, 1.0f
, h0
);
394 v3_copy( rnk
->co
, p1
);
395 v3_muladds( rnk
->co
, rnk
->h
, -1.0f
, h1
);
400 for( int it
=0; it
<256; it
++ )
402 float const k_sample_dist
= 0.02f
;
403 eval_bezier_time( p0
,p1
,h0
,h1
, t
,p
);
404 eval_bezier_time( p0
,p1
,h0
,h1
, t
+k_sample_dist
,pd
);
406 float mod
= k_sample_dist
/ v3_dist( p
, pd
);
409 v3_muls( rnj
->up
, 1.0f
-t
, up
);
410 v3_muladds( up
, rnk
->up
, t
, up
);
413 v3_cross( up
, v0
, right
);
414 v3_normalize( right
);
416 float cur_x
= (1.0f
-t
)*base_x0
+ t
*base_x1
;
418 v3f sc
, sa
, sb
, down
;
419 v3_muladds( p
, right
, cur_x
, sc
);
420 v3_muladds( sc
, up
, 1.5f
, sc
);
421 v3_muladds( sc
, right
, 0.45f
, sa
);
422 v3_muladds( sc
, right
, -0.45f
, sb
);
423 v3_muls( up
, -1.0f
, down
);
428 if(ray_world( sa
, down
, &ha
) &&
429 ray_world( sb
, down
, &hb
))
433 v3_muladds( ha
.pos
, up
, 0.06f
, va
.co
);
434 v3_muladds( hb
.pos
, up
, 0.06f
, vb
.co
);
435 v3_copy( up
, va
.norm
);
436 v3_copy( up
, vb
.norm
);
437 v3_zero( va
.colour
);
438 v3_zero( vb
.colour
);
442 scene_push_vert( &r
->scene_lines
, &va
);
443 scene_push_vert( &r
->scene_lines
, &vb
);
447 /* Connect them with triangles */
448 scene_push_tri( &r
->scene_lines
, (u32
[3]){
449 last_valid
+0-2, last_valid
+1-2, last_valid
+2-2} );
450 scene_push_tri( &r
->scene_lines
, (u32
[3]){
451 last_valid
+1-2, last_valid
+3-2, last_valid
+2-2} );
454 last_valid
= r
->scene_lines
.vertex_count
;
463 /* TODO special case for end of loop, need to add triangles
464 * between first and last rungs */
469 rnj
->current_refs
++;
472 scene_copy_slice( &r
->scene_lines
, &route
->sm
);
475 scene_upload( &r
->scene_lines
);
476 scene_free_offline_buffers( &r
->scene_lines
);
479 static void bind_terrain_textures(void);
480 static void render_world_routes( m4x4f projection
, v3f camera
)
482 struct subworld_routes
*r
= subworld_routes();
484 m4x3f identity_matrix
;
485 m4x3_identity( identity_matrix
);
488 shader_route_uTexGarbage(0);
489 shader_link_standard_ub( _shader_route
.id
, 2 );
490 bind_terrain_textures();
492 shader_route_uPv( projection
);
493 shader_route_uMdl( identity_matrix
);
494 shader_route_uCamera( camera
);
496 scene_bind( &r
->scene_lines
);
498 for( int i
=0; i
<r
->route_count
; i
++ )
500 struct route
*route
= &r
->routes
[i
];
501 route
->factive
= vg_lerpf( route
->factive
, route
->active
, 0.01f
);
504 v3_lerp( (v3f
){0.7f
,0.7f
,0.7f
}, route
->colour
, route
->factive
, colour
);
507 shader_route_uColour( colour
);
508 mdl_draw_submesh( &route
->sm
);
512 static void world_routes_register(void)
514 struct subworld_routes
*r
= subworld_routes();
515 r
->current_run_version
= 2;
517 shader_route_register();
520 static void world_routes_loadfrom( mdl_header
*mdl
)
522 struct subworld_routes
*r
= subworld_routes();
533 for( int i
=0; i
<mdl
->node_count
; i
++ )
535 mdl_node
*pnode
= mdl_node_from_id(mdl
,i
);
538 if( pnode
->classtype
== k_classtype_route_node
||
539 pnode
->classtype
== k_classtype_gate
)
541 mdl_node_transform( pnode
, transform
);
542 pnode
->sub_uid
= r
->node_count
;
544 r
->nodes
= buffer_reserve( r
->nodes
, r
->node_count
, &r
->node_cap
, 1,
545 sizeof( struct route_node
) );
547 struct route_node
*rn
= &r
->nodes
[r
->node_count
];
549 v3_copy( transform
[0], rn
->right
);
550 v3_normalize( rn
->right
);
551 v3_copy( transform
[1], rn
->up
);
552 v3_normalize( rn
->up
);
553 v3_muls( transform
[2], -1.0f
, rn
->h
);
554 v3_copy( transform
[3], rn
->co
);
556 rn
->current_refs
= 0;
557 rn
->special_type
= 0;
560 if( pnode
->classtype
== k_classtype_gate
)
562 struct classtype_gate
*inf
= mdl_get_entdata( mdl
, pnode
);
564 /* H is later scaled based on link distance */
565 v3_normalize( rn
->h
);
566 rn
->next
[0] = inf
->target
;
572 mdl_node
*pother
= mdl_node_from_id( mdl
, inf
->target
);
574 if( pother
->classtype
== k_classtype_gate
)
576 r
->gates
= buffer_reserve( r
->gates
, r
->gate_count
,
578 1, sizeof( struct route_gate
) );
580 struct route_gate
*rg
= &r
->gates
[r
->gate_count
];
581 rg
->node_id
= r
->node_count
;
582 rg
->timing
.time
= 0.0;
583 rg
->timing
.version
= 0;
585 v3_copy( pnode
->co
, rg
->gate
.co
[0] );
586 v3_copy( pother
->co
, rg
->gate
.co
[1] );
587 v4_copy( pnode
->q
, rg
->gate
.q
[0] );
588 v4_copy( pother
->q
, rg
->gate
.q
[1] );
589 v2_copy( inf
->dims
, rg
->gate
.dims
);
591 gate_transform_update( &rg
->gate
);
592 rn
->special_type
= k_route_special_type_gate
;
593 rn
->special_id
= r
->gate_count
;
599 if( rn
->special_type
== 0 )
601 r
->collectors
= buffer_reserve(
602 r
->collectors
, r
->collector_count
, &r
->collector_cap
,
603 1, sizeof( struct route_collector
));
605 struct route_collector
*rc
= &r
->collectors
[r
->collector_count
];
606 rc
->timing
.time
= 0.0;
607 rc
->timing
.version
= 0;
609 rn
->special_type
= k_route_special_type_collector
;
610 rn
->special_id
= r
->collector_count
;
612 r
->collector_count
++;
617 struct classtype_route_node
*inf
= mdl_get_entdata( mdl
, pnode
);
618 rn
->next
[0] = inf
->target
;
619 rn
->next
[1] = inf
->target1
;
624 else if( pnode
->classtype
== k_classtype_route
)
626 struct classtype_route
*inf
= mdl_get_entdata( mdl
, pnode
);
627 r
->routes
= buffer_reserve( r
->routes
, r
->route_count
, &r
->route_cap
,
628 1, sizeof( struct route
) );
630 struct route
*route
= &r
->routes
[r
->route_count
];
632 v3_copy( inf
->colour
, route
->colour
);
633 route
->colour
[3] = 1.0f
;
636 route
->start
= inf
->id_start
;
638 route
->factive
= 0.0f
;
645 * Apply correct system-local ids
647 for( int i
=0; i
<r
->node_count
; i
++ )
649 struct route_node
*rn
= &r
->nodes
[i
];
651 for( int j
=0; j
<2; j
++ )
652 world_id_fixup( &rn
->next
[j
], mdl
);
655 for( int i
=0; i
<r
->route_count
; i
++ )
657 struct route
*route
= &r
->routes
[i
];
658 world_id_fixup( &route
->start
, mdl
);
664 for( int i
=0; i
<r
->route_count
; i
++ )
666 struct route
*route
= &r
->routes
[i
];
669 u32 si
= world_routes_get_path( route
->start
, stack
);
671 for( int sj
=0; sj
<si
; sj
++ )
673 struct route_node
*rn
= &r
->nodes
[ stack
[sj
] ];
674 rn
->route_ids
[ rn
->ref_count
++ ] = i
;
676 if( rn
->ref_count
> 4 )
677 vg_warn( "Too many references on route node %i\n", i
);
681 world_routes_gen_meshes();
684 #endif /* ROUTES_H */