v3f last;
v3_zero(last);
+ world_instance *world = get_active_world();
+
for( int i=0; i<sample_count; i++ )
{
v3f dir;
ray_hit contact;
contact.dist = 15.0f;
- if( ray_world( origin, dir, &contact ) )
+ if( ray_world( world, origin, dir, &contact ) )
{
d += contact.dist;
ray_hit contact;
contact.dist = vg_minf( 16.0f, pos[1] );
+ world_instance *world = get_active_world();
- if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &contact ) )
+ if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &contact ) )
{
- struct world_material *mat = ray_hit_material( &contact );
+ struct world_material *mat = ray_hit_material( world, &contact );
if( mat->info.surface_prop == k_surface_prop_grass)
{
output[1] = 0.0f;
output[2] = pos[2];
- if( world.water.enabled )
+ if( world->water.enabled )
return k_audio_sprite_type_water;
else
return k_audio_sprite_type_none;
#}
#}
+# Classtype 201
+#
+# Purpose: lighting settings for world
+#
+class classtype_lighting_info(Structure):
+#{
+ _pack_ = 1
+ _fields_ = [("colours",(c_float*3)*3),
+ ("directions",(c_float*2)*3),
+ ("states",c_uint32*3),
+ ("shadow_spread",c_float),
+ ("shadow_length",c_float),
+ ("ambient",c_float*3)]
+
+ def encode_obj(_, node, node_def):
+ #{
+ node.classtype = 201
+
+ # TODO
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ pass
+ #}
+#}
+
class classtype_spawn_link(Structure):
#{
_pack_ = 1
shader_model_character_view_uTexMain( 0 );
shader_model_character_view_uCamera( cam->transform[3] );
shader_model_character_view_uPv( cam->mtx.pv );
- shader_link_standard_ub( _shader_model_character_view.id, 2 );
+
+ world_instance *world = get_active_world();
+ world_link_lighting_ub( world, _shader_model_character_view.id, 2 );
+
glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms,
player->playeravatar->sk.bone_count,
0,
*/
VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
{
+ world_instance *world = get_active_world();
+
int run_sim = 0;
ragdoll_frame ++;
rb_solver_reset();
for( int i=0; i<rd->part_count; i ++ )
- rb_collide( &rd->parts[i].rb, &world.rb_geo );
+ rb_collide( &rd->parts[i].rb, &world->rb_geo );
/*
* COLLISION DETECTION
m4x3f mtx, rb_sphere *sphere,
rb_ct *man )
{
+ world_instance *world = get_active_world();
+
int len = 0;
- len = rb_sphere__scene( mtx, sphere, NULL, &world.rb_geo.inf.scene, man );
+ len = rb_sphere__scene( mtx, sphere, NULL, &world->rb_geo.inf.scene, man );
for( int i=0; i<len; i++ )
{
v3f pos, v3f dir, float r,
struct grind_info *inf )
{
+ world_instance *world = get_active_world();
+
v4f plane;
v3_copy( dir, plane );
v3_normalize( plane );
v3_cross( plane, player->basis[1], support_axis );
v3_normalize( support_axis );
- while( bh_next( world.geo_bh, &it, box, &idx ) )
+ while( bh_next( world->geo_bh, &it, box, &idx ) )
{
- u32 *ptri = &world.scene_geo->arrindices[ idx*3 ];
+ u32 *ptri = &world->scene_geo->arrindices[ idx*3 ];
v3f tri[3];
- struct world_material *mat = world_tri_index_material(ptri[0]);
+ struct world_material *mat = world_tri_index_material(world,ptri[0]);
if( !(mat->info.flags & k_material_flag_skate_surface) )
continue;
for( int j=0; j<3; j++ )
- v3_copy( world.scene_geo->arrvertices[ptri[j]].co, tri[j] );
+ v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] );
for( int j=0; j<3; j++ )
{
VG_STATIC
void player__approximate_best_trajectory( player_instance *player )
{
+ world_instance *world = get_active_world();
+
struct player_skate *s = &player->_skate;
float k_trace_delta = k_rb_delta * 10.0f;
if( !grind_located && (launch_vy - gravity*t < 0.0f) )
{
v3f closest;
- if( bh_closest_point( world.geo_bh, co1, closest, 1.0f ) != -1 )
+ if( bh_closest_point( world->geo_bh, co1, closest, 1.0f ) != -1 )
{
v3f ve;
v3_copy( launch_v, ve );
float t1;
v3f n;
- int idx = spherecast_world( co0, co1, k_board_radius, &t1, n );
+ int idx = spherecast_world( world, co0, co1, k_board_radius, &t1, n );
if( idx != -1 )
{
v3f co;
p->score = -v3_dot( ve, p->n );
p->land_dist = t + k_trace_delta * t1;
- u32 vert_index = world.scene_geo->arrindices[ idx*3 ];
- struct world_material *mat = world_tri_index_material( vert_index );
+ u32 vert_index = world->scene_geo->arrindices[ idx*3 ];
+ struct world_material *mat =
+ world_tri_index_material( world, vert_index );
/* Bias prediction towords ramps */
if( !(mat->info.flags & k_material_flag_skate_surface) )
v3f surface_normal, v3f axel_dir )
{
struct player_skate *s = &player->_skate;
+ world_instance *world = get_active_world();
v3f truck, left, right;
m4x3_mulv( player->rb.to_world, ra, truck );
v3_muladds( left, player->rb.to_world[1], k_board_radius, left );
ray_l.dist = 2.1f * k_board_radius;
- res_l = ray_world( left, dir, &ray_l );
+ res_l = ray_world( world, left, dir, &ray_l );
if( res_l )
break;
v3_muladds( right, player->rb.to_world[1], k_board_radius, right );
ray_r.dist = 2.1f * k_board_radius;
- res_r = ray_world( right, dir, &ray_r );
+ res_r = ray_world( world, right, dir, &ray_r );
if( res_r )
break;
{
/* fallback: use the closes point to the trucks */
v3f closest;
- int idx = bh_closest_point( world.geo_bh, midpoint, closest, 0.1f );
+ int idx = bh_closest_point( world->geo_bh, midpoint, closest, 0.1f );
if( idx != -1 )
{
- u32 *tri = &world.scene_geo->arrindices[ idx * 3 ];
+ u32 *tri = &world->scene_geo->arrindices[ idx * 3 ];
v3f verts[3];
for( int j=0; j<3; j++ )
- v3_copy( world.scene_geo->arrvertices[ tri[j] ].co, verts[j] );
+ v3_copy( world->scene_geo->arrvertices[ tri[j] ].co, verts[j] );
v3f vert0, vert1, n;
v3_sub( verts[1], verts[0], vert0 );
v3_muls( dir, 1.0f/ray.dist, dir );
ray.dist -= 0.025f;
- if( ray_world( origin, dir, &ray ) )
+ if( ray_world( get_active_world(), origin, dir, &ray ) )
return 0;
return 1;
VG_STATIC void player__skate_update( player_instance *player )
{
struct player_skate *s = &player->_skate;
+ world_instance *world = get_active_world();
+
v3_copy( player->rb.co, s->state.prev_pos );
s->state.activity_prev = s->state.activity;
v3f n;
float cast_radius = wheels[i].radius - k_penetration_slop * 2.0f;
- if( spherecast_world( current, future, cast_radius, &t, n ) != -1)
+ if( spherecast_world( world, current, future, cast_radius, &t, n ) != -1)
max_time = vg_minf( max_time, t * s->substep );
}
float t;
v3f n;
if( (v3_dist2( head_wp0, head_wp1 ) > 0.001f) &&
- (spherecast_world( head_wp0, head_wp1, 0.2f, &t, n ) != -1) )
+ (spherecast_world( world, head_wp0, head_wp1, 0.2f, &t, n ) != -1) )
{
v3_lerp( start_co, player->rb.co, t, player->rb.co );
rb_update_transform( &player->rb );
rb_ct *cman = &manifold[manifold_len];
- int l = rb_capsule__scene( mtx, &capsule, NULL, &world.rb_geo.inf.scene,
+ int l = rb_capsule__scene( mtx, &capsule, NULL, &world->rb_geo.inf.scene,
cman );
/* weld joints */
vg_line_pt3( s->state.cog, 0.02f, VG__WHITE );
teleport_gate *gate;
- if( (gate = world_intersect_gates( player->rb.co, s->state.prev_pos )) )
+ if( (gate = world_intersect_gates(world, player->rb.co, s->state.prev_pos)) )
{
m4x3_mulv( gate->transport, player->rb.co, player->rb.co );
m3x3_mulv( gate->transport, player->rb.v, player->rb.v );
VG_STATIC int player_walk_scan_for_drop_in( player_instance *player )
{
struct player_walk *w = &player->_walk;
+ world_instance *world = get_active_world();
v3f dir, center;
q_mulv( player->rb.q, (v3f){0.0f,0.0f,1.0f}, dir );
ray_hit *ray = &samples[ sample_count ];
ray->dist = 2.0f;
- if( ray_world( pos, ray_dir, ray ) )
+ if( ray_world( world, pos, ray_dir, ray ) )
{
vg_line( pos, ray->pos, VG__RED );
vg_line_pt3( ray->pos, 0.025f, VG__BLACK );
ray_hit ray;
ray.dist = k_board_length*2.0f + 0.6f;
- if( ray_world( va, v0, &ray ) )
+ if( ray_world( world, va, v0, &ray ) )
{
vg_line( va, vb, VG__RED );
vg_line_pt3( ray.pos, 0.1f, VG__RED );
}
v3_muls( v0, -1.0f, v0 );
- if( ray_world( vb, v0, &ray ) )
+ if( ray_world( world, vb, v0, &ray ) )
{
vg_line( va, vb, VG__RED );
vg_line_pt3( ray.pos, 0.1f, VG__RED );
/*
* Collision detection
*/
+ world_instance *world = get_active_world();
+
len = rb_capsule__scene( mtx, &w->collider, NULL,
- &world.rb_geo.inf.scene, manifold );
+ &world->rb_geo.inf.scene, manifold );
rb_manifold_filter_coplanar( manifold, len, 0.01f );
len = rb_manifold_apply_filtered( manifold, len );
{
player_friction( player->rb.v );
- struct world_material *surface_mat = world_contact_material(manifold);
+ struct world_material *surface_mat =
+ world_contact_material( world, manifold);
w->surface = surface_mat->info.surface_prop;
}
}
float t, sr = w->collider.radius-0.04f;
v3f n;
- if( spherecast_world( lwr_prev, lwr_now, sr, &t, n ) != -1 )
+ if( spherecast_world( world, lwr_prev, lwr_now, sr, &t, n ) != -1 )
{
v3_lerp( lwr_prev, lwr_now, vg_maxf(0.01f,t), player->rb.co );
player->rb.co[1] -= w->collider.radius;
}
teleport_gate *gate;
- if( (gate = world_intersect_gates( player->rb.co, w->state.prev_pos )) )
+ if( (gate = world_intersect_gates(world, player->rb.co, w->state.prev_pos)) )
{
m4x3_mulv( gate->transport, player->rb.co, player->rb.co );
m3x3_mulv( gate->transport, player->rb.v, player->rb.v );
#include "common.h"
#include "model.h"
#include "camera.h"
+#include "world.h"
#include "shaders/blit.h"
#include "shaders/blitblur.h"
#include "shaders/vblend.h"
#endif
-VG_STATIC void render_water_texture( camera *cam );
-VG_STATIC void render_water_surface( camera *cam );
-VG_STATIC void render_world( camera *cam );
-VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id );
-VG_STATIC void render_world_depth( camera *cam );
+VG_STATIC void render_water_texture( world_instance *world, camera *cam );
+VG_STATIC void render_water_surface( world_instance *world, camera *cam );
+VG_STATIC void render_world( world_instance *world, camera *cam );
+VG_STATIC void render_world_depth( world_instance *world, camera *cam );
#ifndef RENDER_H
#define RENDER_H
glmesh fsquad;
framebuffer *fb_main,
- *fb_heightmap,
*fb_water_reflection,
*fb_water_beneath;
- /* STD140 */
- struct ub_world_lighting
- {
- /* v3f (padded) */
- v4f g_light_colours[3],
- g_light_directions[3],
- g_ambient_colour;
-
- v4f g_water_plane,
- g_depth_bounds;
-
- float g_water_fog;
- int g_light_count;
- int g_light_preview;
- int g_shadow_samples;
-
- v4f g_point_light_positions[32];
- v4f g_point_light_colours[32];
- }
- ub_world_lighting;
-
struct light_widget
{
int enabled;
widgets[3];
float shadow_spread, shadow_length;
- GLuint ubo_world_lighting,
- ubo_world;
int ready;
}
},
.shadow_spread = 0.65f,
.shadow_length = 9.50f,
-
- .ub_world_lighting =
- {
- .g_ambient_colour = { 0.09f, 0.03f, 0.07f }
- }
};
struct framebuffer
}
}
},
- {
- /*
- * A ortho projection of the world, used for shadows and ocean colouring.
- * Note: it does not have a render buffer attachement because it's
- * intended to be drawn to in a MAX blending mode
- */
- "heightmap",
- .link = &gpipeline.fb_heightmap,
- .fixed_w = 1024,
- .fixed_h = 1024,
-
- .attachments =
- {
- {
- "depth", k_framebuffer_attachment_type_colour,
-
- .internalformat = GL_R32F,
- .format = GL_RED,
- .type = GL_FLOAT,
- .attachment = GL_COLOR_ATTACHMENT0
- }
- }
- },
{
/*
* Second rendered view from the perspective of the water reflection
/*
* Shaders
*/
-VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id )
-{
- GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );
- glUniformBlockBinding( shader, idx, 0 );
-
- render_fb_bind_texture( gpipeline.fb_heightmap, 0, texture_id );
- glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id );
-}
-
-VG_STATIC void render_update_lighting_ub(void)
-{
- struct ub_world_lighting *winf = &gpipeline.ub_world_lighting;
- int c = 0;
-
- for( int i=0; i<3; i++ )
- {
- struct light_widget *lw = &gpipeline.widgets[i];
-
- if( lw->enabled )
- {
- float pitch = lw->dir[0],
- yaw = lw->dir[1],
- xz = cosf( pitch );
-
- v3_copy( (v3f){ xz*cosf(yaw), sinf(pitch), xz*sinf(yaw) },
- winf->g_light_directions[c] );
- v3_copy( lw->colour, winf->g_light_colours[c] );
-
- c ++;
- }
- }
-
- winf->g_light_count = c;
- winf->g_light_directions[0][3] = gpipeline.shadow_length;
- winf->g_light_colours[0][3] = gpipeline.shadow_spread;
-
- if( vg.quality_profile == k_quality_profile_low )
- winf->g_shadow_samples = 0;
- else
- winf->g_shadow_samples = 8;
-
- glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
- glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting),
- &gpipeline.ub_world_lighting );
-}
#define FB_FORMAT_STR( E ) { E, #E },
VG_CHECK_GL_ERR();
}
-VG_STATIC void render_init_uniform_buffers(void)
-{
- vg_info( "[render] Allocate uniform buffer\n" );
-
- glGenBuffers( 1, &gpipeline.ubo_world_lighting );
- glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
- glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting),
- NULL, GL_DYNAMIC_DRAW );
-
- render_update_lighting_ub();
- glBindBufferBase( GL_UNIFORM_BUFFER, 0, gpipeline.ubo_world_lighting );
-
- VG_CHECK_GL_ERR();
-}
-
VG_STATIC void render_init(void)
{
shader_blit_register();
}
render_init_fs_quad();
- render_init_uniform_buffers();
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
gpipeline.ready = 1;
VG_STATIC scene *scene_fix( void *lin_alloc, scene *pscene )
{
/* FIXME: Why is this disabled? */
-
return pscene;
+
u32 vertex_count = pscene->vertex_count,
indice_count = pscene->indice_count,
vertex_length = vertex_count * sizeof(scene_vert),
index_length = indice_count * sizeof(u32),
- tot_size = sizeof(scene) + vertex_length + index_length;
+ tot_size = sizeof(scene) + vertex_length + index_length;
/* copy down index data */
void *dst_indices = pscene->arrvertices + vertex_length;
#include "audio.h"
#include "world.h"
-#if 0
-#include "player.h"
-#else
+
#include "player.h"
VG_STATIC player_instance localplayer;
+VG_STATIC struct player_avatar localplayer_avatar;
+VG_STATIC glmesh localplayer_meshes[3];
+vg_tex2d localplayer_texture = { .path = "textures/ch_gradient.qoi" };
-#if 0
-#include "player_interface.h"
-#include "player_device_walk.h"
-#include "player_device_skate.h"
-#include "player_device_dead.h"
-#include "player_model.h"
-/* temp */
-VG_STATIC player_interface localplayer;
-#endif
-VG_STATIC struct player_avatar localplayer_avatar;
-VG_STATIC glmesh localplayer_meshes[3];
-vg_tex2d localplayer_texture = { .path = "textures/ch_gradient.qoi" };
-
-#endif
#include "network.h"
{
struct respawn_point *rp = NULL, *r;
+ world_instance *world = get_active_world();
+
if( argc == 1 )
{
- for( int i=0; i<world.spawn_count; i++ )
+ for( int i=0; i<world->spawn_count; i++ )
{
- r = &world.spawns[i];
+ r = &world->spawns[i];
if( !strcmp( r->name, argv[0] ) )
{
rp = r;
{
float min_dist = INFINITY;
- for( int i=0; i<world.spawn_count; i++ )
+ for( int i=0; i<world->spawn_count; i++ )
{
- r = &world.spawns[i];
+ r = &world->spawns[i];
float d = v3_dist2( r->co, localplayer.rb.co );
vg_info( "Dist %s : %f\n", r->name, d );
{
vg_error( "No spawn found\n" );
- if( !world.spawn_count )
+ if( !world->spawn_count )
return 0;
- rp = &world.spawns[0];
+ rp = &world->spawns[0];
}
player__spawn( &localplayer, rp );
world_audio_init();
/* 'systems' are completely loaded now */
+#if 0
strcpy( world.world_name, "maps/mp_mtzero.mdl" );
strcpy( world.world_name, "maps/mp_gridmap.mdl" );
- world_load();
+#endif
+
+ /* load home world */
+ world_load( &world_global.worlds[0], "maps/mp_home.mdl" );
vg_console_load_autos();
}
#endif
player__pre_update( &localplayer );
- world_update( localplayer.rb.co );
+ world_update( get_active_world(), localplayer.rb.co );
}
}
/* Draw world */
glEnable( GL_DEPTH_TEST );
- render_world( &main_camera );
-
+ world_instance *world = get_active_world();
+ render_world( world, &main_camera );
int player_transparent = 1,
player_draw = 1;
if( !player_transparent && player_draw )
player__render( &main_camera, &localplayer );
- render_water_texture( &main_camera );
+
+ render_water_texture( world, &main_camera );
render_fb_bind( gpipeline.fb_main );
- render_water_surface( &main_camera );
- render_world_gates( &main_camera );
+ render_water_surface( world, &main_camera );
+ render_world_gates( world, &main_camera );
if( player_transparent && player_draw )
render_player_transparent();
VG_STATIC void vg_ui(void)
{
player__im_gui( &localplayer );
+ world_instance *world = get_active_world();
#if 0
menu_crap_ui();
#endif
+#if 0
if( cl_light_edit )
{
vg_uictx.cursor[0] = 10;
render_update_lighting_ub();
}
+#endif
//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
if( cl_ui )
{
- render_world_routes_ui();
+ render_world_routes_ui( world );
}
//glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
#include "common.h"
-VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit );
-
#ifndef WORLD_H
#define WORLD_H
+typedef struct world_instance world_instance;
+
#include "vg/vg_loader.h"
#include "network.h"
k_geo_type_water = 2
};
-VG_STATIC struct gworld
+struct world_instance
{
- /*
- * Allocated as system memory
- * --------------------------------------------------------------------------
+ /* This is a small flag we use to changelevel.
+ * It will not be cleared until all sounds stop playing
*/
- /* rendering */
- glmesh skydome;
- mdl_submesh dome_upper, dome_lower;
-
- glmesh mesh_gate_surface;
+ /* Fixed items
+ * -------------------------------------------------------
+ */
- double sky_time, sky_rate, sky_target_rate;
+ char world_name[ 64 ];
- /* water rendering */
struct
{
- struct framebuffer fbreflect, fbdepth;
-
boxf depthbounds;
int depth_computed;
}
water;
- /* split flap display */
- struct
+ /* STD140 */
+ struct ub_world_lighting
{
- mdl_submesh *sm_module, *sm_card;
- glmesh mesh_base, mesh_display;
+ /* v3f (padded) */
+ v4f g_light_colours[3],
+ g_light_directions[3],
+ g_ambient_colour;
- u32 w, h;
- float *buffer;
- }
- sfd;
+ v4f g_water_plane,
+ g_depth_bounds;
- /* timing bars, fixed maximum amount */
- struct route_ui_bar
- {
- GLuint vao, vbo, ebo;
-
- u32 indices_head;
- u32 vertex_head;
+ float g_water_fog;
+ int g_light_count;
+ int g_light_preview;
+ int g_shadow_samples;
- struct route_ui_segment
- {
- float length;
- u32 vertex_start, vertex_count,
- index_start, index_count, notches;
- }
- segments[k_max_ui_segments];
-
- u32 segment_start, segment_count, fade_start, fade_count;
- double fade_timer_start;
- float xpos;
+ v4f g_point_light_positions[32];
+ v4f g_point_light_colours[32];
}
- ui_bars[16];
-
- v3f render_gate_pos;
- int active_route_board;
- int in_trigger;
+ ub_lighting;
+ GLuint ubo_lighting;
+ int ubo_bind_point;
- /* This is a small flag we use to changelevel.
- * It will not be cleared until all sounds stop playing
- */
- int switching_to_new_world;
- char world_name[ 64 ];
+ struct framebuffer heightmap;
/*
* Dynamically allocated when world_load is called.
* (world_gen.h)
* --------------------------------------------------------------------------
*/
- void *dynamic_vgl,
- *audio_vgl; /* sub buffer of the audio buffer */
-
/*
* Main world .mdl
*/
* ----------------------------------------------------
*/
- u32 active_gate,
- current_run_version;
- double time, rewind_from, rewind_to, last_use;
-
/* world geometry */
scene *scene_geo,
*scene_no_collide,
/* graphics */
glmesh mesh_route_lines;
-
glmesh mesh_geo,
mesh_no_collide,
mesh_water;
- mdl_submesh sm_foliage_main;
rigidbody rb_geo; /* todo.. ... */
+};
+
+VG_STATIC struct world_global
+{
+ /*
+ * Allocated as system memory
+ * --------------------------------------------------------------------------
+ */
+ void *generic_heap,
+ *audio_heap; /* sub buffer of the audio buffer */
+
+ /* rendering */
+ glmesh skydome;
+ mdl_submesh dome_upper, dome_lower;
+
+ glmesh mesh_gate_surface;
+
+ double sky_time, sky_rate, sky_target_rate;
+
+ /* gates, TODO: active_gate should also know which instance */
+ u32 active_gate,
+ current_run_version;
+ double time, rewind_from, rewind_to, last_use;
+
+ /* water rendering */
+ struct
+ {
+ struct framebuffer fbreflect, fbdepth;
+ }
+ water;
+
+ /* split flap display */
+ struct
+ {
+ mdl_submesh *sm_module, *sm_card;
+ glmesh mesh_base, mesh_display;
+
+ u32 w, h;
+ float *buffer;
+ }
+ sfd;
+
+ /* timing bars, fixed maximum amount */
+ struct route_ui_bar
+ {
+ GLuint vao, vbo, ebo;
+
+ u32 indices_head;
+ u32 vertex_head;
+
+ struct route_ui_segment
+ {
+ float length;
+ u32 vertex_start, vertex_count,
+ index_start, index_count, notches;
+ }
+ segments[k_max_ui_segments];
+
+ u32 segment_start, segment_count, fade_start, fade_count;
+ double fade_timer_start;
+ float xpos;
+ }
+ ui_bars[16];
+
+ v3f render_gate_pos;
+ int active_route_board;
+ int in_trigger;
+
+ int switching_to_new_world;
+
+ world_instance worlds[4];
+ u32 world_count;
+ u32 active_world;
}
-world;
+world_global;
+VG_STATIC world_instance *get_active_world( void )
+{
+ return &world_global.worlds[ world_global.active_world ];
+}
/*
* API
*/
-VG_STATIC int ray_hit_is_ramp( ray_hit *hit );
-VG_STATIC struct world_material *ray_hit_material( ray_hit *hit );
-VG_STATIC void ray_world_get_tri( ray_hit *hit, v3f tri[3] );
-VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit );
+VG_STATIC
+int ray_hit_is_ramp( world_instance *world, ray_hit *hit );
+
+VG_STATIC
+struct world_material *ray_hit_material( world_instance *world, ray_hit *hit );
+
+VG_STATIC
+void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] );
+
+VG_STATIC
+int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit );
/*
* Submodules
VG_STATIC int world_stop_sound( int argc, const char *argv[] )
{
+ world_instance *world = get_active_world();
+
/*
* None of our world audio runs as one shots, they always have a player.
* Therefore it is safe to delete clip data after the players are
* disconnected
*/
audio_lock();
- for( int i=0; i<world.audio_things_count; i++ )
+ for( int i=0; i<world->audio_things_count; i++ )
{
- struct world_audio_thing *at = &world.audio_things[i];
+ struct world_audio_thing *at = &world->audio_things[i];
if( audio_player_is_playing( &at->player ) )
{
VG_STATIC int world_change_world( int argc, const char *argv[] )
{
+#if 0
+ world_instance *world = get_active_world();
+
if( argc == 0 )
{
vg_info( "%s\n", world.world_name );
world.switching_to_new_world = 1;
world_stop_sound( 0, NULL );
}
+#endif
return 0;
}
VG_STATIC void world_init(void)
{
+#if 0
vg_var_push( (struct vg_var){
.name = "water_enable",
.data = &world.water.enabled,
.opt_i32 = { .min=0, .max=1, .clamp=1 },
.persistent = 0
});
+#endif
vg_function_push( (struct vg_cmd)
{
.function = world_change_world
});
- world.sky_rate = 1.0;
- world.sky_target_rate = 1.0;
+ world_global.sky_rate = 1.0;
+ world_global.sky_target_rate = 1.0;
shader_scene_standard_register();
shader_scene_standard_alphatest_register();
mdl_context *msky = mdl_load_full( vg_mem.scratch, "models/rs_skydome.mdl" );
mdl_node *nupper = mdl_node_from_name( msky, "dome_complete" );
- world.dome_upper = *mdl_node_submesh( msky, nupper, 0 );
+ world_global.dome_upper = *mdl_node_submesh( msky, nupper, 0 );
vg_acquire_thread_sync();
{
- mdl_unpack_glmesh( msky, &world.skydome );
+ mdl_unpack_glmesh( msky, &world_global.skydome );
}
vg_release_thread_sync();
/* Allocate dynamic world memory arena */
u32 max_size = 76*1024*1024;
- world.dynamic_vgl = vg_create_linear_allocator( vg_mem.rtmemory, max_size,
- VG_MEMORY_SYSTEM );
+ world_global.generic_heap = vg_create_linear_allocator( vg_mem.rtmemory,
+ max_size,
+ VG_MEMORY_SYSTEM );
}
VG_STATIC void world_audio_init(void)
u32 size = vg_linear_remaining( vg_audio.audio_pool )
- sizeof(vg_linear_allocator);
- world.audio_vgl = vg_create_linear_allocator( vg_audio.audio_pool,
- size, VG_MEMORY_SYSTEM );
+ world_global.audio_heap = vg_create_linear_allocator( vg_audio.audio_pool,
+ size,
+ VG_MEMORY_SYSTEM );
}
-VG_STATIC void world_trigger_achievement( u32 uid )
+VG_STATIC void world_trigger_achievement( world_instance *world, u32 uid )
{
- struct logic_achievement *ach = &world.logic_achievements[ uid ];
+ struct logic_achievement *ach = &world->logic_achievements[ uid ];
if( ach->achieved )
return;
ach->achieved = 1;
}
-VG_STATIC void world_run_relay( struct relay_target *rt );
-VG_STATIC void world_trigger_relay( u32 uid )
+VG_STATIC void world_run_relay( world_instance *world,
+ struct relay_target *rt );
+
+VG_STATIC void world_trigger_relay( world_instance *world, u32 uid )
{
- struct logic_relay *relay = &world.logic_relays[ uid ];
+ struct logic_relay *relay = &world->logic_relays[ uid ];
for( int i=0; i<relay->target_count; i++ )
{
- world_run_relay( &relay->targets[i] );
+ world_run_relay( world, &relay->targets[i] );
}
}
-VG_STATIC void world_trigger_audio( u32 uid )
+VG_STATIC void world_trigger_audio( world_instance *world, u32 uid )
{
- struct world_audio_thing *wat = &world.audio_things[ uid ];
+ struct world_audio_thing *wat = &world->audio_things[ uid ];
audio_lock();
audio_player_playclip( &wat->player,
audio_unlock();
}
-VG_STATIC void world_run_relay( struct relay_target *rt )
+VG_STATIC void world_run_relay( world_instance *world,
+ struct relay_target *rt )
{
struct entity_instruction
{
enum classtype classtype;
- void (*p_trigger)( u32 uid );
+ void (*p_trigger)( world_instance *world, u32 uid );
}
entity_instructions[] =
{
if( instr->classtype == rt->classtype )
{
- instr->p_trigger( rt->sub_id );
+ instr->p_trigger( world, rt->sub_id );
return;
}
}
vg_error( "Don't know how to trigger classtype %d\n", rt->classtype );
}
-VG_STATIC void world_update( v3f pos )
+VG_STATIC void world_update( world_instance *world, v3f pos )
{
+#if 0
if( world.switching_to_new_world )
{
int all_stopped = 1;
world.sky_time += world.sky_rate * vg.time_delta;
world.sky_rate = vg_lerp( world.sky_rate, world.sky_target_rate,
vg.time_delta * 5.0 );
+#endif
- world_routes_update();
+ world_routes_update( world );
#if 0
world_routes_debug();
#endif
- if( world.route_count > 0 )
+ if( world->route_count > 0 )
{
int closest = 0;
float min_dist = INFINITY;
- for( int i=0; i<world.route_count; i++ )
+ for( int i=0; i<world->route_count; i++ )
{
- float d = v3_dist2( world.routes[i].scoreboard_transform[3], pos );
+ float d = v3_dist2( world->routes[i].scoreboard_transform[3], pos );
if( d < min_dist )
{
}
}
- if( (world.active_route_board != closest) || network_scores_updated )
+ if( (world_global.active_route_board != closest)
+ || network_scores_updated )
{
network_scores_updated = 0;
- world.active_route_board = closest;
+ world_global.active_route_board = closest;
- struct route *route = &world.routes[closest];
+ struct route *route = &world->routes[closest];
u32 id = route->track_id;
}
int in_trigger = 0;
- for( int i=0; i<world.trigger_count; i++ )
+ for( int i=0; i<world->trigger_count; i++ )
{
- struct trigger_zone *zone = &world.triggers[i];
+ struct trigger_zone *zone = &world->triggers[i];
v3f local;
m4x3_mulv( zone->inv_transform, pos, local );
{
in_trigger = 1;
- if( !world.in_trigger )
+ if( !world_global.in_trigger )
{
- world_run_relay( &zone->target );
+ world_run_relay( world, &zone->target );
}
}
0xff00ff00 );
}
- for( int i=0; i<world.light_count; i++ )
+ for( int i=0; i<world->light_count; i++ )
{
- struct world_light *light = &world.lights[i];
+ struct world_light *light = &world->lights[i];
u32 colour = 0xff000000;
u8 r = light->colour[0] * 255.0f,
vg_line_pt3( light->co, 0.25f, colour );
}
- world.in_trigger = in_trigger;
+ world_global.in_trigger = in_trigger;
sfd_update();
}
* -----------------------------------------------------------------------------
*/
-VG_STATIC void ray_world_get_tri( ray_hit *hit, v3f tri[3] )
+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] );
+ v3_copy( world->scene_geo->arrvertices[ hit->tri[i] ].co, tri[i] );
}
-VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit )
+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 );
+ 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( v3f pa, v3f pb, float r, float *t, v3f n )
+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 );
float min_t = 1.0f;
int idx;
- while( bh_next( world.geo_bh, &it, region, &idx ) )
+ while( bh_next( world->geo_bh, &it, region, &idx ) )
{
- u32 *ptri = &world.scene_geo->arrindices[ idx*3 ];
+ u32 *ptri = &world->scene_geo->arrindices[ idx*3 ];
v3f tri[3];
boxf box;
for( int j=0; j<3; j++ )
{
- v3_copy( world.scene_geo->arrvertices[ptri[j]].co, tri[j] );
+ v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] );
box_addpt( box, tri[j] );
}
return hit;
}
-VG_STATIC struct world_material *world_tri_index_material( u32 index )
+VG_STATIC
+struct world_material *world_tri_index_material( world_instance *world,
+ u32 index )
{
- for( int i=1; i<world.material_count; i++ )
+ for( int i=1; i<world->material_count; i++ )
{
- struct world_material *mat = &world.materials[i];
+ struct world_material *mat = &world->materials[i];
if( (index >= mat->sm_geo.vertex_start) &&
(index < mat->sm_geo.vertex_start+mat->sm_geo.vertex_count ) )
}
/* error material */
- return &world.materials[0];
+ return &world->materials[0];
}
-VG_STATIC struct world_material *world_contact_material( rb_ct *ct )
+VG_STATIC struct world_material *world_contact_material( world_instance *world,
+ rb_ct *ct )
{
- return world_tri_index_material( ct->element_id );
+ return world_tri_index_material( world, ct->element_id );
}
-VG_STATIC struct world_material *ray_hit_material( ray_hit *hit )
+VG_STATIC struct world_material *ray_hit_material( world_instance *world,
+ ray_hit *hit )
{
- return world_tri_index_material( hit->tri[0] );
+ return world_tri_index_material( world, hit->tri[0] );
}
#endif /* WORLD_H */
vg_acquire_thread_sync();
{
- mdl_unpack_glmesh( mgate, &world.mesh_gate_surface );
+ mdl_unpack_glmesh( mgate, &world_global.mesh_gate_surface );
}
vg_release_thread_sync();
}
-VG_STATIC int render_gate( teleport_gate *gate, camera *cam )
+VG_STATIC int render_gate( world_instance *world_inside,
+ teleport_gate *gate, camera *cam )
{
v3f viewdir, gatedir;
m3x3_mulv( cam->transform, (v3f){0.0f,0.0f,-1.0f}, viewdir );
glStencilFunc( GL_ALWAYS, 1, 0xFF );
glStencilMask( 0xFF );
- mesh_bind( &world.mesh_gate_surface );
- mesh_draw( &world.mesh_gate_surface );
+ mesh_bind( &world_global.mesh_gate_surface );
+ mesh_draw( &world_global.mesh_gate_surface );
glClear( GL_DEPTH_BUFFER_BIT );
glStencilFunc( GL_EQUAL, 1, 0xFF );
glStencilMask( 0x00 );
}
- render_world( &gate_view );
+ render_world( world_inside, &gate_view );
{
glDisable( GL_STENCIL_TEST );
- render_water_texture( &gate_view );
+ render_water_texture( world_inside, &gate_view );
render_fb_bind( gpipeline.fb_main );
glEnable( GL_STENCIL_TEST );
- render_water_surface( &gate_view );
+ render_water_surface( world_inside, &gate_view );
glStencilMask( 0xFF );
glStencilFunc( GL_ALWAYS, 1, 0xFF );
/*
* Intersect all gates in the world
*/
-VG_STATIC teleport_gate *world_intersect_gates( v3f pos, v3f last )
+VG_STATIC teleport_gate *world_intersect_gates( world_instance *world,
+ v3f pos, v3f last )
{
- for( int i=0; i<world.gate_count; i++ )
+ for( int i=0; i<world->gate_count; i++ )
{
- struct route_gate *rg = &world.gates[i];
+ struct route_gate *rg = &world->gates[i];
teleport_gate *gate = &rg->gate;
if( gate_intersect( gate, pos, last ) )
#include "world.h"
-/* load world TODO: Put back vg back in loading state while this happens */
-VG_STATIC void world_load(void);
-
+VG_STATIC void world_load( world_instance *world, const char *path );
VG_STATIC void world_add_all_if_material( m4x3f transform, scene *pscene,
mdl_context *mdl, u32 id )
}
}
-VG_STATIC void world_add_blob( scene *pscene, ray_hit *hit )
+VG_STATIC void world_add_blob( world_instance *world,
+ scene *pscene, ray_hit *hit )
{
m4x3f transform;
v4f qsurface, qrandom;
scene_vert *dst_verts = &pscene->arrvertices[ pscene->vertex_count ];
u32 *dst_indices = &pscene->arrindices [ pscene->indice_count ];
- scene_vert *ref = &world.scene_geo->arrvertices[ hit->tri[0] ];
+ scene_vert *ref = &world->scene_geo->arrvertices[ hit->tri[0] ];
for( u32 i=0; i<vg_list_size(verts); i++ )
{
}
/* Sprinkle foliage models over the map on terrain material */
-VG_STATIC void world_apply_procedural_foliage( struct world_material *mat )
+VG_STATIC void world_apply_procedural_foliage( world_instance *world,
+ struct world_material *mat )
{
if( vg.quality_profile == k_quality_profile_low )
return;
mdl_load_full( vg_mem.scratch, "models/rs_foliage.mdl");
v3f volume;
- v3_sub( world.scene_geo->bbx[1], world.scene_geo->bbx[0], volume );
+ v3_sub( world->scene_geo->bbx[1], world->scene_geo->bbx[0], volume );
volume[1] = 1.0f;
mdl_node *mblob = mdl_node_from_name( mfoliage, "blob" );
v3f pos;
v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos );
pos[1] = 1000.0f;
- v3_add( pos, world.scene_geo->bbx[0], pos );
+ v3_add( pos, world->scene_geo->bbx[0], pos );
ray_hit hit;
hit.dist = INFINITY;
- if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
+ if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
{
- struct world_material *m1 = ray_hit_material( &hit );
+ struct world_material *m1 = ray_hit_material( world, &hit );
if((hit.normal[1] > 0.8f) && (m1 == mat) && (hit.pos[1] > 0.0f+10.0f))
{
- world_add_blob( world.scene_no_collide, &hit );
+ world_add_blob( world, world->scene_no_collide, &hit );
count ++;
}
}
vg_info( "%d foliage models added\n", count );
}
-VG_STATIC void world_ents_allocate(void)
+VG_STATIC void world_ents_allocate( world_instance *world )
{
vg_info( "Allocating entities\n" );
{
{
k_classtype_spawn,
- (void*)&world.spawns,
+ (void*)&world->spawns,
sizeof(struct respawn_point)
},
{
k_classtype_audio,
- (void*)&world.audio_things,
+ (void*)&world->audio_things,
sizeof(struct world_audio_thing)
},
{
k_classtype_trigger,
- (void*)&world.triggers,
+ (void*)&world->triggers,
sizeof(struct trigger_zone)
},
{
k_classtype_logic_relay,
- (void*)&world.logic_relays,
+ (void*)&world->logic_relays,
sizeof(struct logic_relay)
},
{
k_classtype_logic_achievement,
- (void*)&world.logic_achievements,
+ (void*)&world->logic_achievements,
sizeof(struct logic_achievement)
},
{
k_classtype_point_light,
- (void*)&world.lights,
+ (void*)&world->lights,
sizeof(struct world_light)
}
};
for( int i=0; i<vg_list_size(entity_counts); i++ )
entity_counts[i].count = 0;
- for( int i=0; i<world.meta->info.node_count; i++ )
+ for( int i=0; i<world->meta->info.node_count; i++ )
{
- mdl_node *pnode = mdl_node_from_id( world.meta, i );
+ mdl_node *pnode = mdl_node_from_id( world->meta, i );
for( int j=0; j<vg_list_size(entity_counts); j ++ )
{
struct countable *counter = &entity_counts[i];
u32 bufsize = counter->item_size*counter->count;
- *counter->to_allocate = vg_linear_alloc( world.dynamic_vgl, bufsize );
+ *counter->to_allocate = vg_linear_alloc( world_global.generic_heap,
+ bufsize );
}
}
-VG_STATIC void world_pct_spawn( mdl_node *pnode )
+VG_STATIC void world_pct_spawn( world_instance *world, mdl_node *pnode )
{
- struct respawn_point *rp = &world.spawns[ world.spawn_count ++ ];
+ struct respawn_point *rp = &world->spawns[ world->spawn_count ++ ];
v3_copy( pnode->co, rp->co );
v4_copy( pnode->q, rp->q );
- rp->name = mdl_pstr( world.meta, pnode->pstr_name );
+ rp->name = mdl_pstr( world->meta, pnode->pstr_name );
}
-VG_STATIC void world_pct_water( mdl_node *pnode )
+VG_STATIC void world_pct_water( world_instance *world, mdl_node *pnode )
{
- if( world.water.enabled )
+ if( world->water.enabled )
{
vg_warn( "Multiple water surfaces in level! ('%s')\n",
- mdl_pstr( world.meta, pnode->pstr_name ));
+ mdl_pstr( world->meta, pnode->pstr_name ));
return;
}
- world.water.enabled = 1;
- water_set_surface( pnode->co[1] );
+ world->water.enabled = 1;
+ water_set_surface( world, pnode->co[1] );
}
-VG_STATIC void world_pct_audio( mdl_node *pnode )
+VG_STATIC void world_pct_audio( world_instance *world, mdl_node *pnode )
{
- struct world_audio_thing *thing = &world.audio_things[
- world.audio_things_count ];
+ struct world_audio_thing *thing = &world->audio_things[
+ world->audio_things_count ];
memset( thing, 0, sizeof(struct world_audio_thing) );
- struct classtype_audio *aud = mdl_get_entdata( world.meta, pnode );
+ struct classtype_audio *aud = mdl_get_entdata( world->meta, pnode );
v3_copy( pnode->co, thing->pos );
thing->volume = aud->volume;
thing->flags = aud->flags;
- thing->temp_embedded_clip.path = mdl_pstr( world.meta, aud->pstr_file );
+ thing->temp_embedded_clip.path = mdl_pstr( world->meta, aud->pstr_file );
thing->temp_embedded_clip.source_mode = k_audio_source_mono;
- audio_clip_load( &thing->temp_embedded_clip, world.audio_vgl );
- thing->player.name = mdl_pstr( world.meta, pnode->pstr_name );
+ audio_clip_load( &thing->temp_embedded_clip, world_global.audio_heap );
+ thing->player.name = mdl_pstr( world->meta, pnode->pstr_name );
thing->player.enqued = 0;
- pnode->sub_uid = world.audio_things_count;
- world.audio_things_count ++;
+ pnode->sub_uid = world->audio_things_count;
+ world->audio_things_count ++;
}
-
-VG_STATIC void world_pct_trigger( mdl_node *pnode )
+VG_STATIC void world_pct_trigger( world_instance *world, mdl_node *pnode )
{
- struct trigger_zone *trigger = &world.triggers[ world.trigger_count ];
- struct classtype_trigger *inf = mdl_get_entdata( world.meta, pnode );
+ struct trigger_zone *trigger = &world->triggers[ world->trigger_count ];
+ struct classtype_trigger *inf = mdl_get_entdata( world->meta, pnode );
if( inf->target )
{
- mdl_node *target_node = mdl_node_from_id( world.meta, inf->target );
+ mdl_node *target_node = mdl_node_from_id( world->meta, inf->target );
trigger->target.sub_id = target_node->sub_uid;
trigger->target.classtype = target_node->classtype;
mdl_node_transform( pnode, trigger->transform );
m4x3_invert_full( trigger->transform, trigger->inv_transform );
- world.trigger_count ++;
+ world->trigger_count ++;
}
-VG_STATIC void world_pct_relay( mdl_node *pnode )
+VG_STATIC void world_pct_relay( world_instance *world, mdl_node *pnode )
{
- struct logic_relay *relay = &world.logic_relays[ world.relay_count ];
- struct classtype_logic_relay *inf = mdl_get_entdata( world.meta, pnode );
+ struct logic_relay *relay = &world->logic_relays[ world->relay_count ];
+ struct classtype_logic_relay *inf = mdl_get_entdata( world->meta, pnode );
relay->target_count = 0;
if( inf->targets[i] )
{
struct relay_target *target = &relay->targets[relay->target_count ++];
- mdl_node *other = mdl_node_from_id( world.meta, inf->targets[i] );
+ mdl_node *other = mdl_node_from_id( world->meta, inf->targets[i] );
target->classtype = other->classtype;
target->sub_id = other->sub_uid;
}
v3_copy( pnode->co, relay->pos );
- world.relay_count ++;
+ world->relay_count ++;
}
-VG_STATIC void world_pct_achievement( mdl_node *pnode )
+VG_STATIC void world_pct_achievement( world_instance *world, mdl_node *pnode )
{
struct logic_achievement *ach =
- &world.logic_achievements[ world.achievement_count ];
+ &world->logic_achievements[ world->achievement_count ];
struct classtype_logic_achievement *inf =
- mdl_get_entdata( world.meta, pnode );
+ mdl_get_entdata( world->meta, pnode );
v3_copy( pnode->co, ach->pos );
- ach->achievement_id = mdl_pstr( world.meta, inf->pstr_name );
+ ach->achievement_id = mdl_pstr( world->meta, inf->pstr_name );
ach->achieved = 0;
- world.achievement_count ++;
+ world->achievement_count ++;
}
-VG_STATIC void world_pct_point_light( mdl_node *pnode )
+VG_STATIC void world_pct_point_light( world_instance *world, mdl_node *pnode )
{
- struct world_light *light = &world.lights[ world.light_count ];
+ struct world_light *light = &world->lights[ world->light_count ];
v3_copy( pnode->co, light->co );
- struct classtype_point_light *inf = mdl_get_entdata( world.meta, pnode );
+ struct classtype_point_light *inf = mdl_get_entdata( world->meta, pnode );
v4_copy( inf->colour, light->colour );
- world.light_count ++;
+ world->light_count ++;
}
-VG_STATIC void world_entities_process(void)
+VG_STATIC void world_entities_process( world_instance *world )
{
struct entity_instruction
{
enum classtype ct;
- void (*process)( mdl_node *pnode );
+ void (*process)( world_instance *world, mdl_node *pnode );
}
entity_instructions[] =
{
{ k_classtype_point_light, world_pct_point_light }
};
- for( int i=0; i<world.meta->info.node_count; i++ )
+ for( int i=0; i<world->meta->info.node_count; i++ )
{
- mdl_node *pnode = mdl_node_from_id( world.meta, i );
+ mdl_node *pnode = mdl_node_from_id( world->meta, i );
for( int j=0; j<vg_list_size(entity_instructions); j++ )
{
if( pnode->classtype == instr->ct )
{
- instr->process( pnode );
+ instr->process( world, pnode );
break;
}
}
}
}
-VG_STATIC void world_scene_compute_light_clusters( scene *sc )
+VG_STATIC void world_scene_compute_light_clusters( world_instance *world,
+ scene *sc )
{
for( int i=0; i<sc->vertex_count; i++ )
{
float distances[4] = { INFINITY, INFINITY, INFINITY, INFINITY };
- for( int j=0; j<world.light_count; j ++ )
+ for( int j=0; j<world->light_count; j ++ )
{
- float dist = v3_dist2( world.lights[j].co, vert->co );
+ float dist = v3_dist2( world->lights[j].co, vert->co );
int best_pos = 4;
for( int k=best_pos-1; k>=0; k -- )
}
}
-VG_STATIC void world_generate(void)
+VG_STATIC void world_generate( world_instance *world )
{
/*
* Compile meshes into the world scenes
*/
- world.scene_geo = scene_init( world.dynamic_vgl, 320000, 1200000 );
+ world->scene_geo = scene_init( world_global.generic_heap, 320000, 1200000 );
m4x3f midentity;
m4x3_identity( midentity );
vg_info( "Generating collidable geometry\n" );
- for( int i=0; i<world.material_count; i++ )
+ for( int i=0; i<world->material_count; i++ )
{
- struct world_material *mat = &world.materials[ i ];
+ struct world_material *mat = &world->materials[ i ];
if( mat->info.flags & k_material_flag_collision )
- world_add_all_if_material( midentity, world.scene_geo, world.meta, i );
+ world_add_all_if_material( midentity, world->scene_geo, world->meta, i );
- scene_copy_slice( world.scene_geo, &mat->sm_geo );
+ scene_copy_slice( world->scene_geo, &mat->sm_geo );
}
- world_scene_compute_light_clusters( world.scene_geo );
+ world_scene_compute_light_clusters( world, world->scene_geo );
/* compress that bad boy */
- world.scene_geo = scene_fix( world.dynamic_vgl, world.scene_geo );
+ world->scene_geo = scene_fix( world_global.generic_heap, world->scene_geo );
vg_acquire_thread_sync();
{
- scene_upload( world.scene_geo, &world.mesh_geo );
+ scene_upload( world->scene_geo, &world->mesh_geo );
}
vg_release_thread_sync();
/* setup spacial mapping and rigidbody */
- world.geo_bh = scene_bh_create( world.dynamic_vgl, world.scene_geo );
+ world->geo_bh = scene_bh_create( world_global.generic_heap,
+ world->scene_geo );
- v3_zero( world.rb_geo.co );
- q_identity( world.rb_geo.q );
+ v3_zero( world->rb_geo.co );
+ q_identity( world->rb_geo.q );
- world.rb_geo.type = k_rb_shape_scene;
- world.rb_geo.inf.scene.bh_scene = world.geo_bh;
- world.rb_geo.is_world = 1;
- rb_init( &world.rb_geo );
+ world->rb_geo.type = k_rb_shape_scene;
+ world->rb_geo.inf.scene.bh_scene = world->geo_bh;
+ world->rb_geo.is_world = 1;
+ rb_init( &world->rb_geo );
/*
* Generate scene: non-collidable geometry
*/
vg_info( "Generating non-collidable geometry\n" );
- world.scene_no_collide = scene_init( world.dynamic_vgl, 200000, 500000 );
+ world->scene_no_collide = scene_init( world_global.generic_heap,
+ 200000, 500000 );
- for( int i=0; i<world.material_count; i++ )
+ for( int i=0; i<world->material_count; i++ )
{
- struct world_material *mat = &world.materials[ i ];
+ struct world_material *mat = &world->materials[ i ];
if( !(mat->info.flags & k_material_flag_collision) )
{
- world_add_all_if_material( midentity, world.scene_no_collide,
- world.meta, i );
+ world_add_all_if_material( midentity, world->scene_no_collide,
+ world->meta, i );
}
if( mat->info.flags & k_material_flag_grow_grass )
- world_apply_procedural_foliage( mat );
+ world_apply_procedural_foliage( world, mat );
- scene_copy_slice( world.scene_no_collide, &mat->sm_no_collide );
+ scene_copy_slice( world->scene_no_collide, &mat->sm_no_collide );
}
- world_scene_compute_light_clusters( world.scene_no_collide );
+ world_scene_compute_light_clusters( world, world->scene_no_collide );
/* upload and free that */
vg_acquire_thread_sync();
{
- scene_upload( world.scene_no_collide, &world.mesh_no_collide );
+ scene_upload( world->scene_no_collide, &world->mesh_no_collide );
}
vg_release_thread_sync();
- vg_linear_del( world.dynamic_vgl, world.scene_no_collide );
- world.scene_no_collide = NULL;
+ vg_linear_del( world_global.generic_heap, world->scene_no_collide );
+ world->scene_no_collide = NULL;
}
VG_STATIC int reset_player( int argc, char const *argv[] );
-VG_STATIC void world_post_process(void)
+VG_STATIC void world_post_process( world_instance *world )
{
/* initialize audio if need be */
audio_lock();
- for( int i=0; i<world.audio_things_count; i++ )
+ for( int i=0; i<world->audio_things_count; i++ )
{
- struct world_audio_thing *thingy = &world.audio_things[ i ];
+ struct world_audio_thing *thingy = &world->audio_things[ i ];
audio_player_init( &thingy->player );
audio_player_set_flags( &thingy->player, thingy->flags );
camera ortho;
v3f extent;
- v3_sub( world.scene_geo->bbx[1], world.scene_geo->bbx[0], extent );
+ v3_sub( world->scene_geo->bbx[1], world->scene_geo->bbx[0], extent );
- float fl = world.scene_geo->bbx[0][0],
- fr = world.scene_geo->bbx[1][0],
- fb = world.scene_geo->bbx[0][2],
- ft = world.scene_geo->bbx[1][2],
+ float fl = world->scene_geo->bbx[0][0],
+ fr = world->scene_geo->bbx[1][0],
+ fb = world->scene_geo->bbx[0][2],
+ ft = world->scene_geo->bbx[1][2],
rl = 1.0f / (fr-fl),
tb = 1.0f / (ft-fb);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
- render_fb_bind( gpipeline.fb_heightmap );
+ render_fb_bind( &world->heightmap );
shader_blitcolour_use();
shader_blitcolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} );
render_fsquad();
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_MAX);
- render_world_depth( &ortho );
+ render_world_depth( world, &ortho );
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- /*
- * TODO: World settings entity
- */
- struct ub_world_lighting *winfo = &gpipeline.ub_world_lighting;
-
- if( world.water.enabled )
- v4_copy( world.water.plane, winfo->g_water_plane );
+ /* Upload lighting uniform buffer */
+ if( world->water.enabled )
+ v4_copy( world->water.plane, world->ub_lighting.g_water_plane );
v4f info_vec;
- v3f *bounds = world.scene_geo->bbx;
+ v3f *bounds = world->scene_geo->bbx;
info_vec[0] = bounds[0][0];
info_vec[1] = bounds[0][2];
info_vec[2] = 1.0f/ (bounds[1][0]-bounds[0][0]);
info_vec[3] = 1.0f/ (bounds[1][2]-bounds[0][2]);
- v4_copy( info_vec, winfo->g_depth_bounds );
-
- winfo->g_water_fog = 0.04f;
+ v4_copy( info_vec, world->ub_lighting.g_depth_bounds );
- for( int i=0; i<world.light_count; i++ )
+ /* add scene lights */
+ for( int i=0; i<world->light_count; i++ )
{
- struct world_light *light = &world.lights[i];
+ struct world_light *light = &world->lights[i];
v3_muls( light->colour, light->colour[3] * 2.0f,
- gpipeline.ub_world_lighting.g_point_light_colours[i] );
+ world->ub_lighting.g_point_light_colours[i] );
v3_copy( light->co,
- gpipeline.ub_world_lighting.g_point_light_positions[i] );
+ world->ub_lighting.g_point_light_positions[i] );
}
- render_update_lighting_ub();
+ /* upload full buffer */
+ glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
+ glBufferSubData( GL_UNIFORM_BUFFER, 0,
+ sizeof(struct ub_world_lighting), &world->ub_lighting );
}
vg_release_thread_sync();
#endif
}
-VG_STATIC void world_process_resources(void)
+VG_STATIC void world_process_resources( world_instance *world )
{
vg_info( "Loading textures\n" );
- world.texture_count = world.meta->info.texture_count;
- world.textures =
- vg_linear_alloc( world.dynamic_vgl, sizeof(GLuint)*world.texture_count );
+ world->texture_count = world->meta->info.texture_count;
+ world->textures = vg_linear_alloc( world_global.generic_heap,
+ sizeof(GLuint)*world->texture_count );
vg_acquire_thread_sync();
{
/* error texture */
- world.textures[0] = vg_tex2d_new();
+ world->textures[0] = vg_tex2d_new();
vg_tex2d_set_error();
vg_tex2d_nearest();
vg_tex2d_repeat();
- for( int i=1; i<world.texture_count; i++ )
+ for( int i=1; i<world->texture_count; i++ )
{
- mdl_texture *tex = &world.meta->texture_buffer[i];
+ mdl_texture *tex = &world->meta->texture_buffer[i];
if( !tex->pack_offset )
{
}
vg_linear_clear( vg_mem.scratch );
- world.textures[i] = vg_tex2d_new();
+ world->textures[i] = vg_tex2d_new();
vg_tex2d_set_error();
- vg_tex2d_qoi( world.meta->pack + tex->pack_offset, tex->pack_length,
- mdl_pstr( world.meta, tex->pstr_name ));
+ vg_tex2d_qoi( world->meta->pack + tex->pack_offset, tex->pack_length,
+ mdl_pstr( world->meta, tex->pstr_name ));
vg_tex2d_nearest();
vg_tex2d_repeat();
}
vg_info( "Loading materials\n" );
- u32 size = sizeof(struct world_material) * world.meta->info.material_count;
- world.materials = vg_linear_alloc( world.dynamic_vgl, size );
+ u32 size = sizeof(struct world_material) * world->meta->info.material_count;
+ world->materials = vg_linear_alloc( world_global.generic_heap, size );
- world.material_count = world.meta->info.material_count;
- memset( world.materials, 0, size );
+ world->material_count = world->meta->info.material_count;
+ memset( world->materials, 0, size );
- for( int i=1; i<world.material_count; i++ )
- world.materials[i].info = world.meta->material_buffer[i];
+ for( int i=1; i<world->material_count; i++ )
+ world->materials[i].info = world->meta->material_buffer[i];
/* error material */
- struct world_material *errmat = &world.materials[0];
+ struct world_material *errmat = &world->materials[0];
v4_copy( (v4f){ 1.0f,0.0f,0.0f,1.0f }, errmat->info.colour );
v4_copy( (v4f){ 1.0f,0.0f,0.0f,1.0f }, errmat->info.colour1 );
errmat->info.flags = 0x00;
errmat->info.tex_normal = 0;
}
-VG_STATIC void world_unload(void)
+VG_STATIC void world_unload( world_instance *world )
{
vg_acquire_thread_sync();
/* free meshes */
- mesh_free( &world.mesh_route_lines );
- mesh_free( &world.mesh_geo );
- mesh_free( &world.mesh_no_collide );
-
- world.time = 0.0;
- world.rewind_from = 0.0;
- world.rewind_to = 0.0;
- world.last_use = 0.0;
- world.active_gate = 0;
- world.current_run_version = 2;
- world.active_route_board = 0;
- v3_zero( world.render_gate_pos );
-
- for( int i=0; i<vg_list_size(world.ui_bars); i++ )
+ mesh_free( &world->mesh_route_lines );
+ mesh_free( &world->mesh_geo );
+ mesh_free( &world->mesh_no_collide );
+
+ /* FIXME: CANT DO THIS HERE */
+ world_global.time = 0.0;
+ world_global.rewind_from = 0.0;
+ world_global.rewind_to = 0.0;
+ world_global.last_use = 0.0;
+ world_global.active_gate = 0;
+ world_global.current_run_version = 2;
+ world_global.active_route_board = 0;
+
+ for( int i=0; i<vg_list_size(world_global.ui_bars); i++ )
{
- struct route_ui_bar *uib = &world.ui_bars[i];
+ struct route_ui_bar *uib = &world_global.ui_bars[i];
uib->segment_start = 0;
uib->segment_count = 0;
uib->fade_start = 0;
}
/* delete textures and meshes */
- glDeleteTextures( world.texture_count, world.textures );
+ glDeleteTextures( world->texture_count, world->textures );
/* delete the entire block of memory */
- vg_linear_clear( world.dynamic_vgl );
- vg_linear_clear( world.audio_vgl );
+ /* FIXME: WE CANT DO THIS SHIT ANYMORE, NEED TO DEALLOC FROM ABOVE */
+#if 0
+ vg_linear_clear( world->dynamic_vgl );
+ vg_linear_clear( world->audio_vgl );
+#endif
+
+
+ vg_release_thread_sync();
+}
+
+VG_STATIC void world_add_global_light( world_instance *world,
+ v2f dir, v3f colour )
+{
+ int id = world->ub_lighting.g_light_count;
+
+ v3_copy( colour, world->ub_lighting.g_light_colours[id] );
+ v3_copy( (v3f){ cosf(dir[1]) * cosf(dir[0]),
+ sinf(dir[0]),
+ sinf(dir[1]) * cosf(dir[0]) },
+ world->ub_lighting.g_light_directions[id] );
+
+ world->ub_lighting.g_light_count ++;
+}
+VG_STATIC void world_clean( world_instance *world )
+{
/* clean dangling pointers */
- world.meta = NULL;
+ world->meta = NULL;
- world.textures = NULL;
- world.texture_count = 0;
- world.materials = NULL;
- world.material_count = 0;
+ world->textures = NULL;
+ world->texture_count = 0;
+ world->materials = NULL;
+ world->material_count = 0;
- world.scene_geo = NULL;
- world.scene_no_collide = NULL;
- world.scene_lines = NULL;
+ world->scene_geo = NULL;
+ world->scene_no_collide = NULL;
+ world->scene_lines = NULL;
- world.geo_bh = NULL;
- world.trigger_bh = NULL;
- world.audio_bh = NULL;
+ world->geo_bh = NULL;
+ world->trigger_bh = NULL;
+ world->audio_bh = NULL;
- world.spawns = NULL;
- world.spawn_count = 0;
+ world->spawns = NULL;
+ world->spawn_count = 0;
- world.audio_things = NULL;
- world.audio_things_count = 0;
+ world->audio_things = NULL;
+ world->audio_things_count = 0;
- world.triggers = NULL;
- world.trigger_count = 0;
+ world->triggers = NULL;
+ world->trigger_count = 0;
- world.lights = NULL;
- world.light_count = 0;
+ world->lights = NULL;
+ world->light_count = 0;
- world.logic_relays = NULL;
- world.relay_count = 0;
+ world->logic_relays = NULL;
+ world->relay_count = 0;
- world.logic_achievements = NULL;
- world.achievement_count = 0;
+ world->logic_achievements = NULL;
+ world->achievement_count = 0;
- world.nodes = NULL;
- world.node_count = 0;
+ world->nodes = NULL;
+ world->node_count = 0;
- world.routes = NULL;
- world.route_count = 0;
+ world->routes = NULL;
+ world->route_count = 0;
- world.gates = NULL;
- world.gate_count = 0;
+ world->gates = NULL;
+ world->gate_count = 0;
- world.collectors = NULL;
- world.collector_count = 0;
+ world->collectors = NULL;
+ world->collector_count = 0;
- world.water.enabled = 0;
+ world->water.enabled = 0;
- vg_release_thread_sync();
+
+ /* default lighting conditions
+ * -------------------------------------------------------------*/
+ world->ub_lighting.g_light_count = 0;
+ world->ub_lighting.g_light_preview = 0;
+ world->ub_lighting.g_shadow_samples = 8;
+ world->ub_lighting.g_water_fog = 0.04f;
+
+ v4_zero( world->ub_lighting.g_water_plane );
+ v4_zero( world->ub_lighting.g_depth_bounds );
+ v4_zero( world->ub_lighting.g_ambient_colour );
+
+ v3_copy( (v3f){ 0.09f, 0.03f, 0.07f }, world->ub_lighting.g_ambient_colour );
+
+ world_add_global_light( world, (v2f){ 0.63f, -0.08f },
+ (v3f){ 1.36f, 1.35f, 1.01f } );
+
+ world_add_global_light( world, (v2f){ -2.60f, -0.13f },
+ (v3f){ 0.33f, 0.56f, 0.64f } );
+
+ world_add_global_light( world, (v2f){ 2.60f, -0.84f },
+ (v3f){ 0.05f, 0.05f, 0.23f } );
+
+ world->ub_lighting.g_light_directions[0][3] = 9.50f;
+ world->ub_lighting.g_light_colours[0][3] = 0.65f;
}
-VG_STATIC void world_load(void)
+VG_STATIC void world_load( world_instance *world, const char *path )
{
- world_unload();
+ world_unload( world );
+ world_clean( world );
- world.meta = mdl_load_full( world.dynamic_vgl, world.world_name );
- vg_info( "Loading world: %s\n", world.world_name );
+ world->meta = mdl_load_full( world_global.generic_heap, path );
+ vg_info( "Loading world: %s\n", path );
/* process resources from pack */
- world_process_resources();
+ world_process_resources( world );
/* dynamic allocations */
- world_ents_allocate();
- world_routes_allocate();
+ world_ents_allocate( world );
+ world_routes_allocate( world );
/* meta processing */
- world_routes_process();
- world_entities_process();
+ world_routes_process( world );
+ world_entities_process( world );
/* main bulk */
- world_generate();
- world_routes_generate();
- world_post_process();
+ world_generate( world );
+ world_routes_generate( world );
+ world_post_process( world );
}
#endif /* WORLD_GEN_H */
vg_acquire_thread_sync();
{
vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_noise }, 1 );
+
+
+ vg_info( "Allocate uniform buffers\n" );
+ for( int i=0; i<4; i++ )
+ {
+ world_instance *world = &world_global.worlds[i];
+ world->ubo_bind_point = i;
+
+ glGenBuffers( 1, &world->ubo_lighting );
+ glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
+ glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting),
+ NULL, GL_DYNAMIC_DRAW );
+
+ glBindBufferBase( GL_UNIFORM_BUFFER, i, world->ubo_lighting );
+ VG_CHECK_GL_ERR();
+ }
+
+ vg_info( "Allocate frame buffers\n" );
+ for( int i=0; i<4; i++ )
+ {
+ world_instance *world = &world_global.worlds[i];
+ struct framebuffer *fb = &world->heightmap;
+
+ fb->display_name = NULL;
+ fb->link = NULL;
+ fb->fixed_w = 1024;
+ fb->fixed_h = 1024;
+ fb->resolution_div = 0;
+
+ /* TODO: We could get away with this being R16u, and just have it be
+ * a normed value between min and max of the bounding box Y */
+
+ fb->attachments[0].display_name = NULL;
+ fb->attachments[0].purpose = k_framebuffer_attachment_type_colour;
+ fb->attachments[0].internalformat = GL_R16F;
+ fb->attachments[0].format = GL_RED;
+ fb->attachments[0].type = GL_FLOAT;
+ fb->attachments[0].attachment = GL_COLOR_ATTACHMENT0;
+
+ fb->attachments[1].purpose = k_framebuffer_attachment_type_none;
+ fb->attachments[2].purpose = k_framebuffer_attachment_type_none;
+ fb->attachments[3].purpose = k_framebuffer_attachment_type_none;
+ fb->attachments[4].purpose = k_framebuffer_attachment_type_none;
+
+ render_fb_allocate( fb );
+ }
}
vg_release_thread_sync();
}
-VG_STATIC void render_world_depth( camera *cam );
+VG_STATIC void world_link_lighting_ub( world_instance *world,
+ GLuint shader, int texture_id )
+{
+ GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );
+ glUniformBlockBinding( shader, idx, world->ubo_bind_point );
+
+ render_fb_bind_texture( &world->heightmap, 0, texture_id );
+ glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id );
+}
+
+VG_STATIC void render_world_depth( world_instance *world, camera *cam );
/*
* Rendering
vg_tex2d_bind( &tex_terrain_noise, 0 );
}
-VG_STATIC void world_render_if( enum mdl_shader shader,
+typedef void (*func_bind_point)( world_instance *world,
+ struct world_material *mat );
+
+VG_STATIC void world_render_if( world_instance *world,
+ enum mdl_shader shader,
enum geo_type geo_type,
- void (*bind_point)(struct world_material *mat))
+ func_bind_point bind_point )
{
- for( int i=0; i<world.material_count; i++ )
+ for( int i=0; i<world->material_count; i++ )
{
- struct world_material *mat = &world.materials[i];
+ struct world_material *mat = &world->materials[i];
if( mat->info.shader == shader )
{
if( !sm->indice_count )
continue;
- bind_point( mat );
+ bind_point( world, mat );
mdl_draw_submesh( sm );
}
}
}
-VG_STATIC void world_render_both_stages( enum mdl_shader shader,
- void (*bind_point)(struct world_material *mat))
+VG_STATIC
+void world_render_both_stages( world_instance *world,
+ enum mdl_shader shader,
+ func_bind_point bind_point )
{
- mesh_bind( &world.mesh_geo );
- world_render_if( shader, k_geo_type_solid, bind_point );
+ mesh_bind( &world->mesh_geo );
+ world_render_if( world, shader, k_geo_type_solid, bind_point );
glDisable( GL_CULL_FACE );
- mesh_bind( &world.mesh_no_collide );
- world_render_if( shader, k_geo_type_nonsolid, bind_point );
+ mesh_bind( &world->mesh_no_collide );
+ world_render_if( world, shader, k_geo_type_nonsolid, bind_point );
glEnable( GL_CULL_FACE );
}
-VG_STATIC void bindpoint_diffuse_texture1( struct world_material *mat )
+VG_STATIC void bindpoint_diffuse_texture1( world_instance *world,
+ struct world_material *mat )
{
glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world.textures[ mat->info.tex_diffuse ] );
+ glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] );
}
-VG_STATIC void render_world_vb( camera *cam )
+VG_STATIC void render_world_vb( world_instance *world, camera *cam )
{
m4x3f identity_matrix;
m4x3_identity( identity_matrix );
shader_scene_vertex_blend_use();
shader_scene_vertex_blend_uTexGarbage(0);
shader_scene_vertex_blend_uTexGradients(1);
- shader_link_standard_ub( _shader_scene_vertex_blend.id, 2 );
+ world_link_lighting_ub( world, _shader_scene_vertex_blend.id, 2 );
vg_tex2d_bind( &tex_terrain_noise, 0 );
shader_scene_vertex_blend_uPv( cam->mtx.pv );
shader_scene_vertex_blend_uBoard0( TEMP_BOARD_0 );
shader_scene_vertex_blend_uBoard1( TEMP_BOARD_1 );
- world_render_both_stages( k_shader_standard_vertex_blend,
+ world_render_both_stages( world, k_shader_standard_vertex_blend,
bindpoint_diffuse_texture1 );
}
-VG_STATIC void render_world_standard( camera *cam )
+VG_STATIC void render_world_standard( world_instance *world, camera *cam )
{
m4x3f identity_matrix;
m4x3_identity( identity_matrix );
shader_scene_standard_uTexMain(1);
shader_scene_standard_uPv( cam->mtx.pv );
shader_scene_standard_uPvmPrev( cam->mtx_prev.pv );
- shader_link_standard_ub( _shader_scene_standard.id, 2 );
+ world_link_lighting_ub( world, _shader_scene_standard.id, 2 );
bind_terrain_noise();
shader_scene_standard_uMdl( identity_matrix );
shader_scene_standard_uBoard0( TEMP_BOARD_0 );
shader_scene_standard_uBoard1( TEMP_BOARD_1 );
- world_render_both_stages( k_shader_standard,
+ world_render_both_stages( world, k_shader_standard,
bindpoint_diffuse_texture1 );
}
-VG_STATIC void render_world_alphatest( camera *cam )
+VG_STATIC void render_world_alphatest( world_instance *world, camera *cam )
{
m4x3f identity_matrix;
m4x3_identity( identity_matrix );
shader_scene_standard_alphatest_uTexMain(1);
shader_scene_standard_alphatest_uPv( cam->mtx.pv );
shader_scene_standard_alphatest_uPvmPrev( cam->mtx_prev.pv );
- shader_link_standard_ub( _shader_scene_standard_alphatest.id, 2 );
+ world_link_lighting_ub( world, _shader_scene_standard_alphatest.id, 2 );
bind_terrain_noise();
shader_scene_standard_alphatest_uMdl( identity_matrix );
glDisable(GL_CULL_FACE);
- world_render_both_stages( k_shader_standard_cutout,
+ world_render_both_stages( world, k_shader_standard_cutout,
bindpoint_diffuse_texture1 );
glEnable(GL_CULL_FACE);
}
-VG_STATIC void bindpoint_terrain( struct world_material *mat )
+VG_STATIC void bindpoint_terrain( world_instance *world,
+ struct world_material *mat )
{
glActiveTexture( GL_TEXTURE1 );
- glBindTexture( GL_TEXTURE_2D, world.textures[ mat->info.tex_diffuse ] );
+ glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] );
shader_scene_terrain_uSandColour( mat->info.colour );
shader_scene_terrain_uBlendOffset( mat->info.colour1 );
}
-VG_STATIC void render_terrain( camera *cam )
+VG_STATIC void render_terrain( world_instance *world, camera *cam )
{
m4x3f identity_matrix;
m4x3_identity( identity_matrix );
shader_scene_terrain_use();
shader_scene_terrain_uTexGarbage(0);
shader_scene_terrain_uTexGradients(1);
- shader_link_standard_ub( _shader_scene_terrain.id, 2 );
+ world_link_lighting_ub( world, _shader_scene_terrain.id, 2 );
vg_tex2d_bind( &tex_terrain_noise, 0 );
shader_scene_terrain_uBoard0( TEMP_BOARD_0 );
shader_scene_terrain_uBoard1( TEMP_BOARD_1 );
- world_render_both_stages( k_shader_terrain_blend, bindpoint_terrain );
+ world_render_both_stages( world, k_shader_terrain_blend, bindpoint_terrain );
}
VG_STATIC void render_sky( camera *cam )
shader_model_sky_uPv( pv );
shader_model_sky_uPvmPrev( pv_prev );
shader_model_sky_uTexGarbage(0);
- shader_model_sky_uTime( world.sky_time );
+ shader_model_sky_uTime( world_global.sky_time );
vg_tex2d_bind( &tex_terrain_noise, 0 );
glDepthMask( GL_FALSE );
glDisable( GL_DEPTH_TEST );
- mesh_bind( &world.skydome );
- mdl_draw_submesh( &world.dome_upper );
+ mesh_bind( &world_global.skydome );
+ mdl_draw_submesh( &world_global.dome_upper );
glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
}
-VG_STATIC void render_world_gates( camera *cam )
+VG_STATIC void render_world_gates( world_instance *world, camera *cam )
{
- if( !world.gate_count )
+ if( !world->gate_count )
return;
float closest = INFINITY;
int id = 0;
- for( int i=0; i<world.gate_count; i++ )
+ for( int i=0; i<world->gate_count; i++ )
{
- struct route_gate *rg = &world.gates[i];
+ struct route_gate *rg = &world->gates[i];
float dist = v3_dist2( rg->gate.co[0], cam->transform[3] );
if( dist < closest )
}
}
- render_gate( &world.gates[id].gate, cam );
- v3_lerp( world.render_gate_pos,
- world.gates[id].gate.co[0],
- 1.0f,
- world.render_gate_pos );
+ /* TODO: non-local portals! :D */
+ render_gate( world, &world->gates[id].gate, cam );
}
-VG_STATIC void render_world( camera *cam )
+VG_STATIC void render_world( world_instance *world, camera *cam )
{
render_sky( cam );
- render_world_routes( cam );
- render_world_standard( cam );
- render_world_vb( cam );
- render_world_alphatest( cam );
- render_terrain( cam );
+ render_world_routes( world, cam );
+ render_world_standard( world, cam );
+ render_world_vb( world, cam );
+ render_world_alphatest( world, cam );
+ render_terrain( world, cam );
/* Render SFD's */
int closest = 0;
float min_dist = INFINITY;
- if( !world.route_count )
+ if( !world->route_count )
return;
- for( int i=0; i<world.route_count; i++ )
+ for( int i=0; i<world->route_count; i++ )
{
- float dist = v3_dist2(world.routes[i].scoreboard_transform[3], cam->pos);
+ float dist = v3_dist2(world->routes[i].scoreboard_transform[3], cam->pos);
if( dist < min_dist )
{
}
}
- sfd_render( cam, world.routes[closest].scoreboard_transform );
+ sfd_render( cam, world->routes[closest].scoreboard_transform );
}
-VG_STATIC void render_world_depth( camera *cam )
+VG_STATIC void render_world_depth( world_instance *world, camera *cam )
{
m4x3f identity_matrix;
m4x3_identity( identity_matrix );
shader_scene_depth_uPvmPrev( cam->mtx_prev.pv );
shader_scene_depth_uMdl( identity_matrix );
- mesh_bind( &world.mesh_geo );
- mesh_draw( &world.mesh_geo );
+ mesh_bind( &world->mesh_geo );
+ mesh_draw( &world->mesh_geo );
#if 0
glDisable(GL_CULL_FACE);
/*
* Get a list of node ids in stack, and return how many there is
*/
-VG_STATIC u32 world_routes_get_path( u32 starter, u32 stack[64] )
+VG_STATIC u32 world_routes_get_path( world_instance *world,
+ u32 starter, u32 stack[64] )
{
u32 stack_i[64];
continue;
}
- struct route_node *rn = &world.nodes[stack[si-1]];
+ struct route_node *rn = &world->nodes[stack[si-1]];
u32 nextid = rn->next[stack_i[si-1]];
stack_i[si-1] ++;
*/
VG_STATIC void world_routes_ui_newseg( u32 route )
{
- struct route_ui_bar *pui = &world.ui_bars[route];
+ struct route_ui_bar *pui = &world_global.ui_bars[route];
glBindVertexArray( pui->vao );
if( pui->segment_count )
*/
VG_STATIC void world_routes_ui_updatetime( u32 route, float time )
{
- struct route_ui_bar *pui = &world.ui_bars[route];
+ struct route_ui_bar *pui = &world_global.ui_bars[route];
v2f verts[2];
verts[0][0] = time;
/*
* Draws full bar at Y offset(offset).
*/
-VG_STATIC void world_routes_ui_draw( u32 route, v4f colour, float offset )
+VG_STATIC void world_routes_ui_draw( world_instance *world,
+ u32 route, v4f colour, float offset )
{
float const k_bar_height = 0.05f,
k_bar_scale_x = 0.005f;
- struct route *pr = &world.routes[route];
- struct route_ui_bar *pui = &world.ui_bars[route];
+ /* FIXME(10) ID mishmatch */
+ struct route *pr = &world->routes[route];
+ struct route_ui_bar *pui = &world_global.ui_bars[route];
float cx = pui->xpos;
shader_routeui_use();
glBindVertexArray( pui->vao );
- float fade_amt = world.time - pui->fade_timer_start;
+ float fade_amt = world_global.time - pui->fade_timer_start;
fade_amt = vg_clampf( fade_amt / 1.0f, 0.0f, 1.0f );
float fade_block_size = 0.0f,
fade_colour[3] *= 1.0f-fade_amt;
/* 1 minute timer */
- float timer_delta = (world.time - world.last_use) * (1.0/45.0),
+ float timer_delta = (world_global.time - world_global.last_use) * (1.0/45.0),
timer_scale = 1.0f - vg_minf( timer_delta, 1.0f );
/*
pui->xpos = vg_lerpf( pui->xpos, -main_block_size * 0.5f, 0.03f );
}
-VG_STATIC void world_routes_local_set_record( u32 route, double lap_time )
+VG_STATIC void world_routes_local_set_record( world_instance *world,
+ u32 route, double lap_time )
{
vg_success( " NEW LAP TIME: %f\n", lap_time );
- struct route *pr = &world.routes[route];
+ /* FIXME(10): ID mishmatch */
+ struct route *pr = &world->routes[route];
if( pr->track_id != 0xffffffff )
{
* 2: the time of each segment will be recorded into the data buffer
* (not implemented: TODO)
*/
-VG_STATIC void world_routes_verify_run( u32 route )
+VG_STATIC void world_routes_verify_run( world_instance *world, u32 route )
{
- struct route *pr = &world.routes[route];
- struct route_ui_bar *pui = &world.ui_bars[route];
+ /* FIXME(10): ID mishmatch */
+ struct route *pr = &world->routes[route];
+ struct route_ui_bar *pui = &world_global.ui_bars[route];
u32 stack[64];
- u32 si = world_routes_get_path( world.routes[route].start, stack );
+ u32 si = world_routes_get_path( world, world->routes[route].start, stack );
/*
* we only care about gates that ref gates, so shuffle down the array
u32 sj = 0, maxv = 0, begin = 0;
for( u32 i=0; i<si; i++ )
{
- struct route_node *inode = &world.nodes[stack[i]];
+ struct route_node *inode = &world->nodes[stack[i]];
if( inode->special_type == k_route_special_type_collector )
{
- timings[sj ++] = &world.collectors[ inode->special_id ].timing;
+ timings[sj ++] = &world->collectors[ inode->special_id ].timing;
}
else if( inode->special_type == k_route_special_type_gate )
{
- timings[sj ++] = &world.gates[inode->special_id].timing;
+ timings[sj ++] = &world->gates[inode->special_id].timing;
}
}
}
vg_info( "== begin verification (%u) ==\n", route );
- vg_info( " current version: %u\n", world.current_run_version );
+ vg_info( " current version: %u\n", world_global.current_run_version );
int verified = 0;
- if( timings[begin]->version == world.current_run_version )
+ if( timings[begin]->version == world_global.current_run_version )
verified = 1;
int valid_segment_count = 0;
pui->fade_start = pui->segment_start;
pui->fade_count = 0;
- pui->fade_timer_start = world.time;
+ pui->fade_timer_start = world_global.time;
int orig_seg_count = pui->segment_count;
if( verified )
{
- world_routes_local_set_record( route, lap_time );
+ world_routes_local_set_record( world, route, lap_time );
world_routes_ui_popfirst( pui );
pui->fade_count ++;
}
pui->fade_count ++;
}
- world.routes[route].latest_pass = world.time;
+ world->routes[route].latest_pass = world_global.time;
}
-VG_STATIC void world_routes_clear(void)
+VG_STATIC void world_routes_clear( world_instance *world )
{
- for( u32 i=0; i<world.route_count; i++ )
+ for( u32 i=0; i<world->route_count; i++ )
{
- struct route *route = &world.routes[i];
+ struct route *route = &world->routes[i];
route->active = 0;
}
- world.current_run_version += 4;
- world.last_use = 0.0;
+ world_global.current_run_version += 4;
+ world_global.last_use = 0.0;
}
/*
* When going through a gate this is called for bookkeeping purposes
*/
-VG_STATIC void world_routes_activate_gate( u32 id )
+VG_STATIC void world_routes_activate_gate( world_instance *world, u32 id )
{
- struct route_gate *rg = &world.gates[id];
- struct route_node *pnode = &world.nodes[rg->node_id],
- *pdest = &world.nodes[pnode->next[0]];
+ struct route_gate *rg = &world->gates[id];
+ struct route_node *pnode = &world->nodes[rg->node_id],
+ *pdest = &world->nodes[pnode->next[0]];
- world.last_use = world.time;
+ world_global.last_use = world_global.time;
- struct route_collector *rc = &world.collectors[ pdest->special_id ];
+ struct route_collector *rc = &world->collectors[ pdest->special_id ];
- world.active_gate = id;
- rg->timing.version = world.current_run_version;
- rg->timing.time = world.time;
+ world_global.active_gate = id;
+ rg->timing.version = world_global.current_run_version;
+ rg->timing.time = world_global.time;
- for( u32 i=0; i<world.route_count; i++ )
+ for( u32 i=0; i<world->route_count; i++ )
{
- struct route *route = &world.routes[i];
+ struct route *route = &world->routes[i];
int was_active = route->active;
{
if( pdest->route_ids[j] == i )
{
- world_routes_verify_run( i );
+ world_routes_verify_run( world, i );
route->active = 1;
break;
}
if( was_active && !route->active )
{
- struct route_ui_bar *pui = &world.ui_bars[i];
+ struct route_ui_bar *pui = &world_global.ui_bars[i];
pui->fade_start = pui->segment_start;
pui->fade_count = pui->segment_count;
- pui->fade_timer_start = world.time;
+ pui->fade_timer_start = world_global.time;
world_routes_ui_clear( pui );
vg_success( "CLEARING -> %u %u \n", pui->fade_start,
}
}
- world.current_run_version ++;
+ world_global.current_run_version ++;
- rc->timing.version = world.current_run_version;
- rc->timing.time = world.time;
- world.current_run_version ++;
+ rc->timing.version = world_global.current_run_version;
+ rc->timing.time = world_global.time;
+ world_global.current_run_version ++;
}
/*
*/
VG_STATIC void world_routes_notify_reset(void)
{
- world.rewind_from = world.time;
- world.rewind_to = world.last_use;
-
-#if 0
- for( int i=0; i<r->route_count; i++ )
- {
- struct route *route = &r->routes[i];
-
- if( route->active )
- world_routes_ui_notch( i, r->time - route->latest_pass );
- }
-#endif
+ world_global.rewind_from = world_global.time;
+ world_global.rewind_to = world_global.last_use;
}
/* Rewind between the saved points in time */
VG_STATIC void world_routes_rollback_time( double t )
{
- world.time = vg_lerp( world.rewind_to, world.rewind_from, t );
+ world_global.time = vg_lerp( world_global.rewind_to,
+ world_global.rewind_from, t );
}
/* draw lines along the paths */
-VG_STATIC void world_routes_debug(void)
+VG_STATIC void world_routes_debug( world_instance *world )
{
- for( int i=0; i<world.node_count; i++ )
+ for( int i=0; i<world->node_count; i++ )
{
- struct route_node *rn = &world.nodes[i];
+ struct route_node *rn = &world->nodes[i];
vg_line_pt3( rn->co, 1.0f, rn->special_type? 0xffffff00: 0xff00b2ff );
}
- for( int i=0; i<world.route_count; i++ )
+ for( int i=0; i<world->route_count; i++ )
{
- struct route *route = &world.routes[i];
+ struct route *route = &world->routes[i];
u32 stack[64];
- u32 si = world_routes_get_path( route->start, stack );
+ u32 si = world_routes_get_path( world, route->start, stack );
u32 colours[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
0xff5442f5 };
{
int sk = (sj+1)%si;
- struct route_node *pj = &world.nodes[stack[sj]],
- *pk = &world.nodes[stack[sk]];
+ struct route_node *pj = &world->nodes[stack[sj]],
+ *pk = &world->nodes[stack[sk]];
debug_sbpath( pj, pk, cc, (float)i );
}
}
- for( int i=0; i<world.node_count; i++ )
+ for( int i=0; i<world->node_count; i++ )
{
- struct route_node *ri = &world.nodes[i],
+ struct route_node *ri = &world->nodes[i],
*rj = NULL;
for( int j=0; j<2; j++ )
{
if( ri->next[j] != 0xffffffff )
{
- rj = &world.nodes[ri->next[j]];
+ rj = &world->nodes[ri->next[j]];
vg_line( ri->co, rj->co, 0x20ffffff );
}
}
}
}
-VG_STATIC void world_routes_create_mesh( u32 route_id )
+VG_STATIC void world_routes_create_mesh( world_instance *world, u32 route_id )
{
- struct route *route = &world.routes[ route_id ];
+ struct route *route = &world->routes[ route_id ];
u32 stack[64];
- u32 si = world_routes_get_path( route->start, stack );
+ u32 si = world_routes_get_path( world, route->start, stack );
u32 last_valid = 0;
{
int sk=(sj+1)%si;
- struct route_node *rnj = &world.nodes[ stack[sj] ],
- *rnk = &world.nodes[ stack[sk] ],
+ struct route_node *rnj = &world->nodes[ stack[sj] ],
+ *rnk = &world->nodes[ stack[sk] ],
*rnl;
if( rnj->special_type && rnk->special_type )
if( rnk->special_type )
{
- rnl = &world.nodes[ rnk->next[0] ];
+ rnl = &world->nodes[ rnk->next[0] ];
base_x1 = (float)rnl->ref_count*-0.5f + (float)rnl->current_refs;
}
ray_hit ha, hb;
ha.dist = 8.0f;
hb.dist = 8.0f;
- if( ray_world( sa, down, &ha ) &&
- ray_world( sb, down, &hb ))
+ if( ray_world( world, sa, down, &ha ) &&
+ ray_world( world, sb, down, &hb ))
{
scene_vert va, vb;
v2_zero( va.uv );
v2_zero( vb.uv );
- scene_push_vert( world.scene_lines, &va );
- scene_push_vert( world.scene_lines, &vb );
+ scene_push_vert( world->scene_lines, &va );
+ scene_push_vert( world->scene_lines, &vb );
if( last_valid )
{
/* Connect them with triangles */
- scene_push_tri( world.scene_lines, (u32[3]){
+ scene_push_tri( world->scene_lines, (u32[3]){
last_valid+0-2, last_valid+1-2, last_valid+2-2} );
- scene_push_tri( world.scene_lines, (u32[3]){
+ scene_push_tri( world->scene_lines, (u32[3]){
last_valid+1-2, last_valid+3-2, last_valid+2-2} );
}
- last_valid = world.scene_lines->vertex_count;
+ last_valid = world->scene_lines->vertex_count;
}
else
last_valid = 0;
rnj->current_refs ++;
}
- scene_copy_slice( world.scene_lines, &route->sm );
+ scene_copy_slice( world->scene_lines, &route->sm );
}
+VG_STATIC void world_scene_compute_light_clusters( world_instance *world,
+ scene *sc );
/*
* Create the strips of colour that run through the world along course paths
*/
-VG_STATIC void world_routes_generate(void)
+VG_STATIC void world_routes_generate( world_instance *world )
{
vg_info( "Generating route meshes\n" );
- world.scene_lines = scene_init( world.dynamic_vgl, 200000, 300000 );
+ world->scene_lines = scene_init( world_global.generic_heap, 200000, 300000 );
- for( u32 i=0; i<world.route_count; i++ )
- world_routes_create_mesh( i );
+ for( u32 i=0; i<world->route_count; i++ )
+ world_routes_create_mesh( world, i );
+
+ world_scene_compute_light_clusters( world, world->scene_lines );
vg_acquire_thread_sync();
{
- scene_upload( world.scene_lines, &world.mesh_route_lines );
+ scene_upload( world->scene_lines, &world->mesh_route_lines );
}
vg_release_thread_sync();
- vg_linear_del( world.dynamic_vgl, world.scene_lines );
+ vg_linear_del( world_global.generic_heap, world->scene_lines );
}
/* determine if special type is required for this gate */
-VG_STATIC enum route_special_type world_route_node_type( mdl_node *pnode )
+VG_STATIC enum route_special_type world_route_node_type( world_instance *world,
+ mdl_node *pnode )
{
if( pnode->classtype == k_classtype_gate )
{
- struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode );
+ struct classtype_gate *inf = mdl_get_entdata( world->meta, pnode );
if( inf->target )
{
- mdl_node *pother = mdl_node_from_id( world.meta, inf->target );
+ mdl_node *pother = mdl_node_from_id( world->meta, inf->target );
if( pother->classtype == k_classtype_gate )
{
}
/* count entities and allocate correct amount of memory in advance */
-VG_STATIC void world_routes_allocate(void)
+VG_STATIC void world_routes_allocate( world_instance *world )
{
vg_info( "Allocating routes\n" );
gate_count = 0,
collector_count = 0;
- for( int i=0; i<world.meta->info.node_count; i++ )
+ for( int i=0; i<world->meta->info.node_count; i++ )
{
- mdl_node *pnode = mdl_node_from_id( world.meta, i );
+ mdl_node *pnode = mdl_node_from_id( world->meta, i );
if( pnode->classtype == k_classtype_route_node ||
pnode->classtype == k_classtype_gate )
{
pnode->sub_uid = node_count;
- enum route_special_type type = world_route_node_type( pnode );
+ enum route_special_type type = world_route_node_type( world, pnode );
if( type == k_route_special_type_gate )
gate_count ++;
gate_size = gate_count * sizeof(struct route_gate),
collector_size = collector_count * sizeof(struct route_collector);
- world.nodes = vg_linear_alloc( world.dynamic_vgl, node_size );
- world.routes = vg_linear_alloc( world.dynamic_vgl, route_size );
- world.gates = vg_linear_alloc( world.dynamic_vgl, gate_size );
- world.collectors = vg_linear_alloc( world.dynamic_vgl, collector_size );
+ world->nodes = vg_linear_alloc( world_global.generic_heap, node_size );
+ world->routes = vg_linear_alloc( world_global.generic_heap, route_size );
+ world->gates = vg_linear_alloc( world_global.generic_heap, gate_size );
+ world->collectors = vg_linear_alloc( world_global.generic_heap,
+ collector_size );
}
/* create node from mdl node */
-VG_STATIC struct route_node *world_routes_create_node( mdl_node *pnode )
+VG_STATIC struct route_node *world_routes_create_node( world_instance *world,
+ mdl_node *pnode )
{
- struct route_node *rn = &world.nodes[ world.node_count ++ ];
+ struct route_node *rn = &world->nodes[ world->node_count ++ ];
m4x3f transform;
mdl_node_transform( pnode, transform );
}
/* retrieve the correct node id from mdl subuid */
-VG_STATIC u32 world_routes_get_subuid( u32 target )
+VG_STATIC u32 world_routes_get_subuid( world_instance *world, u32 target )
{
if( target == 0 )
return 0xffffffff;
else
- return mdl_node_from_id( world.meta, target )->sub_uid;
+ return mdl_node_from_id( world->meta, target )->sub_uid;
}
#if 0
#endif
/* process gate attachement onto node */
-VG_STATIC void world_routes_process_gate( struct route_node *rn,
+VG_STATIC void world_routes_process_gate( world_instance *world,
+ struct route_node *rn,
mdl_node *pnode )
{
- struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode );
+ struct classtype_gate *inf = mdl_get_entdata( world->meta, pnode );
/* H is later scaled based on link distance */
v3_normalize( rn->h );
- rn->next[0] = world_routes_get_subuid( inf->target );
+ rn->next[0] = world_routes_get_subuid( world, inf->target );
rn->next[1] = 0xffffffff;
- rn->special_type = world_route_node_type( pnode );
+ rn->special_type = world_route_node_type( world, pnode );
/* process gate type */
if( rn->special_type == k_route_special_type_gate )
{
- mdl_node *pother = mdl_node_from_id( world.meta, inf->target );
+ mdl_node *pother = mdl_node_from_id( world->meta, inf->target );
- struct route_gate *rg = &world.gates[ world.gate_count ];
+ struct route_gate *rg = &world->gates[ world->gate_count ];
- rg->node_id = world.node_count-1;
+ rg->node_id = world->node_count-1;
rg->timing.time = 0.0;
rg->timing.version = 0;
v2_copy( inf->dims, rg->gate.dims );
gate_transform_update( &rg->gate );
- rn->special_id = world.gate_count;
+ rn->special_id = world->gate_count;
- world.gate_count ++;
+ world->gate_count ++;
}
/* process collector type */
else if( rn->special_type == k_route_special_type_collector )
{
struct route_collector *rc =
- &world.collectors[ world.collector_count ];
+ &world->collectors[ world->collector_count ];
rc->timing.time = 0.0;
rc->timing.version = 0;
- rn->special_id = world.collector_count;
- world.collector_count ++;
+ rn->special_id = world->collector_count;
+ world->collector_count ++;
}
else
vg_fatal_exit_loop( "Invalid state" );
}
/* create route from node description */
-VG_STATIC void world_routes_create_route( mdl_node *pnode )
+VG_STATIC void world_routes_create_route( world_instance *world,
+ mdl_node *pnode )
{
- mdl_context *mdl = world.meta;
+ mdl_context *mdl = world->meta;
struct classtype_route *inf = mdl_get_entdata( mdl, pnode );
- struct route *route = &world.routes[ world.route_count ];
+ struct route *route = &world->routes[ world->route_count ];
memset( route, 0, sizeof(struct route) );
v3_copy( inf->colour, route->colour );
}
}
- route->start = world_routes_get_subuid( inf->id_start );
+ route->start = world_routes_get_subuid( world, inf->id_start );
route->active = 0;
route->factive = 0.0f;
mdl_node_transform( pnode, route->scoreboard_transform );
- struct route_ui_bar *pui = &world.ui_bars[ world.route_count ];
+ struct route_ui_bar *pui = &world_global.ui_bars[ world->route_count ];
pui->indices_head = k_route_ui_max_indices - 9;
pui->vertex_head = k_route_ui_max_verts - 200;
pui->segment_start = 0;
pui->fade_count = 0;
pui->fade_timer_start = 0.0;
- world.route_count ++;
+ world->route_count ++;
}
/* load all routes from model header */
-VG_STATIC void world_routes_process(void)
+VG_STATIC void world_routes_process( world_instance *world )
{
vg_info( "Initializing routes\n" );
- mdl_context *mdl = world.meta;
+ mdl_context *mdl = world->meta;
for( int i=0; i<mdl->info.node_count; i++ )
{
if( pnode->classtype == k_classtype_route_node ||
pnode->classtype == k_classtype_gate )
{
- struct route_node *rn = world_routes_create_node( pnode );
+ struct route_node *rn = world_routes_create_node( world, pnode );
if( pnode->classtype == k_classtype_gate )
{
- world_routes_process_gate( rn, pnode );
+ world_routes_process_gate( world, rn, pnode );
}
else
{
struct classtype_route_node *inf = mdl_get_entdata( mdl, pnode );
- rn->next[0] = world_routes_get_subuid( inf->target );
- rn->next[1] = world_routes_get_subuid( inf->target1 );
+ rn->next[0] = world_routes_get_subuid( world, inf->target );
+ rn->next[1] = world_routes_get_subuid( world, inf->target1 );
}
}
else if( pnode->classtype == k_classtype_route )
{
- world_routes_create_route( pnode );
+ world_routes_create_route( world, pnode );
}
}
/*
* Gather references
*/
- for( int i=0; i<world.route_count; i++ )
+ for( int i=0; i<world->route_count; i++ )
{
- struct route *route = &world.routes[i];
+ struct route *route = &world->routes[i];
u32 stack[64];
- u32 si = world_routes_get_path( route->start, stack );
+ u32 si = world_routes_get_path( world, route->start, stack );
for( int sj=0; sj<si; sj++ )
{
- struct route_node *rn = &world.nodes[ stack[sj] ];
+ struct route_node *rn = &world->nodes[ stack[sj] ];
rn->route_ids[ rn->ref_count ++ ] = i;
if( rn->ref_count > 4 )
VG_STATIC void world_routes_init(void)
{
- world.current_run_version = 2;
- world.time = RESET_MAX_TIME*2.0;
- world.last_use = 0.0;
+ world_global.current_run_version = 2;
+ world_global.time = RESET_MAX_TIME*2.0;
+ world_global.last_use = 0.0;
shader_scene_route_register();
shader_routeui_register();
vg_acquire_thread_sync();
{
/* UI buffers */
- for( int i=0; i<vg_list_size(world.ui_bars); i++ )
+ for( int i=0; i<vg_list_size(world_global.ui_bars); i++ )
{
/* OpenGL strips */
- struct route_ui_bar *pui = &world.ui_bars[i];
+ struct route_ui_bar *pui = &world_global.ui_bars[i];
glGenVertexArrays( 1, &pui->vao );
glGenBuffers( 1, &pui->vbo );
vg_release_thread_sync();
}
-VG_STATIC void world_routes_update(void)
+VG_STATIC void world_routes_update( world_instance *world )
{
- world.time += vg.time_delta;
+ world_global.time += vg.time_delta;
- for( int i=0; i<world.route_count; i++ )
+ for( int i=0; i<world->route_count; i++ )
{
- struct route *route = &world.routes[i];
+ struct route *route = &world->routes[i];
route->factive = vg_lerpf( route->factive, route->active,
0.6f*vg.time_delta );
if( route->active )
{
- world_routes_ui_updatetime(i, world.time - route->latest_pass );
+ world_routes_ui_updatetime(i, world_global.time - route->latest_pass );
}
}
}
VG_STATIC void bind_terrain_noise(void);
-VG_STATIC void render_world_routes( camera *cam )
+VG_STATIC void render_world_routes( world_instance *world, camera *cam )
{
m4x3f identity_matrix;
m4x3_identity( identity_matrix );
shader_scene_route_use();
shader_scene_route_uTexGarbage(0);
- shader_link_standard_ub( _shader_scene_route.id, 2 );
+ world_link_lighting_ub( world, _shader_scene_route.id, 2 );
bind_terrain_noise();
shader_scene_route_uPv( cam->mtx.pv );
shader_scene_route_uBoard0( TEMP_BOARD_0 );
shader_scene_route_uBoard1( TEMP_BOARD_1 );
- mesh_bind( &world.mesh_route_lines );
+ mesh_bind( &world->mesh_route_lines );
- for( int i=0; i<world.route_count; i++ )
+ for( int i=0; i<world->route_count; i++ )
{
- struct route *route = &world.routes[i];
+ struct route *route = &world->routes[i];
v4f colour;
v3_lerp( (v3f){0.7f,0.7f,0.7f}, route->colour, route->factive, colour );
}
}
-VG_STATIC void render_world_routes_ui(void)
+VG_STATIC void render_world_routes_ui( world_instance *world )
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
float active_offset = 0.0f;
- for( int i=0; i<world.route_count; i++ )
+ for( int i=0; i<world->route_count; i++ )
{
- struct route *route = &world.routes[i];
- world_routes_ui_draw( i, route->colour, active_offset );
+ struct route *route = &world->routes[i];
+ world_routes_ui_draw( world, i, route->colour, active_offset );
active_offset += route->factive;
}
VG_STATIC void sfd_encode( u32 row, const char *str )
{
int end=0;
- u32 row_h = world.sfd.h -1 -row;
+ u32 row_h = world_global.sfd.h -1 -row;
- for( int i=0; i<world.sfd.w; i++ )
+ for( int i=0; i<world_global.sfd.w; i++ )
{
- u32 idx = (world.sfd.w*row_h + i) * 2;
+ u32 idx = (world_global.sfd.w*row_h + i) * 2;
if( end )
{
- world.sfd.buffer[idx] = 0.0f;
+ world_global.sfd.buffer[idx] = 0.0f;
}
else
{
if( !str[i] )
end = 1;
- world.sfd.buffer[idx] = sfd_encode_glyph( str[i] );
+ world_global.sfd.buffer[idx] = sfd_encode_glyph( str[i] );
}
}
}
VG_STATIC void sfd_update(void)
{
- for( int i=0; i<world.sfd.w*world.sfd.h; i++ )
+ for( int i=0; i<world_global.sfd.w*world_global.sfd.h; i++ )
{
- float *target = &world.sfd.buffer[i*2+0],
- *cur = &world.sfd.buffer[i*2+1];
+ float *target = &world_global.sfd.buffer[i*2+0],
+ *cur = &world_global.sfd.buffer[i*2+1];
float const rate = vg.time_delta * 15.2313131414f;
float d1 = *target-*cur;
{
if( argc == 2 )
{
- int row = vg_min( vg_max(atoi(argv[0]),0), world.sfd.h);
+ int row = vg_min( vg_max(atoi(argv[0]),0), world_global.sfd.h);
sfd_encode( row, argv[1] );
}
vg_acquire_thread_sync();
{
- scene_upload( sc, &world.sfd.mesh_display );
- mdl_unpack_submesh( mboard, &world.sfd.mesh_base, backer );
+ scene_upload( sc, &world_global.sfd.mesh_display );
+ mdl_unpack_submesh( mboard, &world_global.sfd.mesh_base, backer );
vg_tex2d_init( (vg_tex2d *[]){ &tex_scoretext }, 1 );
}
int w = 27,
h = 13;
- world.sfd.w = w;
- world.sfd.h = h;
- world.sfd.buffer = vg_linear_alloc( vg_mem.rtmemory, 2*w*h*sizeof(float) );
+ world_global.sfd.w = w;
+ world_global.sfd.h = h;
+ world_global.sfd.buffer =
+ vg_linear_alloc( vg_mem.rtmemory, 2*w*h*sizeof(float) );
for( int i=0; i<w*h*2; i++ )
- world.sfd.buffer[i] = 0.0f;
+ world_global.sfd.buffer[i] = 0.0f;
}
#endif /* SFD_H */
vg_success( "done\n" );
}
-VG_STATIC void water_set_surface( float height )
+VG_STATIC void water_set_surface( world_instance *world, float height )
{
- world.water.height = height;
- v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world.water.plane );
+ world->water.height = height;
+ v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world->water.plane );
}
+VG_STATIC void world_link_lighting_ub( world_instance *world,
+ GLuint shader, int texture_id );
+
/*
* Does not write motion vectors
*/
-VG_STATIC void render_water_texture( camera *cam )
+VG_STATIC void render_water_texture( world_instance *world, camera *cam )
{
- if( !world.water.enabled || (vg.quality_profile == k_quality_profile_low) )
+ if( !world->water.enabled || (vg.quality_profile == k_quality_profile_low) )
return;
/* Draw reflection buffa */
/*
* Create flipped view matrix. Don't care about motion vectors
*/
- float cam_height = cam->transform[3][1] - world.water.height;
+ float cam_height = cam->transform[3][1] - world->water.height;
camera water_cam;
water_cam.farz = cam->farz;
/*
* Create clipped projection
*/
- v4f clippa = { 0.0f, 1.0f, 0.0f, world.water.height-0.1f };
+ v4f clippa = { 0.0f, 1.0f, 0.0f, world->water.height-0.1f };
m4x3_mulp( water_cam.transform_inverse, clippa, clippa );
clippa[3] *= -1.0f;
* Draw world
*/
glCullFace( GL_FRONT );
- render_world( &water_cam );
+ render_world( world, &water_cam );
glCullFace( GL_BACK );
/*
m4x3_copy( cam->transform, beneath_cam.transform );
camera_update_view( &beneath_cam );
- float bias = -(cam->transform[3][1]-world.water.height)*0.1f;
+ float bias = -(cam->transform[3][1]-world->water.height)*0.1f;
- v4f clippb = { 0.0f, -1.0f, 0.0f, -(world.water.height) + bias };
+ v4f clippb = { 0.0f, -1.0f, 0.0f, -(world->water.height) + bias };
m4x3_mulp( beneath_cam.transform_inverse, clippb, clippb );
clippb[3] *= -1.0f;
m4x4_clip_projection( beneath_cam.mtx.p, clippb );
camera_finalize( &beneath_cam );
- render_world_depth( &beneath_cam );
+ render_world_depth( world, &beneath_cam );
glViewport( 0, 0, vg.window_x, vg.window_y );
}
-VG_STATIC void render_water_surface( camera *cam )
+VG_STATIC void render_water_surface( world_instance *world, camera *cam )
{
- if( !world.water.enabled )
+ if( !world->water.enabled )
return;
if( vg.quality_profile == k_quality_profile_high )
1.0f / (float)vg.window_x,
1.0f / (float)vg.window_y });
- shader_link_standard_ub( _shader_model_water.id, 2 );
+ world_link_lighting_ub( world, _shader_model_water.id, 2 );
render_fb_bind_texture( gpipeline.fb_water_beneath, 0, 3 );
shader_model_water_uTexBack( 3 );
- shader_model_water_uTime( world.time );
+ shader_model_water_uTime( world_global.time );
shader_model_water_uCamera( cam->transform[3] );
- shader_model_water_uSurfaceY( world.water.height );
+ shader_model_water_uSurfaceY( world->water.height );
shader_model_water_uPv( cam->mtx.pv );
shader_model_water_uPvmPrev( cam->mtx_prev.pv );
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
- mesh_bind( &world.mesh_no_collide );
+ mesh_bind( &world->mesh_no_collide );
- for( int i=0; i<world.material_count; i++ )
+ for( int i=0; i<world->material_count; i++ )
{
- struct world_material *mat = &world.materials[i];
+ struct world_material *mat = &world->materials[i];
if( mat->info.shader == k_shader_water )
{
vg_tex2d_bind( &tex_water_surf, 1 );
shader_model_water_fast_uTexDudv( 1 );
- shader_model_water_fast_uTime( world.time );
+ shader_model_water_fast_uTime( world_global.time );
shader_model_water_fast_uCamera( cam->transform[3] );
- shader_model_water_fast_uSurfaceY( world.water.height );
- shader_link_standard_ub( _shader_model_water_fast.id, 2 );
+ shader_model_water_fast_uSurfaceY( world->water.height );
+ world_link_lighting_ub( world, _shader_model_water_fast.id, 2 );
m4x3f full;
m4x3_identity( full );
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
- mesh_bind( &world.mesh_no_collide );
+ mesh_bind( &world->mesh_no_collide );
- for( int i=0; i<world.material_count; i++ )
+ for( int i=0; i<world->material_count; i++ )
{
- struct world_material *mat = &world.materials[i];
+ struct world_material *mat = &world->materials[i];
if( mat->info.shader == k_shader_water )
{