Archived

This topic is now archived and is closed to further replies.

LarrxX

Manual coordinates

Recommended Posts

I set out to do something I thought was simple but apprently I'm missing something. To make it simple, I want to draw a cube (using glutSolidCube ) centered in (x,y,z). I setup the projection matrix, then the modelview matrix and draw my cube, no problem. Now, what I'm trying to do is (I know this looks weird, but it'd be too long to explain), I setup the projection matrix then store it in an array then do a LoadIdentity() on the projection, I then do the same for the modelview matrix. Then I do the following (in a nutshell): GLdouble position[]={0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 1.0 }; glLoadMatrixd( projmatrix ); glMultMatrixd( mvmatrix ); glMultMatrixd( position ); glGetDoublev( GL_MODELVIEW_MATRIX, position ); glLoadIdentity(); glTranslatef( position[12], position[13], position[14] ); glutSolidCube( 0.1 ); I tried all the possible combinations of matrix multiplications but none of them seem to give the same result as the traditional way, can anyone tell me where I'm going wrong? [edited by - LarrxX on October 14, 2003 11:41:03 AM] [edited by - LarrxX on October 15, 2003 4:52:13 AM]

Share this post


Link to post
Share on other sites
inverse matrix
OR

glMatrixMode(GL_PROJECTION); /*__reset__ projection matrix */
glPushMatrix();
glFrustum(...);
glMatrixMode(GL_MODELVIEW); /*__reset__ modelview matrix */
glPushMatrix();
glLoadIdentity();
glTranslatef(x, y, z); /*translate*/
glutSolidCube(0.1f); /*draw*/

glMatrixMode(GL_PROJECTION); /*reset states*/
glPopMatrix();

glMatrixMode(GL_MODELVIEW);
glPopMatrix();




Share this post


Link to post
Share on other sites
quote:
Original post by 666_1337
inverse matrix
OR

glMatrixMode(GL_PROJECTION); /*__reset__ projection matrix */
glPushMatrix();
glFrustum(...);
glMatrixMode(GL_MODELVIEW); /*__reset__ modelview matrix */
glPushMatrix();
glLoadIdentity();
glTranslatef(x, y, z); /*translate*/
glutSolidCube(0.1f); /*draw*/

glMatrixMode(GL_PROJECTION); /*reset states*/
glPopMatrix();

glMatrixMode(GL_MODELVIEW);
glPopMatrix();






I know I can do it this way, but the point is I can''t, for some obscure reasons I won''t go into here.

The bottom line is, I want to know the absolute coordinates of my object once all transformations have been applied to it. So when I use a projection matrix P, and a modelview Matrix M on an object at position (0,5, 0,5, 0,5), what would the absolute position matrix be?

Share this post


Link to post
Share on other sites
there is no "absolute" matrix. only an "absolute" vector...

vector transform_to_clipping_space(vector &vertex)
{
matrix modelview, projection;
glGetFloatv(GL_MODELVIEW_MATRIX, &modelview.mat[0]);
glGetFloatv(GL_PROJECTION_MATRIX, &projection.mat[0]);
vector clipCoord = (projection*modelview)*vertex;
return clipCoord;
}

using this:

#ifndef LINALG
#define LINALG
#include <cmath>

class vector
{
public:
float x,y,z,w;

inline vector()
{ ; };
inline vector(float x0,float y0,float z0)
{
x=x0; y=y0; z=z0;
};
inline vector(float x0,float y0,float z0,float w0)
{
x=x0; y=y0; z=z0; w=w0;
};
inline vector(const float *f)
{
x=f[0]; y=f[1]; z=f[2]; w=f[3];
}
inline vector(const vector &v)
{
*this=v;
};
inline void null(void)
{
x=y=z=0;
};

inline void negate(void)
{
x=-x; y=-y; z=-z;
};
inline float length(void)
{
return sqrt(x*x+y*y+z*z);
}
inline void cross(const vector& v1, const vector& v2)
{
x=v1.y*v2.z-v1.z*v2.y;
y=v1.z*v2.x-v1.x*v2.z;
z=v1.x*v2.y-v1.y*v2.x;
}
inline void normalize(void)
{
float len=1.0f/length();
x*=len; y*=len; z*=len;
}
inline float& operator[](int i)
{
return (&x)[i];
};
}; //__attribute__((aligned(16)));


inline void operator*=(vector& v, const float f)
{
v.x*=f; v.y*=f; v.z*=f;
}
inline void operator/=(vector& v, const float f)
{
float _f = 1.0f/f;
v.x*=_f; v.y*=_f; v.z*=_f;
}
inline void operator-=(vector& v1, const vector& v2)
{
v1.x-=v2.x; v1.y-=v2.y; v1.z-=v2.z;
}
inline void operator+=(vector& v1, const vector& v2)
{
v1.x+=v2.x; v1.y+=v2.y; v1.z+=v2.z;
}
inline void operator*=(vector& v1, const vector& v2)
{
v1.x*=v2.x; v1.y*=v2.y; v1.z*=v2.z;
}
inline void operator/=(vector& v1, const vector& v2)
{
v1.x/=v2.x; v1.y/=v2.y; v1.z/=v2.z;
}

inline vector operator*(vector v1, const vector& v2)
{
v1.x*=v2.x; v1.y*=v2.y; v1.z*=v2.z;
return v1;
}
inline vector operator/(vector v1, const vector& v2)
{
v1.x/=v2.x; v1.y/=v2.y; v1.z/=v2.z;
return v1;
}
inline vector operator*( const float f, vector v)
{
v.x*=f; v.y*=f; v.z*=f;
return v;
}
inline vector operator*(vector v, const float f)
{
v.x*=f; v.y*=f; v.z*=f;
return v;
}
inline vector operator/(vector v, const float f)
{
float _f = 1.0f/f;
v.x*=_f; v.y*=_f; v.z*=_f;
return v;
}

inline vector operator+(vector v1, const vector& v2)
{
v1.x+=v2.x; v1.y+=v2.y; v1.z+=v2.z;
return v1;
}

inline vector operator-(vector v1, const vector& v2)
{
v1.x-=v2.x; v1.y-=v2.y; v1.z-=v2.z;
return v1;
}

inline float vec_dot(vector v1, const vector v2)
{
return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
}

class matrix
{
public:
float mat[16];

inline matrix(float f = 0)
{
for(int i = 0; i < 16; i++)
mat[i] = f;
}

inline matrix(const float *f)
{
for(int i = 0; i < 16; i++)
mat[i] = f[i];
}

inline matrix(const matrix &m)
{
memcpy(mat, m.mat, sizeof(float)*16);
}

inline matrix transpose()
{
matrix m2;
m2[0] = mat[0]; m2[4] = mat[1]; m2[8] = mat[2]; m2[12] = mat[3];
m2[1] = mat[4]; m2[5] = mat[5]; m2[9] = mat[6]; m2[13] = mat[7];
m2[2] = mat[8]; m2[6] = mat[9]; m2[10] = mat[10]; m2[14] = mat[11];
m2[3] = mat[12]; m2[7] = mat[13]; m2[11] = mat[14]; m2[15] = mat[15];
return m2;
}

inline matrix inverse()
{
matrix m2;
float det;

det = mat[0] * mat[5] * mat[10];
det += mat[4] * mat[9] * mat[2];
det += mat[8] * mat[1] * mat[6];
det -= mat[8] * mat[5] * mat[2];
det -= mat[4] * mat[1] * mat[10];
det -= mat[0] * mat[9] * mat[6];
det = 1.0 / det;

m2[0] = (mat[5] * mat[10] - mat[9] * mat[6]) * det;
m2[1] = -(mat[1] * mat[10] - mat[9] * mat[2]) * det;
m2[2] = (mat[1] * mat[6] - mat[5] * mat[2]) * det;
m2[3] = 0.0;
m2[4] = -(mat[4] * mat[10] - mat[8] * mat[6]) * det;
m2[5] = (mat[0] * mat[10] - mat[8] * mat[2]) * det;
m2[6] = -(mat[0] * mat[6] - mat[4] * mat[2]) * det;
m2[7] = 0.0;
m2[8] = (mat[4] * mat[9] - mat[8] * mat[5]) * det;
m2[9] = -(mat[0] * mat[9] - mat[8] * mat[1]) * det;
m2[10] = (mat[0] * mat[5] - mat[4] * mat[1]) * det;
m2[11] = 0.0;
m2[12] = -(mat[12] * m2[0] + mat[13] * m2[4] + mat[14] * m2[8]);
m2[13] = -(mat[12] * m2[1] + mat[13] * m2[5] + mat[14] * m2[9]);
m2[14] = -(mat[12] * m2[2] + mat[13] * m2[6] + mat[14] * m2[10]);
m2[15] = 1.0;
return m2;
}


inline matrix operator*(matrix &m)
{
matrix m2;
m2[0] = mat[0] * m[0] + mat[4] * m[1] + mat[8] * m[2] + mat[12] * m[3];
m2[1] = mat[1] * m[0] + mat[5] * m[1] + mat[9] * m[2] + mat[13] * m[3];
m2[2] = mat[2] * m[0] + mat[6] * m[1] + mat[10] * m[2] + mat[14] * m[3];
m2[3] = mat[3] * m[0] + mat[7] * m[1] + mat[11] * m[2] + mat[15] * m[3];
m2[4] = mat[0] * m[4] + mat[4] * m[5] + mat[8] * m[6] + mat[12] * m[7];
m2[5] = mat[1] * m[4] + mat[5] * m[5] + mat[9] * m[6] + mat[13] * m[7];
m2[6] = mat[2] * m[4] + mat[6] * m[5] + mat[10] * m[6] + mat[14] * m[7];
m2[7] = mat[3] * m[4] + mat[7] * m[5] + mat[11] * m[6] + mat[15] * m[7];
m2[8] = mat[0] * m[8] + mat[4] * m[9] + mat[8] * m[10] + mat[12] * m[11];
m2[9] = mat[1] * m[8] + mat[5] * m[9] + mat[9] * m[10] + mat[13] * m[11];
m2[10] = mat[2] * m[8] + mat[6] * m[9] + mat[10] * m[10] + mat[14] * m[11];
m2[11] = mat[3] * m[8] + mat[7] * m[9] + mat[11] * m[10] + mat[15] * m[11];
m2[12] = mat[0] * m[12] + mat[4] * m[13] + mat[8] * m[14] + mat[12] * m[15];
m2[13] = mat[1] * m[12] + mat[5] * m[13] + mat[9] * m[14] + mat[13] * m[15];
m2[14] = mat[2] * m[12] + mat[6] * m[13] + mat[10] * m[14] + mat[14] * m[15];
m2[15] = mat[3] * m[12] + mat[7] * m[13] + mat[11] * m[14] + mat[15] * m[15];
return m2;
}

inline matrix operator + (const matrix &m)
{
matrix m2;
for(int i = 0; i < 16; i++)
m2.mat[i] = mat[i]+m.mat[i];

return m2;
}

inline matrix operator - (const matrix &m)
{
matrix m2;
for(int i = 0; i < 16; i++)
m2.mat[i] = mat[i]-m.mat[i];

return m2;
}

inline float &operator [](int i)
{
return mat[i];
}

char* toString(void)
{
char *str = new char[1024];
sprintf(str,
"%f, %f, %f, %f\n"
"%f, %f, %f, %f\n"
"%f, %f, %f, %f\n"
"%f, %f, %f, %f\n",
mat[ 0], mat[ 1], mat[ 2], mat[ 3],
mat[ 4], mat[ 5], mat[ 6], mat[ 7],
mat[ 8], mat[ 9], mat[10], mat[11],
mat[12], mat[13], mat[14], mat[15]);
return str;
}
} __attribute__((aligned(16)));

inline vector operator * (const matrix &m, const vector v)
{
vector vec;
vec.x = m.mat[0]*v.x + m.mat[4]*v.y + m.mat[8] *v.z + m.mat[12]*v.w;
vec.y = m.mat[1]*v.x + m.mat[5]*v.y + m.mat[9] *v.z + m.mat[13]*v.w;
vec.z = m.mat[2]*v.x + m.mat[6]*v.y + m.mat[10]*v.z + m.mat[14]*v.w;
vec.w = m.mat[3]*v.x + m.mat[7]*v.y + m.mat[11]*v.z + m.mat[15]*v.w;
return vec;
}

#endif


...
if you now want to get the position on your screen, you have to divide the result of transform_to_clipping_space through its fourth (w-)coordinate. The result is in homogene form (ranging from -1 to +1)

Share this post


Link to post
Share on other sites
Thanx a lot 666_1337, this does get the position right on the button. But as you say there''s no absolute matrix, you mean there''s no way I can get the object''s rotation matrix using the method I am?

Share this post


Link to post
Share on other sites
"there is no absolute matrix" means, that a vertex is not stored into a matrix for drawing, but into a vector

so... i guess you know where the object should be on the screen, and you want to have the position in perspective space?

I don''t know how this exactly works but you could use the methods used for mousecursor-scene-interaction:

quote:

Watt & Polycarpo, Addison Wesley: 3D Games - Real Time Rendering and Software Technology
(1) transform the position into normalized field of view coordinates:
xv = 2xs / sx - 1
yv = 1 - 2ys/sy
zv = Cz
where
(xs, ys) is the position on the screen
(sx, sy) is the screen resoution

(2) Find the Direction D of the ray from C - the camera position - to the screen position:
D = (x, y, z)
where
x = xv*tan(alpha) / aspect_ratio
y = yv*tan(alpha)
z = Cz
alpha is half the field of view angle

(3) Use the ray with origin C and direction D to intersect with the scene
quote:


Share this post


Link to post
Share on other sites
I''m really sorry if this is getting lengthy but, as you might have noticed, matrices are not exactly my cup of tea.

The position vertex given by your previous post (using projection*modelview*position) is exactly what I need (after normalization). But now I have another problem, I need the rotation matrix that goes with it. What I mean is that when I apply the calculus you gave me, it does place the object at the correct position in absolute space, but it''s always got an orientation of (0,0,0) which is normal since I''m not rotating it yet. My question is, how can I get the 3x3 rotation matrix induced by the projection and modelview matrices? Is it sufficient to take the top-left 3x3 matrix in the result of the product between projection and modelview? What do I normalize it with?

Share this post


Link to post
Share on other sites
quote:
Original post by LarrxX
The position vertex given by your previous post (using projection*modelview*position) is exactly what I need (after normalization). But now I have another problem, I need the rotation matrix that goes with it. What I mean is that when I apply the calculus you gave me, it does place the object at the correct position in absolute space, but it''s always got an orientation of (0,0,0) which is normal since I''m not rotating it yet. My question is, how can I get the 3x3 rotation matrix induced by the projection and modelview matrices? Is it sufficient to take the top-left 3x3 matrix in the result of the product between projection and modelview? What do I normalize it with?


clipping space matrix = Projection*Modelview


[ xx, xy, xz, xw ]
Mclip = [ yx, yy, yz, yw ]
[ zx, zy, zz, zw ]
[ tx, ty, tz, 1 ]


the orientation is given by the vectors x(xx, xy, xz), y(yx, yy, yz) and z(zx, zy, zz). once you have the matrices values as vector, you can normalize them as one.

Share this post


Link to post
Share on other sites
when I do the projection*modelview product I get (for example) the following array[16]:

+0.962965 -0.298252 -0.747936 -0.740494 +0.000000 +1.448680 -0.261936 -0.259330 -1.150090 -0.249726 -0.626245 -0.620014 -0.016341 +0.015597 +1.035910 +4.010680

Questions:
1 - Should I divide everything by 4.010680 to normalize everything before I do my calculations?
2 - Are the first 4 values [xx, xy, xz, xw] or [xx, yx, zx, tx]?
3 - When you say to normailze the rotation vectors "as 1" do you mean divide the coordinates for the given axis (A) by the given w (Ax/Aw, Ay/Aw, Az/Aw) ? Or is it the same normalization for all using the global matrix w (which is 4.010680 in this case, and this brings us back to question 1).

Thanks again 666_1337

Share this post


Link to post
Share on other sites
why don''t you "bug" me in icq if its that important?

matrix clip;
...
vector clipX( clip[0], clip[1], clip[2] );
vector clipY( clip[4], clip[5], clip[6] );
vector clipZ( clip[8], clip[9], clip[10]);
vector Position( clip[12], clip[13], clip[14]);

clipX /= clip[3];
clipY /= clip[7];
clipZ /= clip[11];
Position /= clip[15];

the three clip vectors are the coordinate''s axes, projected on the screen. the Position vector holds the position of the locale in the screen (if it is on the screen).

another way to get the orientation is to multiply the clip matrix with (1, 0, 0), (0, 1, 0), (0, 0, 1) or any other vector representing an orientation

Share this post


Link to post
Share on other sites