7 #include "world_info.h"
8 #include "highscores.h"
10 #include "shaders/vblend.h"
11 #include "shaders/route.h"
12 #include "shaders/routeui.h"
14 enum route_special_type
16 k_route_special_type_gate
= 1,
17 k_route_special_type_collector
= 2
20 enum { k_max_ui_segments
= 32 };
21 enum { k_route_ui_max_verts
= 2000 };
22 enum { k_route_ui_max_indices
= 3000 };
24 struct subworld_routes
31 u32 special_type
, special_id
, current_refs
, ref_count
;
32 u32 route_ids
[4]; /* Gates can be linked into up to four routes */
50 double best_lap
, latest_pass
; /* Session */
61 struct route_ui_segment
64 u32 vertex_start
, vertex_count
,
65 index_start
, index_count
;
67 segments
[k_max_ui_segments
];
69 u32 segment_start
, segment_count
, fade_start
, fade_count
;
70 double fade_timer_start
;
75 m4x3f scoreboard_transform
;
90 u32 version
; /* Incremented on every teleport */
97 struct route_collector
99 struct route_timing timing
;
114 static struct subworld_routes
*subworld_routes(void);
116 static void debug_sbpath( struct route_node
*rna
, struct route_node
*rnb
,
117 u32 colour
, float xoffset
)
119 v3f p0
, h0
, p1
, h1
, l
, p
;
121 v3_copy( rna
->co
, p0
);
122 v3_muladds( rna
->co
, rna
->h
, 1.0f
, h0
);
123 v3_copy( rnb
->co
, p1
);
124 v3_muladds( rnb
->co
, rnb
->h
, -1.0f
, h1
);
126 v3_muladds( p0
, rna
->right
, xoffset
, p0
);
127 v3_muladds( h0
, rna
->right
, xoffset
, h0
);
128 v3_muladds( p1
, rnb
->right
, xoffset
, p1
);
129 v3_muladds( h1
, rnb
->right
, xoffset
, h1
);
133 for( int i
=0; i
<5; i
++ )
135 float t
= (float)(i
+1)/5.0f
;
136 eval_bezier_time( p0
, p1
, h0
, h1
, t
, p
);
137 vg_line( p
, l
, colour
);
143 * Get a list of node ids in stack, and return how many there is
145 static u32
world_routes_get_path( u32 starter
, u32 stack
[64] )
147 struct subworld_routes
*r
= subworld_routes();
154 int loop_complete
= 0;
158 if( stack_i
[si
-1] == 2 )
164 struct route_node
*rn
= &r
->nodes
[stack
[si
-1]];
165 u32 nextid
= rn
->next
[stack_i
[si
-1]];
168 if( nextid
!= 0xffffffff )
170 if( nextid
== stack
[0] )
177 for( int sj
=0; sj
<si
; sj
++ )
179 if( stack
[sj
] == nextid
)
203 * Free a segment from the UI bar to be reused later
205 static void world_routes_ui_popfirst( u32 route
)
207 struct subworld_routes
*r
= subworld_routes();
208 struct route
*pr
= &r
->routes
[route
];
210 if( pr
->ui
.segment_count
)
212 pr
->ui
.segment_start
++;
214 if( pr
->ui
.segment_start
== 32 )
215 pr
->ui
.segment_start
= 0;
217 pr
->ui
.segment_count
--;
222 * Reset ui bar completely
224 static void world_routes_ui_clear( u32 route
)
226 struct subworld_routes
*r
= subworld_routes();
227 struct route
*pr
= &r
->routes
[route
];
228 pr
->ui
.segment_start
= (pr
->ui
.segment_start
+ pr
->ui
.segment_count
) %
230 pr
->ui
.segment_count
= 0;
234 * Break a index range into two pieces over the edge of the maximum it can
235 * store. s1 is 0 always, so its a ring buffer.
237 static void world_routes_ui_split_indices( u32 s0
, u32 count
, u32
*c0
, u32
*c1
)
239 *c0
= (VG_MIN( s0
+count
, k_route_ui_max_indices
)) - s0
;
244 * Place a set of indices into gpu array automatically splits
247 static void world_routes_ui_set_indices( struct route
*pr
,
248 u16
*indices
, u32 count
)
251 world_routes_ui_split_indices( pr
->ui
.indices_head
, count
, &c0
, &c1
);
253 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER
, pr
->ui
.ebo
);
257 glBufferSubData( GL_ELEMENT_ARRAY_BUFFER
, pr
->ui
.indices_head
*sizeof(u16
),
258 c0
*sizeof(u16
), indices
);
263 glBufferSubData( GL_ELEMENT_ARRAY_BUFFER
, 0, c1
*sizeof(u16
), indices
+c0
);
264 pr
->ui
.indices_head
= c1
;
267 pr
->ui
.indices_head
+= c0
;
271 * Place a set of vertices into gpu array
273 static u32
world_routes_ui_set_verts( struct route
*pr
, v2f
*verts
, u32 count
)
275 if( pr
->ui
.vertex_head
+ count
>= k_route_ui_max_verts
)
276 pr
->ui
.vertex_head
= 0;
278 u32 vert_start
= pr
->ui
.vertex_head
;
279 pr
->ui
.vertex_head
+= count
;
281 glBindBuffer( GL_ARRAY_BUFFER
, pr
->ui
.vbo
);
282 glBufferSubData( GL_ARRAY_BUFFER
, (GLintptr
)(vert_start
*sizeof(v2f
)),
283 sizeof(v2f
)*count
, verts
);
289 * Update the last (count) vertices positions, does not add any.
290 * Data must already be written to, and not cross either array boundaries.
292 static u32
world_routes_ui_update_verts( struct route
*pr
,
293 v2f
*verts
, u32 count
)
295 u32 vert_start
= pr
->ui
.vertex_head
-count
;
297 glBindBuffer( GL_ARRAY_BUFFER
, pr
->ui
.vbo
);
298 glBufferSubData( GL_ARRAY_BUFFER
, (GLintptr
)(vert_start
*sizeof(v2f
)),
299 sizeof(v2f
)*count
, verts
);
305 * Current/active segment of this UI bar
307 static struct route_ui_segment
*world_routes_ui_curseg( struct route
*pr
)
309 u32 index
= (pr
->ui
.segment_start
+pr
->ui
.segment_count
-1)%k_max_ui_segments
;
310 return &pr
->ui
.segments
[ index
];
314 * Start a new segment in the UI bar, will create a split on the last one if
315 * there is one active currently. (api)
317 static void world_routes_ui_newseg( u32 route
)
319 struct subworld_routes
*r
= subworld_routes();
320 struct route
*pr
= &r
->routes
[route
];
322 pr
->ui
.last_notch
= 0.0;
324 glBindVertexArray( pr
->ui
.vao
);
325 if( pr
->ui
.segment_count
)
327 float const k_gap_width
= 1.0f
;
329 struct route_ui_segment
*cseg
= world_routes_ui_curseg(pr
);
332 verts
[0][0] = cseg
->length
-k_gap_width
;
334 verts
[1][0] = cseg
->length
-k_gap_width
;
337 world_routes_ui_update_verts( pr
, verts
, 2 );
340 pr
->ui
.segment_count
++;
341 struct route_ui_segment
*segment
= world_routes_ui_curseg(pr
);
353 u32 vert_start
= world_routes_ui_set_verts( pr
, verts
, 4 );
356 indices
[0] = vert_start
+ 0;
357 indices
[1] = vert_start
+ 1;
358 indices
[2] = vert_start
+ 3;
359 indices
[3] = vert_start
+ 0;
360 indices
[4] = vert_start
+ 3;
361 indices
[5] = vert_start
+ 2;
363 segment
->vertex_start
= vert_start
;
364 segment
->vertex_count
= 4;
365 segment
->index_start
= pr
->ui
.indices_head
;
366 segment
->index_count
= 6;
368 world_routes_ui_set_indices( pr
, indices
, 6 );
372 * Extend the end of the bar
374 static void world_routes_ui_updatetime( u32 route
, float time
)
376 struct subworld_routes
*r
= subworld_routes();
377 struct route
*pr
= &r
->routes
[route
];
385 u32 vert_start
= pr
->ui
.vertex_head
-2;
387 glBindVertexArray( pr
->ui
.vao
);
388 world_routes_ui_update_verts( pr
, verts
, 2 );
390 struct route_ui_segment
*cseg
= world_routes_ui_curseg(pr
);
395 * Create a notch in the bar, used when a reset is triggered by the user
397 static void world_routes_ui_notch( u32 route
, float time
)
399 struct subworld_routes
*r
= subworld_routes();
400 struct route
*pr
= &r
->routes
[route
];
402 if( (time
- pr
->ui
.last_notch
) > 1.0 )
406 float const k_notch_width
= 1.0f
;
408 float xa
= time
-k_notch_width
,
409 xb
= time
-k_notch_width
* 0.5f
,
420 verts
[3][1] = -0.25f
;
432 glBindVertexArray( pr
->ui
.vao
);
433 u32 vert_start_mod
= world_routes_ui_update_verts( pr
, verts
, 2 ),
434 vert_start_new
= world_routes_ui_set_verts( pr
, verts
+2, 6 );
437 indices
[ 0] = vert_start_mod
+1;
438 indices
[ 1] = vert_start_new
+0;
439 indices
[ 2] = vert_start_mod
+0;
440 indices
[ 3] = vert_start_mod
+1;
441 indices
[ 4] = vert_start_new
+1;
442 indices
[ 5] = vert_start_new
+0;
444 indices
[ 6] = vert_start_new
+0;
445 indices
[ 7] = vert_start_new
+1;
446 indices
[ 8] = vert_start_new
+3;
447 indices
[ 9] = vert_start_new
+0;
448 indices
[10] = vert_start_new
+3;
449 indices
[11] = vert_start_new
+2;
451 indices
[12] = vert_start_new
+3;
452 indices
[13] = vert_start_new
+4;
453 indices
[14] = vert_start_new
+2;
454 indices
[15] = vert_start_new
+3;
455 indices
[16] = vert_start_new
+5;
456 indices
[17] = vert_start_new
+4;
458 world_routes_ui_set_indices( pr
, indices
, 18 );
460 pr
->ui
.last_notch
= time
;
462 struct route_ui_segment
*segment
= world_routes_ui_curseg(pr
);
463 segment
->vertex_count
+= 6;
464 segment
->index_count
+= 18;
468 static void world_routes_ui_draw_segment( struct route_ui_segment
*segment
)
471 world_routes_ui_split_indices( segment
->index_start
,
472 segment
->index_count
, &c0
, &c1
);
474 glDrawElements( GL_TRIANGLES
, c0
, GL_UNSIGNED_SHORT
,
475 (void *)(segment
->index_start
*sizeof(u16
)));
477 glDrawElements( GL_TRIANGLES
, c1
, GL_UNSIGNED_SHORT
, (void *)(0) );
481 * Draws full bar at Y offset(offset).
483 static void world_routes_ui_draw( u32 route
, v4f colour
, float offset
)
485 float const k_bar_height
= 0.05f
,
486 k_bar_scale_x
= 0.005f
;
488 struct subworld_routes
*r
= subworld_routes();
489 struct route
*pr
= &r
->routes
[route
];
491 float cx
= pr
->ui
.xpos
;
493 shader_routeui_use();
494 glBindVertexArray( pr
->ui
.vao
);
496 float fade_amt
= vg_time
- pr
->ui
.fade_timer_start
;
497 fade_amt
= vg_clampf( fade_amt
/ 1.0f
, 0.0f
, 1.0f
);
499 float fade_block_size
= 0.0f
,
500 main_block_size
= 0.0f
;
502 for( u32 i
=0; i
<pr
->ui
.fade_count
; i
++ )
504 u32 j
= (pr
->ui
.fade_start
+ i
) % k_max_ui_segments
;
505 struct route_ui_segment
*segment
= &pr
->ui
.segments
[j
];
507 fade_block_size
+= segment
->length
;
510 cx
-= fade_block_size
* fade_amt
;
513 v4_copy( colour
, fade_colour
);
514 fade_colour
[3] *= 1.0f
-fade_amt
;
520 float height
= pr
->factive
*k_bar_height
,
521 base
= -1.0f
+ (offset
+0.5f
)*k_bar_height
;
523 shader_routeui_uColour( fade_colour
);
524 for( u32 i
=0; i
<pr
->ui
.fade_count
; i
++ )
526 u32 j
= (pr
->ui
.fade_start
+ i
) % k_max_ui_segments
;
527 struct route_ui_segment
*segment
= &pr
->ui
.segments
[j
];
529 shader_routeui_uOffset( (v4f
){ cx
*k_bar_scale_x
, base
,
530 k_bar_scale_x
, height
} );
532 world_routes_ui_draw_segment( segment
);
533 cx
+= segment
->length
;
539 shader_routeui_uColour( colour
);
540 for( u32 i
=0; i
<pr
->ui
.segment_count
; i
++ )
542 u32 j
= (pr
->ui
.segment_start
+ i
) % k_max_ui_segments
;
543 struct route_ui_segment
*segment
= &pr
->ui
.segments
[j
];
545 shader_routeui_uOffset( (v4f
){ cx
*k_bar_scale_x
, base
,
546 k_bar_scale_x
, height
} );
548 world_routes_ui_draw_segment( segment
);
549 cx
+= segment
->length
;
551 main_block_size
+= segment
->length
;
554 pr
->ui
.xpos
= vg_lerpf( pr
->ui
.xpos
, -main_block_size
* 0.5f
, 0.03f
);
557 static void world_routes_local_set_record( u32 route
, double lap_time
)
559 vg_success( " NEW LAP TIME: %f\n", lap_time
);
561 struct subworld_routes
*r
= subworld_routes();
562 struct route
*pr
= &r
->routes
[route
];
564 if( pr
->track_id
!= 0xffffffff )
566 double time_centiseconds
= lap_time
* 100.0;
567 if( time_centiseconds
> (float)0xfffe )
570 highscore_record temp
;
571 temp
.trackid
= pr
->track_id
;
572 temp
.datetime
= time(NULL
);
575 temp
.time
= time_centiseconds
;
577 highscores_push_record( &temp
);
578 track_infos
[ pr
->track_id
].push
= 1;
582 vg_warn( "There is no associated track for this record...\n" );
587 * Will scan the whole run for two things;
588 * 1: we set a new record for the total, complete loop around the course
589 * 2: the time of each segment will be recorded into the data buffer
590 * (not implemented: TODO)
592 static void world_routes_verify_run( u32 route
)
594 struct subworld_routes
*r
= subworld_routes();
595 struct route
*pr
= &r
->routes
[route
];
598 u32 si
= world_routes_get_path( r
->routes
[route
].start
, stack
);
601 * we only care about gates that ref gates, so shuffle down the array
603 struct route_timing
*timings
[64];
604 u32 sj
= 0, maxv
= 0, begin
= 0;
605 for( u32 i
=0; i
<si
; i
++ )
607 if( r
->nodes
[stack
[i
]].special_type
== k_route_special_type_collector
)
608 timings
[sj
++] = &r
->collectors
[r
->nodes
[stack
[i
]].special_id
].timing
;
609 else if( r
->nodes
[stack
[i
]].special_type
== k_route_special_type_gate
)
610 timings
[sj
++] = &r
->gates
[r
->nodes
[stack
[i
]].special_id
].timing
;
613 for( u32 i
=0; i
<sj
; i
++ )
615 if( timings
[i
]->version
> maxv
)
617 maxv
= timings
[i
]->version
;
622 vg_info( "== begin verification (%u) ==\n", route
);
623 vg_info( " current version: %u\n", r
->current_run_version
);
626 if( timings
[begin
]->version
== r
->current_run_version
)
629 int valid_segment_count
= 0;
631 double lap_time
= 0.0;
633 for( u32 i
=0; i
<sj
; i
++ )
635 u32 j
= (sj
+begin
-i
-1) % sj
,
642 /* j1v should equal jv+1 */
643 if( timings
[j1
]->version
== timings
[j
]->version
+1 )
645 diff
= timings
[j1
]->time
- timings
[j
]->time
;
648 if( verified
&& diff
> 0.0 ) valid_segment_count
++;
655 vg_success( " [ %u %f ] %f\n", timings
[j1
]->time
,
656 timings
[j1
]->version
, diff
);
658 vg_warn( " [ %u %f ]\n", timings
[j1
]->time
, timings
[j1
]->version
);
661 pr
->ui
.fade_start
= pr
->ui
.segment_start
;
662 pr
->ui
.fade_count
= 0;
663 pr
->ui
.fade_timer_start
= vg_time
;
665 int orig_seg_count
= pr
->ui
.segment_count
;
667 world_routes_ui_newseg( route
);
671 world_routes_local_set_record( route
, lap_time
);
672 world_routes_ui_popfirst(route
);
673 pr
->ui
.fade_count
++;
676 vg_info( " ctime: %f\n", lap_time
);
678 /* remove any excess we had from previous runs */
679 int to_remove
= orig_seg_count
-valid_segment_count
;
680 for( int i
=0; i
<to_remove
; i
++ )
682 world_routes_ui_popfirst(route
);
683 pr
->ui
.fade_count
++;
686 r
->routes
[route
].latest_pass
= vg_time
;
690 * When going through a gate this is called for bookkeeping purposes
692 static void world_routes_activate_gate( u32 id
)
694 struct subworld_routes
*r
= subworld_routes();
695 struct route_gate
*rg
= &r
->gates
[id
];
696 struct route_node
*pnode
= &r
->nodes
[rg
->node_id
],
697 *pdest
= &r
->nodes
[pnode
->next
[0]];
699 struct route_collector
*rc
= &r
->collectors
[ pdest
->special_id
];
702 rg
->timing
.version
= r
->current_run_version
;
703 rg
->timing
.time
= vg_time
;
704 for( u32 i
=0; i
<r
->route_count
; i
++ )
706 struct route
*route
= &r
->routes
[i
];
708 int was_active
= route
->active
;
711 for( u32 j
=0; j
<pdest
->ref_count
; j
++ )
713 if( pdest
->route_ids
[j
] == i
)
715 world_routes_verify_run( i
);
721 if( was_active
&& !route
->active
)
723 route
->ui
.fade_start
= route
->ui
.segment_start
;
724 route
->ui
.fade_count
= route
->ui
.segment_count
;
725 route
->ui
.fade_timer_start
= vg_time
;
726 world_routes_ui_clear(i
);
728 vg_success( "CLEARING -> %u %u \n", route
->ui
.fade_start
,
729 route
->ui
.fade_count
);
733 r
->current_run_version
++;
735 rc
->timing
.version
= r
->current_run_version
;
736 rc
->timing
.time
= vg_time
;
737 r
->current_run_version
++;
741 * Notify the UI system that we've reset the player
743 static void world_routes_notify_reset(void)
745 struct subworld_routes
*r
= subworld_routes();
747 for( int i
=0; i
<r
->route_count
; i
++ )
749 struct route
*route
= &r
->routes
[i
];
752 world_routes_ui_notch( i
, vg_time
- route
->latest_pass
);
756 static void world_routes_debug(void)
758 struct subworld_routes
*r
= subworld_routes();
760 for( int i
=0; i
<r
->node_count
; i
++ )
762 struct route_node
*rn
= &r
->nodes
[i
];
763 vg_line_pt3( rn
->co
, 1.0f
, rn
->special_type
? 0xffffff00: 0xff00b2ff );
766 for( int i
=0; i
<r
->route_count
; i
++ )
768 struct route
*route
= &r
->routes
[i
];
771 u32 si
= world_routes_get_path( route
->start
, stack
);
773 u32 colours
[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
776 u32 cc
= colours
[i
%vg_list_size(colours
)];
778 for( int sj
=0; sj
<si
; sj
++ )
781 debug_sbpath( &r
->nodes
[stack
[sj
]], &r
->nodes
[stack
[sk
]], cc
,
786 for( int i
=0; i
<r
->node_count
; i
++ )
788 struct route_node
*ri
= &r
->nodes
[i
],
791 for( int j
=0; j
<2; j
++ )
793 if( ri
->next
[j
] != 0xffffffff )
795 rj
= &r
->nodes
[ri
->next
[j
]];
796 vg_line( ri
->co
, rj
->co
, 0x20ffffff );
802 static void world_routes_free(void)
804 struct subworld_routes
*r
= subworld_routes();
811 static void world_id_fixup( u32
*uid
, mdl_header
*mdl
)
814 *uid
= mdl_node_from_id( mdl
, *uid
)->sub_uid
;
820 * Create the strips of colour that run through the world along course paths
822 static void world_routes_gen_meshes(void)
824 struct subworld_routes
*r
= subworld_routes();
825 scene_init( &r
->scene_lines
);
827 for( int i
=0; i
<r
->route_count
; i
++ )
829 struct route
*route
= &r
->routes
[i
];
832 u32 si
= world_routes_get_path( route
->start
, stack
);
836 for( int sj
=0; sj
<si
; sj
++ )
840 struct route_node
*rnj
= &r
->nodes
[ stack
[sj
] ],
841 *rnk
= &r
->nodes
[ stack
[sk
] ],
844 if( rnj
->special_type
&& rnk
->special_type
)
850 float base_x0
= (float)rnj
->ref_count
*-0.5f
+ (float)rnj
->current_refs
,
851 base_x1
= (float)rnk
->ref_count
*-0.5f
+ (float)rnk
->current_refs
;
853 if( rnk
->special_type
)
855 rnl
= &r
->nodes
[ rnk
->next
[0] ];
856 base_x1
= (float)rnl
->ref_count
*-0.5f
+ (float)rnl
->current_refs
;
864 v3f p0
, h0
, p1
, h1
, p
, pd
;
866 v3_copy( rnj
->co
, p0
);
867 v3_muladds( rnj
->co
, rnj
->h
, 1.0f
, h0
);
868 v3_copy( rnk
->co
, p1
);
869 v3_muladds( rnk
->co
, rnk
->h
, -1.0f
, h1
);
874 for( int it
=0; it
<256; it
++ )
876 float const k_sample_dist
= 0.02f
;
877 eval_bezier_time( p0
,p1
,h0
,h1
, t
,p
);
878 eval_bezier_time( p0
,p1
,h0
,h1
, t
+k_sample_dist
,pd
);
880 float mod
= k_sample_dist
/ v3_dist( p
, pd
);
883 v3_muls( rnj
->up
, 1.0f
-t
, up
);
884 v3_muladds( up
, rnk
->up
, t
, up
);
887 v3_cross( up
, v0
, right
);
888 v3_normalize( right
);
890 float cur_x
= (1.0f
-t
)*base_x0
+ t
*base_x1
;
892 v3f sc
, sa
, sb
, down
;
893 v3_muladds( p
, right
, cur_x
, sc
);
894 v3_muladds( sc
, up
, 1.5f
, sc
);
895 v3_muladds( sc
, right
, 0.45f
, sa
);
896 v3_muladds( sc
, right
, -0.45f
, sb
);
897 v3_muls( up
, -1.0f
, down
);
902 if(ray_world( sa
, down
, &ha
) &&
903 ray_world( sb
, down
, &hb
))
907 v3_muladds( ha
.pos
, up
, 0.06f
, va
.co
);
908 v3_muladds( hb
.pos
, up
, 0.06f
, vb
.co
);
909 v3_copy( up
, va
.norm
);
910 v3_copy( up
, vb
.norm
);
914 scene_push_vert( &r
->scene_lines
, &va
);
915 scene_push_vert( &r
->scene_lines
, &vb
);
919 /* Connect them with triangles */
920 scene_push_tri( &r
->scene_lines
, (u32
[3]){
921 last_valid
+0-2, last_valid
+1-2, last_valid
+2-2} );
922 scene_push_tri( &r
->scene_lines
, (u32
[3]){
923 last_valid
+1-2, last_valid
+3-2, last_valid
+2-2} );
926 last_valid
= r
->scene_lines
.vertex_count
;
935 /* TODO special case for end of loop, need to add triangles
936 * between first and last rungs */
941 rnj
->current_refs
++;
944 scene_copy_slice( &r
->scene_lines
, &route
->sm
);
947 scene_upload( &r
->scene_lines
);
948 scene_free_offline_buffers( &r
->scene_lines
);
951 static void world_routes_update(void)
953 struct subworld_routes
*r
= subworld_routes();
955 for( int i
=0; i
<r
->route_count
; i
++ )
957 struct route
*route
= &r
->routes
[i
];
958 route
->factive
= vg_lerpf( route
->factive
, route
->active
, 0.01f
);
962 world_routes_ui_updatetime( i
, vg_time
- route
->latest_pass
);
967 static void bind_terrain_textures(void);
968 static void render_world_routes( m4x4f projection
, v3f camera
)
970 struct subworld_routes
*r
= subworld_routes();
972 m4x3f identity_matrix
;
973 m4x3_identity( identity_matrix
);
976 shader_route_uTexGarbage(0);
977 shader_link_standard_ub( _shader_route
.id
, 2 );
978 bind_terrain_textures();
980 shader_route_uPv( projection
);
981 shader_route_uMdl( identity_matrix
);
982 shader_route_uCamera( camera
);
984 scene_bind( &r
->scene_lines
);
986 for( int i
=0; i
<r
->route_count
; i
++ )
988 struct route
*route
= &r
->routes
[i
];
991 v3_lerp( (v3f
){0.7f
,0.7f
,0.7f
}, route
->colour
, route
->factive
, colour
);
994 shader_route_uColour( colour
);
995 mdl_draw_submesh( &route
->sm
);
999 static void render_world_routes_ui(void)
1002 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1003 glBlendEquation(GL_FUNC_ADD
);
1005 struct subworld_routes
*r
= subworld_routes();
1007 float active_offset
= 0.0f
;
1008 for( int i
=0; i
<r
->route_count
; i
++ )
1010 struct route
*route
= &r
->routes
[i
];
1011 world_routes_ui_draw( i
, route
->colour
, active_offset
);
1012 active_offset
+= route
->factive
;
1015 glDisable(GL_BLEND
);
1018 static void world_routes_register(void)
1020 struct subworld_routes
*r
= subworld_routes();
1021 r
->current_run_version
= 2;
1023 shader_route_register();
1024 shader_routeui_register();
1027 static void world_routes_loadfrom( mdl_header
*mdl
)
1029 struct subworld_routes
*r
= subworld_routes();
1040 for( int i
=0; i
<mdl
->node_count
; i
++ )
1042 mdl_node
*pnode
= mdl_node_from_id(mdl
,i
);
1045 if( pnode
->classtype
== k_classtype_route_node
||
1046 pnode
->classtype
== k_classtype_gate
)
1048 mdl_node_transform( pnode
, transform
);
1049 pnode
->sub_uid
= r
->node_count
;
1051 r
->nodes
= buffer_reserve( r
->nodes
, r
->node_count
, &r
->node_cap
, 1,
1052 sizeof( struct route_node
) );
1054 struct route_node
*rn
= &r
->nodes
[r
->node_count
];
1056 v3_copy( transform
[0], rn
->right
);
1057 v3_normalize( rn
->right
);
1058 v3_copy( transform
[1], rn
->up
);
1059 v3_normalize( rn
->up
);
1060 v3_muls( transform
[2], -1.0f
, rn
->h
);
1061 v3_copy( transform
[3], rn
->co
);
1063 rn
->current_refs
= 0;
1064 rn
->special_type
= 0;
1067 if( pnode
->classtype
== k_classtype_gate
)
1069 struct classtype_gate
*inf
= mdl_get_entdata( mdl
, pnode
);
1071 /* H is later scaled based on link distance */
1072 v3_normalize( rn
->h
);
1073 rn
->next
[0] = inf
->target
;
1079 mdl_node
*pother
= mdl_node_from_id( mdl
, inf
->target
);
1081 if( pother
->classtype
== k_classtype_gate
)
1083 r
->gates
= buffer_reserve( r
->gates
, r
->gate_count
,
1085 1, sizeof( struct route_gate
) );
1087 struct route_gate
*rg
= &r
->gates
[r
->gate_count
];
1088 rg
->node_id
= r
->node_count
;
1089 rg
->timing
.time
= 0.0;
1090 rg
->timing
.version
= 0;
1092 v3_copy( pnode
->co
, rg
->gate
.co
[0] );
1093 v3_copy( pother
->co
, rg
->gate
.co
[1] );
1094 v4_copy( pnode
->q
, rg
->gate
.q
[0] );
1095 v4_copy( pother
->q
, rg
->gate
.q
[1] );
1096 v2_copy( inf
->dims
, rg
->gate
.dims
);
1098 gate_transform_update( &rg
->gate
);
1099 rn
->special_type
= k_route_special_type_gate
;
1100 rn
->special_id
= r
->gate_count
;
1106 if( rn
->special_type
== 0 )
1108 r
->collectors
= buffer_reserve(
1109 r
->collectors
, r
->collector_count
, &r
->collector_cap
,
1110 1, sizeof( struct route_collector
));
1112 struct route_collector
*rc
= &r
->collectors
[r
->collector_count
];
1113 rc
->timing
.time
= 0.0;
1114 rc
->timing
.version
= 0;
1116 rn
->special_type
= k_route_special_type_collector
;
1117 rn
->special_id
= r
->collector_count
;
1119 r
->collector_count
++;
1124 struct classtype_route_node
*inf
= mdl_get_entdata( mdl
, pnode
);
1125 rn
->next
[0] = inf
->target
;
1126 rn
->next
[1] = inf
->target1
;
1131 else if( pnode
->classtype
== k_classtype_route
)
1133 struct classtype_route
*inf
= mdl_get_entdata( mdl
, pnode
);
1134 r
->routes
= buffer_reserve( r
->routes
, r
->route_count
, &r
->route_cap
,
1135 1, sizeof( struct route
) );
1137 struct route
*route
= &r
->routes
[r
->route_count
];
1139 v3_copy( inf
->colour
, route
->colour
);
1140 route
->colour
[3] = 1.0f
;
1143 route
->track_id
= 0xffffffff;
1144 for( u32 j
=0; j
<vg_list_size(track_infos
); j
++ )
1146 if( !strcmp( mdl_pstr(mdl
,pnode
->pstr_name
), track_infos
[j
].name
))
1148 route
->track_id
= j
;
1153 route
->start
= inf
->id_start
;
1155 route
->factive
= 0.0f
;
1156 mdl_node_transform( pnode
, route
->scoreboard_transform
);
1159 glGenVertexArrays( 1, &route
->ui
.vao
);
1160 glGenBuffers( 1, &route
->ui
.vbo
);
1161 glGenBuffers( 1, &route
->ui
.ebo
);
1162 glBindVertexArray( route
->ui
.vao
);
1164 size_t stride
= sizeof(v2f
);
1166 glBindBuffer( GL_ARRAY_BUFFER
, route
->ui
.vbo
);
1167 glBufferData( GL_ARRAY_BUFFER
, k_route_ui_max_verts
*stride
,
1168 NULL
, GL_DYNAMIC_DRAW
);
1169 glBindVertexArray( route
->ui
.vao
);
1170 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER
, route
->ui
.ebo
);
1171 glBufferData( GL_ELEMENT_ARRAY_BUFFER
,
1172 k_route_ui_max_indices
*sizeof(u16
), NULL
,
1175 glVertexAttribPointer( 0, 2, GL_FLOAT
, GL_FALSE
, stride
, (void *)0 );
1176 glEnableVertexAttribArray( 0 );
1179 route
->ui
.indices_head
= k_route_ui_max_indices
- 9;
1180 route
->ui
.vertex_head
= k_route_ui_max_verts
- 200;
1181 route
->ui
.segment_start
= 0;
1182 route
->ui
.segment_count
= 0;
1183 route
->ui
.last_notch
= 0.0;
1184 route
->ui
.fade_start
= 0;
1185 route
->ui
.fade_count
= 0;
1186 route
->ui
.fade_timer_start
= 0.0;
1193 * Apply correct system-local ids
1195 for( int i
=0; i
<r
->node_count
; i
++ )
1197 struct route_node
*rn
= &r
->nodes
[i
];
1199 for( int j
=0; j
<2; j
++ )
1200 world_id_fixup( &rn
->next
[j
], mdl
);
1203 for( int i
=0; i
<r
->route_count
; i
++ )
1205 struct route
*route
= &r
->routes
[i
];
1206 world_id_fixup( &route
->start
, mdl
);
1212 for( int i
=0; i
<r
->route_count
; i
++ )
1214 struct route
*route
= &r
->routes
[i
];
1217 u32 si
= world_routes_get_path( route
->start
, stack
);
1219 for( int sj
=0; sj
<si
; sj
++ )
1221 struct route_node
*rn
= &r
->nodes
[ stack
[sj
] ];
1222 rn
->route_ids
[ rn
->ref_count
++ ] = i
;
1224 if( rn
->ref_count
> 4 )
1225 vg_warn( "Too many references on route node %i\n", i
);
1229 world_routes_gen_meshes();
1232 #endif /* ROUTES_H */