path = F"{folder}{collection.name}.mdl"
print( path )
+ os.makedirs(os.path.dirname(path),exist_ok=True)
fp = open( path, "wb" )
header = mdl_header()
header.version = 101
stack[2] = bh->nodes[0].ir;
v3f dir_inv;
- dir_inv[0] = 1.0f/dir[0];
- dir_inv[1] = 1.0f/dir[1];
- dir_inv[2] = 1.0f/dir[2];
+ v3_div( (v3f){1.0f,1.0f,1.0f}, dir, dir_inv );
while(depth){
bh_node *inode = &bh->nodes[ stack[depth] ];
typedef struct bh_iter bh_iter;
struct bh_iter
{
- struct
- {
- int id, depth;
+ struct {
+ i32 id, depth;
}
stack[64];
- int depth, i;
+ enum bh_query_type{
+ k_bh_query_box,
+ k_bh_query_ray
+ }
+ query;
+
+ union{
+ struct{
+ boxf box;
+ }
+ box;
+
+ struct{
+ v3f co, inv_dir;
+ f32 max_dist;
+ }
+ ray;
+ };
+
+ i32 depth, i;
};
-VG_STATIC void bh_iter_init( int root, bh_iter *it )
+VG_STATIC void bh_iter_init_box( i32 root, bh_iter *it, boxf box )
{
+ it->query = k_bh_query_box;
it->stack[0].id = root;
it->stack[0].depth = 0;
it->depth = 0;
it->i = 0;
+
+ box_copy( box, it->box.box );
}
-VG_STATIC int bh_next( bh_tree *bh, bh_iter *it, boxf box, int *em )
+VG_STATIC void bh_iter_init_ray( i32 root, bh_iter *it, v3f co,
+ v3f dir, f32 max_dist )
+{
+ it->query = k_bh_query_ray;
+ it->stack[0].id = root;
+ it->stack[0].depth = 0;
+ it->depth = 0;
+ it->i = 0;
+
+ v3_div( (v3f){1.0f,1.0f,1.0f}, dir, it->ray.inv_dir );
+ v3_copy( co, it->ray.co );
+ it->ray.max_dist = max_dist;
+}
+
+VG_STATIC i32 bh_next( bh_tree *bh, bh_iter *it, i32 *em )
{
while( it->depth >= 0 ){
bh_node *inode = &bh->nodes[ it->stack[it->depth].id ];
/* Only process overlapping nodes */
- if( !box_overlap( inode->bbx, box ) ){
+ i32 q = 0;
+
+ if( it->query == k_bh_query_box )
+ q = box_overlap( inode->bbx, it->box.box );
+ else
+ q = ray_aabb1( inode->bbx, it->ray.co,
+ it->ray.inv_dir, it->ray.max_dist );
+
+ if( !q ){
it->depth --;
continue;
}
vg_loader_start( workshop_scan_thread, NULL );
}
+/*
+ * op: k_async_op_world_scan
+ * -----------------------------------------------------------------------------
+ */
+
+/*
+ * Reciever for scan completion. copies the registry_count back into t0
+ */
+VG_STATIC void workshop_async_world_reg_update( void *data, u32 size )
+{
+ vg_info( "World registry update notify\n" );
+ global_skateshop.world_registry_count =
+ global_skateshop.t1_world_registry_count;
+ skaterift_end_op();
+}
+
+/*
+ * Add a local world folder to the registry, it will verify existing ones are
+ * still there too.
+ */
+VG_STATIC void world_scan_register_local( const char *folder_name )
+{
+ u32 hash = vg_strdjb2( folder_name );
+ for( u32 i=0; i<global_skateshop.t1_world_registry_count; i++ ){
+ struct registry_world *reg =
+ &global_skateshop.world_registry[i];
+
+ if( const_str_eq( hash, folder_name, reg->foldername ) ){
+ reg->state = k_registry_board_state_indexed;
+ return;
+ }
+ }
+
+ if( global_skateshop.t1_world_registry_count == SKATESHOP_WORLDS_MAX ){
+ vg_error( "You have too many worlds installed!\n" );
+ return;
+ }
+
+ vg_info( "new listing!: %s\n", folder_name );
+
+ struct registry_world *reg = &global_skateshop.world_registry[
+ global_skateshop.t1_world_registry_count ++ ];
+
+ vg_strncpy( folder_name, reg->foldername, 64, k_strncpy_overflow_fatal );
+ reg->foldername_hash = hash;
+ reg->state = k_registry_board_state_indexed;
+ reg->meta_present = 0;
+}
+
+/*
+ * Async thread which scans local files for boards, as well as scheduling
+ * synchronous calls to the workshop
+ */
+VG_STATIC void world_scan_thread( void *_args )
+{
+ vg_linear_clear( vg_mem.scratch );
+
+ for( u32 i=0; i<global_skateshop.t1_world_registry_count; i++ ){
+ struct registry_world *reg = &global_skateshop.world_registry[i];
+ reg->state = k_registry_board_state_indexed_absent;
+ }
+
+ /*
+ * Local disk scan
+ */
+ vg_info( "Scanning maps/*.mdl\n" );
+
+ char path_buf[4096];
+ vg_str path;
+ vg_strnull( &path, path_buf, 4096 );
+ vg_strcat( &path, "maps/" );
+
+ DIR *dir = opendir( path.buffer );
+ if( !dir ){
+ vg_error( "opendir('maps') failed\n" );
+ vg_async_call( workshop_async_any_complete, NULL, 0 );
+ return;
+ }
+
+ struct dirent *entry;
+ while( (entry = readdir(dir)) ){
+ if( entry->d_type == DT_DIR ){
+ if( entry->d_name[0] == '.' ) continue;
+
+ vg_str folder = path;
+ char *folder_name = folder.buffer+folder.i;
+
+ if( strlen( entry->d_name ) >
+ vg_list_size(global_skateshop.world_registry[0].foldername)){
+ vg_warn( "Map folder too long: %s\n", entry->d_name );
+ continue;
+ }
+
+ vg_strcat( &folder, entry->d_name );
+ if( !vg_strgood( &folder ) ) break;
+
+ DIR *subdir = opendir( folder.buffer );
+ while( (entry = readdir(subdir)) ){
+ if( entry->d_type == DT_REG ){
+ if( entry->d_name[0] == '.' ) continue;
+
+ vg_str file = folder;
+ vg_strcat( &file, "/" );
+ vg_strcat( &file, entry->d_name );
+ if( !vg_strgood( &file ) ) break;
+
+ char *ext = vg_strch( &file, '.' );
+ if( !ext ) continue;
+ if( strcmp(ext,".mdl") ) continue;
+
+ vg_strcat( &folder, "" );
+ world_scan_register_local( folder_name );
+ }
+ }
+ closedir(subdir);
+ }
+ }
+ closedir(dir);
+
+ vg_async_call( workshop_async_world_reg_update, NULL, 0 );
+
+#if 0
+ tinydir_close(&dir);
+
+ if( steam_ready ) workshop_steam_scan();
+
+ vg_async_call( workshop_async_reg_update, NULL, 0 );
+ vg_async_stall();
+ workshop_visibile_load_loop_thread(NULL);
+#endif
+}
+
+/*
+ * Asynchronous scan of local disk for worlds
+ */
+VG_STATIC void skateshop_op_world_scan(void)
+{
+ skaterift_begin_op( k_async_op_world_scan );
+ vg_loader_start( world_scan_thread, NULL );
+}
+
/*
* Regular stuff
* -----------------------------------------------------------------------------
VG_STATIC void skateshop_init(void)
{
u32 reg_size = sizeof(struct registry_board)*SKATESHOP_REGISTRY_MAX,
+ wreg_size = sizeof(struct registry_world)*SKATESHOP_WORLDS_MAX,
cache_size = sizeof(struct cache_board)*SKATESHOP_BOARD_CACHE_MAX;
global_skateshop.registry = vg_linear_alloc( vg_mem.rtmemory, reg_size );
- global_skateshop.registry_count = 0;
+ global_skateshop.world_registry =
+ vg_linear_alloc( vg_mem.rtmemory, wreg_size );
global_skateshop.cache = vg_linear_alloc( vg_mem.rtmemory, cache_size );
memset( global_skateshop.cache, 0, cache_size );
}
}
else if( shop->type == k_skateshop_type_worldshop ){
- gui_helper_action( axis_display_string( k_sraxis_mbrowse_h ), "browse" );
-
- v2f input;
- joystick_state( k_srjoystick_steer, input );
- pointcloud.control[0] += input[0] * vg.time_delta;
- pointcloud.control[2] += input[1] * vg.time_delta;
+ if( global_skateshop.world_registry_count ){
+ gui_helper_action( axis_display_string(k_sraxis_mbrowse_h), "browse" );
+ }
+
+ int change = 0;
+ if( button_down( k_srbind_mleft ) ){
+ if( global_skateshop.selected_world_id > 0 ){
+ global_skateshop.selected_world_id --;
+ change = 1;
+ }
+ }
- pointcloud.control[0] = vg_clampf( pointcloud.control[0], -10.0f, 10.0f );
- pointcloud.control[2] = vg_clampf( pointcloud.control[2], -10.0f, 10.0f );
+ if( button_down( k_srbind_mright ) ){
+ if( global_skateshop.selected_world_id+1 <
+ global_skateshop.world_registry_count ){
+ global_skateshop.selected_world_id ++;
+ change = 1;
+ }
+ }
+
+ if( change && (pointcloud.anim == k_pointcloud_anim_idle) ){
+ pointcloud.anim = k_pointcloud_anim_hiding;
+ pointcloud.anim_start = vg.time;
+ }
- if( button_press( k_srbind_trick1 ) ){
- pointcloud.control[3] += vg.time_delta*0.2f;
+ if( button_down( k_srbind_maccept ) ){
+ vg_info( "Select world (%u)\n", global_skateshop.selected_world_id );
+ global_skateshop_exit();
+ return;
}
- if( button_press( k_srbind_trick0 ) ){
- pointcloud.control[3] -= vg.time_delta*0.2f;
-}
- pointcloud.control[3] = vg_clampf( pointcloud.control[3], 0.001f, 10.0f );
}
else{
vg_fatal_error( "Unknown store (%u)\n", shop->type );
mlocal[3][0] = -font3d_string_width( &world_global.font, 0, info->title );
mlocal[3][0] *= scale*0.5f;
mlocal[3][1] = 0.1f;
+ mlocal[3][2] = 0.0f;
m4x3_mul( mtext, mlocal, mmdl );
font3d_simple_draw( &world_global.font, 0, info->title, &main_camera, mmdl );
info->author_name );
mlocal[3][0] *= scale*0.5f;
mlocal[3][1] = 0.0f;
+ mlocal[3][2] = 0.0f;
m4x3_mul( mtext, mlocal, mmdl );
font3d_simple_draw( &world_global.font, 0,
info->author_name, &main_camera, mmdl );
{
world_instance *world = get_active_world();
- m4x3f mmdl;
ent_skateshop *shop = global_skateshop.ptr_ent;
ent_marker *mark_display = mdl_arritm( &world->ent_marker,
- mdl_entity_id_id(shop->worlds.id_display));
- mdl_transform_m4x3( &mark_display->transform, mmdl );
-
- /* TODO? ... */
-#if 0
- v3f vol;
- v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], vol );
-
- v2f rect = { 1.0f, 1.0f },
- map = { vol[0], vol[2] },
- result;
-
- f32 rp = rect[0] * map[1],
- rc = rect[1] * map[0];
+ mdl_entity_id_id(shop->worlds.id_display)),
+ *mark_info = mdl_arritm( &world->ent_marker,
+ mdl_entity_id_id(shop->boards.id_info));
+
+ /* Text */
+ char buftext[128], bufsubtext[128];
+ vg_str info, subtext;
+ vg_strnull( &info, buftext, 128 );
+ vg_strnull( &subtext, bufsubtext, 128 );
- u32 axis, other;
- if( rc > rp ) axis = 0;
- else axis = 1;
- other = axis ^ 0x1;
-
- result[axis] = rect[axis];
- result[other] = (rect[axis] * map[other]) / map[axis];
+ if( global_skateshop.world_registry_count ){
+ struct registry_world *rw = &global_skateshop.world_registry[
+ global_skateshop.selected_world_id ];
+
+ info.i+=highscore_intl( info.buffer+info.i,
+ global_skateshop.selected_world_id+1, 3 );
+ info.buffer[info.i++] = '/';
+ info.i+=highscore_intl( info.buffer+info.i,
+ global_skateshop.world_registry_count, 3 );
+ info.buffer[info.i++] = ' ';
+ info.buffer[info.i] = '\0';
+
+ if( rw->meta_present ){
+ vg_fatal_error("");
+ }
+ else{
+ vg_strcat( &info, rw->foldername );
+ vg_strcat( &subtext, "No information" );
+ }
+ }
+ else{
+ vg_strcat( &info, "No worlds installed" );
+ }
- m4x3f mlocal, mx;
- m4x3_identity( mlocal );
+ m4x3f mtext,mlocal,mtextmdl;
+ mdl_transform_m4x3( &mark_info->transform, mtext );
- mlocal[0][0] = result[0];
- mlocal[2][2] = result[1];
- mlocal[1][1] = (vol[1]/vol[0]) * mlocal[0][0];
- mlocal[3][0] = (rect[0]-result[0])*0.5f - rect[0]*0.5f; /* sea level? */
- mlocal[3][2] = (rect[1]-result[1])*0.5f - rect[1]*0.5f;
- m4x3_mul( mmdl, mlocal, mx );
-#endif
+ font3d_bind( &world_global.font, &main_camera );
+ shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
+ float scale = 0.2f, thickness = 0.015f, scale1 = 0.08f;
+ m3x3_zero( mlocal );
+ m3x3_setdiagonalv3( mlocal, (v3f){ scale, scale, thickness } );
+ mlocal[3][0] = -font3d_string_width( &world_global.font, 0, buftext );
+ mlocal[3][0] *= scale*0.5f;
+ mlocal[3][1] = 0.1f;
+ mlocal[3][2] = 0.0f;
+ m4x3_mul( mtext, mlocal, mtextmdl );
+ font3d_simple_draw( &world_global.font, 0, buftext, &main_camera, mtextmdl );
+
+ m3x3_setdiagonalv3( mlocal, (v3f){ scale1, scale1, thickness } );
+ mlocal[3][0] = -font3d_string_width( &world_global.font, 0, bufsubtext );
+ mlocal[3][0] *= scale1*0.5f;
+ mlocal[3][1] = -scale1*0.3f;
+ m4x3_mul( mtext, mlocal, mtextmdl );
+ font3d_simple_draw( &world_global.font, 0, bufsubtext,
+ &main_camera, mtextmdl );
+
+ /* pointcloud */
+ m4x3f mmdl;
+ mdl_transform_m4x3( &mark_display->transform, mmdl );
m4x3_rotate_y( mmdl, vg.time * 0.2 );
-#if 1
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDisable(GL_DEPTH_TEST);
-#endif
pointcloud_render( world, &main_camera, mmdl );
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
skateshop_update_viewpage();
workshop_op_item_scan();
}
+ else if( shop->type == k_skateshop_type_worldshop ){
+ pointcloud.anim = k_pointcloud_anim_opening;
+ pointcloud.anim_start = vg.time;
+ skateshop_op_world_scan();
+ }
}
}
#define SKATESHOP_REGISTRY_MAX 64
#define SKATESHOP_BOARD_CACHE_MAX 10
+#define SKATESHOP_WORLDS_MAX 32
#define SKATESHOP_VIEW_SLOT_MAX 6
#define SKATESHOP_REGISTRYID_NONE 0xffffffff
registry_count;
u32 selected_registry_id;
+
+ /* worlds */
+ struct registry_world{
+ enum registry_board_state state;
+ char foldername[64];
+ u32 foldername_hash;
+
+ int meta_present;
+ ent_worldinfo info;
+ }
+ *world_registry;
+ u32 t1_world_registry_count,
+ world_registry_count,
+ selected_world_id;
}
static global_skateshop;
boxf box;
v3_add( pos, (v3f){ r, r, r }, box[1] );
v3_sub( pos, (v3f){ r, r, r }, box[0] );
-
- bh_iter it;
- bh_iter_init( 0, &it );
- int idx;
struct grind_sample
{
v3_cross( plane, player->basis[1], support_axis );
v3_normalize( support_axis );
- while( bh_next( world->geo_bh, &it, box, &idx ) ){
+ bh_iter it;
+ bh_iter_init_box( 0, &it, box );
+ i32 idx;
+
+ while( bh_next( world->geo_bh, &it, &idx ) ){
u32 *ptri = &world->scene_geo.arrindices[ idx*3 ];
v3f tri[3];
struct pointcloud{
GLuint vao, vbo;
u32 count;
- v4f control;
+
+ f64 anim_start;
+ f32 visibility;
+ enum pointcloud_anim{
+ k_pointcloud_anim_opening = 0,
+ k_pointcloud_anim_hiding = 1,
+ k_pointcloud_anim_idle = 2
+ }
+ anim;
}
-static pointcloud = { .control = {0.0f,0.0f,0.0f,1.0f} };
+static pointcloud;
#pragma pack(push,1)
struct pointcloud_vert{
static void pointcloud_render( world_instance *world, camera *cam, m4x3f model )
{
+ if( pointcloud.anim != k_pointcloud_anim_idle ){
+ f32 const k_transition = 1.0f;
+ f32 t = (vg.time - pointcloud.anim_start) / k_transition;
+
+ if( pointcloud.anim == k_pointcloud_anim_hiding ){
+ if( t > 1.0f ){
+ pointcloud.visibility = 0.0f;
+ pointcloud.anim = k_pointcloud_anim_idle;
+ }
+ else pointcloud.visibility = 1.0f-t;
+ }
+ else if( pointcloud.anim == k_pointcloud_anim_opening ){
+ if( t > 1.0f ){
+ pointcloud.visibility = 1.0f;
+ pointcloud.anim = k_pointcloud_anim_idle;
+ }
+ else pointcloud.visibility = t;
+ }
+ }
+
+ if( pointcloud.visibility == 0.0f ) return;
+
m4x4f upvmprev;
m4x3_expand( model, upvmprev );
m4x4_mul( cam->mtx_prev.pv, upvmprev, upvmprev );
shader_point_map_uPvmPrev( upvmprev );
shader_point_map_uMdl( model );
shader_point_map_uCamera( cam->pos );
- shader_point_map_uTime( (v2f){ vg.time, sinf(vg.time) } );
- shader_point_map_uTransform( pointcloud.control );
+ shader_point_map_uAnim( (v4f){ 32, 1.0f-pointcloud.visibility,
+ 0.0f, vg.time } );
glBindVertexArray( pointcloud.vao );
glEnable( GL_PROGRAM_POINT_SIZE );
{
scene_context *sc = s->bh_scene->user;
- bh_iter it;
- bh_iter_init( 0, &it );
- int idx;
-
int count = 0;
float r = b->radius + 0.1f;
boxf box;
v3_sub( mtxA[3], (v3f){ r,r,r }, box[0] );
v3_add( mtxA[3], (v3f){ r,r,r }, box[1] );
+
+ bh_iter it;
+ i32 idx;
+ bh_iter_init_box( 0, &it, box );
- while( bh_next( s->bh_scene, &it, box, &idx ) ){
+ while( bh_next( s->bh_scene, &it, &idx ) ){
u32 *ptri = &sc->arrindices[ idx*3 ];
v3f tri[3];
m4x3_invert_affine( mtxA, to_local );
bh_iter it;
- bh_iter_init( 0, &it );
+ bh_iter_init_box( 0, &it, world_bbx );
int idx;
int count = 0;
vg_line_boxf( world_bbx, VG__RED );
- while( bh_next( s->bh_scene, &it, world_bbx, &idx ) ){
+ while( bh_next( s->bh_scene, &it, &idx ) ){
u32 *ptri = &sc->arrindices[ idx*3 ];
for( int j=0; j<3; j++ )
m4x3f mtxB, rb_scene *s,
rb_ct *buf )
{
- bh_iter it;
- bh_iter_init( 0, &it );
- int idx;
int count = 0;
boxf bbx;
scene_context *sc = s->bh_scene->user;
- while( bh_next( s->bh_scene, &it, bbx, &idx ) ){
+ bh_iter it;
+ bh_iter_init_box( 0, &it, bbx );
+ i32 idx;
+ while( bh_next( s->bh_scene, &it, &idx ) ){
u32 *ptri = &sc->arrindices[ idx*3 ];
v3f tri[3];
uniform mat3 uNormMtx;
uniform mat4 uPv;
uniform mat4 uPvmPrev;
-uniform vec2 uTime;
-uniform vec4 uTransform;
+uniform vec4 uAnim;
out vec4 aColour;
out vec3 aWorldCo;
return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y));
}
-vec3 mapP( vec3 p )
+vec3 gridify( vec3 p, float s, float t )
{
- return p;
- float t = max(0.0,uTime.y);
+ vec3 co = p*s;
+ vec2 r2 = rand_hash22(p.xz);
+ vec3 grid = vec3(floor(co.x),co.y,floor(co.z)) * (1.0/s);
- vec3 lco = p * 20.0;
- vec3 grid = vec3(floor(lco.x),lco.y,floor(lco.z));//fract(p);
+ float t1 = 1.0-t;
+ t1 = 1.0-t1*t1;
+ float t2 = t*t;
- return mix(p,grid * (1.0/20.0), t)*vec3(1.0+t,1.0-t,1.0+t);
+ return mix( p, grid, t1 ) + t2*vec3(0.0,r2.y*r2.y*0.2,0.0);
}
void main()
{
- vec3 mco = a_co.xyz * uTransform.w + uTransform.xyz;
+ vec3 co = gridify( a_co.xyz, uAnim.x, uAnim.y );
-
- vec3 center = vec3(0.5);
- vec3 lco = mapP(mco);
-
- vec3 world_pos0 = uMdl * vec4( mco, 1.0 );
+ vec3 world_pos0 = uMdl * vec4( co, 1.0 );
vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );
- vec4 vproj1 = uPvmPrev * vec4( mco, 1.0 );
+ vec4 vproj1 = uPvmPrev * vec4( co, 1.0 );
- float t = max(0.0,uTime.y);
- float scaler = smoothstep(0.6,0.58,length(lco.xz));
+ float scaler = smoothstep(0.6,0.58,length(co.xz));
vs_motion_out( vproj0, vproj1 );
gl_Position = vproj0;
- gl_PointSize = (9.0*uTransform.w*scaler) / (gl_Position.z + 0.01);
+ gl_PointSize = (9.0*scaler) / (gl_Position.z + 0.01);
aWorldCo = world_pos0;
- aColour = a_colour*scaler;
- aCo = mco;
+ aColour = a_colour*scaler*(1.0-uAnim.y*uAnim.y);
+ aCo = co;
}
"uniform mat3 uNormMtx;\n"
"uniform mat4 uPv;\n"
"uniform mat4 uPvmPrev;\n"
-"uniform vec2 uTime;\n"
-"uniform vec4 uTransform;\n"
+"uniform vec4 uAnim;\n"
"\n"
"out vec4 aColour;\n"
"out vec3 aWorldCo;\n"
" return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y));\n"
"}\n"
"\n"
-"vec3 mapP( vec3 p )\n"
+"vec3 gridify( vec3 p, float s, float t )\n"
"{\n"
-" return p;\n"
-" float t = max(0.0,uTime.y);\n"
+" vec3 co = p*s;\n"
+" vec2 r2 = rand_hash22(p.xz);\n"
+" vec3 grid = vec3(floor(co.x),co.y,floor(co.z)) * (1.0/s);\n"
"\n"
-" vec3 lco = p * 20.0;\n"
-" vec3 grid = vec3(floor(lco.x),lco.y,floor(lco.z));//fract(p);\n"
+" float t1 = 1.0-t;\n"
+" t1 = 1.0-t1*t1;\n"
+" float t2 = t*t;\n"
"\n"
-" return mix(p,grid * (1.0/20.0), t)*vec3(1.0+t,1.0-t,1.0+t);\n"
+" return mix( p, grid, t1 ) + t2*vec3(0.0,r2.y*r2.y*0.2,0.0);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
-" vec3 mco = a_co.xyz * uTransform.w + uTransform.xyz;\n"
+" vec3 co = gridify( a_co.xyz, uAnim.x, uAnim.y );\n"
"\n"
-"\n"
-" vec3 center = vec3(0.5);\n"
-" vec3 lco = mapP(mco);\n"
-"\n"
-" vec3 world_pos0 = uMdl * vec4( mco, 1.0 );\n"
+" vec3 world_pos0 = uMdl * vec4( co, 1.0 );\n"
" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n"
-" vec4 vproj1 = uPvmPrev * vec4( mco, 1.0 );\n"
+" vec4 vproj1 = uPvmPrev * vec4( co, 1.0 );\n"
"\n"
-" float t = max(0.0,uTime.y);\n"
-" float scaler = smoothstep(0.6,0.58,length(lco.xz));\n"
+" float scaler = smoothstep(0.6,0.58,length(co.xz));\n"
"\n"
" vs_motion_out( vproj0, vproj1 );\n"
"\n"
" gl_Position = vproj0;\n"
-" gl_PointSize = (9.0*uTransform.w*scaler) / (gl_Position.z + 0.01);\n"
+" gl_PointSize = (9.0*scaler) / (gl_Position.z + 0.01);\n"
" aWorldCo = world_pos0;\n"
-" aColour = a_colour*scaler;\n"
-" aCo = mco;\n"
+" aColour = a_colour*scaler*(1.0-uAnim.y*uAnim.y);\n"
+" aCo = co;\n"
"}\n"
""},
.fs =
static GLuint _uniform_point_map_uNormMtx;
static GLuint _uniform_point_map_uPv;
static GLuint _uniform_point_map_uPvmPrev;
-static GLuint _uniform_point_map_uTime;
-static GLuint _uniform_point_map_uTransform;
+static GLuint _uniform_point_map_uAnim;
static GLuint _uniform_point_map_uCamera;
static void shader_point_map_uMdl(m4x3f m){
glUniformMatrix4x3fv(_uniform_point_map_uMdl,1,GL_FALSE,(float*)m);
static void shader_point_map_uPvmPrev(m4x4f m){
glUniformMatrix4fv(_uniform_point_map_uPvmPrev,1,GL_FALSE,(float*)m);
}
-static void shader_point_map_uTime(v2f v){
- glUniform2fv(_uniform_point_map_uTime,1,v);
-}
-static void shader_point_map_uTransform(v4f v){
- glUniform4fv(_uniform_point_map_uTransform,1,v);
+static void shader_point_map_uAnim(v4f v){
+ glUniform4fv(_uniform_point_map_uAnim,1,v);
}
static void shader_point_map_uCamera(v3f v){
glUniform3fv(_uniform_point_map_uCamera,1,v);
_uniform_point_map_uNormMtx = glGetUniformLocation( _shader_point_map.id, "uNormMtx" );
_uniform_point_map_uPv = glGetUniformLocation( _shader_point_map.id, "uPv" );
_uniform_point_map_uPvmPrev = glGetUniformLocation( _shader_point_map.id, "uPvmPrev" );
- _uniform_point_map_uTime = glGetUniformLocation( _shader_point_map.id, "uTime" );
- _uniform_point_map_uTransform = glGetUniformLocation( _shader_point_map.id, "uTransform" );
+ _uniform_point_map_uAnim = glGetUniformLocation( _shader_point_map.id, "uAnim" );
_uniform_point_map_uCamera = glGetUniformLocation( _shader_point_map.id, "uCamera" );
}
#endif /* SHADER_point_map_H */
/* 'systems' are completely loaded now */
/* load home/permanent world */
- world_load( 0, "maps/mp_spawn.mdl" );
+ world_load( 0, "maps/mp_spawn/main.mdl" );
vg_console_load_autos();
menu_link();
k_async_op_clientloading,
k_async_op_world_preloading,
k_async_op_world_loading,
- k_async_op_cloud_loading,
+ k_async_op_world_scan,
k_workshop_form_op_loading_model,
k_workshop_form_op_downloading_submission,
k_workshop_form_op_publishing_update,
#include "vg/vg.h"
#include "vg/vg_steam_remote_storage.h"
#include "skaterift.h"
+#include "pointcloud.h"
struct workshop_file_info{
u64 author;
char title[64];
};
+struct world_file_info{
+ char title[64]; /* extracted from ent_worldinfo */
+ char location[64];
+
+ u32 pointcloud_count;
+ pointcloud_vert pointcloud[];
+};
+
struct async_workshop_filepath_info{
PublishedFileId_t id;
char *buf;
v3_sub( pos, (v3f){ radius, radius, radius }, volume_proximity[0] );
bh_iter it;
- bh_iter_init( 0, &it );
- int idx;
+ bh_iter_init_box( 0, &it, volume_proximity );
+ i32 idx;
int in_volume = 0;
- while( bh_next( world->volume_bh, &it, volume_proximity, &idx ) ){
+ while( bh_next( world->volume_bh, &it, &idx ) ){
ent_volume *volume = mdl_arritm( &world->ent_volume, idx );
boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
VG_STATIC int spherecast_world( world_instance *world,
v3f pa, v3f pb, float r, float *t, v3f n )
{
- bh_iter it;
- bh_iter_init( 0, &it );
-
boxf region;
box_init_inf( region );
box_addpt( region, pa );
int hit = -1;
float min_t = 1.0f;
- int idx;
- while( bh_next( world->geo_bh, &it, region, &idx ) ){
+ bh_iter it;
+ bh_iter_init_box( 0, &it, region );
+ i32 idx;
+ while( bh_next( world->geo_bh, &it, &idx ) ){
u32 *ptri = &world->scene_geo.arrindices[ idx*3 ];
v3f tri[3];
VG_STATIC void world_routes_surface_grid( world_instance *world,
pointcloud_buffer *pcbuf )
{
- i32 const k_gridlines = 63,
+ i32 const k_gridlines = 32,
k_gridres = 255;
v3f inv_ext;
v3_sub( pcbuf->boundary[1], pcbuf->boundary[0], inv_ext );
v3_div( (v3f){1.0f,1.0f,1.0f}, inv_ext, inv_ext );
v4f colour = {0.2f,0.2f,0.2f,1.0f};
+ v3f dir = {0.0f,-1.0f,0.0f};
for( u32 k=0; k<2; k++ ){
u32 a = k*2,
f32 tz = (float)z / (float)k_gridres,
pz = vg_lerpf(pcbuf->boundary[0][b],pcbuf->boundary[1][b], tz);
- v3f ro;
+ v3f ro, hit;
ro[a] = px;
ro[1] = 1000.0f;
ro[b] = pz;
- ray_hit hit;
- hit.dist = INFINITY;
+ bh_iter it;
+ bh_iter_init_ray( 0, &it, ro, dir, INFINITY );
+ i32 idx;
- if( ray_world( world, ro, (v3f){0.0f,-1.0f,0.0f}, &hit )){
- struct world_surface *m1 = ray_hit_surface( world, &hit );
+ while( bh_next( world->geo_bh, &it, &idx ) ){
+ u32 *tri = &world->scene_geo.arrindices[ idx*3 ];
+ v3f vs[3];
- if( world->water.enabled )
- if( hit.pos[1] < world->water.height )
+ for( u32 i=0; i<3; i++ ){
+ v3_copy( world->scene_geo.arrvertices[tri[i]].co, vs[i] );
+ }
+
+ f32 t;
+ if( ray_tri( vs, ro, dir, &t ) ){
+ v3_muladds( ro, dir, t, hit );
+ struct world_surface *m1 =
+ world_tri_index_surface( world, tri[0] );
+
+ if( !(m1->info.flags & k_material_flag_preview_visibile) )
continue;
- if( pcbuf->count >= pcbuf->max ) return;
+ if( world->water.enabled )
+ if( hit[1] < world->water.height )
+ continue;
- pointcloud_vert *vert = &pcbuf->buf[ pcbuf->count ++ ];
+ if( pcbuf->count >= pcbuf->max ) return;
- v3f co;
- v3_sub( hit.pos, pcbuf->boundary[0], co );
- v3_mul( co, inv_ext, co );
+ pointcloud_vert *vert = &pcbuf->buf[ pcbuf->count ++ ];
- for( u32 i=0; i<3; i++ ){
- vert->pos[i] = (co[i]-0.5f) * 32767.0f;
- }
+ v3f co;
+ v3_sub( hit, pcbuf->boundary[0], co );
+ v3_mul( co, inv_ext, co );
+
+ for( u32 i=0; i<3; i++ ){
+ vert->pos[i] = (co[i]-0.5f) * 32767.0f;
+ }
- for( u32 i=0; i<4; i++ ){
- vert->colour[i] = colour[i] * 255.0f;
+ for( u32 i=0; i<4; i++ ){
+ vert->colour[i] = colour[i] * 255.0f;
+ }
}
}
}