+ route_count ++;
+ }
+ }
+
+ /* allocate */
+ u32 node_size = node_count * sizeof(struct route_node),
+ route_size = route_count * sizeof(struct route),
+ gate_size = gate_count * sizeof(struct route_gate),
+ collector_size = collector_count * sizeof(struct route_collector);
+
+ world.nodes = vg_linear_alloc( world.dynamic_vgl, node_size );
+ world.routes = vg_linear_alloc( world.dynamic_vgl, route_size );
+ world.gates = vg_linear_alloc( world.dynamic_vgl, gate_size );
+ world.collectors = vg_linear_alloc( world.dynamic_vgl, collector_size );
+}
+
+/* create node from mdl node */
+VG_STATIC struct route_node *world_routes_create_node( mdl_node *pnode )
+{
+ struct route_node *rn = &world.nodes[ world.node_count ++ ];
+
+ m4x3f transform;
+ mdl_node_transform( pnode, transform );
+
+ v3_copy( transform[3], rn->co );
+ v3_copy( transform[0], rn->right );
+ v3_copy( transform[1], rn->up );
+ v3_muls( transform[2], -1.0f, rn->h );
+ v3_normalize( rn->right );
+ v3_normalize( rn->up );
+
+ rn->next[0] = 0xffffffff;
+ rn->next[1] = 0xffffffff;
+
+ rn->special_type = 0;
+ rn->special_id = 0;
+ rn->current_refs = 0;
+ rn->ref_count = 0;
+
+ return rn;
+}
+
+/* retrieve the correct node id from mdl subuid */
+VG_STATIC u32 world_routes_get_subuid( u32 target )
+{
+ if( target == 0 )
+ return 0xffffffff;
+ else
+ return mdl_node_from_id( world.meta, target )->sub_uid;
+}
+
+#if 0
+VG_STATIC void world_id_fixup( u32 *uid, mdl_context *mdl )
+{
+ if( *uid )
+ *uid = mdl_node_from_id( mdl, *uid )->sub_uid;
+ else
+ *uid = 0xffffffff;
+}
+#endif
+
+/* process gate attachement onto node */
+VG_STATIC void world_routes_process_gate( struct route_node *rn,
+ mdl_node *pnode )
+{
+ struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode );
+
+ /* H is later scaled based on link distance */
+ v3_normalize( rn->h );
+
+ rn->next[0] = world_routes_get_subuid( inf->target );
+ rn->next[1] = 0xffffffff;
+ rn->special_type = world_route_node_type( pnode );
+
+ /* process gate type */
+ if( rn->special_type == k_route_special_type_gate )
+ {
+ mdl_node *pother = mdl_node_from_id( world.meta, inf->target );
+
+ struct route_gate *rg = &world.gates[ world.gate_count ];
+
+ rg->node_id = world.node_count-1;
+ rg->timing.time = 0.0;
+ rg->timing.version = 0;
+
+ v3_copy( pnode->co, rg->gate.co[0] );
+ v3_copy( pother->co, rg->gate.co[1] );
+ v4_copy( pnode->q, rg->gate.q[0] );
+ v4_copy( pother->q, rg->gate.q[1] );
+ v2_copy( inf->dims, rg->gate.dims );
+
+ gate_transform_update( &rg->gate );
+ rn->special_id = world.gate_count;
+
+ world.gate_count ++;
+ }
+
+ /* process collector type */
+ else if( rn->special_type == k_route_special_type_collector )
+ {
+ struct route_collector *rc =
+ &world.collectors[ world.collector_count ];
+
+ rc->timing.time = 0.0;
+ rc->timing.version = 0;
+
+ rn->special_id = world.collector_count;
+ world.collector_count ++;
+ }
+ else
+ vg_fatal_exit_loop( "Invalid state" );
+}
+
+/* create route from node description */
+VG_STATIC void world_routes_create_route( mdl_node *pnode )
+{
+ mdl_context *mdl = world.meta;
+
+ struct classtype_route *inf = mdl_get_entdata( mdl, pnode );
+ struct route *route = &world.routes[ world.route_count ];
+ memset( route, 0, sizeof(struct route) );
+
+ v3_copy( inf->colour, route->colour );
+ route->colour[3] = 1.0f;
+ route->track_id = 0xffffffff;
+
+ for( u32 j=0; j<vg_list_size(track_infos); j++ )
+ {
+ if( !strcmp( mdl_pstr(mdl,pnode->pstr_name), track_infos[j].name ))
+ {
+ route->track_id = j;
+ break;
+ }
+ }
+
+ route->start = world_routes_get_subuid( inf->id_start );
+ route->active = 0;
+ route->factive = 0.0f;
+ mdl_node_transform( pnode, route->scoreboard_transform );
+
+ struct route_ui_bar *pui = &world.ui_bars[ world.route_count ];
+ pui->indices_head = k_route_ui_max_indices - 9;
+ pui->vertex_head = k_route_ui_max_verts - 200;
+ pui->segment_start = 0;
+ pui->segment_count = 0;
+ pui->fade_start = 0;
+ pui->fade_count = 0;
+ pui->fade_timer_start = 0.0;
+
+ world.route_count ++;
+}
+
+/* load all routes from model header */
+VG_STATIC void world_routes_process(void)
+{
+ vg_info( "Initializing routes\n" );
+ mdl_context *mdl = world.meta;