latest
[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 world;
67
68 vg_tex2d tex_terrain_colours = { .path = "textures/gradients.qoi",
69 .flags = VG_TEXTURE_CLAMP|VG_TEXTURE_NEAREST };
70
71 vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi",
72 .flags = VG_TEXTURE_NEAREST };
73
74 static void ray_world_get_tri( ray_hit *hit, v3f tri[3] )
75 {
76 for( int i=0; i<3; i++ )
77 v3_copy( world.geo.verts[ hit->tri[i] ].co, tri[i] );
78 }
79
80 static int ray_world( v3f pos, v3f dir, ray_hit *hit )
81 {
82 return scene_raycast( &world.geo, pos, dir, hit );
83 }
84
85 static int ray_hit_is_ramp( ray_hit *hit )
86 {
87 return hit->tri[0] > world.sm_geo_std_oob.vertex_count;
88 }
89
90 static void world_register(void)
91 {
92 shader_terrain_register();
93 shader_sky_register();
94 shader_planeinf_register();
95 shader_gpos_register();
96 shader_fscolour_register();
97 }
98
99 static void world_free(void)
100 {
101 /* TODO.. */
102 }
103
104 static void render_world_depth( m4x4f projection, m4x3f camera );
105
106 static void add_all_if_material( scene *pscene, mdl_header *mdl, u32 id )
107 {
108 for( int i=0; i<mdl->node_count; i++ )
109 {
110 mdl_node *pnode = mdl_node_from_id( mdl, i );
111
112 for( int j=0; j<pnode->submesh_count; j++ )
113 {
114 mdl_submesh *sm = mdl_node_submesh( mdl, pnode, j );
115
116 if( sm->material_id == id )
117 {
118 m4x3f transform;
119 mdl_node_transform( pnode, transform );
120 scene_add_submesh( pscene, mdl, sm, transform );
121 }
122 }
123 }
124 }
125
126 static void world_apply_foliage(void)
127 {
128 scene_init( &world.foliage );
129 mdl_header *mfoliage = mdl_load("models/rs_foliage.mdl");
130
131 v3f volume;
132 v3_sub( world.geo.bbx[1], world.geo.bbx[0], volume );
133 volume[1] = 1.0f;
134
135 m4x3f transform;
136 mdl_node *mblob = mdl_node_from_name( mfoliage, "blob" );
137 mdl_submesh *sm_blob = mdl_node_submesh( mfoliage, mblob, 0 );
138
139 for( int i=0;i<100000;i++ )
140 {
141 v3f pos;
142 v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos );
143 pos[1] = 1000.0f;
144 v3_add( pos, world.geo.bbx[0], pos );
145
146 ray_hit hit;
147 hit.dist = INFINITY;
148
149 if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
150 {
151 if( hit.normal[1] > 0.8f && !ray_hit_is_ramp(&hit) &&
152 hit.pos[1] > water_height()+10.0f )
153 {
154 v4f qsurface, qrandom;
155 v3f axis;
156
157 v3_cross( (v3f){0.0f,1.0f,0.0f}, hit.normal, axis );
158
159 float angle = v3_dot(hit.normal,(v3f){0.0f,1.0f,0.0f});
160 q_axis_angle( qsurface, axis, angle );
161 q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf()*VG_TAUf );
162 q_mul( qsurface, qrandom, qsurface );
163 q_m3x3( qsurface, transform );
164
165 v3_copy( hit.pos, transform[3] );
166 scene_add_submesh( &world.foliage, mfoliage, sm_blob, transform);
167 }
168 }
169 }
170
171 scene_upload( &world.foliage );
172 free( mfoliage );
173 }
174
175 static void world_load(void)
176 {
177 mdl_header *mworld = mdl_load( "models/mp_dev.mdl" );
178
179 world.spawn_count = 0;
180 world.gate_count = 0;
181 world.rb_count = 0;
182 world.traffic_count = 0;
183
184 scene_init( &world.geo );
185
186 /*
187 * Compile meshes into the world scenes
188 */
189 u32 mat_surf = 0,
190 mat_surf_oob = 0,
191 mat_vertex_blend = 0;
192
193 for( int i=1; i<mworld->material_count; i++ )
194 {
195 mdl_material *mat = mdl_material_from_id( mworld, i );
196 const char *mat_name = mdl_pstr( mworld, mat->pstr_name );
197
198 vg_info( "%d %s\n", mat->pstr_name, mat_name );
199
200 if( !strcmp( "surf", mat_name ))
201 mat_surf = i;
202 else if( !strcmp( "surf_oob", mat_name ))
203 mat_surf_oob = i;
204 else if( !strcmp( "vertex_blend", mat_name ))
205 mat_vertex_blend = i;
206 }
207
208 if( mat_surf_oob )
209 add_all_if_material( &world.geo, mworld, mat_surf_oob );
210 else
211 vg_warn( "No OOB surface\n" );
212 scene_copy_slice( &world.geo, &world.sm_geo_std_oob );
213
214 if( mat_surf )
215 add_all_if_material( &world.geo, mworld, mat_surf );
216 scene_copy_slice( &world.geo, &world.sm_geo_std );
217
218 if( mat_vertex_blend )
219 add_all_if_material( &world.geo, mworld, mat_vertex_blend );
220 scene_copy_slice( &world.geo, &world.sm_geo_vb );
221
222 scene_upload( &world.geo );
223 scene_bh_create( &world.geo );
224
225 /*
226 * Process entities
227 */
228 for( int i=0; i<mworld->node_count; i++ )
229 {
230 mdl_node *pnode = mdl_node_from_id( mworld, i );
231
232 if( pnode->classtype == k_classtype_none )
233 {}
234 else if( pnode->classtype == k_classtype_gate )
235 {
236 struct classtype_gate *entgate = mdl_get_entdata( mworld, pnode );
237
238 if( entgate->target )
239 {
240 mdl_node *pother = mdl_node_from_id( mworld, entgate->target );
241
242 teleport_gate *gate = &world.gates[ world.gate_count ++ ];
243
244 v3_copy( pnode->co, gate->co[0] );
245 v3_copy( pother->co, gate->co[1] );
246 v4_copy( pnode->q, gate->q[0] );
247 v4_copy( pother->q, gate->q[1] );
248 v2_copy( pnode->s, gate->dims );
249
250 gate_transform_update( gate );
251 }
252 }
253 else if( pnode->classtype == k_classtype_block )
254 {
255 struct classtype_block *block = mdl_get_entdata( mworld, pnode );
256
257 m4x3f transform;
258 mdl_node_transform( pnode, transform );
259
260 rigidbody *rb = &world.temp_rbs[ world.rb_count ++ ];
261
262 box_copy( block->bbx, rb->bbx ); /* TODO: apply scale */
263 v3_copy( pnode->co, rb->co );
264 rb_init( rb );
265 v4_copy( pnode->q, rb->q );
266 rb_update_transform( rb );
267 }
268 else if( pnode->classtype == k_classtype_spawn )
269 {
270 struct respawn_point *rp = &world.spawns[ world.spawn_count ++ ];
271
272 v3_copy( pnode->co, rp->co );
273 v4_copy( pnode->q, rp->q );
274 strcpy( rp->name, mdl_pstr( mworld, pnode->pstr_name ) );
275 }
276 else if( pnode->classtype == k_classtype_water )
277 {
278 if( wrender.enabled )
279 {
280 vg_warn( "Multiple water surfaces in level! ('%s')\n",
281 mdl_pstr( mworld, pnode->pstr_name ));
282 continue;
283 }
284
285 mdl_submesh *sm = mdl_node_submesh( mworld, pnode, 0 );
286
287 if( sm )
288 {
289 glmesh surf;
290 mdl_unpack_submesh( mworld, &surf, sm );
291 water_init();
292 water_set_surface( &surf, pnode->co[1] );
293 }
294 }
295 else if( pnode->classtype == k_classtype_car_path )
296 {
297 struct classtype_car_path *p = mdl_get_entdata( mworld, pnode );
298 traffic_node *tn = &world.traffic[ world.traffic_count ];
299 tn->mn_next = NULL;
300 tn->mn_next1 = NULL;
301
302 if( p->target ) tn->mn_next = mdl_node_from_id( mworld, p->target );
303 if( p->target1 ) tn->mn_next1 = mdl_node_from_id( mworld, p->target1 );
304
305 m4x3f transform;
306 mdl_node_transform( pnode, transform );
307 m3x3_mulv( transform, (v3f){1.0f,0.0f,0.0f}, tn->h );
308 v3_copy( transform[3], tn->co );
309
310 pnode->sub_uid = world.traffic_count ++;
311 }
312 }
313
314 traffic_finalize( world.traffic, world.traffic_count );
315 for( int i=0; i<vg_list_size(world.van_man); i++ )
316 world.van_man[i].current =&world.traffic[vg_randint(world.traffic_count)];
317
318 world_apply_foliage();
319 free( mworld );
320
321 /*
322 * Rendering the depth map
323 */
324 m4x4f ortho;
325 m4x3f camera;
326
327 v3f extent;
328 v3_sub( world.geo.bbx[1], world.geo.bbx[0], extent );
329
330 float fl = world.geo.bbx[0][0],
331 fr = world.geo.bbx[1][0],
332 fb = world.geo.bbx[0][2],
333 ft = world.geo.bbx[1][2],
334 rl = 1.0f / (fr-fl),
335 tb = 1.0f / (ft-fb);
336
337 m4x4_zero( ortho );
338 ortho[0][0] = 2.0f * rl;
339 ortho[2][1] = 2.0f * tb;
340 ortho[3][0] = (fr + fl) * -rl;
341 ortho[3][1] = (ft + fb) * -tb;
342 ortho[3][3] = 1.0f;
343 m4x3_identity( camera );
344
345 glViewport( 0, 0, 1024, 1024 );
346 glDisable(GL_DEPTH_TEST);
347 glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap );
348 shader_fscolour_use();
349 shader_fscolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} );
350 render_fsquad();
351
352 glEnable(GL_BLEND);
353 glBlendFunc(GL_ONE, GL_ONE);
354 glBlendEquation(GL_MAX);
355 render_world_depth( ortho, camera );
356 glDisable(GL_BLEND);
357 glEnable(GL_DEPTH_TEST);
358
359 /*
360 * TODO: World settings entity
361 */
362 struct ub_world_lighting *winfo = &gpipeline.ub_world_lighting;
363 v4_copy( wrender.plane, winfo->g_water_plane );
364
365 v4f bounds;
366 bounds[0] = world.geo.bbx[0][0];
367 bounds[1] = world.geo.bbx[0][2];
368 bounds[2] = 1.0f/ (world.geo.bbx[1][0]-world.geo.bbx[0][0]);
369 bounds[3] = 1.0f/ (world.geo.bbx[1][2]-world.geo.bbx[0][2]);
370 v4_copy( bounds, winfo->g_depth_bounds );
371
372 winfo->g_water_fog = 0.04f;
373 render_update_lighting_ub();
374
375
376 world.mr_ball.type = k_rb_shape_sphere;
377 world.mr_ball.inf.sphere.radius = 2.0f;
378 v3_copy( (v3f){ 0.0f, 110.0f, 0.0f }, world.mr_ball.co );
379
380 q_identity(world.mr_ball.q);
381 rb_init( &world.mr_ball );
382 }
383
384 static void world_init(void)
385 {
386 vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_colours,
387 &tex_terrain_noise }, 2 );
388
389
390 mdl_header *msky = mdl_load("models/rs_skydome.mdl");
391 mdl_unpack_glmesh( msky, &world.skydome );
392
393 mdl_node *nlower = mdl_node_from_name( msky, "dome_lower" ),
394 *nupper = mdl_node_from_name( msky, "dome_upper" );
395
396 world.dome_lower = *mdl_node_submesh( msky, nlower, 0 );
397 world.dome_upper = *mdl_node_submesh( msky, nupper, 0 );
398 free(msky);
399
400 mdl_header *mcars = mdl_load( "models/rs_cars.mdl" );
401 mdl_unpack_glmesh( mcars, &world.cars );
402 mdl_node *nholden = mdl_node_from_name( mcars, "holden" );
403 world.car_holden = *mdl_node_submesh( mcars, nholden, 0 );
404 free(mcars);
405
406 /*
407 * Setup scene collider
408 */
409 v3_zero( world.rb_geo.co );
410 q_identity( world.rb_geo.q );
411
412 world.rb_geo.type = k_rb_shape_scene;
413 world.rb_geo.inf.scene.pscene = &world.geo;
414 world.rb_geo.is_world = 1;
415 rb_init( &world.rb_geo );
416 }
417
418 static void world_update(void)
419 {
420 #if 0
421 rb_solver_reset();
422 rb_build_manifold_terrain_sphere( &world.mr_ball );
423
424 for( int i=0; i<5; i++ )
425 rb_solve_contacts( rb_contact_buffer, rb_contact_count );
426
427 rb_iter( &world.mr_ball );
428 rb_update_transform( &world.mr_ball );
429 rb_debug( &world.mr_ball, 0 );
430 #endif
431
432 for( int i=0; i<vg_list_size(world.van_man); i++ )
433 {
434 traffic_drive( &world.van_man[i] );
435 traffic_visualize_car( &world.van_man[i] );
436 }
437 }
438
439 /*
440 * Rendering
441 */
442
443 static void bind_terrain_textures(void)
444 {
445 vg_tex2d_bind( &tex_terrain_noise, 0 );
446 vg_tex2d_bind( &tex_terrain_colours, 1 );
447 }
448
449 static void render_world_vb( m4x4f projection, v3f camera )
450 {
451 m4x3f identity_matrix;
452 m4x3_identity( identity_matrix );
453
454 shader_vblend_use();
455 shader_vblend_uTexGarbage(0);
456 shader_vblend_uTexGradients(1);
457 shader_link_standard_ub( _shader_vblend.id, 2 );
458 bind_terrain_textures();
459
460 shader_vblend_uPv( projection );
461 shader_vblend_uMdl( identity_matrix );
462 shader_vblend_uCamera( camera );
463
464 scene_bind( &world.geo );
465 mdl_draw_submesh( &world.sm_geo_vb );
466
467 mesh_bind( &world.cars );
468
469 for( int i=0; i<vg_list_size(world.van_man); i++ )
470 {
471 shader_vblend_uMdl( world.van_man[i].transform );
472 mdl_draw_submesh( &world.car_holden );
473 }
474 }
475
476 static void render_terrain( m4x4f projection, v3f camera )
477 {
478 m4x3f identity_matrix;
479 m4x3_identity( identity_matrix );
480
481 shader_terrain_use();
482 shader_terrain_uTexGarbage(0);
483 shader_terrain_uTexGradients(1);
484 shader_link_standard_ub( _shader_terrain.id, 2 );
485 bind_terrain_textures();
486
487 shader_terrain_uPv( projection );
488 shader_terrain_uMdl( identity_matrix );
489 shader_terrain_uCamera( camera );
490
491 scene_bind( &world.geo );
492 mdl_draw_submesh( &world.sm_geo_std_oob );
493 mdl_draw_submesh( &world.sm_geo_std );
494
495 glDisable(GL_CULL_FACE);
496 scene_bind( &world.foliage );
497 scene_draw( &world.foliage );
498 glEnable(GL_CULL_FACE);
499 }
500
501 static void render_lowerdome( m4x3f camera )
502 {
503 m4x4f projection, full;
504 pipeline_projection( projection, 0.4f, 1000.0f );
505
506 m4x3f inverse;
507 m3x3_transpose( camera, inverse );
508 v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
509 m4x3_expand( inverse, full );
510 m4x4_mul( projection, full, full );
511
512 m4x3f identity_matrix;
513 m4x3_identity( identity_matrix );
514
515 shader_planeinf_use();
516 shader_planeinf_uMdl(identity_matrix);
517 shader_planeinf_uPv(full);
518 shader_planeinf_uCamera(camera[3]);
519 shader_planeinf_uPlane( (v4f){0.0f,1.0f,0.0f, water_height()} );
520
521 mdl_draw_submesh( &world.dome_lower );
522 }
523
524 static void render_sky(m4x3f camera)
525 {
526 m4x4f projection, full;
527 pipeline_projection( projection, 0.4f, 1000.0f );
528
529 m4x3f inverse;
530 m3x3_transpose( camera, inverse );
531 v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
532 m4x3_expand( inverse, full );
533 m4x4_mul( projection, full, full );
534
535 m4x3f identity_matrix;
536 m4x3_identity( identity_matrix );
537
538 shader_sky_use();
539 shader_sky_uMdl(identity_matrix);
540 shader_sky_uPv(full);
541 shader_sky_uTexGarbage(0);
542 shader_sky_uTime( vg_time );
543
544 vg_tex2d_bind( &tex_terrain_noise, 0 );
545
546 glDepthMask( GL_FALSE );
547 glDisable( GL_DEPTH_TEST );
548
549 mesh_bind( &world.skydome );
550 mdl_draw_submesh( &world.dome_upper );
551
552 glEnable( GL_DEPTH_TEST );
553 glDepthMask( GL_TRUE );
554 }
555
556 static void render_world( m4x4f projection, m4x3f camera )
557 {
558 render_sky( camera );
559 render_world_vb( projection, camera[3] );
560 render_terrain( projection, camera[3] );
561 }
562
563 static void render_world_depth( m4x4f projection, m4x3f camera )
564 {
565 m4x3f identity_matrix;
566 m4x3_identity( identity_matrix );
567
568 shader_gpos_use();
569 shader_gpos_uCamera( camera[3] );
570 shader_gpos_uPv( projection );
571 shader_gpos_uMdl( identity_matrix );
572
573 scene_bind( &world.geo );
574 scene_draw( &world.geo );
575
576 #if 0
577 glDisable(GL_CULL_FACE);
578 scene_bind( &world.foliage );
579 scene_draw( &world.foliage );
580 glEnable(GL_CULL_FACE);
581 #endif
582 }
583
584 #endif /* WORLD_H */