Started by Mar 06 2008 10:05 AM

,
11 replies to this topic

Posted 06 March 2008 - 10:05 AM

Hi all!
I must calculate the projected area of triangle
I've 3 points with coordinates x,y,z.
I retrive the projection matrix with the function
glGetFloatv(GL_PROJECTION_MATRIX, m), and i multiply this matrix for my triangle points.
It's correct?
Now, how i can find the triangle area?
Thanks!

Posted 06 March 2008 - 10:33 AM

Project the points of your triangle (A, B, C):

A' = m * A

B' = m * B

C' = m * C

u = B' - A'

v = C' - A'

area = 1/2 * |u x v|

(x is vector cross product)

A' = m * A

B' = m * B

C' = m * C

u = B' - A'

v = C' - A'

area = 1/2 * |u x v|

(x is vector cross product)

Posted 06 March 2008 - 03:43 PM

That doesn't seem right, CodeMunkie. The projection matrix is a 4x3 matrix. You need to put a 1 as a fourth coordinate for each point. The resulting projected points now have 3 coordinates, and you need to divide by the last coordinate to turn them into meaningful 2D points.

Now that you have 3 2D points, the cross product that you are proposing isn't really defined in 2D. You can add a third coordinate that is 0 and do it the way you described (now in 3D), or you can just compute the area as the absolute value of

|x1 y1 1|

|x2 y2 1| * 1/2

|x3 y3 1|

Now that you have 3 2D points, the cross product that you are proposing isn't really defined in 2D. You can add a third coordinate that is 0 and do it the way you described (now in 3D), or you can just compute the area as the absolute value of

|x1 y1 1|

|x2 y2 1| * 1/2

|x3 y3 1|

Posted 06 March 2008 - 10:39 PM

With glGetFloatv(GL_PROJECTION_MATRIX, m) function i have a 4x4 matrix, not a 4x3 matrix.

I put a 1 as fourth coordinate for each point, then for each point i do the product between my 4x4 matrix and my point vector (with four rows). The result is a new point vector (with four rows).

Now, what i do?

Thanks!

I put a 1 as fourth coordinate for each point, then for each point i do the product between my 4x4 matrix and my point vector (with four rows). The result is a new point vector (with four rows).

Now, what i do?

Thanks!

Posted 06 March 2008 - 11:48 PM

Converting from a homogeneous position vector to an affine position vector requires the homogeneous co-ordinate to be 1. If it isn't, dividing the vector by its homogeneous co-ordinate does the trick.

Then simply drop the homogeneous co-ordinate to yield in the equivalent affine vector. Now you still have 3 co-ordinates left, but you can ignore the z co-ordinate if you're not interested in a depth value. Hence all you have to do is to pick out the x and y co-ordinates.

BTW, be aware that the PROJECTION matrix does include neither local-to-global nor global-to-eye/camera transformations. So the vertex co-ordinates mentioned in the OP have to already be given relative to the camera's co-ordinate frame.

Then simply drop the homogeneous co-ordinate to yield in the equivalent affine vector. Now you still have 3 co-ordinates left, but you can ignore the z co-ordinate if you're not interested in a depth value. Hence all you have to do is to pick out the x and y co-ordinates.

BTW, be aware that the PROJECTION matrix does include neither local-to-global nor global-to-eye/camera transformations. So the vertex co-ordinates mentioned in the OP have to already be given relative to the camera's co-ordinate frame.

Posted 07 March 2008 - 03:11 AM

Quote:

Original post by haegarr

BTW, be aware that the PROJECTION matrix does include neither local-to-global nor global-to-eye/camera transformations. So the vertex co-ordinates mentioned in the OP have to already be given relative to the camera's co-ordinate frame.

Don't understand this point...

Posted 07 March 2008 - 04:46 AM

Quote:

Original post by enigmagame

Original post by haegarr

BTW, be aware that the PROJECTION matrix does include neither local-to-global nor global-to-eye/camera transformations. So the vertex co-ordinates mentioned in the OP have to already be given relative to the camera's co-ordinate frame.

Don't understand this point...

Normally geometry of a mesh is given w.r.t. a co-ordinate system especially for that mesh. Now, the mesh as a whole is rotated to the wanted orientation and located in the world. This in summary is what is called the local-to-global transformation. In OpenGL this is what makes the MODEL portion of the MODELVIEW matrix. Let's name it

Normally you'll look into the world by a camera. The camera, normally handled like any other object in the world, also has a local-to-global transformation. However, what you want is to see the scene from the camera, not from the world. Hence you are interested in fact in the inverse of the camera's co-ordinate frame (i.e. its global-to-local transformation). This transformation makes the VIEW portion of OpenGL's MODELVIEW matrix. Let's name it

if

The PROJECTION matrix is applied to the geometry after it is transformed to be camera local. If the projection is named

(using column vectors, as OpenGL does). So you have to consider this if your geometry is not already give w.r.t. the camera's local co-ordinate frame.

Posted 07 March 2008 - 05:25 AM

I have positioned the model with glTranslate() function, and i setup the camera with the gluLookAt() function.

So i must multiply each triangles point for the M (MODELVIEW MATRIX) and then for the P (PROJECTION MATRIX)?

For example if V1, V2, V3 is triangle points:

glGet(GL_MODELVIEW_MATRIX, M);

glGet(GL_PROJECTION_MATRIX, P);

and then

M*P*V1 = V1'

M*P*V2 = V2'

M*P*V3 = V3'

It's correct, or i have forgot the view transformation?

Thanks!

So i must multiply each triangles point for the M (MODELVIEW MATRIX) and then for the P (PROJECTION MATRIX)?

For example if V1, V2, V3 is triangle points:

glGet(GL_MODELVIEW_MATRIX, M);

glGet(GL_PROJECTION_MATRIX, P);

and then

M*P*V1 = V1'

M*P*V2 = V2'

M*P*V3 = V3'

It's correct, or i have forgot the view transformation?

Thanks!

Posted 07 March 2008 - 06:50 AM

Quote:Assuming that these steps are done with the GL_MODELVIEW_MATRIX being active, then you've specified said MODELVIEW matrix. But, of course, you have to invoke the camera settings (e.g. gluLookAt)

Original post by enigmagame

I have positioned the model with glTranslate() function, and i setup the camera with the gluLookAt() function.

Quote:The view transformation is part of the MODELVIEW transformation, and you get both in combination if you invoke glGet(GL_MODELVIEW_MATRIX, M). Some people think it is nasty, but OpenGL does it that way. However, you've forgotten about the fact that mathematically column vectors and row vectors have to be distinguished clearly. OpenGL uses column vectors (as opposed to D3D, which uses row vectors). A matrix-vector product with column vectors is written as

Original post by enigmagame

So i must multiply each triangles point for the M (MODELVIEW MATRIX) and then for the P (PROJECTION MATRIX)?

For example if V1, V2, V3 is triangle points:

glGet(GL_MODELVIEW_MATRIX, M);

glGet(GL_PROJECTION_MATRIX, P);

and then

M*P*V1 = V1'

M*P*V2 = V2'

M*P*V3 = V3'

It's correct, or i have forgot the view transformation?

w/

Order of matrices is very important!

With these aspects in mind, your formula

M*P*V1 = V1'

is wrong, since it means "transform the vertex with P (the projection matrix), and transform the result with M (the modelview matrix)". Please compare this with the formula i've posted in my previous answer:

or, with the combined MODELVIEW matrix (and hence closer to your style)

which means "transform the (here not shown) vertex with the modelview matrix, and transform the result with the projection matrix".

Now coming back to your sentence I've cited at first in this post, it is important that after clearing the MODELVIEW matrix, you first have to set the camera (i.e. invoke gluLookAt), and after that you have to set the model transformation:

glLoadIdentity();

gluLookAt(...); // camera

glTranslate(...); // model

since this order of invocations is equivalent to

what builds the MODELVIEW matrix correctly.

Taking all this together, I'd say that

would be the solution you're looking for. Notice please that I assume here that your vector API works with column vectors, since your "code snippet" has shown the vector on the right side.

glGet(GL_MODELVIEW_MATRIX, M);

glGet(GL_PROJECTION_MATRIX, P);

V1' = P*M*V1

Posted 09 March 2008 - 11:09 PM

Quote:

Original post by haegarr

Assuming that these steps are done with the GL_MODELVIEW_MATRIX being active, then you've specified said MODELVIEW matrix. But, of course, you have to invoke the camera settings (e.g. gluLookAt)beforeyou invoke the model settings, or else things will go wrong. See below for why.

Yes, yes, first i set the camera (with gluLookAt function) and then i invoke the model settings.

Quote:

Original post by haegarr

Taking all this together, I'd say that

glGet(GL_MODELVIEW_MATRIX, M);

glGet(GL_PROJECTION_MATRIX, P);

V1' = P*M*V1

I must calculate for each triangle a weight factor, where the weight factor is: (area of projected triangle)/(surface area of triangle), and then i must render each triangle, flat filled, with intensity proportional to the weight factor.

I've tried with this model, and with your indication for the projected area.

http://img156.imageshack.us/img156/7909/scimmiahx4.jpg

But for me, the results is wrong...

I think I make mistakes to calculate the projected area.

I've made this:

glGet(GL_MODELVIEW_MATRIX, M);

glGet(GL_PROJECTION_MATRIX, P);

M and P is a vector, then with a function I create two 4x4 matrix with M and P values. I've multiplied P*M. I've added a fourth co-ordinate (1) to each vertex.

I've multiplied the results of P*M for each vertex (A,B,C) so:

- A' = P*M*A

- B' = P*M*B

- C' = P*M*C

Then i've divided each x and y vertex co-odrinate for the fourth co-ordinate and i set the z co-ordinate to 0.

I've calculated this vectors:

- V1 = B - A

- V2 = C - A

then i made the cross product of V1 and V2 and i return half of magnitude.

It's wrong?

Thanks!

Posted 10 March 2008 - 01:24 AM

On how to convert the "vector" into a matrix (you haven't written how you've done it, so I mention it here): OpenGL not only uses column vectors but also column major order for their linear matrix storage. That means that a sequence of coefficients

The algorithm you've outlined above seems me correct so far. However, there are many possibilities to build bugs into the code, of course. It may be best to check the results of the various steps for plausibility. E.g. generate a quad in front of the camera, the face perpendicular and centric to the line-of-view. Then look at the matrices when freshly returned by glGet. Do they look as expected? And after multiplying the vertex positions, are the projected positions also okay? Simplify the test cases as much as possible for the first tests, e.g. let the camera rest at**0** and don't change its looking direction. Use **I** as model matrix and compute the quad's vertices as they were in global co-ordinates.

I don't assume so, but it may be that the one or other matrix needs to be inverted. Looking at simplified test cases may expose such algorithmic errors earlier or later, also it may expose coding errors.

as is returned by glGet, has to be interpreted as a matrix like in

c00 c01 c02 c03 c04 ... c15

[ c00 c04 c08 c12 }

[ c01 c05 c09 c13 }

[ c02 c06 c10 c14 }

[ c03 c07 c11 c15 }

The algorithm you've outlined above seems me correct so far. However, there are many possibilities to build bugs into the code, of course. It may be best to check the results of the various steps for plausibility. E.g. generate a quad in front of the camera, the face perpendicular and centric to the line-of-view. Then look at the matrices when freshly returned by glGet. Do they look as expected? And after multiplying the vertex positions, are the projected positions also okay? Simplify the test cases as much as possible for the first tests, e.g. let the camera rest at

I don't assume so, but it may be that the one or other matrix needs to be inverted. Looking at simplified test cases may expose such algorithmic errors earlier or later, also it may expose coding errors.