82d5da7925b0ee67749bb35f91ba77ec1e658fe0
8 #include "shaders/vblend.h"
9 #include "shaders/route.h"
11 struct subworld_routes
18 u32 is_gate
, gate_id
, current_refs
, ref_count
;
19 u32 route_ids
[4]; /* Gates can be linked into up to four routes */
59 static struct subworld_routes
*subworld_routes(void);
63 * when a gate is passed through it needs to trigger into an active state
66 static void debug_sbpath( struct route_node
*rna
, struct route_node
*rnb
,
67 u32 colour
, float xoffset
)
69 v3f p0
, h0
, p1
, h1
, l
, p
;
71 v3_copy( rna
->co
, p0
);
72 v3_muladds( rna
->co
, rna
->h
, 1.0f
, h0
);
73 v3_copy( rnb
->co
, p1
);
74 v3_muladds( rnb
->co
, rnb
->h
, -1.0f
, h1
);
76 v3_muladds( p0
, rna
->right
, xoffset
, p0
);
77 v3_muladds( h0
, rna
->right
, xoffset
, h0
);
78 v3_muladds( p1
, rnb
->right
, xoffset
, p1
);
79 v3_muladds( h1
, rnb
->right
, xoffset
, h1
);
83 for( int i
=0; i
<5; i
++ )
85 float t
= (float)(i
+1)/5.0f
;
86 eval_bezier_time( p0
, p1
, h0
, h1
, t
, p
);
87 vg_line( p
, l
, colour
);
92 static void world_routes_activate_gate( u32 id
)
94 struct subworld_routes
*r
= subworld_routes();
95 struct route_gate
*ig
= &r
->gates
[id
];
96 struct route_node
*pnode
= &r
->nodes
[ig
->node_id
],
97 *pdest
= &r
->nodes
[pnode
->next
[0]];
101 for( int i
=0; i
<r
->route_count
; i
++ )
103 struct route
*route
= &r
->routes
[i
];
106 for( int j
=0; j
<pdest
->ref_count
; j
++ )
108 if( pdest
->route_ids
[j
] == i
)
117 static u32
world_routes_get_path( struct route
*route
, u32 stack
[64] )
119 struct subworld_routes
*r
= subworld_routes();
122 stack
[0] = route
->start
;
126 int loop_complete
= 0;
130 if( stack_i
[si
-1] == 2 )
136 struct route_node
*rn
= &r
->nodes
[stack
[si
-1]];
137 u32 nextid
= rn
->next
[stack_i
[si
-1]];
140 if( nextid
!= 0xffffffff )
142 if( nextid
== stack
[0] )
149 for( int sj
=0; sj
<si
; sj
++ )
151 if( stack
[sj
] == nextid
)
174 static void world_routes_debug(void)
176 struct subworld_routes
*r
= subworld_routes();
178 for( int i
=0; i
<r
->node_count
; i
++ )
180 struct route_node
*rn
= &r
->nodes
[i
];
181 vg_line_pt3( rn
->co
, 1.0f
, rn
->is_gate
? 0xffffff00: 0xff00b2ff );
184 for( int i
=0; i
<r
->route_count
; i
++ )
186 struct route
*route
= &r
->routes
[i
];
189 u32 si
= world_routes_get_path( route
, stack
);
191 u32 colours
[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
194 u32 cc
= colours
[i
%vg_list_size(colours
)];
196 for( int sj
=0; sj
<si
; sj
++ )
199 debug_sbpath( &r
->nodes
[stack
[sj
]], &r
->nodes
[stack
[sk
]], cc
,
204 for( int i
=0; i
<r
->node_count
; i
++ )
206 struct route_node
*ri
= &r
->nodes
[i
],
209 for( int j
=0; j
<2; j
++ )
211 if( ri
->next
[j
] != 0xffffffff )
213 rj
= &r
->nodes
[ri
->next
[j
]];
214 vg_line( ri
->co
, rj
->co
, 0x20ffffff );
220 static void world_routes_free(void)
222 struct subworld_routes
*r
= subworld_routes();
229 static void world_id_fixup( u32
*uid
, mdl_header
*mdl
)
232 *uid
= mdl_node_from_id( mdl
, *uid
)->sub_uid
;
237 static void world_routes_gen_meshes(void)
239 struct subworld_routes
*r
= subworld_routes();
240 scene_init( &r
->scene_lines
);
242 for( int i
=0; i
<r
->route_count
; i
++ )
244 struct route
*route
= &r
->routes
[i
];
247 u32 si
= world_routes_get_path( route
, stack
);
251 for( int sj
=0; sj
<si
; sj
++ )
255 struct route_node
*rnj
= &r
->nodes
[ stack
[sj
] ],
256 *rnk
= &r
->nodes
[ stack
[sk
] ],
259 if( rnj
->is_gate
&& rnk
->is_gate
)
265 float base_x0
= (float)rnj
->ref_count
*-0.5f
+ (float)rnj
->current_refs
,
266 base_x1
= (float)rnk
->ref_count
*-0.5f
+ (float)rnk
->current_refs
;
270 rnl
= &r
->nodes
[ rnk
->next
[0] ];
271 base_x1
= (float)rnl
->ref_count
*-0.5f
+ (float)rnl
->current_refs
;
279 v3f p0
, h0
, p1
, h1
, p
, pd
;
281 v3_copy( rnj
->co
, p0
);
282 v3_muladds( rnj
->co
, rnj
->h
, 1.0f
, h0
);
283 v3_copy( rnk
->co
, p1
);
284 v3_muladds( rnk
->co
, rnk
->h
, -1.0f
, h1
);
289 for( int it
=0; it
<256; it
++ )
291 float const k_sample_dist
= 0.02f
;
292 eval_bezier_time( p0
,p1
,h0
,h1
, t
,p
);
293 eval_bezier_time( p0
,p1
,h0
,h1
, t
+k_sample_dist
,pd
);
295 float mod
= k_sample_dist
/ v3_dist( p
, pd
);
298 v3_muls( rnj
->up
, 1.0f
-t
, up
);
299 v3_muladds( up
, rnk
->up
, t
, up
);
302 v3_cross( up
, v0
, right
);
303 v3_normalize( right
);
305 float cur_x
= (1.0f
-t
)*base_x0
+ t
*base_x1
;
307 v3f sc
, sa
, sb
, down
;
308 v3_muladds( p
, right
, cur_x
, sc
);
309 v3_muladds( sc
, up
, 1.5f
, sc
);
310 v3_muladds( sc
, right
, 0.45f
, sa
);
311 v3_muladds( sc
, right
, -0.45f
, sb
);
312 v3_muls( up
, -1.0f
, down
);
317 if(ray_world( sa
, down
, &ha
) &&
318 ray_world( sb
, down
, &hb
))
322 v3_muladds( ha
.pos
, up
, 0.06f
, va
.co
);
323 v3_muladds( hb
.pos
, up
, 0.06f
, vb
.co
);
324 v3_copy( up
, va
.norm
);
325 v3_copy( up
, vb
.norm
);
326 v3_zero( va
.colour
);
327 v3_zero( vb
.colour
);
331 scene_push_vert( &r
->scene_lines
, &va
);
332 scene_push_vert( &r
->scene_lines
, &vb
);
336 /* Connect them with triangles */
337 scene_push_tri( &r
->scene_lines
, (u32
[3]){
338 last_valid
+0-2, last_valid
+1-2, last_valid
+2-2} );
339 scene_push_tri( &r
->scene_lines
, (u32
[3]){
340 last_valid
+1-2, last_valid
+3-2, last_valid
+2-2} );
343 last_valid
= r
->scene_lines
.vertex_count
;
352 /* TODO special case for end of loop, need to add triangles
353 * between first and last rungs */
358 rnj
->current_refs
++;
361 scene_copy_slice( &r
->scene_lines
, &route
->sm
);
364 scene_upload( &r
->scene_lines
);
365 scene_free_offline_buffers( &r
->scene_lines
);
368 static void bind_terrain_textures(void);
369 static void render_world_routes( m4x4f projection
, v3f camera
)
371 struct subworld_routes
*r
= subworld_routes();
373 m4x3f identity_matrix
;
374 m4x3_identity( identity_matrix
);
377 shader_route_uTexGarbage(0);
378 shader_link_standard_ub( _shader_route
.id
, 2 );
379 bind_terrain_textures();
381 shader_route_uPv( projection
);
382 shader_route_uMdl( identity_matrix
);
383 shader_route_uCamera( camera
);
385 scene_bind( &r
->scene_lines
);
387 for( int i
=0; i
<r
->route_count
; i
++ )
389 struct route
*route
= &r
->routes
[i
];
390 route
->factive
= vg_lerpf( route
->factive
, route
->active
, 0.01f
);
393 v3_lerp( (v3f
){0.7f
,0.7f
,0.7f
}, route
->colour
, route
->factive
, colour
);
396 shader_route_uColour( colour
);
397 mdl_draw_submesh( &route
->sm
);
401 static void world_routes_register(void)
403 shader_route_register();
406 static void world_routes_loadfrom( mdl_header
*mdl
)
408 struct subworld_routes
*r
= subworld_routes();
419 for( int i
=0; i
<mdl
->node_count
; i
++ )
421 mdl_node
*pnode
= mdl_node_from_id(mdl
,i
);
424 if( pnode
->classtype
== k_classtype_route_node
||
425 pnode
->classtype
== k_classtype_gate
)
427 mdl_node_transform( pnode
, transform
);
428 pnode
->sub_uid
= r
->node_count
;
430 r
->nodes
= buffer_reserve( r
->nodes
, r
->node_count
, &r
->node_cap
, 1,
431 sizeof( struct route_node
) );
433 struct route_node
*rn
= &r
->nodes
[r
->node_count
];
435 v3_copy( transform
[0], rn
->right
);
436 v3_normalize( rn
->right
);
437 v3_copy( transform
[1], rn
->up
);
438 v3_normalize( rn
->up
);
439 v3_muls( transform
[2], -1.0f
, rn
->h
);
440 v3_copy( transform
[3], rn
->co
);
442 rn
->current_refs
= 0;
444 if( pnode
->classtype
== k_classtype_gate
)
446 r
->gates
= buffer_reserve( r
->gates
, r
->gate_count
, &r
->gate_cap
,
447 1, sizeof( struct route_gate
) );
449 struct classtype_gate
*inf
= mdl_get_entdata( mdl
, pnode
);
451 /* H is later scaled based on link distance */
452 v3_normalize( rn
->h
);
453 rn
->next
[0] = inf
->target
;
455 rn
->gate_id
= r
->gate_count
;
461 mdl_node
*pother
= mdl_node_from_id( mdl
, inf
->target
);
463 if( pother
->classtype
== k_classtype_gate
)
465 struct route_gate
*rg
= &r
->gates
[r
->gate_count
];
466 rg
->node_id
= r
->node_count
;
468 v3_copy( pnode
->co
, rg
->gate
.co
[0] );
469 v3_copy( pother
->co
, rg
->gate
.co
[1] );
470 v4_copy( pnode
->q
, rg
->gate
.q
[0] );
471 v4_copy( pother
->q
, rg
->gate
.q
[1] );
472 v2_copy( inf
->dims
, rg
->gate
.dims
);
474 gate_transform_update( &rg
->gate
);
482 struct classtype_route_node
*inf
= mdl_get_entdata( mdl
, pnode
);
483 rn
->next
[0] = inf
->target
;
484 rn
->next
[1] = inf
->target1
;
490 else if( pnode
->classtype
== k_classtype_route
)
492 struct classtype_route
*inf
= mdl_get_entdata( mdl
, pnode
);
493 r
->routes
= buffer_reserve( r
->routes
, r
->route_count
, &r
->route_cap
,
494 1, sizeof( struct route
) );
496 struct route
*route
= &r
->routes
[r
->route_count
];
498 v3_copy( inf
->colour
, route
->colour
);
499 route
->colour
[3] = 1.0f
;
502 route
->start
= inf
->id_start
;
504 route
->factive
= 0.0f
;
511 * Apply correct system-local ids
513 for( int i
=0; i
<r
->node_count
; i
++ )
515 struct route_node
*rn
= &r
->nodes
[i
];
517 for( int j
=0; j
<2; j
++ )
518 world_id_fixup( &rn
->next
[j
], mdl
);
521 for( int i
=0; i
<r
->route_count
; i
++ )
523 struct route
*route
= &r
->routes
[i
];
524 world_id_fixup( &route
->start
, mdl
);
530 for( int i
=0; i
<r
->route_count
; i
++ )
532 struct route
*route
= &r
->routes
[i
];
535 u32 si
= world_routes_get_path( route
, stack
);
537 for( int sj
=0; sj
<si
; sj
++ )
539 struct route_node
*rn
= &r
->nodes
[ stack
[sj
] ];
540 rn
->route_ids
[ rn
->ref_count
++ ] = i
;
542 if( rn
->ref_count
> 4 )
543 vg_warn( "Too many references on route node %i\n", i
);
547 world_routes_gen_meshes();
550 #endif /* ROUTES_H */