8 #include "shaders/vblend.h"
9 #include "shaders/route.h"
10 #include "shaders/routeui.h"
12 enum route_special_type
14 k_route_special_type_gate
= 1,
15 k_route_special_type_collector
= 2
18 enum { k_max_ui_segments
= 32 };
19 enum { k_route_ui_max_verts
= 2000 };
20 enum { k_route_ui_max_indices
= 3000 };
22 struct subworld_routes
29 u32 special_type
, special_id
, current_refs
, ref_count
;
30 u32 route_ids
[4]; /* Gates can be linked into up to four routes */
48 double best_lap
; /* Session */
59 struct route_ui_segment
63 u32 vertex_start
, vertex_count
,
64 index_start
, index_count
;
66 segments
[k_max_ui_segments
];
68 u32 segment_start
, segment_count
;
85 u32 version
; /* Incremented on every teleport */
92 struct route_collector
94 struct route_timing timing
;
109 static struct subworld_routes
*subworld_routes(void);
111 static void debug_sbpath( struct route_node
*rna
, struct route_node
*rnb
,
112 u32 colour
, float xoffset
)
114 v3f p0
, h0
, p1
, h1
, l
, p
;
116 v3_copy( rna
->co
, p0
);
117 v3_muladds( rna
->co
, rna
->h
, 1.0f
, h0
);
118 v3_copy( rnb
->co
, p1
);
119 v3_muladds( rnb
->co
, rnb
->h
, -1.0f
, h1
);
121 v3_muladds( p0
, rna
->right
, xoffset
, p0
);
122 v3_muladds( h0
, rna
->right
, xoffset
, h0
);
123 v3_muladds( p1
, rnb
->right
, xoffset
, p1
);
124 v3_muladds( h1
, rnb
->right
, xoffset
, h1
);
128 for( int i
=0; i
<5; i
++ )
130 float t
= (float)(i
+1)/5.0f
;
131 eval_bezier_time( p0
, p1
, h0
, h1
, t
, p
);
132 vg_line( p
, l
, colour
);
138 * Get a list of node ids in stack, and return how many there is
140 static u32
world_routes_get_path( u32 starter
, u32 stack
[64] )
142 struct subworld_routes
*r
= subworld_routes();
149 int loop_complete
= 0;
153 if( stack_i
[si
-1] == 2 )
159 struct route_node
*rn
= &r
->nodes
[stack
[si
-1]];
160 u32 nextid
= rn
->next
[stack_i
[si
-1]];
163 if( nextid
!= 0xffffffff )
165 if( nextid
== stack
[0] )
172 for( int sj
=0; sj
<si
; sj
++ )
174 if( stack
[sj
] == nextid
)
198 * Free a segment from the UI bar to be reused later
200 static void world_routes_ui_popfirst( u32 route
)
202 struct subworld_routes
*r
= subworld_routes();
203 struct route
*pr
= &r
->routes
[route
];
205 if( pr
->ui
.segment_count
)
207 pr
->ui
.segment_start
++;
209 if( pr
->ui
.segment_start
== 32 )
210 pr
->ui
.segment_start
= 0;
212 pr
->ui
.segment_count
--;
217 * Break a index range into two pieces over the edge of the maximum it can
218 * store. s1 is 0 always, so its a ring buffer.
220 static void world_routes_ui_split_indices( u32 s0
, u32 count
, u32
*c0
, u32
*c1
)
222 *c0
= (VG_MIN( s0
+count
, k_route_ui_max_indices
)) - s0
;
227 * Place a set of indices into gpu array automatically splits
230 static void world_routes_ui_set_indices( struct route
*pr
,
231 u16
*indices
, u32 count
)
234 world_routes_ui_split_indices( pr
->ui
.indices_head
, count
, &c0
, &c1
);
236 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER
, pr
->ui
.ebo
);
240 glBufferSubData( GL_ELEMENT_ARRAY_BUFFER
, pr
->ui
.indices_head
*sizeof(u16
),
241 c0
*sizeof(u16
), indices
);
246 glBufferSubData( GL_ELEMENT_ARRAY_BUFFER
, 0, c1
*sizeof(u16
), indices
+c0
);
247 pr
->ui
.indices_head
= c1
;
250 pr
->ui
.indices_head
+= c0
;
254 * Place a set of vertices into gpu array
256 static u32
world_routes_ui_set_verts( struct route
*pr
, v2f
*verts
, u32 count
)
258 if( pr
->ui
.vertex_head
+ count
>= k_route_ui_max_verts
)
259 pr
->ui
.vertex_head
= 0;
261 u32 vert_start
= pr
->ui
.vertex_head
;
262 pr
->ui
.vertex_head
+= count
;
264 glBindBuffer( GL_ARRAY_BUFFER
, pr
->ui
.vbo
);
265 glBufferSubData( GL_ARRAY_BUFFER
, (GLintptr
)(vert_start
*sizeof(v2f
)),
266 sizeof(v2f
)*count
, verts
);
272 * Update the last (count) vertices positions, does not add any.
273 * Data must already be written to, and not cross either array boundaries.
275 static u32
world_routes_ui_update_verts( struct route
*pr
,
276 v2f
*verts
, u32 count
)
278 u32 vert_start
= pr
->ui
.vertex_head
-count
;
280 glBindBuffer( GL_ARRAY_BUFFER
, pr
->ui
.vbo
);
281 glBufferSubData( GL_ARRAY_BUFFER
, (GLintptr
)(vert_start
*sizeof(v2f
)),
282 sizeof(v2f
)*count
, verts
);
288 * Current/active segment of this UI bar
290 static struct route_ui_segment
*world_routes_ui_curseg( struct route
*pr
)
292 u32 index
= (pr
->ui
.segment_start
+pr
->ui
.segment_count
-1)%k_max_ui_segments
;
293 return &pr
->ui
.segments
[ index
];
297 * Start a new segment in the UI bar, will create a split on the last one if
298 * there is one active currently. (api)
300 static void world_routes_ui_newseg( u32 route
, float time
)
302 struct subworld_routes
*r
= subworld_routes();
303 struct route
*pr
= &r
->routes
[route
];
305 pr
->ui
.last_notch
= 0.0;
307 glBindVertexArray( pr
->ui
.vao
);
308 if( pr
->ui
.segment_count
)
310 float const k_gap_width
= 1.0f
;
313 verts
[0][0] = time
-k_gap_width
;
315 verts
[1][0] = time
-k_gap_width
;
318 world_routes_ui_update_verts( pr
, verts
, 2 );
321 pr
->ui
.segment_count
++;
322 struct route_ui_segment
*segment
= world_routes_ui_curseg(pr
);
334 u32 vert_start
= world_routes_ui_set_verts( pr
, verts
, 4 );
337 indices
[0] = vert_start
+ 0;
338 indices
[1] = vert_start
+ 1;
339 indices
[2] = vert_start
+ 3;
340 indices
[3] = vert_start
+ 0;
341 indices
[4] = vert_start
+ 3;
342 indices
[5] = vert_start
+ 2;
344 segment
->vertex_start
= vert_start
;
345 segment
->vertex_count
= 4;
346 segment
->index_start
= pr
->ui
.indices_head
;
347 segment
->index_count
= 6;
349 world_routes_ui_set_indices( pr
, indices
, 6 );
353 * Extend the end of the bar
355 static void world_routes_ui_updatetime( u32 route
, float time
)
357 struct subworld_routes
*r
= subworld_routes();
358 struct route
*pr
= &r
->routes
[route
];
366 u32 vert_start
= pr
->ui
.vertex_head
-2;
368 glBindVertexArray( pr
->ui
.vao
);
369 world_routes_ui_update_verts( pr
, verts
, 2 );
373 * Create a notch in the bar, used when a reset is triggered by the user
375 static void world_routes_ui_notch( u32 route
, float time
)
377 struct subworld_routes
*r
= subworld_routes();
378 struct route
*pr
= &r
->routes
[route
];
380 if( (time
- pr
->ui
.last_notch
) > 1.0 )
384 float const k_notch_width
= 1.0f
;
386 float xa
= time
-k_notch_width
,
387 xb
= time
-k_notch_width
* 0.5f
,
398 verts
[3][1] = -0.25f
;
410 glBindVertexArray( pr
->ui
.vao
);
411 u32 vert_start_mod
= world_routes_ui_update_verts( pr
, verts
, 2 ),
412 vert_start_new
= world_routes_ui_set_verts( pr
, verts
+2, 6 );
415 indices
[ 0] = vert_start_mod
+1;
416 indices
[ 1] = vert_start_new
+0;
417 indices
[ 2] = vert_start_mod
+0;
418 indices
[ 3] = vert_start_mod
+1;
419 indices
[ 4] = vert_start_new
+1;
420 indices
[ 5] = vert_start_new
+0;
422 indices
[ 6] = vert_start_new
+0;
423 indices
[ 7] = vert_start_new
+1;
424 indices
[ 8] = vert_start_new
+3;
425 indices
[ 9] = vert_start_new
+0;
426 indices
[10] = vert_start_new
+3;
427 indices
[11] = vert_start_new
+2;
429 indices
[12] = vert_start_new
+3;
430 indices
[13] = vert_start_new
+4;
431 indices
[14] = vert_start_new
+2;
432 indices
[15] = vert_start_new
+3;
433 indices
[16] = vert_start_new
+5;
434 indices
[17] = vert_start_new
+4;
436 world_routes_ui_set_indices( pr
, indices
, 18 );
438 pr
->ui
.last_notch
= time
;
440 struct route_ui_segment
*segment
= world_routes_ui_curseg(pr
);
441 segment
->vertex_count
+= 6;
442 segment
->index_count
+= 18;
446 static void world_routes_ui_draw( u32 route
)
448 //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
450 struct subworld_routes
*r
= subworld_routes();
451 struct route
*pr
= &r
->routes
[route
];
453 shader_routeui_use();
454 glBindVertexArray( pr
->ui
.vao
);
456 for( u32 i
=0; i
<pr
->ui
.segment_count
; i
++ )
458 u32 j
= (pr
->ui
.segment_start
+ i
) % k_max_ui_segments
;
459 struct route_ui_segment
*segment
= &pr
->ui
.segments
[j
];
462 world_routes_ui_split_indices( segment
->index_start
,
463 segment
->index_count
, &c0
, &c1
);
466 glDrawElements( GL_TRIANGLES
, c0
, GL_UNSIGNED_SHORT
,
467 (void *)(segment
->index_start
*sizeof(u16
)));
469 glDrawElements( GL_TRIANGLES
, c1
, GL_UNSIGNED_SHORT
, (void *)(0) );
472 //glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
476 * Will scan the whole run for two things;
477 * 1: we set a new record for the total, complete loop around the course
478 * 2: the time of each segment will be recorded into the data buffer
479 * (not implemented: TODO)
481 static void world_routes_verify_run( u32 route
)
483 struct subworld_routes
*r
= subworld_routes();
486 u32 si
= world_routes_get_path( r
->routes
[route
].start
, stack
);
489 * we only care about gates that ref gates, so shuffle down the array
491 struct route_timing
*timings
[64];
492 u32 sj
= 0, maxv
= 0, begin
= 0;
493 for( u32 i
=0; i
<si
; i
++ )
495 if( r
->nodes
[stack
[i
]].special_type
== k_route_special_type_collector
)
496 timings
[sj
++] = &r
->collectors
[r
->nodes
[stack
[i
]].special_id
].timing
;
497 else if( r
->nodes
[stack
[i
]].special_type
== k_route_special_type_gate
)
498 timings
[sj
++] = &r
->gates
[r
->nodes
[stack
[i
]].special_id
].timing
;
501 for( u32 i
=0; i
<sj
; i
++ )
503 if( timings
[i
]->version
> maxv
)
505 maxv
= timings
[i
]->version
;
510 vg_info( "== begin verification (%u) ==\n", route
);
511 vg_info( " current version: %u\n", r
->current_run_version
);
514 if( timings
[begin
]->version
== r
->current_run_version
)
517 double lap_time
= 0.0;
519 for( u32 i
=0; i
<sj
; i
++ )
521 u32 j
= (sj
+begin
-i
-1) % sj
,
528 /* j1v should equal jv+1 */
529 if( timings
[j1
]->version
== timings
[j
]->version
+1 )
531 diff
= timings
[j1
]->time
- timings
[j
]->time
;
539 vg_success( " [ %u %f ] %f\n", timings
[j1
]->time
,
540 timings
[j1
]->version
, diff
);
542 vg_warn( " [ %u %f ]\n", timings
[j1
]->time
, timings
[j1
]->version
);
546 vg_success( " NEW LAP TIME: %f\n", lap_time
);
548 vg_info( " ctime: %f\n", lap_time
);
552 * When going through a gate this is called for bookkeeping purposes
554 static void world_routes_activate_gate( u32 id
)
556 struct subworld_routes
*r
= subworld_routes();
557 struct route_gate
*rg
= &r
->gates
[id
];
558 struct route_node
*pnode
= &r
->nodes
[rg
->node_id
],
559 *pdest
= &r
->nodes
[pnode
->next
[0]];
561 struct route_collector
*rc
= &r
->collectors
[ pdest
->special_id
];
564 rg
->timing
.version
= r
->current_run_version
;
565 rg
->timing
.time
= vg_time
;
566 for( u32 i
=0; i
<r
->route_count
; i
++ )
568 struct route
*route
= &r
->routes
[i
];
571 for( u32 j
=0; j
<pdest
->ref_count
; j
++ )
573 if( pdest
->route_ids
[j
] == i
)
575 world_routes_verify_run( i
);
582 r
->current_run_version
++;
584 rc
->timing
.version
= r
->current_run_version
;
585 rc
->timing
.time
= vg_time
;
586 r
->current_run_version
++;
589 static void world_routes_debug(void)
591 struct subworld_routes
*r
= subworld_routes();
593 for( int i
=0; i
<r
->node_count
; i
++ )
595 struct route_node
*rn
= &r
->nodes
[i
];
596 vg_line_pt3( rn
->co
, 1.0f
, rn
->special_type
? 0xffffff00: 0xff00b2ff );
599 for( int i
=0; i
<r
->route_count
; i
++ )
601 struct route
*route
= &r
->routes
[i
];
604 u32 si
= world_routes_get_path( route
->start
, stack
);
606 u32 colours
[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
609 u32 cc
= colours
[i
%vg_list_size(colours
)];
611 for( int sj
=0; sj
<si
; sj
++ )
614 debug_sbpath( &r
->nodes
[stack
[sj
]], &r
->nodes
[stack
[sk
]], cc
,
619 for( int i
=0; i
<r
->node_count
; i
++ )
621 struct route_node
*ri
= &r
->nodes
[i
],
624 for( int j
=0; j
<2; j
++ )
626 if( ri
->next
[j
] != 0xffffffff )
628 rj
= &r
->nodes
[ri
->next
[j
]];
629 vg_line( ri
->co
, rj
->co
, 0x20ffffff );
635 static void world_routes_free(void)
637 struct subworld_routes
*r
= subworld_routes();
644 static void world_id_fixup( u32
*uid
, mdl_header
*mdl
)
647 *uid
= mdl_node_from_id( mdl
, *uid
)->sub_uid
;
653 * Create the strips of colour that run through the world along course paths
655 static void world_routes_gen_meshes(void)
657 struct subworld_routes
*r
= subworld_routes();
658 scene_init( &r
->scene_lines
);
660 for( int i
=0; i
<r
->route_count
; i
++ )
662 struct route
*route
= &r
->routes
[i
];
665 u32 si
= world_routes_get_path( route
->start
, stack
);
669 for( int sj
=0; sj
<si
; sj
++ )
673 struct route_node
*rnj
= &r
->nodes
[ stack
[sj
] ],
674 *rnk
= &r
->nodes
[ stack
[sk
] ],
677 if( rnj
->special_type
&& rnk
->special_type
)
683 float base_x0
= (float)rnj
->ref_count
*-0.5f
+ (float)rnj
->current_refs
,
684 base_x1
= (float)rnk
->ref_count
*-0.5f
+ (float)rnk
->current_refs
;
686 if( rnk
->special_type
)
688 rnl
= &r
->nodes
[ rnk
->next
[0] ];
689 base_x1
= (float)rnl
->ref_count
*-0.5f
+ (float)rnl
->current_refs
;
697 v3f p0
, h0
, p1
, h1
, p
, pd
;
699 v3_copy( rnj
->co
, p0
);
700 v3_muladds( rnj
->co
, rnj
->h
, 1.0f
, h0
);
701 v3_copy( rnk
->co
, p1
);
702 v3_muladds( rnk
->co
, rnk
->h
, -1.0f
, h1
);
707 for( int it
=0; it
<256; it
++ )
709 float const k_sample_dist
= 0.02f
;
710 eval_bezier_time( p0
,p1
,h0
,h1
, t
,p
);
711 eval_bezier_time( p0
,p1
,h0
,h1
, t
+k_sample_dist
,pd
);
713 float mod
= k_sample_dist
/ v3_dist( p
, pd
);
716 v3_muls( rnj
->up
, 1.0f
-t
, up
);
717 v3_muladds( up
, rnk
->up
, t
, up
);
720 v3_cross( up
, v0
, right
);
721 v3_normalize( right
);
723 float cur_x
= (1.0f
-t
)*base_x0
+ t
*base_x1
;
725 v3f sc
, sa
, sb
, down
;
726 v3_muladds( p
, right
, cur_x
, sc
);
727 v3_muladds( sc
, up
, 1.5f
, sc
);
728 v3_muladds( sc
, right
, 0.45f
, sa
);
729 v3_muladds( sc
, right
, -0.45f
, sb
);
730 v3_muls( up
, -1.0f
, down
);
735 if(ray_world( sa
, down
, &ha
) &&
736 ray_world( sb
, down
, &hb
))
740 v3_muladds( ha
.pos
, up
, 0.06f
, va
.co
);
741 v3_muladds( hb
.pos
, up
, 0.06f
, vb
.co
);
742 v3_copy( up
, va
.norm
);
743 v3_copy( up
, vb
.norm
);
744 v3_zero( va
.colour
);
745 v3_zero( vb
.colour
);
749 scene_push_vert( &r
->scene_lines
, &va
);
750 scene_push_vert( &r
->scene_lines
, &vb
);
754 /* Connect them with triangles */
755 scene_push_tri( &r
->scene_lines
, (u32
[3]){
756 last_valid
+0-2, last_valid
+1-2, last_valid
+2-2} );
757 scene_push_tri( &r
->scene_lines
, (u32
[3]){
758 last_valid
+1-2, last_valid
+3-2, last_valid
+2-2} );
761 last_valid
= r
->scene_lines
.vertex_count
;
770 /* TODO special case for end of loop, need to add triangles
771 * between first and last rungs */
776 rnj
->current_refs
++;
779 scene_copy_slice( &r
->scene_lines
, &route
->sm
);
782 scene_upload( &r
->scene_lines
);
783 scene_free_offline_buffers( &r
->scene_lines
);
786 static void bind_terrain_textures(void);
787 static void render_world_routes( m4x4f projection
, v3f camera
)
789 struct subworld_routes
*r
= subworld_routes();
791 m4x3f identity_matrix
;
792 m4x3_identity( identity_matrix
);
795 shader_route_uTexGarbage(0);
796 shader_link_standard_ub( _shader_route
.id
, 2 );
797 bind_terrain_textures();
799 shader_route_uPv( projection
);
800 shader_route_uMdl( identity_matrix
);
801 shader_route_uCamera( camera
);
803 scene_bind( &r
->scene_lines
);
805 for( int i
=0; i
<r
->route_count
; i
++ )
807 struct route
*route
= &r
->routes
[i
];
808 route
->factive
= vg_lerpf( route
->factive
, route
->active
, 0.01f
);
811 v3_lerp( (v3f
){0.7f
,0.7f
,0.7f
}, route
->colour
, route
->factive
, colour
);
814 shader_route_uColour( colour
);
815 mdl_draw_submesh( &route
->sm
);
819 static void world_routes_register(void)
821 struct subworld_routes
*r
= subworld_routes();
822 r
->current_run_version
= 2;
824 shader_route_register();
825 shader_routeui_register();
828 static void world_routes_loadfrom( mdl_header
*mdl
)
830 struct subworld_routes
*r
= subworld_routes();
841 for( int i
=0; i
<mdl
->node_count
; i
++ )
843 mdl_node
*pnode
= mdl_node_from_id(mdl
,i
);
846 if( pnode
->classtype
== k_classtype_route_node
||
847 pnode
->classtype
== k_classtype_gate
)
849 mdl_node_transform( pnode
, transform
);
850 pnode
->sub_uid
= r
->node_count
;
852 r
->nodes
= buffer_reserve( r
->nodes
, r
->node_count
, &r
->node_cap
, 1,
853 sizeof( struct route_node
) );
855 struct route_node
*rn
= &r
->nodes
[r
->node_count
];
857 v3_copy( transform
[0], rn
->right
);
858 v3_normalize( rn
->right
);
859 v3_copy( transform
[1], rn
->up
);
860 v3_normalize( rn
->up
);
861 v3_muls( transform
[2], -1.0f
, rn
->h
);
862 v3_copy( transform
[3], rn
->co
);
864 rn
->current_refs
= 0;
865 rn
->special_type
= 0;
868 if( pnode
->classtype
== k_classtype_gate
)
870 struct classtype_gate
*inf
= mdl_get_entdata( mdl
, pnode
);
872 /* H is later scaled based on link distance */
873 v3_normalize( rn
->h
);
874 rn
->next
[0] = inf
->target
;
880 mdl_node
*pother
= mdl_node_from_id( mdl
, inf
->target
);
882 if( pother
->classtype
== k_classtype_gate
)
884 r
->gates
= buffer_reserve( r
->gates
, r
->gate_count
,
886 1, sizeof( struct route_gate
) );
888 struct route_gate
*rg
= &r
->gates
[r
->gate_count
];
889 rg
->node_id
= r
->node_count
;
890 rg
->timing
.time
= 0.0;
891 rg
->timing
.version
= 0;
893 v3_copy( pnode
->co
, rg
->gate
.co
[0] );
894 v3_copy( pother
->co
, rg
->gate
.co
[1] );
895 v4_copy( pnode
->q
, rg
->gate
.q
[0] );
896 v4_copy( pother
->q
, rg
->gate
.q
[1] );
897 v2_copy( inf
->dims
, rg
->gate
.dims
);
899 gate_transform_update( &rg
->gate
);
900 rn
->special_type
= k_route_special_type_gate
;
901 rn
->special_id
= r
->gate_count
;
907 if( rn
->special_type
== 0 )
909 r
->collectors
= buffer_reserve(
910 r
->collectors
, r
->collector_count
, &r
->collector_cap
,
911 1, sizeof( struct route_collector
));
913 struct route_collector
*rc
= &r
->collectors
[r
->collector_count
];
914 rc
->timing
.time
= 0.0;
915 rc
->timing
.version
= 0;
917 rn
->special_type
= k_route_special_type_collector
;
918 rn
->special_id
= r
->collector_count
;
920 r
->collector_count
++;
925 struct classtype_route_node
*inf
= mdl_get_entdata( mdl
, pnode
);
926 rn
->next
[0] = inf
->target
;
927 rn
->next
[1] = inf
->target1
;
932 else if( pnode
->classtype
== k_classtype_route
)
934 struct classtype_route
*inf
= mdl_get_entdata( mdl
, pnode
);
935 r
->routes
= buffer_reserve( r
->routes
, r
->route_count
, &r
->route_cap
,
936 1, sizeof( struct route
) );
938 struct route
*route
= &r
->routes
[r
->route_count
];
940 v3_copy( inf
->colour
, route
->colour
);
941 route
->colour
[3] = 1.0f
;
944 route
->start
= inf
->id_start
;
946 route
->factive
= 0.0f
;
949 glGenVertexArrays( 1, &route
->ui
.vao
);
950 glGenBuffers( 1, &route
->ui
.vbo
);
951 glGenBuffers( 1, &route
->ui
.ebo
);
952 glBindVertexArray( route
->ui
.vao
);
954 size_t stride
= sizeof(v2f
);
956 glBindBuffer( GL_ARRAY_BUFFER
, route
->ui
.vbo
);
957 glBufferData( GL_ARRAY_BUFFER
, k_route_ui_max_verts
*stride
,
958 NULL
, GL_DYNAMIC_DRAW
);
959 glBindVertexArray( route
->ui
.vao
);
960 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER
, route
->ui
.ebo
);
961 glBufferData( GL_ELEMENT_ARRAY_BUFFER
,
962 k_route_ui_max_indices
*sizeof(u16
), NULL
,
965 glVertexAttribPointer( 0, 2, GL_FLOAT
, GL_FALSE
, stride
, (void *)0 );
966 glEnableVertexAttribArray( 0 );
969 route
->ui
.indices_head
= k_route_ui_max_indices
- 9;
970 route
->ui
.vertex_head
= k_route_ui_max_verts
- 200;
971 route
->ui
.segment_start
= 0;
972 route
->ui
.segment_count
= 0;
973 route
->ui
.last_notch
= 0.0;
980 * Apply correct system-local ids
982 for( int i
=0; i
<r
->node_count
; i
++ )
984 struct route_node
*rn
= &r
->nodes
[i
];
986 for( int j
=0; j
<2; j
++ )
987 world_id_fixup( &rn
->next
[j
], mdl
);
990 for( int i
=0; i
<r
->route_count
; i
++ )
992 struct route
*route
= &r
->routes
[i
];
993 world_id_fixup( &route
->start
, mdl
);
999 for( int i
=0; i
<r
->route_count
; i
++ )
1001 struct route
*route
= &r
->routes
[i
];
1004 u32 si
= world_routes_get_path( route
->start
, stack
);
1006 for( int sj
=0; sj
<si
; sj
++ )
1008 struct route_node
*rn
= &r
->nodes
[ stack
[sj
] ];
1009 rn
->route_ids
[ rn
->ref_count
++ ] = i
;
1011 if( rn
->ref_count
> 4 )
1012 vg_warn( "Too many references on route node %i\n", i
);
1016 world_routes_gen_meshes();
1019 #endif /* ROUTES_H */