+ vg_loader_step( world_render_init, NULL );
+ vg_loader_step( world_sfd_init, NULL );
+ vg_loader_step( world_water_init, NULL );
+ vg_loader_step( world_gates_init, NULL );
+ vg_loader_step( world_routes_init, NULL );
+
+ /* Allocate dynamic world memory arena */
+ u32 max_size = 76*1024*1024;
+ world_global.generic_heap = vg_create_linear_allocator( vg_mem.rtmemory,
+ max_size,
+ VG_MEMORY_SYSTEM );
+}
+
+typedef struct ent_call ent_call;
+struct ent_call{
+ ent_index ent;
+ u32 function;
+ void *data;
+};
+
+VG_STATIC void entity_call( world_instance *world, ent_call *call );
+
+VG_STATIC void ent_volume_call( world_instance *world, ent_call *call )
+{
+ ent_volume *volume = mdl_arritm( &world->ent_volume, call->ent.index );
+ if( !volume->target.type ) return;
+
+ if( call->function == k_ent_function_trigger ){
+ call->ent = volume->target;
+
+ if( volume->type == k_volume_subtype_particle ){
+ v3f co;
+ co[0] = vg_randf()*2.0f-1.0f;
+ co[1] = vg_randf()*2.0f-1.0f;
+ co[2] = vg_randf()*2.0f-1.0f;
+ m4x3_mulv( volume->to_world, co, co );
+
+ call->function = k_ent_function_particle_spawn;
+ call->data = co;
+ entity_call( world, call );
+ }
+ else
+ entity_call( world, call );
+ }
+}
+
+VG_STATIC void ent_audio_call( world_instance *world, ent_call *call )
+{
+ ent_audio *audio = mdl_arritm( &world->ent_audio, call->ent.index );
+
+ v3f sound_co;
+
+ if( call->function == k_ent_function_particle_spawn ){
+ v3_copy( call->data, sound_co );
+ }
+ else if( call->function == k_ent_function_trigger ){
+ v3_copy( audio->transform.co, sound_co );
+ }
+ else
+ vg_fatal_exit_loop( "ent_audio_call (invalid function id)" );
+
+ float chance = vg_randf()*100.0f,
+ bar = 0.0f;
+
+ for( u32 i=0; i<audio->clip_count; i++ ){
+ ent_audio_clip *clip = mdl_arritm( &world->ent_audio_clip,
+ audio->clip_start+i );
+
+ float mod = world->probabilities[ audio->probability_curve ],
+ p = clip->probability * mod;
+
+ bar += p;
+
+ if( chance < bar ){
+
+ audio_lock();
+
+ if( audio->behaviour == k_channel_behaviour_unlimited ){
+ audio_oneshot_3d( &clip->clip, sound_co,
+ audio->transform.s[0],
+ audio->volume );
+ }
+ else if( audio->behaviour == k_channel_behaviour_discard_if_full ){
+ audio_channel *ch =
+ audio_get_group_idle_channel( audio->group,
+ audio->max_channels );
+
+ if( ch ){
+ audio_channel_init( ch, &clip->clip, audio->flags );
+ audio_channel_group( ch, audio->group );
+ audio_channel_set_spacial( ch, sound_co, audio->transform.s[0] );
+ audio_channel_edit_volume( ch, audio->volume, 1 );
+ ch = audio_relinquish_channel( ch );
+ }
+ }
+ else if( audio->behaviour == k_channel_behaviour_crossfade_if_full){
+ audio_channel *ch =
+ audio_get_group_idle_channel( audio->group,
+ audio->max_channels );
+
+ /* group is full */
+ if( !ch ){
+ audio_channel *existing =
+ audio_get_group_first_active_channel( audio->group );
+
+ if( existing ){
+ if( existing->source == &clip->clip ){
+ audio_unlock();
+ return;
+ }
+
+ existing = audio_channel_fadeout( existing, audio->crossfade);
+ }
+
+ ch = audio_get_first_idle_channel();
+ }
+
+ if( ch ){
+ audio_channel_init( ch, &clip->clip, audio->flags );
+ audio_channel_group( ch, audio->group );
+ audio_channel_fadein( ch, audio->crossfade );
+ ch = audio_relinquish_channel( ch );
+ }
+ }
+
+ audio_unlock();
+ return;
+ }
+ }