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