* Add all triangles from the model, which match the material ID
* applies affine transform to the model
*/
-VG_STATIC void world_add_all_if_material( m4x3f transform, scene_context *scene,
+static void world_add_all_if_material( m4x3f transform, scene_context *scene,
mdl_context *mdl, u32 id )
{
for( u32 i=0; i<mdl_arrcount(&mdl->meshs); i++ ){
* | |
* |________|
*/
-VG_STATIC void world_gen_add_blob( scene_context *scene, ray_hit *hit )
+static void world_gen_add_blob( world_instance *world,
+ scene_context *scene, ray_hit *hit )
{
- world_instance *world = world_loading_instance();
m4x3f transform;
v4f qsurface, qrandom;
v3f axis;
scene_vert *ref = &world->scene_geo.arrvertices[ hit->tri[0] ];
- for( u32 i=0; i<vg_list_size(verts); i++ )
- {
+ for( u32 i=0; i<vg_list_size(verts); i++ ){
scene_vert *pvert = &dst_verts[ i ],
*src = &verts[ i ];
m4x3_mulv( transform, src->co, pvert->co );
- scene_vert_pack_norm( pvert, transform[1] );
+ scene_vert_pack_norm( pvert, transform[1], 0.0f );
v2_copy( ref->uv, pvert->uv );
}
/*
* Sprinkle foliage models over the map on terrain material
*/
-VG_STATIC void world_apply_procedural_foliage( scene_context *scene,
+static void world_apply_procedural_foliage( world_instance *world,
+ scene_context *scene,
struct world_surface *mat )
{
if( vg.quality_profile == k_quality_profile_low )
return;
- world_instance *world = world_loading_instance();
vg_info( "Applying foliage (%u)\n", mat->info.pstr_name );
v3f volume;
ray_hit hit;
hit.dist = INFINITY;
- if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &hit )){
+ if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &hit,
+ k_material_flag_ghosts )){
struct world_surface *m1 = ray_hit_surface( world, &hit );
if((hit.normal[1] > 0.8f) && (m1 == mat) && (hit.pos[1] > 0.0f+10.0f)){
- world_gen_add_blob( scene, &hit );
+ world_gen_add_blob( world, scene, &hit );
count ++;
}
}
vg_info( "%d foliage models added\n", count );
}
+static
+void world_unpack_submesh_dynamic( world_instance *world,
+ scene_context *scene, mdl_submesh *sm ){
+ if( sm->flags & k_submesh_flag_consumed ) return;
+
+ m4x3f identity;
+ m4x3_identity( identity );
+ scene_add_mdl_submesh( scene, &world->meta, sm, identity );
+
+ scene_copy_slice( scene, sm );
+ sm->flags |= k_submesh_flag_consumed;
+}
+
/*
* Create the main meshes for the world
*/
-VG_STATIC void world_gen_generate_meshes(void)
-{
+static void world_gen_generate_meshes( world_instance *world ){
/*
* Compile meshes into the world scenes
*/
- world_instance *world = world_loading_instance();
scene_init( &world->scene_geo, 320000, 1200000 );
u32 buf_size = scene_mem_required( &world->scene_geo );
u8 *buffer = vg_linear_alloc( world->heap, buf_size );
&world->meta, i );
scene_copy_slice( &world->scene_geo, &surf->sm_geo );
+ scene_set_vertex_flags( &world->scene_geo,
+ surf->sm_geo.vertex_start,
+ surf->sm_geo.vertex_count,
+ (u16)(surf->info.flags & 0xffff) );
}
/* compress that bad boy */
&world->scene_no_collide, &world->meta, i );
}
- if( surf->info.flags & k_material_flag_grow_grass )
- world_apply_procedural_foliage( &world->scene_no_collide, surf );
+ if( surf->info.flags & k_material_flag_grow_grass ){
+ world_apply_procedural_foliage( world, &world->scene_no_collide,
+ surf );
+ }
scene_copy_slice( &world->scene_no_collide, &surf->sm_no_collide );
}
+ /* unpack traffic models.. TODO: should we just put all these submeshes in a
+ * dynamic models list? and then the actual entitities point to the
+ * models. we only have 2 types at the moment which need dynamic models but
+ * would make sense to do this when/if we have more.
+ */
for( u32 i=0; i<mdl_arrcount( &world->ent_traffic ); i++ ){
ent_traffic *vehc = mdl_arritm( &world->ent_traffic, i );
for( u32 j=0; j<vehc->submesh_count; j++ ){
mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
vehc->submesh_start+j );
+ world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ }
+ }
- if( sm->flags & k_submesh_flag_consumed ){
- continue;
- }
+ /* unpack challenge models */
+ for( u32 i=0; i<mdl_arrcount( &world->ent_objective ); i++ ){
+ ent_objective *objective = mdl_arritm( &world->ent_objective, i );
+
+ for( u32 j=0; j<objective->submesh_count; j ++ ){
+ mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
+ objective->submesh_start+j );
+ world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ }
+ }
+
+ /* unpack region models */
+ for( u32 i=0; i<mdl_arrcount( &world->ent_region ); i++ ){
+ ent_region *region = mdl_arritm( &world->ent_region, i );
+
+ for( u32 j=0; j<region->submesh_count; j ++ ){
+ mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
+ region->submesh_start+j );
+ world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ }
+ }
- m4x3f identity;
- m4x3_identity( identity );
- scene_add_mdl_submesh( &world->scene_no_collide,
- &world->meta, sm, identity );
+ /* unpack gate models */
+ for( u32 i=0; i<mdl_arrcount( &world->ent_gate ); i++ ){
+ ent_gate *gate = mdl_arritm( &world->ent_gate, i );
- scene_copy_slice( &world->scene_no_collide, sm );
- sm->flags |= k_submesh_flag_consumed;
+ if( !(gate->flags & k_ent_gate_custom_mesh) ) continue;
+
+ for( u32 j=0; j<gate->submesh_count; j ++ ){
+ mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
+ gate->submesh_start+j );
+ world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ }
+ }
+
+ /* unpack prop models */
+ for( u32 i=0; i<mdl_arrcount( &world->ent_prop ); i++ ){
+ ent_prop *prop = mdl_arritm( &world->ent_prop, i );
+
+ for( u32 j=0; j<prop->submesh_count; j ++ ){
+ mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
+ prop->submesh_start+j );
+ world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
}
}
}
/* signed distance function for cone */
-static f32 fsd_cone_infinite( v3f p, v2f c )
-{
+static f32 fsd_cone_infinite( v3f p, v2f c ){
v2f q = { v2_length( (v2f){ p[0], p[2] } ), -p[1] };
float s = vg_maxf( 0.0f, v2_dot( q, c ) );
/*
* Async reciever to buffer light index data
*/
-VG_STATIC void async_upload_light_indices( void *payload, u32 size )
-{
+static void async_upload_light_indices( void *payload, u32 size ){
struct light_indices_upload_info *info = payload;
glGenTextures( 1, &info->world->tex_light_cubes );
/*
* Computes light indices for world
*/
-VG_STATIC void world_gen_compute_light_indices(void)
-{
+static void world_gen_compute_light_indices( world_instance *world ){
/* light cubes */
- world_instance *world = world_loading_instance();
v3f cubes_min, cubes_max;
v3_muls( world->scene_geo.bbx[0], 1.0f/k_world_light_cube_size, cubes_min );
v3_muls( world->scene_geo.bbx[1], 1.0f/k_world_light_cube_size, cubes_max );
v3f closest;
closest_point_aabb( light->transform.co, bbx, closest );
- float dist = v3_dist( closest, light->transform.co ),
- influence = 1.0f/(dist+1.0f);
+ f32 dist2 = v3_dist2( closest, light->transform.co );
- if( dist > light->range )
+ if( dist2 > light->range*light->range )
continue;
+ f32 dist = sqrtf(dist2),
+ influence = 1.0f/(dist+1.0f);
+
if( light->type == k_light_type_spot){
v3f local;
m4x3_mulv( light->inverse_world, center, local );
/*
* Rendering pass needed to complete the world
*/
-VG_STATIC void async_world_postprocess_render( void *payload, u32 _size )
-{
+static void async_world_postprocess( void *payload, u32 _size ){
/* create scene lighting buffer */
- world_instance *world = world_loading_instance();
+ world_instance *world = payload;
u32 size = VG_MAX(mdl_arrcount(&world->ent_light),1) * sizeof(float)*12;
vg_info( "Upload %ubytes (lighting)\n", size );
glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
glBufferSubData( GL_UNIFORM_BUFFER, 0,
sizeof(struct ub_world_lighting), &world->ub_lighting );
+
+ /*
+ * Allocate cubemaps
+ */
+ for( u32 i=0; i<mdl_arrcount(&world->ent_cubemap); i++ ){
+ ent_cubemap *cm = mdl_arritm(&world->ent_cubemap,i);
+
+ glGenTextures( 1, &cm->texture_id );
+ glBindTexture( GL_TEXTURE_CUBE_MAP, cm->texture_id );
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+ for( u32 j=0; j<6; j ++ ) {
+ glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, 0, GL_RGB,
+ WORLD_CUBEMAP_RES, WORLD_CUBEMAP_RES,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
+ }
+
+ glGenFramebuffers( 1, &cm->framebuffer_id );
+ glBindFramebuffer( GL_FRAMEBUFFER, cm->framebuffer_id );
+ glGenRenderbuffers(1, &cm->renderbuffer_id );
+ glBindRenderbuffer( GL_RENDERBUFFER, cm->renderbuffer_id );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,
+ WORLD_CUBEMAP_RES, WORLD_CUBEMAP_RES );
+
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X, cm->texture_id, 0 );
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, cm->renderbuffer_id );
+
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X, cm->texture_id, 0 );
+
+ if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ){
+ vg_error( "Cubemap framebuffer incomplete.\n" );
+ }
+ }
+
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
/* Loads textures from the pack file */
-VG_STATIC void world_gen_load_surfaces(void)
-{
- world_instance *world = world_loading_instance();
+static void world_gen_load_surfaces( world_instance *world ){
vg_info( "Loading textures\n" );
world->texture_count = 0;