+#ifndef WORLD_H
+#define WORLD_H
+
+#define VG_3D
+#include "vg/vg.h"
+
+#include "scene.h"
+#include "terrain.h"
+#include "render.h"
+#include "water.h"
+
+#include "shaders/standard.h"
+
+static struct gworld
+{
+ scene geo, foliage;
+ submodel sm_road, sm_terrain;
+ glmesh skybox;
+
+ v3f tutorial;
+}
+world;
+
+static void render_world( m4x4f projection, m4x3f camera )
+{
+ render_sky( camera );
+
+ m4x3f identity_matrix;
+ m4x3_identity( identity_matrix );
+
+ render_terrain( projection );
+ scene_bind( &world.geo );
+ scene_draw( &world.geo );
+
+ glDisable(GL_CULL_FACE);
+ scene_bind( &world.foliage );
+ scene_draw( &world.foliage );
+ glEnable(GL_CULL_FACE);
+}
+
+static int ray_world( v3f pos, v3f dir, ray_hit *hit )
+{
+ return bvh_raycast( &world.geo, pos, dir, hit );
+}
+
+static int ray_hit_is_ramp( ray_hit *hit )
+{
+ return hit->tri[0] < world.sm_road.vertex_count;
+}
+
+static void world_init_default(void)
+{
+ /* Setup scene */
+ scene_init( &world.geo );
+ model *mworld = vg_asset_read( "models/mp_dev.mdl" );
+
+ scene_add_model( &world.geo, mworld, submodel_get( mworld, "mp_dev" ),
+ (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
+ scene_copy_slice( &world.geo, &world.sm_road );
+
+ scene_add_model( &world.geo, mworld, submodel_get( mworld, "terrain" ),
+ (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
+ scene_copy_slice( &world.geo, &world.sm_terrain );
+
+ v3_copy( model_marker_get( mworld, "mp_dev_tutorial" )->co, world.tutorial );
+
+
+ /* GATE DEV */
+#if 0
+ {
+ model_marker *ga = model_marker_get(mworld,"gate_a"),
+ *gb = model_marker_get(mworld,"gate_a_recv");
+
+ v3_copy( ga->co, gate_a.co );
+ v3_copy( gb->co, gate_b.co );
+ v4_copy( ga->q, gate_a.q );
+ v4_copy( gb->q, gate_b.q );
+ v2_copy( ga->s, gate_a.dims );
+ v2_copy( gb->s, gate_b.dims );
+
+ gate_a.other = &gate_b;
+ gate_b.other = &gate_a;
+
+ gate_transform_update( &gate_a );
+ gate_transform_update( &gate_b );
+ }
+#endif
+
+ /* WATER DEV */
+ {
+ glmesh surf;
+ submodel *sm = submodel_get(mworld,"mp_dev_water");
+ model_unpack_submodel( mworld, &surf, sm );
+
+ water_init();
+ water_set_surface( &surf, sm->pivot[1] );
+ }
+
+ free( mworld );
+ scene_upload( &world.geo );
+ bvh_create( &world.geo );
+
+
+
+ scene_init( &world.foliage );
+ model *mfoliage = vg_asset_read("models/rs_foliage.mdl");
+
+ v3f volume;
+ v3_sub( world.geo.bbx[1], world.geo.bbx[0], volume );
+ volume[1] = 1.0f;
+
+ m4x3f transform;
+
+ for( int i=0;i<100000;i++ )
+ {
+ v3f pos;
+ v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos );
+ v3_add( pos, world.geo.bbx[0], pos );
+
+ ray_hit hit;
+ hit.dist = INFINITY;
+
+ if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
+ {
+ if( hit.normal[1] > 0.8f && !ray_hit_is_ramp(&hit) )
+ {
+ v4f qsurface, qrandom;
+ v3f axis;
+
+ v3_cross( (v3f){0.0f,1.0f,0.0f}, hit.normal, axis );
+
+ 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_randf()*VG_TAUf );
+ q_mul( qsurface, qrandom, qsurface );
+ q_m3x3( qsurface, transform );
+
+ v3_copy( hit.pos, transform[3] );
+
+ scene_add_foliage( &world.foliage, mfoliage,
+ model_get_submodel( mfoliage, 0 ), transform );
+ }
+ }
+ }
+
+ free( mfoliage );
+ scene_upload( &world.foliage );
+}
+
+#endif /* WORLD_H */