longjump gates
authorhgn <hgodden00@gmail.com>
Fri, 24 Feb 2023 02:29:39 +0000 (02:29 +0000)
committerhgn <hgodden00@gmail.com>
Fri, 24 Feb 2023 02:29:39 +0000 (02:29 +0000)
18 files changed:
blender_export.py
camera.h
maps_src/mp_gridmap.mdl
maps_src/mp_home.mdl
maps_src/mp_mtzero.mdl
model.h
player.c
player.h
player_api.h
player_common.c
player_skate.c
player_walk.c
scene.h
skaterift.c
world.h
world_gate.h
world_gen.h
world_render.h

index d6da9c2864f358c8be0ee5f51dc7473ac9d4c114..ccad7bfcb04d001d45f56c083d8dc2f8b8d6262e 100644 (file)
@@ -255,6 +255,40 @@ class classtype_gate(Structure):
    #}
 #}
 
    #}
 #}
 
+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 3
 #
 #  Purpose: player can reset here, its a safe place
@@ -2633,6 +2667,7 @@ class CV_OBJ_SETTINGS(bpy.types.PropertyGroup):
       ('classtype_logic_achievement',"classtype_logic_achievement","",101),
       ('classtype_logic_relay',"classtype_logic_relay","",102),
       ('classtype_spawn_link',"classtype_spawn_link","",150),
       ('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)
       ])
 #}
 
       ])
 #}
 
index 77fc0893f4e885e6766e001617b23b2bab33bcb6..405f055e216328450bef5a804b342a2be4959c87 100644 (file)
--- a/camera.h
+++ b/camera.h
@@ -25,7 +25,7 @@ struct camera
    mtx,
    mtx_prev;
 }
    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 )
 {
 
 VG_STATIC void camera_lerp_angles( v3f a, v3f b, float t, v3f d )
 {
index cb5211b434b91c4b03bc99086158344809de8f4c..ca0c37a08cd17b4a2a631a0cc7d5570e6086b551 100644 (file)
Binary files a/maps_src/mp_gridmap.mdl and b/maps_src/mp_gridmap.mdl differ
index 761e527bdaf05a0a161d9090521cac6659a621bd..a09afb0937233acd438f3ae9f077930bbfa7d5bb 100644 (file)
Binary files a/maps_src/mp_home.mdl and b/maps_src/mp_home.mdl differ
index 96165c9dd9419b24ee463a7c74388a7e965ec874..9213d015f16e1aba1346b1b36540ac59cdbce58c 100644 (file)
Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ
diff --git a/model.h b/model.h
index 54987233a1f3cd8200468f5e1dcbee3640b6b407..95d6676e4d8589c512fd86a6a93436651250f28c 100644 (file)
--- a/model.h
+++ b/model.h
@@ -42,7 +42,8 @@ enum classtype
    k_classtype_trigger              = 100,
    k_classtype_logic_achievement    = 101,
    k_classtype_logic_relay          = 102,
    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
 };
 
 enum mdl_shader
index b705d7fe75d92929918d679f7162c819479b7fdd..115ecf2e361b3f420d3ff8a50329e76a9b6f294b 100644 (file)
--- a/player.c
+++ b/player.c
@@ -176,6 +176,11 @@ VG_STATIC void player_apply_transport_to_cam( m4x3f transport )
    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 );
    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))
 }
 
 __attribute__ ((deprecated))
@@ -197,22 +202,25 @@ VG_STATIC void gate_rotate_angles( teleport_gate *gate, v3f angles, v3f d )
  * Applies gate transport to a player_interface
  */
 PLAYER_API
  * 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_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 );
    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 )
 }
 
 VG_STATIC void player__pre_render( player_instance *player )
@@ -316,6 +324,7 @@ PLAYER_API void player__spawn( player_instance *player,
    m3x3_identity( player->invbasis );
 
    player->subsystem = k_player_subsystem_walk;
    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 );
 
    if( _player_reset[ player->subsystem ] )
       _player_reset[ player->subsystem ]( player, rp );
index 8ecce407508b9c4b0adddbce198cb33055c902a5..8923cf9190f6352631567a7a14b78614b44fabea 100644 (file)
--- a/player.h
+++ b/player.h
@@ -16,6 +16,7 @@ struct player_instance
 
    v4f   qbasis;
    m3x3f basis, invbasis, basis_gate;
 
    v4f   qbasis;
    m3x3f basis, invbasis, basis_gate;
+   world_instance *viewable_world;
 
    /*
     * Camera management
 
    /*
     * Camera management
index 75c387379bdb02ee72e1c9a6c4d37dee4cec1b0d..8819772a78912f446bb89e8fcf3fb6178dc5d0b4 100644 (file)
@@ -62,7 +62,7 @@ PLAYER_API void player__spawn       ( player_instance *player,
                                       struct respawn_point *rp );
 PLAYER_API void player__kill        ( player_instance *player );
 PLAYER_API void player__pass_gate   ( player_instance *player,
                                       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
 
 /*
  * Utiltiy
index 43112f94cd7b12022b8f65dfd20472807d8cde75..0e0c8a949a0c283c71228e56ccc93ca8d0641dc9 100644 (file)
@@ -42,6 +42,7 @@ VG_STATIC void player_camera_portal_correction( player_instance *player )
          vg_success( "Plane cleared\n" );
          player_apply_transport_to_cam( player->gate_waiting->transport );
          player->gate_waiting = NULL;
          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
       {
       }
       else
       {
index 098ce8ad42d1fe26e1bc138e3b193b5318f53278..847f7f5bc6399335eb0f0f131bc3a4de67d7d9a1 100644 (file)
@@ -2219,11 +2219,12 @@ begin_collision:;
    }
 
    skate_integrate( player );
    }
 
    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 );
       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 );
@@ -2239,7 +2240,7 @@ begin_collision:;
       rb_update_transform( &player->rb );
 
       s->state_gate_storage = s->state;
       rb_update_transform( &player->rb );
 
       s->state_gate_storage = s->state;
-      player__pass_gate( player, gate );
+      player__pass_gate( player, &hit );
    }
 }
 
    }
 }
 
index 00ee7fb4807cf27d197331f941c4018ce4278c57..fbae15d4e1dc12b1c18bb21094d0dcdf645c89b6 100644 (file)
@@ -580,9 +580,10 @@ VG_STATIC void player__walk_update( player_instance *player )
       }
    }
 
       }
    }
 
-   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 );
 
       m4x3_mulv( gate->transport, player->rb.co, player->rb.co );
       m3x3_mulv( gate->transport, player->rb.v,  player->rb.v );
 
@@ -593,7 +594,7 @@ VG_STATIC void player__walk_update( player_instance *player )
       rb_update_transform( &player->rb );
 
       w->state_gate_storage = w->state;
       rb_update_transform( &player->rb );
 
       w->state_gate_storage = w->state;
-      player__pass_gate( player, gate );
+      player__pass_gate( player, &hit );
    }
 }
 
    }
 }
 
diff --git a/scene.h b/scene.h
index 7a9460b4dbfe1a7f463b401f61718dc0c3eea5b0..bf69a632b0aab6cd46e6937357391c0ec7c8708b 100644 (file)
--- a/scene.h
+++ b/scene.h
@@ -182,7 +182,6 @@ __attribute__((warn_unused_result))
 VG_STATIC scene *scene_fix( void *lin_alloc, scene *pscene )
 {
    /* FIXME: Why is this disabled? */
 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,
 
    u32 vertex_count  = pscene->vertex_count,
        indice_count  = pscene->indice_count,
@@ -191,7 +190,7 @@ VG_STATIC scene *scene_fix( void *lin_alloc, scene *pscene )
        tot_size      = sizeof(scene) + vertex_length + index_length;
 
    /* copy down index data */
        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 */
    memmove( dst_indices, pscene->arrindices, index_length );
 
    /* realloc */
index 9e162b2c322af6695a7857e08275c1c726910744..6ca61ee8b034aa9a6b36eefb5e1a48f5bc56d2fb 100644 (file)
@@ -264,6 +264,9 @@ VG_STATIC void vg_load(void)
 
    /* load home world */
    world_load( &world_global.worlds[0], "maps/mp_home.mdl" );
 
    /* 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();
 }
 
    vg_console_load_autos();
 }
 
@@ -411,8 +414,8 @@ VG_STATIC void render_scene(void)
    /* Draw world */
    glEnable( GL_DEPTH_TEST );
 
    /* 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;
 
    int player_transparent = 1,
        player_draw        = 1;
@@ -427,10 +430,10 @@ VG_STATIC void render_scene(void)
       player__render( &main_camera, &localplayer );
 
 
       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_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();
 
    if( player_transparent && player_draw )
       render_player_transparent();
diff --git a/world.h b/world.h
index b80db3776879f2b1dfb760b64ef432c2010ce6f1..7611c249a7001558df94a1fdf96d2b19e5097f1e 100644 (file)
--- a/world.h
+++ b/world.h
@@ -251,7 +251,9 @@ struct world_instance
          v4f q[2];
          v2f dims;
 
          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;
 
       }
       gate;
 
@@ -267,6 +269,16 @@ struct world_instance
    *gates;
    u32 gate_count;
 
    *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;
    struct route_collector
    {
       struct route_timing timing;
index 1e8c26247a718ef270e27dc71951883ab871efd3..b6942519c4fe93059a9f881284dcd51db9a799d3 100644 (file)
@@ -81,30 +81,29 @@ VG_STATIC int render_gate( world_instance *world_inside,
    }
 
    /* update gate camera */
    }
 
    /* 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] );
    
 
    /* 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 )
    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 */
 
    /* 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 );
    {
       m4x3f gate_xform;
       m4x3_copy( gate->to_world, gate_xform );
@@ -132,17 +131,17 @@ VG_STATIC int render_gate( world_instance *world_inside,
       glStencilMask( 0x00 ); 
    }
 
       glStencilMask( 0x00 ); 
    }
 
-   render_world( world_inside, &gate_view );
+   render_world( world_inside, &gate_camera );
 
    {
       glDisable( GL_STENCIL_TEST );
 
 
    {
       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_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 );
 
       glStencilMask( 0xFF );
       glStencilFunc( GL_ALWAYS, 1, 0xFF );
@@ -211,11 +210,18 @@ VG_STATIC int gate_intersect( teleport_gate *gate, v3f pos, v3f last )
    return 0;
 }
 
    return 0;
 }
 
+struct gate_hit
+{
+   struct nonlocal_gate *nonlocal;
+   struct route_gate    *route;
+   teleport_gate *gate;
+};
+
 /* 
  * Intersect all gates in the world
  */
 /* 
  * 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++ )
    {
 {
    for( int i=0; i<world->gate_count; i++ )
    {
@@ -223,10 +229,29 @@ VG_STATIC teleport_gate *world_intersect_gates( world_instance *world,
       teleport_gate *gate = &rg->gate;
 
       if( gate_intersect( gate, pos, last ) )
       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 */
 }
 
 #endif /* WORLD_GATE_H */
index 3290def58a7f7e2010fc602aa74640242cf0131a..2b2ba57d91b2eaa4ece165ec559d0f4765d9ff8b 100644 (file)
@@ -187,6 +187,11 @@ VG_STATIC void world_ents_allocate( world_instance *world )
          k_classtype_point_light,
          (void*)&world->lights,
          sizeof(struct world_light)
          k_classtype_point_light,
          (void*)&world->lights,
          sizeof(struct world_light)
+      },
+      {
+         k_classtype_nonlocal_gate,
+         (void*)&world->nonlocal_gates,
+         sizeof(struct nonlocal_gate)
       }
    };
 
       }
    };
 
@@ -341,6 +346,18 @@ VG_STATIC void world_pct_point_light( world_instance *world, mdl_node *pnode )
    world->light_count ++;
 }
 
    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
 VG_STATIC void world_entities_process( world_instance *world )
 {
    struct entity_instruction
@@ -356,7 +373,8 @@ VG_STATIC void world_entities_process( world_instance *world )
       { k_classtype_trigger,  world_pct_trigger },
       { k_classtype_logic_relay, world_pct_relay },
       { k_classtype_logic_achievement, world_pct_achievement },
       { 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++ )
    };
 
    for( int i=0; i<world->meta->info.node_count; i++ )
@@ -376,6 +394,60 @@ VG_STATIC void world_entities_process( world_instance *world )
    }
 }
 
    }
 }
 
+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 )
 {
 VG_STATIC void world_scene_compute_light_clusters( world_instance *world,
                                                    scene *sc )
 {
@@ -771,6 +843,9 @@ VG_STATIC void world_clean( world_instance *world )
    world->collectors = NULL;
    world->collector_count = 0;
 
    world->collectors = NULL;
    world->collector_count = 0;
 
+   world->nonlocal_gates = NULL;
+   world->nonlocalgate_count = 0;
+
    world->water.enabled = 0;
 
 
    world->water.enabled = 0;
 
 
index fd0b39f214a34e9785de222f5c19c6e6b79d052b..873374f08b37ea2ac928b6e1e0f50b427724585f 100644 (file)
@@ -295,26 +295,50 @@ VG_STATIC void render_sky( camera *cam )
 
 VG_STATIC void render_world_gates( world_instance *world, camera *cam )
 {
 
 VG_STATIC void render_world_gates( world_instance *world, camera *cam )
 {
-   if( !world->gate_count )
-      return;
-
    float closest = INFINITY;
    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] );
 
 
    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;
       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 )
 }
 
 VG_STATIC void render_world( world_instance *world, camera *cam )