routes
[carveJwlIkooP6JGAAIwe30JlM.git] / world.h
1 #include "common.h"
2
3 static int ray_world( v3f pos, v3f dir, ray_hit *hit );
4
5 #ifndef WORLD_H
6 #define WORLD_H
7
8 #include "scene.h"
9 #include "terrain.h"
10 #include "render.h"
11 #include "water.h"
12 #include "rigidbody.h"
13 #include "gate.h"
14 #include "bvh.h"
15 #include "lighting.h"
16 #include "model.h"
17
18 #include "traffic.h" /*TODO: -> world_traffic.h */
19 #include "world_routes.h"
20
21 #include "shaders/terrain.h"
22 #include "shaders/sky.h"
23 #include "shaders/planeinf.h"
24 #include "shaders/standard.h"
25 #include "shaders/vblend.h"
26 #include "shaders/gpos.h"
27 #include "shaders/fscolour.h"
28 #include "shaders/alphatest.h"
29
30 static struct gworld
31 {
32 /* gameplay */
33 struct respawn_point
34 {
35 v3f co;
36 v4f q;
37 char name[32];
38 }
39 spawns[32];
40 u32 spawn_count;
41
42 struct subworld_routes routes;
43
44 /* ...
45 struct subworld_spawns system_spawns;
46 struct subworld_physics system_physics;
47 */
48
49 /* Paths */
50 traffic_node traffic[128];
51 u32 traffic_count;
52
53 #if 0
54 traffic_driver van_man[6];
55 #endif
56
57 /* Physics */
58
59 /* Rendering & geometry */
60 scene geo, foliage;
61 rigidbody rb_geo;
62
63 mdl_submesh sm_geo_std_oob, sm_geo_std, sm_geo_vb,
64 sm_foliage_main, sm_foliage_alphatest;
65
66 glmesh skybox, skydome;
67 mdl_submesh dome_upper, dome_lower;
68
69 glmesh cars;
70 mdl_submesh car_holden;
71
72 rigidbody mr_ball;
73
74 /* Load time */
75
76 struct instance_cache
77 {
78 mdl_header *mdl;
79 u32 pstr_file;
80 }
81 * instance_cache;
82 u32 instance_cache_count,
83 instance_cache_cap;
84 }
85 world;
86
87 static struct subworld_routes *subworld_routes(void) { return &world.routes; }
88
89
90 vg_tex2d tex_terrain_colours = { .path = "textures/gradients.qoi",
91 .flags = VG_TEXTURE_CLAMP|VG_TEXTURE_NEAREST };
92
93 vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi",
94 .flags = VG_TEXTURE_NEAREST };
95
96 vg_tex2d tex_alphatest = { .path = "textures/alphatest.qoi",
97 .flags = VG_TEXTURE_NEAREST };
98
99 static void ray_world_get_tri( ray_hit *hit, v3f tri[3] )
100 {
101 for( int i=0; i<3; i++ )
102 v3_copy( world.geo.verts[ hit->tri[i] ].co, tri[i] );
103 }
104
105 static int ray_world( v3f pos, v3f dir, ray_hit *hit )
106 {
107 return scene_raycast( &world.geo, pos, dir, hit );
108 }
109
110 static int ray_hit_is_ramp( ray_hit *hit )
111 {
112 return hit->tri[0] > world.sm_geo_std_oob.vertex_count;
113 }
114
115 static void world_register(void)
116 {
117 shader_terrain_register();
118 shader_sky_register();
119 shader_planeinf_register();
120 shader_gpos_register();
121 shader_fscolour_register();
122 shader_alphatest_register();
123
124 world_routes_register();
125 }
126
127 static void world_free(void)
128 {
129 /* TODO.. */
130 }
131
132 static void render_world_depth( m4x4f projection, m4x3f camera );
133
134 static void add_all_if_material( m4x3f transform, scene *pscene,
135 mdl_header *mdl, u32 id )
136 {
137 for( int i=0; i<mdl->node_count; i++ )
138 {
139 mdl_node *pnode = mdl_node_from_id( mdl, i );
140
141 for( int j=0; j<pnode->submesh_count; j++ )
142 {
143 mdl_submesh *sm = mdl_node_submesh( mdl, pnode, j );
144
145 if( sm->material_id == id )
146 {
147 m4x3f transform2;
148 mdl_node_transform( pnode, transform2 );
149 m4x3_mul( transform, transform2, transform2 );
150
151 scene_add_submesh( pscene, mdl, sm, transform2 );
152 }
153 }
154
155 if( pnode->classtype == k_classtype_instance )
156 {
157 if( pnode->sub_uid )
158 {
159 u32 instance_id = pnode->sub_uid -1;
160 struct instance_cache *cache = &world.instance_cache[instance_id];
161 mdl_header *mdl2 = cache->mdl;
162
163 m4x3f transform2;
164 mdl_node_transform( pnode, transform2 );
165 m4x3_mul( transform, transform2, transform2 );
166
167 add_all_if_material( transform2, pscene, mdl2, id );
168 }
169 }
170 }
171 }
172
173 static void world_apply_procedural_foliage(void)
174 {
175 mdl_header *mfoliage = mdl_load("models/rs_foliage.mdl");
176
177 v3f volume;
178 v3_sub( world.geo.bbx[1], world.geo.bbx[0], volume );
179 volume[1] = 1.0f;
180
181 m4x3f transform;
182 mdl_node *mblob = mdl_node_from_name( mfoliage, "blob" );
183 mdl_submesh *sm_blob = mdl_node_submesh( mfoliage, mblob, 0 );
184
185 for( int i=0;i<100000;i++ )
186 {
187 v3f pos;
188 v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos );
189 pos[1] = 1000.0f;
190 v3_add( pos, world.geo.bbx[0], pos );
191
192 ray_hit hit;
193 hit.dist = INFINITY;
194
195 if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
196 {
197 if( hit.normal[1] > 0.8f && !ray_hit_is_ramp(&hit) &&
198 hit.pos[1] > water_height()+10.0f )
199 {
200 v4f qsurface, qrandom;
201 v3f axis;
202
203 v3_cross( (v3f){0.0f,1.0f,0.0f}, hit.normal, axis );
204
205 float angle = v3_dot(hit.normal,(v3f){0.0f,1.0f,0.0f});
206 q_axis_angle( qsurface, axis, angle );
207 q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf()*VG_TAUf );
208 q_mul( qsurface, qrandom, qsurface );
209 q_m3x3( qsurface, transform );
210
211 v3_copy( hit.pos, transform[3] );
212 scene_add_submesh( &world.foliage, mfoliage, sm_blob, transform);
213 }
214 }
215 }
216 free( mfoliage );
217 }
218
219 static void world_load(void)
220 {
221 mdl_header *mworld = mdl_load( "models/mp_dev.mdl" );
222
223 world.spawn_count = 0;
224 world.traffic_count = 0;
225 world.instance_cache = NULL;
226
227 /*
228 * Process entities
229 */
230 for( int i=0; i<mworld->node_count; i++ )
231 {
232 mdl_node *pnode = mdl_node_from_id( mworld, i );
233
234 if( pnode->classtype == k_classtype_none )
235 {}
236 else if( pnode->classtype == k_classtype_spawn )
237 {
238 struct respawn_point *rp = &world.spawns[ world.spawn_count ++ ];
239
240 v3_copy( pnode->co, rp->co );
241 v4_copy( pnode->q, rp->q );
242 strcpy( rp->name, mdl_pstr( mworld, pnode->pstr_name ) );
243 }
244 else if( pnode->classtype == k_classtype_water )
245 {
246 if( wrender.enabled )
247 {
248 vg_warn( "Multiple water surfaces in level! ('%s')\n",
249 mdl_pstr( mworld, pnode->pstr_name ));
250 continue;
251 }
252
253 mdl_submesh *sm = mdl_node_submesh( mworld, pnode, 0 );
254
255 if( sm )
256 {
257 glmesh surf;
258 mdl_unpack_submesh( mworld, &surf, sm );
259 water_init();
260 water_set_surface( &surf, pnode->co[1] );
261 }
262 }
263 else if( pnode->classtype == k_classtype_car_path )
264 {
265 struct classtype_car_path *p = mdl_get_entdata( mworld, pnode );
266 traffic_node *tn = &world.traffic[ world.traffic_count ];
267 tn->mn_next = NULL;
268 tn->mn_next1 = NULL;
269
270 if( p->target ) tn->mn_next = mdl_node_from_id( mworld, p->target );
271 if( p->target1 ) tn->mn_next1 = mdl_node_from_id( mworld, p->target1 );
272
273 m4x3f transform;
274 mdl_node_transform( pnode, transform );
275 m3x3_mulv( transform, (v3f){1.0f,0.0f,0.0f}, tn->h );
276 v3_copy( transform[3], tn->co );
277
278 pnode->sub_uid = world.traffic_count ++;
279 }
280 else if( pnode->classtype == k_classtype_instance )
281 {
282 struct classtype_instance *inst = mdl_get_entdata( mworld, pnode );
283 pnode->sub_uid = 0;
284
285 int cached = 0;
286 for( int i=0; i<world.instance_cache_count; i++ )
287 {
288 struct instance_cache *cache = &world.instance_cache[i];
289 if( inst->pstr_file == cache->pstr_file )
290 {
291 cached = 1;
292 pnode->sub_uid = i+1;
293 break;
294 }
295 }
296
297 if( !cached )
298 {
299 world.instance_cache = buffer_reserve(
300 world.instance_cache, world.instance_cache_count,
301 &world.instance_cache_cap, 1,
302 sizeof(struct instance_cache) );
303
304 struct instance_cache *cache =
305 &world.instance_cache[world.instance_cache_count];
306
307 const char *filename = mdl_pstr(mworld, inst->pstr_file);
308
309 cache->pstr_file = inst->pstr_file;
310 cache->mdl = mdl_load( filename );
311
312 if( cache->mdl )
313 {
314 world.instance_cache_count ++;
315 pnode->sub_uid = world.instance_cache_count;
316 mdl_link_materials( mworld, cache->mdl );
317 vg_success( "Cached %s\n", filename );
318 }
319 else
320 {
321 vg_warn( "Failed to cache %s\n", filename );
322 }
323 }
324 }
325 }
326
327 world.instance_cache = buffer_fix( world.instance_cache,
328 world.instance_cache_count,
329 &world.instance_cache_cap,
330 sizeof( struct instance_cache ) );
331
332 #if 0
333 traffic_finalize( world.traffic, world.traffic_count );
334 for( int i=0; i<vg_list_size(world.van_man); i++ )
335 world.van_man[i].current =&world.traffic[vg_randint(world.traffic_count)];
336 #endif
337
338 /*
339 * Compile meshes into the world scenes
340 */
341 scene_init( &world.geo );
342
343 u32 mat_surf = 0,
344 mat_surf_oob = 0,
345 mat_vertex_blend = 0,
346 mat_alphatest = 0;
347
348 for( int i=1; i<mworld->material_count; i++ )
349 {
350 mdl_material *mat = mdl_material_from_id( mworld, i );
351 const char *mat_name = mdl_pstr( mworld, mat->pstr_name );
352
353 if( !strcmp( "surf", mat_name ))
354 mat_surf = i;
355 else if( !strcmp( "surf_oob", mat_name ))
356 mat_surf_oob = i;
357 else if( !strcmp( "vertex_blend", mat_name ))
358 mat_vertex_blend = i;
359 else if( !strcmp( "alphatest", mat_name ))
360 mat_alphatest = i;
361 }
362
363 m4x3f midentity;
364 m4x3_identity( midentity );
365
366 if( mat_surf_oob )
367 add_all_if_material( midentity, &world.geo, mworld, mat_surf_oob );
368 else
369 vg_warn( "No OOB surface\n" );
370 scene_copy_slice( &world.geo, &world.sm_geo_std_oob );
371
372 if( mat_surf )
373 add_all_if_material( midentity, &world.geo, mworld, mat_surf );
374 scene_copy_slice( &world.geo, &world.sm_geo_std );
375
376 if( mat_vertex_blend )
377 add_all_if_material( midentity, &world.geo, mworld, mat_vertex_blend );
378 scene_copy_slice( &world.geo, &world.sm_geo_vb );
379
380 scene_upload( &world.geo );
381 scene_bh_create( &world.geo );
382
383
384 /* Foliage /nocollide layer.
385 * TODO: Probably should have material traits for this
386 */
387 scene_init( &world.foliage );
388
389 world_apply_procedural_foliage();
390 scene_copy_slice( &world.foliage, &world.sm_foliage_main );
391
392 add_all_if_material( midentity, &world.foliage, mworld, mat_alphatest );
393 scene_copy_slice( &world.foliage, &world.sm_foliage_alphatest );
394
395 scene_upload( &world.foliage );
396 world_routes_loadfrom( mworld );
397
398 for( int i=0; i<world.instance_cache_count; i++ )
399 free( world.instance_cache[i].mdl );
400
401 free( world.instance_cache );
402 free( mworld );
403
404 /*
405 * Rendering the depth map
406 */
407 m4x4f ortho;
408 m4x3f camera;
409
410 v3f extent;
411 v3_sub( world.geo.bbx[1], world.geo.bbx[0], extent );
412
413 float fl = world.geo.bbx[0][0],
414 fr = world.geo.bbx[1][0],
415 fb = world.geo.bbx[0][2],
416 ft = world.geo.bbx[1][2],
417 rl = 1.0f / (fr-fl),
418 tb = 1.0f / (ft-fb);
419
420 m4x4_zero( ortho );
421 ortho[0][0] = 2.0f * rl;
422 ortho[2][1] = 2.0f * tb;
423 ortho[3][0] = (fr + fl) * -rl;
424 ortho[3][1] = (ft + fb) * -tb;
425 ortho[3][3] = 1.0f;
426 m4x3_identity( camera );
427
428 glViewport( 0, 0, 1024, 1024 );
429 glDisable(GL_DEPTH_TEST);
430 glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap );
431 shader_fscolour_use();
432 shader_fscolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} );
433 render_fsquad();
434
435 glEnable(GL_BLEND);
436 glBlendFunc(GL_ONE, GL_ONE);
437 glBlendEquation(GL_MAX);
438 render_world_depth( ortho, camera );
439 glDisable(GL_BLEND);
440 glEnable(GL_DEPTH_TEST);
441
442 /*
443 * TODO: World settings entity
444 */
445 struct ub_world_lighting *winfo = &gpipeline.ub_world_lighting;
446 v4_copy( wrender.plane, winfo->g_water_plane );
447
448 v4f bounds;
449 bounds[0] = world.geo.bbx[0][0];
450 bounds[1] = world.geo.bbx[0][2];
451 bounds[2] = 1.0f/ (world.geo.bbx[1][0]-world.geo.bbx[0][0]);
452 bounds[3] = 1.0f/ (world.geo.bbx[1][2]-world.geo.bbx[0][2]);
453 v4_copy( bounds, winfo->g_depth_bounds );
454
455 winfo->g_water_fog = 0.04f;
456 render_update_lighting_ub();
457
458
459 world.mr_ball.type = k_rb_shape_sphere;
460 world.mr_ball.inf.sphere.radius = 2.0f;
461 v3_copy( (v3f){ 0.0f, 110.0f, 0.0f }, world.mr_ball.co );
462
463 q_identity(world.mr_ball.q);
464 rb_init( &world.mr_ball );
465
466 /*
467 * Setup scene collider
468 */
469 v3_zero( world.rb_geo.co );
470 q_identity( world.rb_geo.q );
471
472 world.rb_geo.type = k_rb_shape_scene;
473 world.rb_geo.inf.scene.pscene = &world.geo;
474 world.rb_geo.is_world = 1;
475 rb_init( &world.rb_geo );
476 }
477
478 static void world_init(void)
479 {
480 vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_colours,
481 &tex_terrain_noise,
482 &tex_alphatest }, 3 );
483
484 mdl_header *mcars = mdl_load( "models/rs_cars.mdl" );
485 mdl_unpack_glmesh( mcars, &world.cars );
486 mdl_node *nholden = mdl_node_from_name( mcars, "holden" );
487 world.car_holden = *mdl_node_submesh( mcars, nholden, 0 );
488 free(mcars);
489
490
491 mdl_header *msky = mdl_load("models/rs_skydome.mdl");
492 mdl_unpack_glmesh( msky, &world.skydome );
493
494 mdl_node *nlower = mdl_node_from_name( msky, "dome_lower" ),
495 *nupper = mdl_node_from_name( msky, "dome_upper" );
496
497 world.dome_lower = *mdl_node_submesh( msky, nlower, 0 );
498 world.dome_upper = *mdl_node_submesh( msky, nupper, 0 );
499 free(msky);
500 }
501
502 static void world_update(void)
503 {
504 world_routes_debug();
505
506 #if 0
507 rb_solver_reset();
508 rb_build_manifold_terrain_sphere( &world.mr_ball );
509
510 for( int i=0; i<5; i++ )
511 rb_solve_contacts( rb_contact_buffer, rb_contact_count );
512
513 rb_iter( &world.mr_ball );
514 rb_update_transform( &world.mr_ball );
515 rb_debug( &world.mr_ball, 0 );
516
517 for( int i=0; i<vg_list_size(world.van_man); i++ )
518 {
519 traffic_drive( &world.van_man[i] );
520 traffic_visualize_car( &world.van_man[i] );
521 }
522 #endif
523 }
524
525 /*
526 * Rendering
527 */
528
529 static void bind_terrain_textures(void)
530 {
531 vg_tex2d_bind( &tex_terrain_noise, 0 );
532 vg_tex2d_bind( &tex_terrain_colours, 1 );
533 }
534
535 static void render_world_vb( m4x4f projection, v3f camera )
536 {
537 m4x3f identity_matrix;
538 m4x3_identity( identity_matrix );
539
540 shader_vblend_use();
541 shader_vblend_uTexGarbage(0);
542 shader_vblend_uTexGradients(1);
543 shader_link_standard_ub( _shader_vblend.id, 2 );
544 bind_terrain_textures();
545
546 shader_vblend_uPv( projection );
547 shader_vblend_uMdl( identity_matrix );
548 shader_vblend_uCamera( camera );
549
550 scene_bind( &world.geo );
551 mdl_draw_submesh( &world.sm_geo_vb );
552
553 mesh_bind( &world.cars );
554
555 #if 0
556 for( int i=0; i<vg_list_size(world.van_man); i++ )
557 {
558 shader_vblend_uMdl( world.van_man[i].transform );
559 mdl_draw_submesh( &world.car_holden );
560 }
561 #endif
562 }
563
564 static void render_world_alphatest( m4x4f projection, v3f camera )
565 {
566 m4x3f identity_matrix;
567 m4x3_identity( identity_matrix );
568
569 shader_alphatest_use();
570 shader_alphatest_uTexGarbage(0);
571 shader_alphatest_uTexMain(1);
572 shader_link_standard_ub( _shader_alphatest.id, 2 );
573
574 vg_tex2d_bind( &tex_terrain_noise, 0 );
575 vg_tex2d_bind( &tex_alphatest, 1 );
576
577 shader_alphatest_uPv( projection );
578 shader_alphatest_uMdl( identity_matrix );
579 shader_alphatest_uCamera( camera );
580
581 glDisable(GL_CULL_FACE);
582 scene_bind( &world.foliage );
583 mdl_draw_submesh( &world.sm_foliage_alphatest );
584 glEnable(GL_CULL_FACE);
585 }
586
587 static void render_terrain( m4x4f projection, v3f camera )
588 {
589 m4x3f identity_matrix;
590 m4x3_identity( identity_matrix );
591
592 shader_terrain_use();
593 shader_terrain_uTexGarbage(0);
594 shader_terrain_uTexGradients(1);
595 shader_link_standard_ub( _shader_terrain.id, 2 );
596 bind_terrain_textures();
597
598 shader_terrain_uPv( projection );
599 shader_terrain_uMdl( identity_matrix );
600 shader_terrain_uCamera( camera );
601
602 scene_bind( &world.geo );
603 mdl_draw_submesh( &world.sm_geo_std_oob );
604 mdl_draw_submesh( &world.sm_geo_std );
605
606 /* TODO: Dont draw in reflection */
607 glDisable(GL_CULL_FACE);
608 scene_bind( &world.foliage );
609 mdl_draw_submesh( &world.sm_foliage_main );
610 glEnable(GL_CULL_FACE);
611 }
612
613 static void render_lowerdome( m4x3f camera )
614 {
615 m4x4f projection, full;
616 pipeline_projection( projection, 0.4f, 1000.0f );
617
618 m4x3f inverse;
619 m3x3_transpose( camera, inverse );
620 v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
621 m4x3_expand( inverse, full );
622 m4x4_mul( projection, full, full );
623
624 m4x3f identity_matrix;
625 m4x3_identity( identity_matrix );
626
627 shader_planeinf_use();
628 shader_planeinf_uMdl(identity_matrix);
629 shader_planeinf_uPv(full);
630 shader_planeinf_uCamera(camera[3]);
631 shader_planeinf_uPlane( (v4f){0.0f,1.0f,0.0f, water_height()} );
632
633 mdl_draw_submesh( &world.dome_lower );
634 }
635
636 static void render_sky(m4x3f camera)
637 {
638 m4x4f projection, full;
639 pipeline_projection( projection, 0.4f, 1000.0f );
640
641 m4x3f inverse;
642 m3x3_transpose( camera, inverse );
643 v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
644 m4x3_expand( inverse, full );
645 m4x4_mul( projection, full, full );
646
647 m4x3f identity_matrix;
648 m4x3_identity( identity_matrix );
649
650 shader_sky_use();
651 shader_sky_uMdl(identity_matrix);
652 shader_sky_uPv(full);
653 shader_sky_uTexGarbage(0);
654 shader_sky_uTime( vg_time );
655
656 vg_tex2d_bind( &tex_terrain_noise, 0 );
657
658 glDepthMask( GL_FALSE );
659 glDisable( GL_DEPTH_TEST );
660
661 mesh_bind( &world.skydome );
662 mdl_draw_submesh( &world.dome_upper );
663
664 glEnable( GL_DEPTH_TEST );
665 glDepthMask( GL_TRUE );
666 }
667
668 static void render_world_gates( m4x4f projection, m4x3f camera )
669 {
670 int count = 0;
671 for( int i=0; i<world.routes.gate_count; i++ )
672 {
673 struct route_gate *rg = &world.routes.gates[i];
674 count += render_gate( &rg->gate, camera );
675
676 if( count == 2 )
677 return;
678 }
679 }
680
681 static void render_world( m4x4f projection, m4x3f camera )
682 {
683 render_sky( camera );
684 render_world_routes( projection, camera[3] );
685 render_world_vb( projection, camera[3] );
686 render_world_alphatest( projection, camera[3] );
687 render_terrain( projection, camera[3] );
688 }
689
690 static void render_world_depth( m4x4f projection, m4x3f camera )
691 {
692 m4x3f identity_matrix;
693 m4x3_identity( identity_matrix );
694
695 shader_gpos_use();
696 shader_gpos_uCamera( camera[3] );
697 shader_gpos_uPv( projection );
698 shader_gpos_uMdl( identity_matrix );
699
700 scene_bind( &world.geo );
701 scene_draw( &world.geo );
702
703 #if 0
704 glDisable(GL_CULL_FACE);
705 scene_bind( &world.foliage );
706 scene_draw( &world.foliage );
707 glEnable(GL_CULL_FACE);
708 #endif
709 }
710
711 #endif /* WORLD_H */