Transforming coordinates between two reference frames in a scene.

Started by
10 comments, last by LlelanD 22 years, 8 months ago
In what manner can you use OpenGL to transform the coordinates from another frame to the current frame? An example: Object1 is an object within the scene that has a target coordinate relative to the local frame (say - a dot on a sphere). Object2 is another object within the scene (say - a long thin cylinder along the z-axis) that needs to be oriented so that the Z+ axis points towards the target coordinate of Object1. What you get is a cylinder that always points to the dot on the sphere no matter their relative positions. In what manner is OpenGL designed to be used to transform the target coordinate from the local reference frame of Object1 to the local reference frame of Object2 so that Object2 can then be correctly oriented? I can see a way using feedback mode to transform the coordinate using the Object1 matrix and the inverse of the Object2 matrix, but this seems an incredibly convoluted process for such a basic and common operations using data that the graphics system should already have available. Is this something that OpenGL is even capable of doing, or must you rely on the matrix operation capabilities of your host CPU?
Advertisement
I do not think that OpenGL has any extra support for this. OpenGL is doing many transformations but only the ones needed for displaying things right. You are seeking a function for something else.

You have functions like glLoadMatrix and glMultMatrix but it seems like an overkill to use them in your example.
I apologize if I''m missing something here, but your answer makes no sense. I wish to use OpenGL to display an object that is oriented at another object. This is precisely what the OpenGL 3D matrix transformation system was made for, is it not? To display this, as well as other, very common types of scene correctly?

The only potential solutions I''ve seen so far are:
  • Replicate the 3D matrix operations on the host CPU and figure out all object relations before sending data through OpenGL.
  • Put OpenGL in feedback mode, paint the related objects, get the related data, and then render the whole scene.

The problem with the first is that you''re wasting all that nice 3D matrix acceleration hardware on your graphics processor by having the host crunch data and transformations that you''re going to give to the graphics processor anyway. A huge waste of time.

The problem with the second is that you''re multiply rendering objects in feedback mode for each of their relationships to get the translated data, and then rendering them once again to paint. Another redundant waste of time since the 3D hardware will make the appropriate transformation matrices during the paint render.

This question is: How is OpenGL designed to be used to render a scene of related objects, such as one object oriented toward another?

You only build need to build the matrices : Say you have a frame f1 formed by three vectors U1,V1,W1 and a position P1.
a frame f2 formed by U2,V2,W2 and a position P2. And then there is the world frame worldf i,j,k

You want to transform and object from frame f2 to f1. You simply need to build a matrix to go from f2 to f1, pass this matrix to opengl and let the hardware to the work :

Now to transform from f2 to f1, if you remember stuff about vector spaces, what you need to do is this:

build the matrix f2 to worldf.(M1)
build the matrix worldf to f1.(M2)

multiply M2*M1 and voila!!! you have your coordinate change.

In detail :



M1 = |1 0 0 P2x||U2x V2x W2x 0|
|0 1 0 P2y||U2y V2y W2y 0|
|0 0 1 P2z||U2z V2z W2z 0|
|0 0 0 1 ||0 0 0 1|

M2 = |U1x U1y U1z 0||1 0 0 -P1x|
|V1x V1y V1z 0||0 1 0 -P1y|
|W1x W1y W1z 0||0 0 1 -P1z|
|0 0 0 1||0 0 0 1|

you can let opengl have all the fun by splitting M1 and M2 in their 2 respective matrix M1 = M11*M22 and M2=M21*M22


    glPushMatrix();glMatrixMode(GL_MODEL_VIEW);glLoadIdentity();glScalef(-1,1,-1); //this is necessary because our basic frame                    //is (0,0,1) (0,1,0) (0,0,1) and opengl is                    //(0,0,-1) (0,1,0) (0,0,-1)float* M11;//build M11glMultMatrixf( M11 );float* M12;//build M12glMultMatrixf( M12 );float* M21;//build M21glMultMatrixf( M21 );float* M22;//build M22glMultMatrixf( M22 );//Draw your object!glPopMatrix();    


Now for a more down to earth explanation of the above math:

What the code above does is setting up the view so that frame f1 views object f2 in world.

matrix M2 is the object space to world space matrix of f1.
And M2 is the world space to object space of f2, or put simply it is a view matrix.



Edited by - Gorg on August 10, 2001 12:29:58 PM
You've missed the point of the question. What you have described is the math needed to transform a point from another reference frame (F2) to the reference frame currently being rendered (F1). The code you've shown is how you would create the transformation matrix (F2 X inv(F1)).

BTW: I like how you did the example code. I'll keep it in mind.

The problem is not with the math or with the creation of the matrix. It is a procedural problem with how OpenGL is designed to be used to render a scene. When in render mode, you transform from the world frame (FW) to F2 and apply your local coordinates. Then you pop back to FW and transform to F1. But F1 must now be oriented to a point that is still expressed in F2 coordinates. The question is how to use OpenGL to use the 3D matrix hardware to translate that point's coordinates from F2 to F1 so you can orient F1 correctly.

  glMatrixMode(GL_MODEL_VIEW);glLoadIdentity(); transformFromView(frame1);     // From the frame1 viewpoint to frameWorld. glPushMatrix();                // Render frame2.applyFrame(frame2);renderFrame(frame2);glPopMatrix(); glPushMatrix();                // Render frame1.// applyFrame(frame1);/* * We need to translate the frame * and then orient it to a point in frame2 coordinates. * How do we use OpenGL to transform the frame2 coordinates to frame1? */renderFrame(frame1);glPushMatrix();  


Some experimentation with the so-called feedback mode shows that only clipped window coordinates are returned. If you try to use feedback mode to transform a coordinate that is not currently in direct view of the window it will not be returned. I can find no way to alter this odd behavior. This means that we have all this lovely accelerated matrix hardware and we cannot use it via OpenGL for anything except a slaved render of data that cannot be related.

Unless someone can uncover some other function in OpenGL I guess this means the only method is to use the host CPU to perform the same matrix calculations that the graphics system already does to obtain reference frame transforms of related data. This seems to me to be an incredible waste of resources that I find difficult to believe.

Edited by - LlelanD on August 10, 2001 10:56:09 AM
Well, I guess you are talking about something else. I read the original question as a problem with two points in world/model space. Building matrices for that would certainly be big and ugly and far from efficent.
Trying to take advantage of hardware accelerated matrix functions would probably make things worse (one vertex!).

I do not understand your new question. It talks about OpenGL and rendering releated objects but asks how to orient objects.
Just FYI, to make a source code box like the one in Gorg''s post, write like this:

[ source ]
Your code goes here
[ /source ]

but without any whitespace in between the [ and ] pairs. Then it will look like this:

  Your code goes here  
I''m not asking how to create or apply the math to orient one frame to another (been doing that for decades), I''m asking how to use OpenGL, or even if you can use it, to perform the matrix transformation of the coordinates for a point in F2 to the coordinates in F1.

To get the parameters for orienting F1 to point its z-axis at the point P in F2 you need to transform the F2 coordinates:

[F2] X inv([F1]) X [P] = P in F1 coordinates

With the F1 coordinates for P you can now orient F1. I stated a simple example where a slim cylinder (F1) would always be rendered pointed toward a designated spot (P) on a sphere (F2) no matter the relative position or orientation of both objects.

I can do this on the host CPU by creating a function that performs the transform, but this seems a terrible waste when performing matrix transforms is what the graphics hardware is designed to do, and relating one frame''s coordinates to another frame is a fundamental part of the render process. I mean, a camera that follows a viewed object no matter to where it moves is pretty common.
I should have been more descriptive my source code should have looked like that(it is using a bit of yours ) :

I actually did a little mistake in my code, I did M1*M2, it should have been M2 * M1 or (M21*M22)(M11*M22), anyway..

        glMatrixMode(GL_MODEL_VIEW);glLoadIdentity(); transformFromView(frame1);     // From the frame1 viewpoint to frameWorld. glPushMatrix();                // Render frame2.applyFrame(frame2);renderFrame(frame2);glPopMatrix(); glPushMatrix();                // Render frame1.applyFrame(2); //I assume this function works with standard opengl frameglScalef(-1,1,-1); //want to synchronize our frames with openglframe//buildMatrix to go from XYZ to f2glMultMatrix(XYZTof2);//build matrix to go from f1 to XYZglMultMatrix(f1ToXYZ);renderFrame(frame1);glPopMatrix();        


What the code above does is this for frame1 is:


PointInXYZ = ViewMatrix * f2ToXYZ * XYZTof2 * f1ToXYZ *

or splitted :

transformed object in f1 to f2

pointInF2 = XYZTof2 * f1ToXYZ * pointInF1;


move object from f2 to view frame.

pointInXYZ = ViewMatrix * f2ToXYZ * pointInF2;


Which I believe is what you want.



Edited by - Gorg on August 10, 2001 12:20:59 PM

Edited by - Gorg on August 10, 2001 12:26:05 PM

Edited by - Gorg on August 10, 2001 3:12:10 PM
One quick note: Unless the video card supports hardware T&L and you''re using the T&L extensions, the transforms will be performed by the CPU anyway, no matter how you do them.

This topic is closed to new replies.

Advertisement