+ if( audio_channel_finished(s->channels[j]) )
+ s->channels[j] = audio_relinquish_channel( s->channels[j] );
+ else
+ s->usage_count ++;
+ }
+ }
+ }
+ audio_unlock();
+#endif
+}
+
+/*
+ * -----------------------------------------------------------------------------
+ * API implementation
+ * -----------------------------------------------------------------------------
+ */
+
+VG_STATIC void ray_world_get_tri( world_instance *world,
+ ray_hit *hit, v3f tri[3] )
+{
+ for( int i=0; i<3; i++ )
+ v3_copy( world->scene_geo->arrvertices[ hit->tri[i] ].co, tri[i] );
+}
+
+VG_STATIC int ray_world( world_instance *world,
+ v3f pos, v3f dir, ray_hit *hit )
+{
+ return scene_raycast( world->scene_geo, world->geo_bh, pos, dir, hit );
+}
+
+/*
+ * Cast a sphere from a to b and see what time it hits
+ */
+VG_STATIC int spherecast_world( world_instance *world,
+ v3f pa, v3f pb, float r, float *t, v3f n )
+{
+ bh_iter it;
+ bh_iter_init( 0, &it );
+
+ boxf region;
+ box_init_inf( region );
+ box_addpt( region, pa );
+ box_addpt( region, pb );
+
+ v3_add( (v3f){ r, r, r}, region[1], region[1] );
+ v3_add( (v3f){-r,-r,-r}, region[0], region[0] );
+
+ v3f dir;
+ v3_sub( pb, pa, dir );
+
+ v3f dir_inv;
+ dir_inv[0] = 1.0f/dir[0];
+ dir_inv[1] = 1.0f/dir[1];
+ dir_inv[2] = 1.0f/dir[2];
+
+ int hit = -1;
+ float min_t = 1.0f;
+
+ int idx;
+ while( bh_next( world->geo_bh, &it, region, &idx ) )
+ {
+ u32 *ptri = &world->scene_geo->arrindices[ idx*3 ];
+ v3f tri[3];