+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 )
+{
+ for( int i=0; i<sc->vertex_count; i++ )
+ {
+ scene_vert *vert = &sc->arrvertices[i];
+ vert->lights[0] = 255;
+ vert->lights[1] = 255;
+ vert->lights[2] = 255;
+ vert->lights[3] = 255;
+
+ float distances[4] = { INFINITY, INFINITY, INFINITY, INFINITY };
+
+ for( int j=0; j<world->light_count; j ++ )
+ {
+ float dist = v3_dist2( world->lights[j].co, vert->co );
+
+ int best_pos = 4;
+ for( int k=best_pos-1; k>=0; k -- )
+ if( dist < distances[k] )
+ best_pos = k;
+
+ if( best_pos < 4 )
+ {
+ for( int k=3; k>best_pos; k -- )
+ {
+ distances[k] = distances[k-1];
+ vert->lights[k] = vert->lights[k-1];
+ }
+
+ distances[best_pos] = dist;
+ vert->lights[best_pos] = j;
+ }
+ }
+ }
+}
+
+VG_STATIC void world_generate( world_instance *world )