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