# portal-portal rotation

This topic is 4164 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

im working on a game which uses teleportals to transport players. the stencil buffer rendering portion is done with. unfortunately though, i cant figure out how to rotate the scene to fit properly into the linked portal. take the following image for example. i have several planes with normals facing in different directions. the planes are the portals i want to draw a translated world into. i have the normals and position of each portal. i can get the up and right vectors if needed. my problem is, i dont know how to use the normals to rotate the world into place. using the dot product of the 2 normals just gives me a single angle but no axis to rotate the world on. i tried translating the world by the vector from the origin to the first portal. i could then rotate the world about the origin with the dot product and then translate it again by the vector from the origin to the linked portal. this only works on one axis, mainly the y-axis. im really confused and would appreciate any light on the subject! i hope im making sense. thanks! -adam

##### Share on other sites
If you have the normal, up, and side vector (all of unit length) then you can assemble a rotation/orientation matrix from them. There is most often no need to compute the corresponding angles (in whatever flavor) from them. Together with the position the full transformation is known (assuming you avoid scaling in this situation).

I assume the two sides of the portal are related by co-ordinate frames, both given in global space for simplicity. On this side of the portal (i.e. where the camera is) is the frame descibed by transformation T1, and on the other side is T2. Virtually, but not physically, the both frames should overlap to identity.

Anything given in global space can then be localized on the other side of the portal and then globalized on this side by multiplying with (notice that I'll use column vectors)
T1 * T2-1
This actually means that the thing of interest is virtually moved in global space so that its spatial relation to frame 1 after transformation is the same as to frame 2 before transformation.

If necessary the other way around is also possible, of course:
T2 * T1-1
to transfer something seen on this side of the portal to the other.

Any locally related space can be incorporated the usual way by globalizing and multiplying. Which steps are actually necessary depends on the particular problem you have to solve.

Hopefully its the stuff above you are looking for!?

[Edited by - haegarr on September 28, 2006 3:45:35 AM]

##### Share on other sites
Quote:
 Original post by haegarrIf you have the normal, up, and side vector (all of unit length) then you can assemble a rotation/orientation matrix from them. There is most often no need to compute the corresponding angles (in whatever flavor) from them. Together with the position the full transformation is known (assuming you avoid scaling in this situation).I assume the two sides of the portal are related by co-ordinate frames, both given in global space for simplicity. On this side of the portal (i.e. where the camera is) is the frame descibed by transformation T1, and on the other side is T2. Virtually, but not physically, the both frames should overlap to identity.Anything given in global space can then be localized on the other side of the portal and then globalized on this side by multiplying with (notice that I'll use column vectors)T1 * T2-1This actually means that the thing of interest is virtually moved in global space so that its spatial relation to frame 1 after transformation is the same as to frame 2 before transformation.If necessary the other way around is also possible, of course:T2 * T1-1to transfer something seen on this side of the portal to the other.Any locally related space can be incorporated the usual way by globalizing and multiplying. Which steps are actually necessary depends on the particular problem you have to solve.Hopefully its the stuff above you are looking for!?

you are correct about me putting them in a global coordinate system, for easier math. now let me see if i understand what you are talking about. lets say i have 2 portals which are linked. their matrices (im assuming you are calling them column vectors) look like this:
for simplicities sake:               and the linked portal's matrix:right  [1, 0, 0]                     [0, 0, 1]up     [0, 1, 0]                     [1, 0, 0]normal [0, 0, 1]                     [0, 1, 0]

if i multiply the matrices together i get another matrix. from there im stuck. i dont know how to use it for rotations.

also am i understanding that my "translate, rotate, translate" method is the right way to go?

[Edited by - adam17 on September 28, 2006 10:32:06 AM]

##### Share on other sites
I'll answering your post in several replies, because it is too much for one.

Be aware that using either "column vectors" or "row vectors" makes a big difference when applying matrices. E.g. when using column vectors, multiplication of a matrix and a vector is done this way
v' := M * v
while when using row vectors it is done this way
v' := v * M

That plays a role since matrix multiplication isn't commutative. If you build up the matrix from several sub-matrices (as is often the case for transformation matrices), then the this in column vector representation
v' := M2 * M1 * v
means that 1st M1 is applied to the vector, than M2 is applied on the result. The same in row vector representation is
v' := v * M1 * M2
Notice the change in order.

The relation of a column and row vector is the transpose operation:
vC = vRT
To be correct the one kind has to be written transposed if both kinds appear in the same text.

To yield in the same result, also the matrices are related in this way:
MC = MRT
You can see that if actually performing the matrix vector product in both ways.

Hence, whenever dealing with matrices, make clear what kind of vectors you are using!

[Edited by - haegarr on September 28, 2006 12:49:59 PM]

##### Share on other sites
ok cool! im getting the idea of the multiplication and importance of column vectors and row vectors. i have one question though. when you are building the matrix, how do you store them?

like this maybe?
axis-->        X  Y  Zright vector  <1, 0, 0>up vector     <0, 1, 0>normal vector <0, 0, 1>

it may help if i mention that im using OpenGL (a right-handed coordinate system)

##### Share on other sites
Quote:
 Original post by adam17lets say i have 2 portals which are linked. their matrices (im assuming you are calling them column vectors) look like this:for simplicities sake: and the linked portal's matrix:right [1, 0, 0] [0, 0, 1]up [0, 1, 0] [1, 0, 0]normal [0, 0, 1] [0, 1, 0]if i multiply the matrices together i get another matrix. from there im stuck. i dont know how to use it for rotations.

First, if you have the 3 vectors, and each vector is of unit length, and they are pairwise orthogonal so that
r x u = n
(and so forth), then writing all vectors as column vectors (or, if used instead, as row vectors) of a matrix
M := [ r   u   n ]
then you have effectively a so-called "ortho-normal basis". That matrix is by itself a rotation matrix.

You can extend this matrix to a homogeneous matrix to supply translations in the same matrix as well.

Quote:
 Original post by adam17lets say i have 2 portals which are also am i understanding that my "translate, rotate, translate" method is the right way to go?

A local to global transformation is (for column vectors) normally modelled as
T * R
that is first a rotation, then a translation. Doing so for portal 1 and portal 2, and setting this into the transformation I suggested in an earlier reply, yields in
( T1 * R1 ) * ( T2 * R2 )-1 = T1 * R1 * R2-1 * T2-1
The overall structure is hence a translation, then a rotation (assembed by 2 particular rotations), then another translation. So you are right with the structure.

EDIT: Please notice that in one of my previous replies the T has denoted a whole transformation, while in this reply the T means a translation matrix only!

[Edited by - haegarr on September 28, 2006 11:14:47 AM]

##### Share on other sites
Quote:
 Original post by adam17ok cool! im getting the idea of the multiplication and importance of column vectors and row vectors. i have one question though. when you are building the matrix, how do you store them? like this maybe?axis--> X Y Zright vector <1, 0, 0>up vector <0, 1, 0>normal vector <0, 0, 1>it may help if i mention that im using OpenGL (a right-handed coordinate system)

OpenGL uses column vectors, so you are lucky since I prefer using column vectors in my explanations as well ;)

The (homogeneous) matrix structure as used by OpenGL is
[ right_x  up_x  normal_x  0 ][ right_y  up_y  normal_y  0 ][ right_z  up_z  normal_z  0 ][    0       0       0     1 ]

if you interpret right being the x vector, up being the y vector, and normal being the z vector.

EDIT: As an array, OpenGL expects right_x at index 0, right_y at index 1, ... up_x at index 4, ...

##### Share on other sites
okay, cool i think im getting it. so let me try an example with translation.

portal1 (facing +Z and @ position <5 0 0>[ 1  0  0  5][ 0  1  0  0][ 0  0  1  0][ 0  0  0  1]portal2 (facing +Y and @ position <0 0 2>[ 0  1  0  0][ 0  0  1  0][ 1  0  0  2][ 0  0  0  1]

if i try to rotate the world to fit into portal 1, i would do the following:
(Mr = final rotation matrix, M1 = portal1's matrix, and M2 = portal2's matrix
Mr = M1 * M2^-1     [ 1  0  0]   [ 0  1  0]-1  Mr = [ 0  1  0] * [ 0  0  1]  =      [ 0  0  1]   [ 1  0  0]            [ 1  0  0]   [ 0  0  1]   [ 0  0  1]   = [ 0  1  0] * [ 1  0  0] = [ 1  0  0]     [ 0  0  1]   [ 0  1  0]   [ 0  1  0]

the M2^-1 appears to be the transverse of M2 but i think im wrong. am i?
maybe because i was using an identity matrix for the first matrix, but the answer seems to be the same as M2^-1. am i wrong?

btw you dont know just how MUCH i appreciate your help!!! thanks

##### Share on other sites
im still struggling with the matrices and all but i had a stroke of genius!

i take the 2 normals of the portals and find the dot product. then i take the cross product of the 2 normals, and rotate the scene around the cross product! i think it will work....

EDIT: it works, but the dot product is not oriented correctly. its only 0 <= theta <= pi. i need something for 0 <= theta <= 2pi

[Edited by - adam17 on September 30, 2006 1:15:22 AM]

##### Share on other sites
Quote:
 Original post by adam17if i try to rotate the world to fit into portal 1, i would do the following:(Mr = final rotation matrix, M1 = portal1's matrix, and M2 = portal2's matrixMr = M1 * M2^-1 [ 1 0 0] [ 0 1 0]-1 Mr = [ 0 1 0] * [ 0 0 1] = [ 0 0 1] [ 1 0 0] [ 1 0 0] [ 0 0 1] [ 0 0 1] = [ 0 1 0] * [ 1 0 0] = [ 1 0 0] [ 0 0 1] [ 0 1 0] [ 0 1 0]the M2^-1 appears to be the transverse of M2 but i think im wrong. am i?

For ortho-normal matrixes the inverse is identical to the transpose. I don't know the term transverse for this, but perhaps it is (also) a valid term?!

Quote:
 Original post by adam17maybe because i was using an identity matrix for the first matrix, but the answer seems to be the same as M2^-1. am i wrong?

Nope, you're correct. That is what gives the identity matrix its name: The fact that it does an identity mapping if used for multiplication.

BTW: If you're interested in: This kind of naming is also used for scalar algebras. E.g. 1 is the identity value for the scalar multiplication, and 0 is the identity value for the scalar addition. Here you can see that "identity" is AFAIK normally only a valid term if used in conjuntion with an operation.

[Edited by - haegarr on September 30, 2006 6:47:14 AM]

##### Share on other sites
Notice please that the transformation I've suggested means the following: Something that is given in the same co-ordinate system (usually the global space) as the 2nd portal's frame is, is converted into the local co-ordinate system of portal 2 and then converted back to the co-ordinates (again usually the global space) portal 1 is given in by using the frame of portal 1. By "switching" the local reference frame in-between these steps a re-interpretation of the space is done! It simulates the things being moving from the one portal to the other.

E.g. lets assume the example you've given above. Now, a point at the global co-ordinates [0,3,2]T is located 3 length unit in front of the second portal. This is because [0,1,0]T is the normal of the second portal; multiplied with 3 length units in this direction, and added to the location [0,0,2]T of portal 2 yields in just that [0,3,2]T.

Now, that point should be seen throught portal 1. Hence, applying the transformation in total
T1 * R1 * R2-1 * T2-1 * [ 0   3   2 ]T
Doing this stepwise from right to left for clarity means
(1) a := T2-1 * [ 0   3   2 ]T
  [ 1 0 0 0 ]-1   [ 0 ]   [ 1 0 0  0 ]   [ 0 ]   [ 0 ]= [ 0 1 0 0 ]   * [ 3 ] = [ 0 1 0  0 ] * [ 3 ] = [ 3 ]  [ 0 0 1 2 ]     [ 2 ]   [ 0 0 1 -2 ]   [ 2 ]   [ 0 ]  [ 0 0 0 1 ]     [ 1 ]   [ 0 0 0  1 ]   [ 1 ]   [ 1 ]

(2) b := ( R1 * R2-1 ) * a
  [ 0 0 1 0 ]   [ 0 ]   [ 0 ]= [ 1 0 0 0 ] * [ 3 ] = [ 0 ]  [ 0 1 0 0 ]   [ 0 ]   [ 3 ]  [ 0 0 0 1 ]   [ 1 ]   [ 1 ]

Here can already be seen that the point's "in front of" has changed to the global z axis!

(3) T1 * b
  [ 1 0 0 0 ]   [ 5 ]   [ 5 ]= [ 0 1 0 0 ] * [ 0 ] = [ 0 ]  [ 0 0 1 0 ]   [ 0 ]   [ 3 ]  [ 0 0 0 1 ]   [ 1 ]   [ 1 ]

Exactly what I would expect. Althought the point is actually located 3 units in front of portal 2, it appears to be 3 units in front of portal 1!

[Edited by - haegarr on September 30, 2006 7:02:57 AM]

##### Share on other sites
Quote:
 Original post by adam17im still struggling with the matrices and all but i had a stroke of genius!

:)

Quote:
 Original post by adam17i take the 2 normals of the portals and find the dot product. then i take the cross product of the 2 normals, and rotate the scene around the cross product! i think it will work....

That is in fact the way usual when 1 vector should be rotated onto another one.

Quote:
 Original post by adam17EDIT: it works, but the dot product is not oriented correctly. its only 0 <= theta <= pi. i need something for 0 <= theta <= 2pi

Yes, and no. Notice please that exchanging the arguments of the cross product will negate the result. This means that there is another "degree of freedom", allowing you to rotate either up to 180° in CW direction but also up to 180° in CCW direction, making a total of 360°!

However, using this method and a following pivot axis/angle to matrix conversion is just another way to compute
R1 * R2-1
and hence is a valid substitute for computing the up and right vectors and building the inside matrix product, but doesn't change the overall algorithm.

##### Share on other sites
woohoo! i was thinking about how the cross product would negate the angle last night, but i wasnt too sure about it. today the inverse matrix finally clicked and made sense!

unfortunately there must be a bug in my code, because nothing is rendering correctly. take a look:

for(size_t i=0; i<portals.size(); i++){	glPushMatrix();	//get position of second portal	Vector3 trans1 = objects[objects[portals].portal.linkPortalLoc].portal.pos;	//get position of first portal	Vector3 trans2 = objects[portals].portal.pos;	//get normal of first portal	Vector3 norm1 = objects[portals].portal.normal;	//get normal of second portal	Vector3 norm2 = objects[objects[portals].portal.linkPortalLoc].portal.normal;	//get the cross product of the two normals	Vector3 cross = Cross(norm1, norm2);	//...angle	GLfloat	angle = (180/3.1416) * Dot3(norm1, norm2);										glTranslatef(-trans1.x, -trans1.y, -trans1.z);	glRotatef(angle, cross.x, cross.y, cross.z);	glTranslatef(trans2.x, trans2.y, trans2.z);	//render scene in portal	glPopMatrix();}

this is a basic idea of how it renders. the blue and red symbols are the actual portals. the light red and light blue symbols are what the portals are showing:

i am a little worried about my math functions for the cross product and the dot product. i keep checking them but im not seeing anything wrong. there are several different ways of achieving the cross product

Vector3 Cross(Vector3 v1, Vector3 v2){	Vector3	temp_vector;	temp_vector.x = (v1.y * v2.z) - (v1.z * v2.y);	temp_vector.y = (-v1.x * v2.z) + (v1.z * v2.x);	temp_vector.z = (v1.x * v2.y) - (v1.y * v2.x);	return temp_vector;}float Dot3(Vector3 vector1, Vector3 vector2){	float p1;	float p2;	p1 = (vector1.x * vector2.x) + (vector1.y * vector2.y) + (vector1.z * vector2.z);	p2 = Magnitude(vector1) * Magnitude(vector2);	return acos(p1/p2);}

[Edited by - adam17 on October 1, 2006 2:13:50 AM]

##### Share on other sites
The dot product is just
float Dot(Vector3 v1, Vector3 v2){ return (v1.x*v2.x)+(v1.y*v2.y)+(v1.z*v2.z);}

##### Share on other sites
Not looked at the rendering code yet, but at the math code snippets:

Quote:
 Original post by adam17i am a little worried about my math functions for the cross product and the dot product. i keep checking them but im not seeing anything wrong. there are several different ways of achieving the cross product

The cross product seems me correctly implemented. AFAIK OpenGL's glRotate normalizes the vector, so you don't need to do so by yourself.

The other routine seems me correct as well, but it doesn't implement the dot product and hence shouldn't be named so. It implements the computation of the angle between 2 vectors, and hence you may take into account to declare it as
float angleBetween(Vector a, Vector b);

##### Share on other sites
I'm not totally sure about what portal is mapped to what portal, but I see an error in the order of transformations. If you implement
T1 * R * T2-1
then in OpenGL

glTranslatef(T1.x, T1.y, T1.z);
glRotatef( ... );
glTranslatef(-T2.x, -T2.y, -T2.z);
// followed by the scene objects here

would be the correct order. Notice that (due to column vector use) particular transformations more to the right in the formula appear "nearer" to the scene objects in the program. The order in the formula and in the program flow has to be effectively the same.

If it still doesn't work, then try to negate the angle (or else, as an alternative, exhange the arguments to the cross product invocation).

##### Share on other sites
OMG!!!!!!! i got it to work!! THANK YOU SOOOO MUCH! i was about in another reply that it still was not working but i switched the glTranslatef's and it worked! omg im soooooo happy now!

now i just have to figure out how to get my lighting code to work inside of the portals, the recursive nature of portals when facing each other and then the actual transporting!

once again, thank you soo much!