Originally Posted By: 3run
After reading several article and unsucsessfuly trying to convert the calculation from the Tom's Blog (it works, but independently from portal angles, so if you rotate destination or source portal, everything get's **** up), I tried to create something by myself. Thank to those article, I somehow got the main idea of what I needed to do, so I came up with a small demo (only math calculations, no reflation and fancy stuff yet).

HERE IS THE SOURCE (just save it and run from SED):
Code:
ENTITY* heroEnt;
ENTITY* ghost1Ent;

ENTITY* portal1Ent;
ENTITY* portal2Ent;

void calculatePortal(ENTITY* ent, VECTOR* srcPos, VECTOR* dstPos, ANGLE* srcAng, ANGLE* dstAng){
	
	if(!heroEnt){ return; }
	
	ANGLE tempAng;
	vec_fill(tempAng.pan, 0);
	
	VECTOR tempPos;	
	vec_fill(tempPos.x, 0);
	
	ang_diff(tempAng.pan, dstAng.pan, srcAng.pan);
	vec_diff(tempPos.x, srcPos.x, heroEnt.x);
	vec_rotate(tempPos.x, tempAng.pan);
	vec_inverse(tempPos.x);
	vec_add(tempPos.x, dstPos.x);
	
	
	ANGLE temp2Ang, endAng;
	vec_fill(temp2Ang.pan, 0);
	vec_fill(endAng.pan, 0);
	
	ang_diff(temp2Ang.pan, srcAng.pan, heroEnt.pan);
	vec_set(endAng.pan, dstAng.pan);
	vec_inverse(temp2Ang.pan);
	ang_add(endAng.pan, temp2Ang.pan);
	
	
	// if player far away from us:
	if(vec_dist(heroEnt.x, ent.x) > 25){
		if(!is(ent.parent, INVISIBLE)){
			set(ent.parent, INVISIBLE);
		}
	}
	else{
		if(is(ent.parent, INVISIBLE)){
			reset(ent.parent, INVISIBLE);
		}
		vec_set(ent.parent.x, tempPos.x);
		vec_set(ent.parent.pan, endAng.pan);
	}
}

void portal1(){
	VECTOR tempVec;
	vec_fill(tempVec.x, 0);
	
	portal1Ent = my;
	
	vec_set(my.scale_x, vector(0.05, 1, 1));
	my.pan += random(360);
	set(my, LIGHT | UNLIT | PASSABLE);
	vec_set(my.blue, COLOR_RED);
	
	my.parent = ent_create(CUBE_MDL, my.x, NULL);
	vec_set(my.parent.scale_x, vector(0.25, 0.25, 0.25));
	set(my.parent, TRANSLUCENT | LIGHT | UNLIT | PASSABLE);
	vec_set(my.parent.blue, COLOR_RED);
	
	while(!portal2Ent){ wait(1); }
	
	while(1){
		
		my.pan += 5 * (key_cul - key_cur) * time_step;
		
		my.x += 5 * (key_t - key_g) * time_step;
		my.y += 5 * (key_f - key_h) * time_step;
		
		vec_set(tempVec.x, vector(5, 0, 0));
		vec_rotate(tempVec.x, my.pan);
		vec_add(tempVec.x, my.x);
		draw_line3d(tempVec.x, NULL, 100); 
		draw_line3d(tempVec.x, COLOR_RED, 100); 
		draw_line3d(my.x, COLOR_RED, 100); 
		draw_point3d(tempVec.x, COLOR_RED, 100, 1);
		
		calculatePortal(my, my.x, portal2Ent.x, my.pan, portal2Ent.pan);
		
		wait(1);
	}
}


void portal2(){
	VECTOR tempVec;
	vec_fill(tempVec.x, 0);
	
	portal2Ent = my;
	
	vec_set(my.scale_x, vector(0.05, 1, 1));
	my.pan += random(360);
	set(my, LIGHT | UNLIT | PASSABLE);
	vec_set(my.blue, COLOR_GREEN);
	
	my.parent = ent_create(CUBE_MDL, my.x, NULL);
	vec_set(my.parent.scale_x, vector(0.25, 0.25, 0.25));
	set(my.parent, TRANSLUCENT | LIGHT | UNLIT | PASSABLE);
	vec_set(my.parent.blue, COLOR_GREEN);
	
	while(!portal1Ent){ wait(1); }
	
	while(1){
		
		my.pan += 5 * (key_cuu - key_cud) * time_step;
		
		my.x += 5 * (key_i - key_k) * time_step;
		my.y += 5 * (key_j - key_l) * time_step;
		
		vec_set(tempVec.x, vector(5, 0, 0));
		vec_rotate(tempVec.x, my.pan);
		vec_add(tempVec.x, my.x);
		draw_line3d(tempVec.x, NULL, 100); 
		draw_line3d(tempVec.x, COLOR_GREEN, 100); 
		draw_line3d(my.x, COLOR_GREEN, 100); 
		draw_point3d(tempVec.x, COLOR_GREEN, 100, 1);
		
		calculatePortal(my, my.x, portal1Ent.x, my.pan, portal1Ent.pan);
		
		wait(1);
	}
}


void main(){
	
	fps_max = 60;
	level_load("");
	
	random_seed(0);
	
	// create portals:	
	ent_create(CUBE_MDL, vector(-25, 25, 0), portal1);	
	ent_create(CUBE_MDL, vector(25, -25, 0), portal2);
	
	heroEnt = ent_create(CUBE_MDL, nullvector, NULL);
	vec_set(heroEnt.scale_x, vector(0.25, 0.25, 0.25));
	set(heroEnt, TRANSLUCENT | LIGHT | UNLIT);
	vec_set(heroEnt.blue, COLOR_WHITE);
	c_setminmax(heroEnt);	
	
	sun_light = 0;
	set(camera, ISOMETRIC);
	camera.arc = 10;
	camera.z = 100;
	camera.tilt = -90;
	
	while(1){
		
		DEBUG_VAR(heroEnt.pan, 210);
		DEBUG_VAR(portal1Ent.pan, 250);
		DEBUG_VAR(portal2Ent.pan, 270);
		
		heroEnt.skill1 = 5 * (key_w - key_s) * time_step;
		heroEnt.skill2 = 5 * (key_a - key_d) * time_step;
		heroEnt.pan += 5 * (key_z - key_x) * time_step;
		c_move(heroEnt, nullvector, heroEnt.skill1, IGNORE_PASSABLE | GLIDE);
		
		draw_text("green and red cubes are 'ghost' players position in the destination portals\nwhite cube is player, and those two white lines are portals\nyou can see the way they are facing from the lines comming out of portals\nthe one near by the player is source portal and the other\none is destination portal, use cursor keys to rotate the portals\nuse WSAD to move the player around and TGFH and IKJL to move portals", 10, 10, COLOR_WHITE);
		
		wait(1);
	}
}

Please give it a try guys and tell me, am I even on the right track?

Edit: I think, this will at least help me with object duplication, to get the seamless transition of object from one portal to another.

Best regards!


Thats cool , im also have a solution for portal view rendring so it not look like a flat tv ,i will upload the source here.