+ for( int j=0; j<3; j++ ){
+ v3_copy( world->scene_geo.arrvertices[ptri[j]].co, tri[j] );
+ box_addpt( box, tri[j] );
+ }
+
+ v3_add( (v3f){ r, r, r}, box[1], box[1] );
+ v3_add( (v3f){-r,-r,-r}, box[0], box[0] );
+
+ if( !ray_aabb1( box, pa, dir_inv, 1.0f ) )
+ continue;
+
+ float t;
+ v3f n1;
+ if( spherecast_triangle( tri, pa, dir, r, &t, n1 ) ){
+ if( t < min_t ){
+ min_t = t;
+ hit = idx;
+ v3_copy( n1, n );
+ }
+ }
+ }
+
+ *t = min_t;
+ return hit;
+}
+
+VG_STATIC
+struct world_surface *world_tri_index_surface( world_instance *world,
+ u32 index )
+{
+ for( int i=1; i<world->surface_count; i++ ){
+ struct world_surface *surf = &world->surfaces[i];
+
+ if( (index >= surf->sm_geo.vertex_start) &&
+ (index < surf->sm_geo.vertex_start+surf->sm_geo.vertex_count ) )
+ {
+ return surf;
+ }
+ }
+
+ return &world->surfaces[0];
+}
+
+VG_STATIC struct world_surface *world_contact_surface( world_instance *world,
+ rb_ct *ct )
+{
+ return world_tri_index_surface( world, ct->element_id );
+}
+
+VG_STATIC struct world_surface *ray_hit_surface( world_instance *world,
+ ray_hit *hit )
+{
+ return world_tri_index_surface( world, hit->tri[0] );
+}
+
+/*
+ * -----------------------------------------------------------------------------
+ * Audio sampling
+ * -----------------------------------------------------------------------------
+ */
+
+VG_STATIC
+enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output);
+VG_STATIC void world_audio_sample_distances( v3f co, int *index, float *value );
+
+#include "audio.h"
+
+/*
+ * Trace out a random point, near the player to try and determine water areas
+ */
+VG_STATIC
+enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output)
+{
+ v3f chance = { (vg_randf()-0.5f) * 30.0f,
+ 8.0f,
+ (vg_randf()-0.5f) * 30.0f };
+
+ v3f pos;
+ v3_add( chance, origin, pos );
+
+ ray_hit contact;
+ contact.dist = vg_minf( 16.0f, pos[1] );
+
+ world_instance *world = get_active_world();
+
+ if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &contact ) ){
+ struct world_surface *mat = ray_hit_surface( world, &contact );
+
+ if( mat->info.surface_prop == k_surface_prop_grass){
+ v3_copy( contact.pos, output );
+ return k_audio_sprite_type_grass;
+ }
+ else{
+ return k_audio_sprite_type_none;
+ }
+ }
+
+ output[0] = pos[0];
+ output[1] = 0.0f;
+ output[2] = pos[2];
+
+ float dist = fabsf(output[1] - origin[1]);
+
+ if( world->water.enabled && dist<=40.0f )
+ return k_audio_sprite_type_water;
+ else
+ return k_audio_sprite_type_none;