Getting absolute value of a transformed point coordinate

Hi guys,

I’m defining a point after using a transformation like:

  
	ofPushMatrix();  
	ofTranslate(center.x, center.y);  
	ofRotate(rotation);   
	ofPoint relativePoint = ofPoint(-3, +6);  
	[...]   
	ofPopMatrix();  
  
	ofPoint absolutePoint = ???????; // relativePoint once it's transformed, not with -3, 6 values  
  

Is there any way to get the point’s “absolute” position of that point?
E.g.: The x and y of the point in the screen.

Thanks in advance.

1 Like

Because what you’re doing is with all the rotates and transforms is basically just multiplying a vectors, you can do all the multiplications and translations to a ofxVec3f vector and then multiply your point by that late to get the point, or you can call glGetFloatv() at the end of all your transformations to store everything you’ve done. Check out this page http://www.songho.ca/opengl/gl-transform.html for some info on that GL method and how it’s done. The somewhat less than friendly docs on that are here: http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml

The basic idea is to store everything you’ve done in an array and then multiply your point by the appropriate values in the matrix that you get back from glGetFloatv()

Thank you Joshua, that was exactly what I am looking for.

Initially I had done all the calculation with vectors but then I found very convenient using oF functions.

Storing the oF functions’ transformations is what I was trying to find. I’ll give it a try :slight_smile:

Ok, I tried:

  
  
	ofPushMatrix();  
	ofTranslate(center.x, center.y);  
	ofSetRectMode(OF_RECTMODE_CENTER);  
	ofRotate(rotation);  
	  
	  
	GLfloat* m;  
	glGetFloatv(GL_MODELVIEW_MATRIX, m);  
  

but I’m getting a wonderful Program received signal: “EXC_BAD_ACCESS”.
Isn’t there any example with it working or some kind of source code i can use?

Thanks again for your help.

try

  
  
	GLfloat m[16];  
	glGetFloatv(GL_MODELVIEW_MATRIX, &m);  
  

cheers,
Stephan

error: cannot convert ‘GLfloat* (*)[16]’ to ‘GLfloat*’ for argument ‘2’ to ‘void glGetFloatv(GLenum, GLfloat*)’

But passing the variable instead of the pointer reference did the trick:

  
GLfloat m[16];  
glGetFloatv(GL_MODELVIEW_MATRIX, m);  

Now I have all the transformations in m variable (good!). But I’m still not sure on how to apply them to my ofPoint. :S

Playing with ofxVec2f did the trick as I can normalize it, rotate, scale… and the rest of things I was missing in ofPoint.

It would still be interesting to see how to apply m to a point vector though :slight_smile:

you can use an ofxMatrix4x4 like:

  
GLfloat m[16];  
glGetFloatv(GL_MODELVIEW_MATRIX, m);  
ofxMatrix4x4 mat(m);  
ofxVec3d point(x,y,0);  
ofxVec3d transformed_point = point * mat;  

1 Like

Now, THAT was what I was looking for. Thank you! :slight_smile:

hey folks,

i’ve been trying to wrap my head around this very same problem, and mr. noble’s code sample helps quite a fair bit but it doesn’t completely solve my problem.

what i’ve observed is that the modelview matrix contains the rotation that was calculated but does not seem to take the preceding translation (the one before the rotation) into consideration.

… and the so value of the translation needs to be added back first in order to get the correct absolute 3d position.

  
// center the object  
glTranslatef(ofGetWidth()/2, ofGetHeight()/2, 0);  
  
// rotate around z and y  
glRotatef(ofNoise(ofGetFrameNum() * 0.002) * 360, 0, 0, 1);   
glRotatef(ofNoise((ofGetFrameNum() + 251) * 0.002) * 360, 0, 1, 0);   
  
GLfloat mv[16];  
glGetFloatv(GL_MODELVIEW_MATRIX, mx);  
ofxMatrix4x4 mat(mv);  
  
// calculate the position of the rotated point  
ofxVec3f point(200, 0, 0);  
ofxVec3f result = point * mat;  
  
// invert the y position  
res.y *= -1;  
  
// add back that original translation, which makes me scratch my head  
res += ofxVec3f(ofGetWidth()/2, ofGetHeight()/2, 0);  

is this b/c of the way that oF handles the opengl viewport, setting 0, 0 to be the upper left corner of the screen?

any insights would be greatly appreciated!

thanks++

jeremy

ok, a little bit of extra reading about matrix math helped quite a bit. if anybody is curious … or similarly lost, this article in particular was helpful: http://www.sjbaker.org/steve/omniv/matr-…-iends.html. matrices are indeed my friends now.

i now understand that gluLookAt does in fact affect the modelview matrix, so the position values in that matrix were reflecting this. i’m still not 100% certain if there’s a better way to do this, but i needed to add the eyeX and eyeY and dist values (from the gluLookAt function) to get the absolute position.

by the way, really easy way to determine the position of an object after transformations:

  
  
  
GLfloat modelview[16];  
glGetFloatv(GL_MODELVIEW_MATRIX, modelview);  
  
ofxVec3f translation;  
translation.x = modelview[12];   
translation.y = modelview[13];  
translation.z = modelview[14];  
  
  

jeremy

I had the same question as ozke, trying to get the absolute position of the point and found this thread. Unfortunately it doesn’t work for me, so I think I have misunderstood something.
Here is what my draw code is :

ofPoint myPoint(60, 40);
ofSetColor(ofColor::green);
ofCircle(myPoint, 10);

ofPushMatrix();
ofTranslate(ofPoint(400, 300));	

GLfloat m[16];
glGetFloatv(GL_MODELVIEW_MATRIX, m);
ofMatrix4x4 mat(m);

ofSetColor(ofColor::red);
ofCircle(myPoint, 10);

ofPopMatrix();

ofPoint absolutePoint = myPoint * mat;
ofSetColor(ofColor::blue);
ofCircle(absolutePoint, 10);

And here is the result :

The absolutePoint should display at the same position as the red circle, but it is scaled down and not at the good coordinates.
Where is my mistake ?

the problem is that the model view matrix that OF uses by default is not the identity since we set the 0,0 at the top,left and move the camera back from z=0 so the coordinates of the screen are those of the size of the window

When you download the current model view and multiply that by your point you are actually multiplying that transformation twice + the translation, to get the exact same result as the red circle you would need to set the modelview to the identity like:

ofPoint myPoint(60, 40);
ofSetColor(ofColor::green);
ofCircle(myPoint, 10);

ofPushMatrix();
ofTranslate(ofPoint(400, 300));	

GLfloat m[16];
glGetFloatv(GL_MODELVIEW_MATRIX, m);
ofMatrix4x4 mat(m);

ofSetColor(ofColor::red);
ofCircle(myPoint, 10);

ofPopMatrix();

ofPoint absolutePoint = myPoint * mat;
ofSetColor(ofColor::blue);
ofPushMatrix();
ofLoadMatrix(ofMatrix4x4::newIdentityMatrix());
ofCircle(absolutePoint, 10);
ofPopMatrix();

another posibility is to multiply the matrix with the translation by the inverse of the default OF model view like:

        glGetFloatv(GL_MODELVIEW_MATRIX, m);
        ofMatrix4x4 matDefault(m);

        ofPoint absolutePoint = myPoint * matDefault.getInverse() * mat;

or even just create a matrix with the translation and use that to transform the GL coordinate space and to transform the point in the cpu like:

ofPoint myPoint(60, 40);
ofSetColor(ofColor::green);
ofCircle(myPoint, 10);

ofMatrix4x4 translation = ofMatrix4x4::newTranslationMatrix(ofVec3f(400,300));
ofPushMatrix();

ofMultMatrix(translation);
ofSetColor(ofColor::red);
ofCircle(myPoint, 10);

ofPopMatrix();

ofPoint absolutePoint = myPoint * translation;
ofSetColor(ofColor::blue);
ofCircle(absolutePoint, 10);

this latest option is the fastest since you don’t need to download anything from the gpu or calculate the inverse of a matrix which can be really slow depending on how often you need to do it

3 Likes

Great, thanks for your answer, arturo

Hey everybody. I tried the example by Arturo but unfortunately I still can’t find the answer to the problem. Arturo is applying only a translation. In my case I am also adding a rotation.
Why is the blue and red circles not aligned and how can I make them to do so? The translation bit works. It’s the rotation that’s giving me a headache. Any help much appreciated.

void ofApp::draw(){
    ofBackground(0);

    ofSetRectMode(OF_RECTMODE_CENTER);
    ofPoint myPoint(50, 50);
    ofSetColor(ofColor::green);
    ofCircle(myPoint, 20);

    //===================================
    ofPushMatrix();
    ofMatrix4x4 translation = ofMatrix4x4::newTranslationMatrix(ofVec3f(ofGetWidth()/2,ofGetHeight()/2,0));
    ofMatrix4x4 rotation = ofMatrix4x4::newRotationMatrix(45, 0, 0, 1);
    ofMultMatrix(translation);
    ofMultMatrix(rotation);
    ofSetColor(ofColor::red);
    ofCircle(myPoint, 20);
    ofPopMatrix();

    //==================================
    ofPushMatrix();
    ofVec3f absolutePoint;
    absolutePoint = myPoint.getRotated(45, ofVec3f(0,0,1));
    absolutePoint = myPoint * translation;
    ofSetColor(ofColor::blue);
    ofCircle(absolutePoint, 10);
    ofPopMatrix();
}

isn’t it rotate instead of getRotated?

maybe this is what you wanted?

absolutePoint = myPoint * rotation;
absolutePoint = absolutePoint * translation;

yes! that’s was exactly it. I had to reverse the order of the transformations. I thought I had tried it already but I guess I hadn’t.

Thanks @JordiPuig. I spent a good 4-5 hours last Sunday trying to figure out what was wrong. Oh well.

marinero

BTW i think this post by @tgfrerer has a really nice explanation of some of this issues

glGetFloatv(GL_MODELVIEW_MATRIX, m) is deprecated, the values returning are wrong.

Can anyone help me to fix this?

Cheers!