#}
#}
+class classtype_nonlocal_gate(classtype_gate):
+#{
+ def encode_obj(_,node,node_def):
+ #{
+ node.classtype = 300
+
+ obj = node_def['obj']
+ _.target = encoder_process_pstr( node_def['obj'].cv_data.strp )
+
+ if obj.type == 'MESH':
+ #{
+ _.dims[0] = obj.data.cv_data.v0[0]
+ _.dims[1] = obj.data.cv_data.v0[1]
+ _.dims[2] = obj.data.cv_data.v0[2]
+ #}
+ else:
+ #{
+ _.dims[0] = obj.cv_data.v0[0]
+ _.dims[1] = obj.cv_data.v0[1]
+ _.dims[2] = obj.cv_data.v0[2]
+ #}
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ layout.prop( obj.cv_data, "strp", text="Nonlocal ID" )
+
+ mesh = obj.data
+ layout.label( text=F"(i) Data is stored in {mesh.name}" )
+ layout.prop( mesh.cv_data, "v0", text="Gate dimensions" )
+ #}
+#}
+
# Classtype 3
#
# Purpose: player can reset here, its a safe place
('classtype_logic_achievement',"classtype_logic_achievement","",101),
('classtype_logic_relay',"classtype_logic_relay","",102),
('classtype_spawn_link',"classtype_spawn_link","",150),
+ ('classtype_nonlocal_gate', "classtype_nonlocal_gate", "", 300)
])
#}
mtx,
mtx_prev;
}
-VG_STATIC main_camera;
+VG_STATIC main_camera, gate_camera;
VG_STATIC void camera_lerp_angles( v3f a, v3f b, float t, v3f d )
{
k_classtype_trigger = 100,
k_classtype_logic_achievement = 101,
k_classtype_logic_relay = 102,
- k_classtype_point_light = 200
+ k_classtype_point_light = 200,
+ k_classtype_nonlocal_gate = 300
};
enum mdl_shader
m4x3_expand( transport_i, transport_4 );
m4x4_mul( main_camera.mtx.pv, transport_4, main_camera.mtx.pv );
m4x4_mul( main_camera.mtx.v, transport_4, main_camera.mtx.v );
+
+ /* we want the regular transform here no the inversion */
+ m4x3_expand( transport, transport_4 );
+ m4x4_mul( gate_camera.mtx.pv, transport_4, gate_camera.mtx.pv );
+ m4x4_mul( gate_camera.mtx.v, transport_4, gate_camera.mtx.v );
}
__attribute__ ((deprecated))
* Applies gate transport to a player_interface
*/
PLAYER_API
-void player__pass_gate( player_instance *player, teleport_gate *gate )
+void player__pass_gate( player_instance *player, struct gate_hit *hit )
{
- player->gate_waiting = gate;
+ player->gate_waiting = hit->gate;
- m4x3_mulv( gate->transport, player->tpv_lpf, player->tpv_lpf );
- m3x3_mulv( gate->transport, player->cam_velocity_smooth,
- player->cam_velocity_smooth );
+ m4x3_mulv( hit->gate->transport, player->tpv_lpf, player->tpv_lpf );
+ m3x3_mulv( hit->gate->transport, player->cam_velocity_smooth,
+ player->cam_velocity_smooth );
m3x3_copy( player->basis, player->basis_gate );
v4f q;
- m3x3_q( gate->transport, q );
+ m3x3_q( hit->gate->transport, q );
q_mul( q, player->qbasis, player->qbasis );
q_normalize( player->qbasis );
q_m3x3( player->qbasis, player->basis );
m3x3_transpose( player->basis, player->invbasis );
+
+ if( hit->nonlocal )
+ world_global.active_world = hit->nonlocal->target_map_index;
}
VG_STATIC void player__pre_render( player_instance *player )
m3x3_identity( player->invbasis );
player->subsystem = k_player_subsystem_walk;
+ player->viewable_world = get_active_world();
if( _player_reset[ player->subsystem ] )
_player_reset[ player->subsystem ]( player, rp );
v4f qbasis;
m3x3f basis, invbasis, basis_gate;
+ world_instance *viewable_world;
/*
* Camera management
struct respawn_point *rp );
PLAYER_API void player__kill ( player_instance *player );
PLAYER_API void player__pass_gate ( player_instance *player,
- teleport_gate *gate );
+ struct gate_hit *hit );
/*
* Utiltiy
vg_success( "Plane cleared\n" );
player_apply_transport_to_cam( player->gate_waiting->transport );
player->gate_waiting = NULL;
+ player->viewable_world = get_active_world();
}
else
{
}
skate_integrate( player );
- vg_line_pt3( s->state.cog, 0.02f, VG__WHITE );
+ vg_line_pt3( s->state.cog, 0.02f, VG__WHITE );
- teleport_gate *gate;
- if( (gate = world_intersect_gates(world, player->rb.co, s->state.prev_pos)) )
+ struct gate_hit hit;
+ if( world_intersect_gates(world, player->rb.co, s->state.prev_pos, &hit) )
{
+ teleport_gate *gate = hit.gate;
m4x3_mulv( gate->transport, player->rb.co, player->rb.co );
m3x3_mulv( gate->transport, player->rb.v, player->rb.v );
m4x3_mulv( gate->transport, s->state.cog, s->state.cog );
rb_update_transform( &player->rb );
s->state_gate_storage = s->state;
- player__pass_gate( player, gate );
+ player__pass_gate( player, &hit );
}
}
}
}
- teleport_gate *gate;
- if( (gate = world_intersect_gates(world, player->rb.co, w->state.prev_pos)) )
+ struct gate_hit hit;
+ if( world_intersect_gates(world, player->rb.co, w->state.prev_pos, &hit) )
{
+ teleport_gate *gate = hit.gate;
m4x3_mulv( gate->transport, player->rb.co, player->rb.co );
m3x3_mulv( gate->transport, player->rb.v, player->rb.v );
rb_update_transform( &player->rb );
w->state_gate_storage = w->state;
- player__pass_gate( player, gate );
+ player__pass_gate( player, &hit );
}
}
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,
tot_size = sizeof(scene) + vertex_length + index_length;
/* copy down index data */
- void *dst_indices = pscene->arrvertices + vertex_length;
+ void *dst_indices = pscene->arrvertices + vertex_count;
memmove( dst_indices, pscene->arrindices, index_length );
/* realloc */
/* load home world */
world_load( &world_global.worlds[0], "maps/mp_home.mdl" );
+ world_load( &world_global.worlds[1], "maps/mp_gridmap.mdl" );
+ world_link_nonlocal_gates( 0, 1 );
+
vg_console_load_autos();
}
/* Draw world */
glEnable( GL_DEPTH_TEST );
- world_instance *world = get_active_world();
- render_world( world, &main_camera );
+ world_instance *view_world = localplayer.viewable_world;
+ render_world( view_world, &main_camera );
int player_transparent = 1,
player_draw = 1;
player__render( &main_camera, &localplayer );
- render_water_texture( world, &main_camera );
+ render_water_texture( view_world, &main_camera );
render_fb_bind( gpipeline.fb_main );
- render_water_surface( world, &main_camera );
- render_world_gates( world, &main_camera );
+ render_water_surface( view_world, &main_camera );
+ render_world_gates( view_world, &main_camera );
if( player_transparent && player_draw )
render_player_transparent();
v4f q[2];
v2f dims;
- m4x3f to_world, recv_to_world, transport;
+ m4x3f to_world, recv_to_world, /* TODO: can probably remove these */
+
+ transport;
}
gate;
*gates;
u32 gate_count;
+ struct nonlocal_gate
+ {
+ struct teleport_gate gate;
+ mdl_node *node;
+
+ u32 target_map_index, working;
+ }
+ *nonlocal_gates;
+ u32 nonlocalgate_count;
+
struct route_collector
{
struct route_timing timing;
}
/* update gate camera */
- static camera gate_view;
- gate_view.fov = cam->fov;
- gate_view.nearz = 0.1f;
- gate_view.farz = 2000.0f;
+ gate_camera.fov = cam->fov;
+ gate_camera.nearz = 0.1f;
+ gate_camera.farz = 2000.0f;
- m4x3_mul( gate->transport, cam->transform, gate_view.transform );
- camera_update_view( &gate_view );
- camera_update_projection( &gate_view );
+ m4x3_mul( gate->transport, cam->transform, gate_camera.transform );
+ camera_update_view( &gate_camera );
+ camera_update_projection( &gate_camera );
/* Add special clipping plane to projection */
v4f surface;
m3x3_mulv( gate->recv_to_world, (v3f){0.0f,0.0f,-1.0f}, surface );
surface[3] = v3_dot( surface, gate->co[1] );
- m4x3_mulp( gate_view.transform_inverse, surface, surface );
+ m4x3_mulp( gate_camera.transform_inverse, surface, surface );
surface[3] = -fabsf(surface[3]);
if( dist < -0.5f )
- m4x4_clip_projection( gate_view.mtx.p, surface );
+ m4x4_clip_projection( gate_camera.mtx.p, surface );
/* Ready to draw with new camrea */
- camera_finalize( &gate_view );
+ camera_finalize( &gate_camera );
- vg_line_pt3( gate_view.transform[3], 0.3f, 0xff00ff00 );
+ vg_line_pt3( gate_camera.transform[3], 0.3f, 0xff00ff00 );
{
m4x3f gate_xform;
m4x3_copy( gate->to_world, gate_xform );
glStencilMask( 0x00 );
}
- render_world( world_inside, &gate_view );
+ render_world( world_inside, &gate_camera );
{
glDisable( GL_STENCIL_TEST );
- render_water_texture( world_inside, &gate_view );
+ render_water_texture( world_inside, &gate_camera );
render_fb_bind( gpipeline.fb_main );
glEnable( GL_STENCIL_TEST );
- render_water_surface( world_inside, &gate_view );
+ render_water_surface( world_inside, &gate_camera );
glStencilMask( 0xFF );
glStencilFunc( GL_ALWAYS, 1, 0xFF );
return 0;
}
+struct gate_hit
+{
+ struct nonlocal_gate *nonlocal;
+ struct route_gate *route;
+ teleport_gate *gate;
+};
+
/*
* Intersect all gates in the world
*/
-VG_STATIC teleport_gate *world_intersect_gates( world_instance *world,
- v3f pos, v3f last )
+VG_STATIC int world_intersect_gates( world_instance *world,
+ v3f pos, v3f last, struct gate_hit *hit )
{
for( int i=0; i<world->gate_count; i++ )
{
teleport_gate *gate = &rg->gate;
if( gate_intersect( gate, pos, last ) )
- return gate;
+ {
+ hit->gate = gate;
+ hit->nonlocal = NULL;
+ hit->route = rg;
+ return 1;
+ }
}
- return NULL;
+ for( int i=0; i<world->nonlocalgate_count; i++ )
+ {
+ struct nonlocal_gate *nlg = &world->nonlocal_gates[i];
+ teleport_gate *gate = &nlg->gate;
+
+ if( gate_intersect( gate, pos, last ) )
+ {
+ hit->gate = gate;
+ hit->nonlocal = nlg;
+ hit->route = NULL;
+ return 1;
+ }
+ }
+
+ return 0;
}
#endif /* WORLD_GATE_H */
k_classtype_point_light,
(void*)&world->lights,
sizeof(struct world_light)
+ },
+ {
+ k_classtype_nonlocal_gate,
+ (void*)&world->nonlocal_gates,
+ sizeof(struct nonlocal_gate)
}
};
world->light_count ++;
}
+VG_STATIC void world_pct_nonlocal_gate( world_instance *world, mdl_node *pnode )
+{
+ struct nonlocal_gate *gate = &world->nonlocal_gates[
+ world->nonlocalgate_count ++ ];
+ struct classtype_gate *inf = mdl_get_entdata( world->meta, pnode );
+
+ gate->working = 0;
+ gate->node = pnode;
+ gate->target_map_index = 0;
+ v2_copy( inf->dims, gate->gate.dims );
+}
+
VG_STATIC void world_entities_process( world_instance *world )
{
struct entity_instruction
{ k_classtype_trigger, world_pct_trigger },
{ k_classtype_logic_relay, world_pct_relay },
{ k_classtype_logic_achievement, world_pct_achievement },
- { k_classtype_point_light, world_pct_point_light }
+ { k_classtype_point_light, world_pct_point_light },
+ { k_classtype_nonlocal_gate, world_pct_nonlocal_gate }
};
for( int i=0; i<world->meta->info.node_count; i++ )
}
}
+VG_STATIC void world_link_nonlocal_gates( int index_a, int index_b )
+{
+ vg_info( "Linking non-local gates\n" );
+ world_instance *a = &world_global.worlds[ index_a ],
+ *b = &world_global.worlds[ index_b ];
+
+ for( int i=0; i<a->nonlocalgate_count; i++ )
+ {
+ struct nonlocal_gate *ga = &a->nonlocal_gates[i];
+ struct classtype_gate *ga_inf = mdl_get_entdata( a->meta, ga->node );
+ const char *ga_name = mdl_pstr( a->meta, ga_inf->target );
+
+ for( int j=0; j<b->nonlocalgate_count; j++ )
+ {
+ struct nonlocal_gate *gb = &b->nonlocal_gates[j];
+ struct classtype_gate *gb_inf = mdl_get_entdata( b->meta, gb->node );
+ const char *gb_name = mdl_pstr( b->meta, gb_inf->target );
+
+ if( !strcmp( ga_name, gb_name ) )
+ {
+ vg_success( "Created longjump for ID '%s'\n", ga_name );
+
+ v4f qYflip;
+ q_axis_angle( qYflip, (v3f){0.0f,1.0f,0.0f}, VG_PIf );
+
+ /* TODO: Gates are created very wonkily. refactor. */
+ ga->target_map_index = index_b;
+ gb->target_map_index = index_a;
+ ga->working = 1;
+ gb->working = 1;
+
+ v4_copy( ga->node->q, ga->gate.q[0] );
+ v4_copy( gb->node->q, ga->gate.q[1] );
+ v3_copy( ga->node->co, ga->gate.co[0] );
+ v3_copy( gb->node->co, ga->gate.co[1] );
+
+ v4_copy( gb->node->q, gb->gate.q[0] );
+ v4_copy( ga->node->q, gb->gate.q[1] );
+ v3_copy( gb->node->co, gb->gate.co[0] );
+ v3_copy( ga->node->co, gb->gate.co[1] );
+
+ /* reverse B's direction */
+ q_mul( gb->gate.q[0], qYflip, gb->gate.q[0] );
+ q_mul( gb->gate.q[1], qYflip, gb->gate.q[1] );
+ q_normalize( gb->gate.q[0] );
+ q_normalize( gb->gate.q[1] );
+
+ gate_transform_update( &ga->gate );
+ gate_transform_update( &gb->gate );
+ }
+ }
+ }
+}
+
VG_STATIC void world_scene_compute_light_clusters( world_instance *world,
scene *sc )
{
world->collectors = NULL;
world->collector_count = 0;
+ world->nonlocal_gates = NULL;
+ world->nonlocalgate_count = 0;
+
world->water.enabled = 0;
VG_STATIC void render_world_gates( world_instance *world, camera *cam )
{
- if( !world->gate_count )
- return;
-
float closest = INFINITY;
- int id = 0;
+
+ struct teleport_gate *gate = NULL;
+ world_instance *dest_world = world;
for( int i=0; i<world->gate_count; i++ )
{
struct route_gate *rg = &world->gates[i];
float dist = v3_dist2( rg->gate.co[0], cam->transform[3] );
+ vg_line_pt3( rg->gate.co[0], 0.25f, VG__BLUE );
+
+ if( dist < closest )
+ {
+ closest = dist;
+ gate = &rg->gate;
+ dest_world = world;
+ }
+ }
+
+ for( int i=0; i<world->nonlocalgate_count; i++ )
+ {
+ struct nonlocal_gate *nlg = &world->nonlocal_gates[i];
+
+ if( !nlg->working )
+ {
+ vg_line_pt3( nlg->gate.co[0], 0.25f, VG__RED );
+ continue;
+ }
+ else
+ vg_line_pt3( nlg->gate.co[0], 0.25f, VG__GREEN );
+
+ float dist = v3_dist2( nlg->gate.co[0], cam->transform[3] );
+
if( dist < closest )
{
closest = dist;
- id = i;
+ gate = &nlg->gate;
+ dest_world = &world_global.worlds[ nlg->target_map_index ];
}
}
- /* TODO: non-local portals! :D */
- render_gate( world, &world->gates[id].gate, cam );
+ if( gate )
+ render_gate( dest_world, gate, cam );
}
VG_STATIC void render_world( world_instance *world, camera *cam )