* World generation/population. Different to regular loading, since it needs to
* create geometry, apply procedural stuff and save that image to files etc.
*/
-
-#ifndef WORLD_GEN_C
-#define WORLD_GEN_C
-
#include "world.h"
#include "world_gen.h"
#include "world_load.h"
#include "world_volumes.h"
#include "world_gate.h"
+#include <string.h>
/*
* Add all triangles from the model, which match the material ID
* | |
* |________|
*/
-static void world_gen_add_blob( world_instance *world,
+static void world_gen_add_blob( vg_rand *rand, world_instance *world,
scene_context *scene, ray_hit *hit )
{
m4x3f transform;
float angle = v3_dot(hit->normal,(v3f){0.0f,1.0f,0.0f});
q_axis_angle( qsurface, axis, angle );
- q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf64()*VG_TAUf );
+ q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf64(rand)*VG_TAUf );
q_mul( qsurface, qrandom, qsurface );
q_m3x3( qsurface, transform );
v3_copy( hit->pos, transform[3] );
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 );
}
scene_context *scene,
struct world_surface *mat )
{
- if( vg.quality_profile == k_quality_profile_low )
+ if( (vg.quality_profile == k_quality_profile_low) ||
+ (vg.quality_profile == k_quality_profile_min) )
return;
vg_info( "Applying foliage (%u)\n", mat->info.pstr_name );
float area = volume[0]*volume[2];
u32 particles = 0.08f * area;
- /* TODO: Quasirandom? */
vg_info( "Map area: %f. Max particles: %u\n", area, particles );
+ u64 t0 = SDL_GetPerformanceCounter();
+#if 0
for( u32 i=0; i<particles; i++ ){
v3f pos;
v3_mul( volume, (v3f){ vg_randf64(), 1000.0f, vg_randf64() }, pos );
}
}
}
+#else
+
+ vg_rand rand;
+ vg_rand_seed( &rand, 3030 );
+
+ const f32 tile_scale = 16.0f;
+ v2i tiles = { volume[0]/tile_scale, volume[2]/tile_scale };
+
+ u32 per_tile = particles/(tiles[0]*tiles[1]);
+
+ for( i32 x=0; x<tiles[0]; x ++ ){
+ for( i32 z=0; z<tiles[1]; z ++ ){
+ for( u32 i=0; i<per_tile; i ++ ){
+ v3f co = { (f32)x+vg_randf64(&rand), 0, (f32)z+vg_randf64(&rand) };
+ v3_muls( co, tile_scale, co );
+ co[1] = 1000.0f;
+ v3_add( co, world->scene_geo.bbx[0], co );
+
+ ray_hit hit;
+ hit.dist = INFINITY;
+
+ if( ray_world( world, co, (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( &rand, world, scene, &hit );
+ count ++;
+ }
+ }
+
+ }
+ }
+ }
+
+#endif
+
- vg_info( "%d foliage models added\n", count );
+
+ u64 t1 = SDL_GetPerformanceCounter(),
+ utime_blobs = t1-t0,
+ ufreq = SDL_GetPerformanceFrequency();
+ f64 ftime_blobs = ((f64)utime_blobs / (f64)ufreq)*1000.0;
+
+ vg_info( "%d foliage models added. %f%% (%fms)\n", count,
+ 100.0*((f64)count/(f64)particles), ftime_blobs);
}
static
/*
* Create the main meshes for the world
*/
-static void world_gen_generate_meshes( world_instance *world ){
+void world_gen_generate_meshes( world_instance *world )
+{
/*
* Compile meshes into the world scenes
*/
/* need send off the memory to the gpu before we can create the bvh. */
vg_async_stall();
vg_info( "creating bvh\n" );
-
- /* setup spacial mapping and rigidbody */
world->geo_bh = scene_bh_create( world->heap, &world->scene_geo );
- v3_zero( world->rb_geo.rb.co );
- v3_zero( world->rb_geo.rb.v );
- q_identity( world->rb_geo.rb.q );
- v3_zero( world->rb_geo.rb.w );
-
- world->rb_geo.type = k_rb_shape_scene;
- world->rb_geo.inf.scene.bh_scene = world->geo_bh;
- rb_init_object( &world->rb_geo );
-
/*
* Generate scene: non-collidable geometry
* ----------------------------------------------------------------
mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
vehc->submesh_start+j );
world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+ world->surfaces[ sm->material_id ].flags |= WORLD_SURFACE_HAS_TRAFFIC;
}
}
}
}
+ /* 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 );
+ }
+ }
+
/* unpack gate models */
for( u32 i=0; i<mdl_arrcount( &world->ent_gate ); i++ ){
ent_gate *gate = mdl_arritm( &world->ent_gate, i );
for( u32 j=0; j<prop->submesh_count; j ++ ){
mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
prop->submesh_start+j );
+ world->surfaces[ sm->material_id ].flags |= WORLD_SURFACE_HAS_PROPS;
world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
}
}
/*
* Computes light indices for world
*/
-static void world_gen_compute_light_indices( world_instance *world ){
+void world_gen_compute_light_indices( world_instance *world )
+{
/* light cubes */
v3f cubes_min, cubes_max;
v3_muls( world->scene_geo.bbx[0], 1.0f/k_world_light_cube_size, cubes_min );
/*
* Rendering pass needed to complete the world
*/
-static void async_world_postprocess( void *payload, u32 _size ){
+void async_world_postprocess( void *payload, u32 _size )
+{
/* create scene lighting buffer */
world_instance *world = payload;
/*
* Rendering the depth map
*/
- camera ortho;
+ vg_camera ortho;
v3f extent;
v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], extent );
ortho.mtx.p[3][1] = (ft + fb) * -tb;
ortho.mtx.p[3][3] = 1.0f;
m4x3_identity( ortho.transform );
- camera_update_view( &ortho );
- camera_finalize( &ortho );
+ vg_camera_update_view( &ortho );
+ vg_camera_finalize( &ortho );
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
}
/* Loads textures from the pack file */
-static void world_gen_load_surfaces( world_instance *world ){
+void world_gen_load_surfaces( world_instance *world )
+{
vg_info( "Loading textures\n" );
world->texture_count = 0;
world->texture_count = world->meta.textures.count+1;
world->textures = vg_linear_alloc( world->heap,
vg_align8(sizeof(GLuint)*world->texture_count) );
+ world->textures[0] = vg.tex_missing;
- vg_tex2d_replace_with_error( &world->textures[0] );
-
- for( u32 i=0; i<mdl_arrcount(&world->meta.textures); i++ ){
+ for( u32 i=0; i<mdl_arrcount(&world->meta.textures); i++ )
+ {
mdl_texture *tex = mdl_arritm( &world->meta.textures, i );
- if( !tex->file.pack_size ){
+ if( !tex->file.pack_size )
+ {
vg_fatal_error( "World models must have packed textures!" );
}
struct world_surface *errmat = &world->surfaces[0];
memset( errmat, 0, sizeof(struct world_surface) );
- for( u32 i=0; i<mdl_arrcount(&world->meta.materials); i++ ){
- world->surfaces[i+1].info =
- *(mdl_material *)mdl_arritm( &world->meta.materials, i );
+ for( u32 i=0; i<mdl_arrcount(&world->meta.materials); i++ )
+ {
+ struct world_surface *surf = &world->surfaces[i+1];
+ surf->info = *(mdl_material *)mdl_arritm( &world->meta.materials, i );
+ surf->flags = 0;
+
+ if( surf->info.shader == k_shader_water )
+ {
+ struct shader_props_water *props = surf->info.props.compiled;
+ world->ub_lighting.g_water_fog = props->fog_scale;
+ }
+
+ if( surf->info.shader == k_shader_standard_cutout ||
+ surf->info.shader == k_shader_foliage )
+ {
+ struct shader_props_standard *props = surf->info.props.compiled;
+ surf->alpha_tex = props->tex_diffuse;
+ }
+ else
+ surf->alpha_tex = 0;
}
}
-
-#endif /* WORLD_GEN_C */