• Create Account

## Transforming coordinates between two reference frames in a scene.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

11 replies to this topic

### #1LlelanD  Members

Posted 08 August 2001 - 02:21 PM

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?

### #2Obelix  Members

Posted 09 August 2001 - 07:10 AM

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.

### #3LlelanD  Members

Posted 09 August 2001 - 04:54 PM

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?

### #4Gorg  Members

Posted 09 August 2001 - 05:29 PM

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

### #5LlelanD  Members

Posted 10 August 2001 - 03:39 AM

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

### #6Obelix  Members

Posted 10 August 2001 - 03:52 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.

### #7Anonymous Poster_Anonymous Poster_*  Guests

Posted 10 August 2001 - 04:00 AM

Just FYI, to make a source code box like the one in Gorg''s post, write like this:

[ source ]
[ /source ]

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

  Your code goes here

### #8LlelanD  Members

Posted 10 August 2001 - 04:12 AM

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.

### #9Gorg  Members

Posted 10 August 2001 - 05:16 AM

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

### #10TerranFury  Members

Posted 10 August 2001 - 10:08 AM

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.

### #11Gorg  Members

Posted 10 August 2001 - 10:45 AM

quote:
Original post by TerranFury
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.

True, but it needs to be implemented by the driver anyway, and so if the writers are nice, they will use whatever machine code optimisation they can to do it. So in most cases, it should still be faster then "manually doing the calculations".

### #12LlelanD  Members

Posted 12 August 2001 - 07:46 AM

Well, Gorg ol' buddy, I've got no idea where you're going with that. As far as I can see, after transforming to, rendering, and popping back from F2, you are:
• re-transforming to F2,
• using a loaded matrix to re-transform back out to frame world (FW),
• using a loaded matrix to transform to F1,
• and then drawing F1.
This does not orient F1 to point to a coordinate in F2. Either I'm being neutronically dense, or we're talking apples and Studebakers here.

Fortunately, I've figured out a way to do it. It's a little cheesy, but it works and it uses the graphic hardware via OpenGL to do the matrix operations instead of the host CPU.

• Transform to, render, and pop back from the target frame (F2).
• Transform to the tracker frame (F1).
• Push the model matrix and load the identity matrix.
• Apply the inverse transform for F1.
• Apply the transform for F2.
• Cheesy part - Use a loaded matrix to hold up to 4 coordinates which will be transformed by the set of matrices we just applied.
• Do a glMultMatrix() to transform the points.
• Read back the current matrix using "glGetFloatv(GL_MODELVIEW_MATRIX, matrix);" (or glGetDouble()) to get the transformed coordinates.
• Pop the F1 frame back in.
• Orient the frame with the coordinates you just transformed from F2 to F1.

Works like a charm. Here's the display code. If you'd like to see this run, you can download my zipped GLUT example and try it out for yourself. It's just a simplified example with a few keyboard controls.
• F1 will toggle full-screen/windowed.
• 'a' toggles the frame axes.
• 'g' toggle the XZ grid.
• '+' and '-' speed up/slow down the animation speed.

If anyone has a better way of using OpenGL to transform points between frames, Please let me know.

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Transform from view (FV) to world (FW). glLoadIdentity(); gluLookAt(2.0, 4.0, 12.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // Draw FW objects. drawGrid(); // Draw the target frame (F2). glPushMatrix(); applyF2(); renderF2(); glPopMatrix(); // Draw the tracker frame (F1). glPushMatrix(); applyF1(); // This F1 tracker must always orient its z-axis to the F2 point [0, 0, 0] // (The center of the wandering purple piece of fuzz). // We must transform the F2 point coordinates (PF2) to F1 coordinates (PF1). // PF1 = inv(F1) x F2 x PF2 glPushMatrix(); glLoadIdentity(); applyInvF1(); applyF2(); // Use a transformation matrix as a set of 4 points to transform. // (We're only going to use the first point) GLfloat m[16]; zero(m); m[ 0] = 0.0; m[ 1] = 0.0; m[ 2] = 0.0; m[ 3] = 1.0; glMultMatrixf(m); glGetFloatv(GL_MODELVIEW_MATRIX, m); glPopMatrix(); // Orient F1 to point the z-axis to the point now in F1 coordinates. track(m[0], m[1], m[2], 0.0); renderF1(); glPopMatrix(); // Update the display. glutSwapBuffers();

Some screen shots:

Edited by - LlelanD on August 12, 2001 2:53:33 PM

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.