3 static int ray_world( v3f pos
, v3f dir
, ray_hit
*hit
);
12 #include "rigidbody.h"
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"
39 teleport_gate gates
[64];
43 traffic_node traffic
[128];
46 traffic_driver van_man
[6];
49 rigidbody temp_rbs
[128];
52 /* Rendering & geometry */
56 mdl_submesh sm_geo_std_oob
, sm_geo_std
, sm_geo_vb
;
58 glmesh skybox
, skydome
;
59 mdl_submesh dome_upper
, dome_lower
;
62 mdl_submesh car_holden
;
74 u32 instance_cache_count
,
79 vg_tex2d tex_terrain_colours
= { .path
= "textures/gradients.qoi",
80 .flags
= VG_TEXTURE_CLAMP
|VG_TEXTURE_NEAREST
};
82 vg_tex2d tex_terrain_noise
= { .path
= "textures/garbage.qoi",
83 .flags
= VG_TEXTURE_NEAREST
};
85 static void ray_world_get_tri( ray_hit
*hit
, v3f tri
[3] )
87 for( int i
=0; i
<3; i
++ )
88 v3_copy( world
.geo
.verts
[ hit
->tri
[i
] ].co
, tri
[i
] );
91 static int ray_world( v3f pos
, v3f dir
, ray_hit
*hit
)
93 return scene_raycast( &world
.geo
, pos
, dir
, hit
);
96 static int ray_hit_is_ramp( ray_hit
*hit
)
98 return hit
->tri
[0] > world
.sm_geo_std_oob
.vertex_count
;
101 static void world_register(void)
103 shader_terrain_register();
104 shader_sky_register();
105 shader_planeinf_register();
106 shader_gpos_register();
107 shader_fscolour_register();
110 static void world_free(void)
115 static void render_world_depth( m4x4f projection
, m4x3f camera
);
117 static void add_all_if_material( m4x3f transform
, scene
*pscene
,
118 mdl_header
*mdl
, u32 id
)
120 for( int i
=0; i
<mdl
->node_count
; i
++ )
122 mdl_node
*pnode
= mdl_node_from_id( mdl
, i
);
124 for( int j
=0; j
<pnode
->submesh_count
; j
++ )
126 mdl_submesh
*sm
= mdl_node_submesh( mdl
, pnode
, j
);
128 if( sm
->material_id
== id
)
131 mdl_node_transform( pnode
, transform2
);
132 m4x3_mul( transform
, transform2
, transform2
);
134 scene_add_submesh( pscene
, mdl
, sm
, transform2
);
138 if( pnode
->classtype
== k_classtype_instance
)
142 u32 instance_id
= pnode
->sub_uid
-1;
143 struct instance_cache
*cache
= &world
.instance_cache
[instance_id
];
144 mdl_header
*mdl2
= cache
->mdl
;
147 mdl_node_transform( pnode
, transform2
);
148 m4x3_mul( transform
, transform2
, transform2
);
150 add_all_if_material( transform2
, pscene
, mdl2
, id
);
156 static void world_apply_foliage(void)
158 scene_init( &world
.foliage
);
159 mdl_header
*mfoliage
= mdl_load("models/rs_foliage.mdl");
162 v3_sub( world
.geo
.bbx
[1], world
.geo
.bbx
[0], volume
);
166 mdl_node
*mblob
= mdl_node_from_name( mfoliage
, "blob" );
167 mdl_submesh
*sm_blob
= mdl_node_submesh( mfoliage
, mblob
, 0 );
169 for( int i
=0;i
<100000;i
++ )
172 v3_mul( volume
, (v3f
){ vg_randf(), 1000.0f
, vg_randf() }, pos
);
174 v3_add( pos
, world
.geo
.bbx
[0], pos
);
179 if( ray_world( pos
, (v3f
){0.0f
,-1.0f
,0.0f
}, &hit
))
181 if( hit
.normal
[1] > 0.8f
&& !ray_hit_is_ramp(&hit
) &&
182 hit
.pos
[1] > water_height()+10.0f
)
184 v4f qsurface
, qrandom
;
187 v3_cross( (v3f
){0.0f
,1.0f
,0.0f
}, hit
.normal
, axis
);
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
);
195 v3_copy( hit
.pos
, transform
[3] );
196 scene_add_submesh( &world
.foliage
, mfoliage
, sm_blob
, transform
);
201 scene_upload( &world
.foliage
);
205 static void world_load(void)
207 mdl_header
*mworld
= mdl_load( "models/mp_dev.mdl" );
209 world
.spawn_count
= 0;
210 world
.gate_count
= 0;
212 world
.traffic_count
= 0;
213 world
.instance_cache
= NULL
;
218 for( int i
=0; i
<mworld
->node_count
; i
++ )
220 mdl_node
*pnode
= mdl_node_from_id( mworld
, i
);
222 if( pnode
->classtype
== k_classtype_none
)
224 else if( pnode
->classtype
== k_classtype_gate
)
226 struct classtype_gate
*entgate
= mdl_get_entdata( mworld
, pnode
);
228 if( entgate
->target
)
230 mdl_node
*pother
= mdl_node_from_id( mworld
, entgate
->target
);
232 teleport_gate
*gate
= &world
.gates
[ world
.gate_count
++ ];
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
);
240 gate_transform_update( gate
);
243 else if( pnode
->classtype
== k_classtype_block
)
245 struct classtype_block
*block
= mdl_get_entdata( mworld
, pnode
);
248 mdl_node_transform( pnode
, transform
);
250 rigidbody
*rb
= &world
.temp_rbs
[ world
.rb_count
++ ];
252 box_copy( block
->bbx
, rb
->bbx
); /* TODO: apply scale */
253 v3_copy( pnode
->co
, rb
->co
);
255 v4_copy( pnode
->q
, rb
->q
);
256 rb_update_transform( rb
);
258 else if( pnode
->classtype
== k_classtype_spawn
)
260 struct respawn_point
*rp
= &world
.spawns
[ world
.spawn_count
++ ];
262 v3_copy( pnode
->co
, rp
->co
);
263 v4_copy( pnode
->q
, rp
->q
);
264 strcpy( rp
->name
, mdl_pstr( mworld
, pnode
->pstr_name
) );
266 else if( pnode
->classtype
== k_classtype_water
)
268 if( wrender
.enabled
)
270 vg_warn( "Multiple water surfaces in level! ('%s')\n",
271 mdl_pstr( mworld
, pnode
->pstr_name
));
275 mdl_submesh
*sm
= mdl_node_submesh( mworld
, pnode
, 0 );
280 mdl_unpack_submesh( mworld
, &surf
, sm
);
282 water_set_surface( &surf
, pnode
->co
[1] );
285 else if( pnode
->classtype
== k_classtype_car_path
)
287 struct classtype_car_path
*p
= mdl_get_entdata( mworld
, pnode
);
288 traffic_node
*tn
= &world
.traffic
[ world
.traffic_count
];
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
);
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
);
300 pnode
->sub_uid
= world
.traffic_count
++;
302 else if( pnode
->classtype
== k_classtype_instance
)
304 struct classtype_instance
*inst
= mdl_get_entdata( mworld
, pnode
);
308 for( int i
=0; i
<world
.instance_cache_count
; i
++ )
310 struct instance_cache
*cache
= &world
.instance_cache
[i
];
311 if( inst
->pstr_file
== cache
->pstr_file
)
314 pnode
->sub_uid
= i
+1;
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
) );
326 struct instance_cache
*cache
=
327 &world
.instance_cache
[world
.instance_cache_count
];
329 const char *filename
= mdl_pstr(mworld
, inst
->pstr_file
);
331 cache
->pstr_file
= inst
->pstr_file
;
332 cache
->mdl
= mdl_load( filename
);
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
);
343 vg_warn( "Failed to cache %s\n", filename
);
349 world
.instance_cache
= buffer_fix( world
.instance_cache
,
350 world
.instance_cache_count
,
351 &world
.instance_cache_cap
,
352 sizeof( struct instance_cache
) );
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
)];
359 * Compile meshes into the world scenes
361 scene_init( &world
.geo
);
365 mat_vertex_blend
= 0;
367 for( int i
=1; i
<mworld
->material_count
; i
++ )
369 mdl_material
*mat
= mdl_material_from_id( mworld
, i
);
370 const char *mat_name
= mdl_pstr( mworld
, mat
->pstr_name
);
372 if( !strcmp( "surf", mat_name
))
374 else if( !strcmp( "surf_oob", mat_name
))
376 else if( !strcmp( "vertex_blend", mat_name
))
377 mat_vertex_blend
= i
;
380 vg_info( "surf %d\noob %d\nvert_blend %d\n", mat_surf
, mat_surf_oob
,
384 m4x3_identity( midentity
);
387 add_all_if_material( midentity
, &world
.geo
, mworld
, mat_surf_oob
);
389 vg_warn( "No OOB surface\n" );
390 scene_copy_slice( &world
.geo
, &world
.sm_geo_std_oob
);
393 add_all_if_material( midentity
, &world
.geo
, mworld
, mat_surf
);
394 scene_copy_slice( &world
.geo
, &world
.sm_geo_std
);
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
);
400 scene_upload( &world
.geo
);
401 scene_bh_create( &world
.geo
);
403 world_apply_foliage();
404 free( world
.instance_cache
);
408 * Rendering the depth map
414 v3_sub( world
.geo
.bbx
[1], world
.geo
.bbx
[0], extent
);
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],
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
;
429 m4x3_identity( camera
);
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
} );
439 glBlendFunc(GL_ONE
, GL_ONE
);
440 glBlendEquation(GL_MAX
);
441 render_world_depth( ortho
, camera
);
443 glEnable(GL_DEPTH_TEST
);
446 * TODO: World settings entity
448 struct ub_world_lighting
*winfo
= &gpipeline
.ub_world_lighting
;
449 v4_copy( wrender
.plane
, winfo
->g_water_plane
);
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
);
458 winfo
->g_water_fog
= 0.04f
;
459 render_update_lighting_ub();
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
);
466 q_identity(world
.mr_ball
.q
);
467 rb_init( &world
.mr_ball
);
470 static void world_init(void)
472 vg_tex2d_init( (vg_tex2d
*[]){ &tex_terrain_colours
,
473 &tex_terrain_noise
}, 2 );
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 );
482 mdl_header
*msky
= mdl_load("models/rs_skydome.mdl");
483 mdl_unpack_glmesh( msky
, &world
.skydome
);
485 mdl_node
*nlower
= mdl_node_from_name( msky
, "dome_lower" ),
486 *nupper
= mdl_node_from_name( msky
, "dome_upper" );
488 world
.dome_lower
= *mdl_node_submesh( msky
, nlower
, 0 );
489 world
.dome_upper
= *mdl_node_submesh( msky
, nupper
, 0 );
493 * Setup scene collider
495 v3_zero( world
.rb_geo
.co
);
496 q_identity( world
.rb_geo
.q
);
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
);
504 static void world_update(void)
508 rb_build_manifold_terrain_sphere( &world
.mr_ball
);
510 for( int i
=0; i
<5; i
++ )
511 rb_solve_contacts( rb_contact_buffer
, rb_contact_count
);
513 rb_iter( &world
.mr_ball
);
514 rb_update_transform( &world
.mr_ball
);
515 rb_debug( &world
.mr_ball
, 0 );
518 for( int i
=0; i
<vg_list_size(world
.van_man
); i
++ )
520 traffic_drive( &world
.van_man
[i
] );
521 traffic_visualize_car( &world
.van_man
[i
] );
529 static void bind_terrain_textures(void)
531 vg_tex2d_bind( &tex_terrain_noise
, 0 );
532 vg_tex2d_bind( &tex_terrain_colours
, 1 );
535 static void render_world_vb( m4x4f projection
, v3f camera
)
537 m4x3f identity_matrix
;
538 m4x3_identity( identity_matrix
);
541 shader_vblend_uTexGarbage(0);
542 shader_vblend_uTexGradients(1);
543 shader_link_standard_ub( _shader_vblend
.id
, 2 );
544 bind_terrain_textures();
546 shader_vblend_uPv( projection
);
547 shader_vblend_uMdl( identity_matrix
);
548 shader_vblend_uCamera( camera
);
550 scene_bind( &world
.geo
);
551 mdl_draw_submesh( &world
.sm_geo_vb
);
553 mesh_bind( &world
.cars
);
555 for( int i
=0; i
<vg_list_size(world
.van_man
); i
++ )
557 shader_vblend_uMdl( world
.van_man
[i
].transform
);
558 mdl_draw_submesh( &world
.car_holden
);
562 static void render_terrain( m4x4f projection
, v3f camera
)
564 m4x3f identity_matrix
;
565 m4x3_identity( identity_matrix
);
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();
573 shader_terrain_uPv( projection
);
574 shader_terrain_uMdl( identity_matrix
);
575 shader_terrain_uCamera( camera
);
577 scene_bind( &world
.geo
);
578 mdl_draw_submesh( &world
.sm_geo_std_oob
);
579 mdl_draw_submesh( &world
.sm_geo_std
);
581 glDisable(GL_CULL_FACE
);
582 scene_bind( &world
.foliage
);
583 scene_draw( &world
.foliage
);
584 glEnable(GL_CULL_FACE
);
587 static void render_lowerdome( m4x3f camera
)
589 m4x4f projection
, full
;
590 pipeline_projection( projection
, 0.4f
, 1000.0f
);
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
);
598 m4x3f identity_matrix
;
599 m4x3_identity( identity_matrix
);
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()} );
607 mdl_draw_submesh( &world
.dome_lower
);
610 static void render_sky(m4x3f camera
)
612 m4x4f projection
, full
;
613 pipeline_projection( projection
, 0.4f
, 1000.0f
);
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
);
621 m4x3f identity_matrix
;
622 m4x3_identity( identity_matrix
);
625 shader_sky_uMdl(identity_matrix
);
626 shader_sky_uPv(full
);
627 shader_sky_uTexGarbage(0);
628 shader_sky_uTime( vg_time
);
630 vg_tex2d_bind( &tex_terrain_noise
, 0 );
632 glDepthMask( GL_FALSE
);
633 glDisable( GL_DEPTH_TEST
);
635 mesh_bind( &world
.skydome
);
636 mdl_draw_submesh( &world
.dome_upper
);
638 glEnable( GL_DEPTH_TEST
);
639 glDepthMask( GL_TRUE
);
642 static void render_world( m4x4f projection
, m4x3f camera
)
644 render_sky( camera
);
645 render_world_vb( projection
, camera
[3] );
646 render_terrain( projection
, camera
[3] );
649 static void render_world_depth( m4x4f projection
, m4x3f camera
)
651 m4x3f identity_matrix
;
652 m4x3_identity( identity_matrix
);
655 shader_gpos_uCamera( camera
[3] );
656 shader_gpos_uPv( projection
);
657 shader_gpos_uMdl( identity_matrix
);
659 scene_bind( &world
.geo
);
660 scene_draw( &world
.geo
);
663 glDisable(GL_CULL_FACE
);
664 scene_bind( &world
.foliage
);
665 scene_draw( &world
.foliage
);
666 glEnable(GL_CULL_FACE
);