OpenGL 投影矩阵急问
某点C[x y z 1]先和Modelview矩阵相乘,再和Projection矩阵相乘最后得到
P[x y z w],我看了写glOrtho填写ProjectionMatrix的方法,大概推测其后的
渲染过程如下,大家看对不:
1.与ModelviewMatrix和ProjectionMatrix相乘结果最后得到P[x y z w]
2.如果P点满足 x,y,z都包含于[-w,w)区间,则此点可以被显示出来,否则舍去
3.归一化处理V=P/w=[x/w,y/w,z/w,1],此时(Vx, Vy)点就已经是设备坐标了,
4.根据glViewport(x,y,width,height)设置的数值,计算窗口坐标:
Xw = (Vx + 1) * width / 2 + x
Yw = (-Vy + 1) * height / 2 + y
5.正常在窗口上面渲染
试问OpenGL其过程是否真如上面所说??如果是那么我有如下问题:
1.现在ModelViewMatrix是单位矩阵
如果我设置一个Projection矩阵如下:那么危险了,因为他和C[x y z 1]相乘
[ 1 0 0 0 ]
PM = [ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 -1 0 ]
结果变成:
[ 1 0 0 0 ] [ x ] [ x ]
[ 0 1 0 0 ] * [ y ] = [ y ]
[ 0 0 1 0 ] [ z ] [ z ]
[ 0 0 -1 0 ] [ 1 ] [-z ]
P=PM * C = [ x y z -z] 如果C点的z=0那么做归一化处理的时候w=0,还要让
V=P/w=[x/w, y/w, z/w, 1]启不是无穷大了??
OpenGL 是如何处理的??或者我设置Projection矩阵为:
[ 1 0 0 0 ] 然后我作图,居然能正常显示一条(-1,-1)-(1,1)的直线,
[ 0 1 0 0 ] 但是不能正常显示三角形了,会变成一屏幕的红色,有点搞笑
[ 0 0 1 0 ]
[ 0 0 0 0 ]
到底什么原因呢??谁能给我说下OpenGL是如何处理这最后的一步的??
2.如上面所假设成功,那么我判断是个点是否在视锥中只要简单乘与Modelview
和Projection两个矩阵,然后判断 x,y,z是否属于[-w,w)这个范围就可以了
嘛,但是我见过一个判断视锥的代码十分复杂:是不是很搞笑,是不是它的
方法太复杂了,还是[-w,w)这个范围本来有错误??
代码如下,请高手指点!!
void iFrustum::ExtractFrustum(iMatrix *ModelView,iMatrix *Project)
{
float clip[16];
float t;
i_matrix_mul(ModelView,Project,(iMatrix*)clip);
frustum[0][0] = clip[ 3] - clip[ 0]; // Extract the RIGHT clipping plane
frustum[0][1] = clip[ 7] - clip[ 4];
frustum[0][2] = clip[11] - clip[ 8];
frustum[0][3] = clip[15] - clip[12];
t = (float) sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] );
if (t==0) t=1;
frustum[0][0] /= t;
frustum[0][1] /= t;
frustum[0][2] /= t;
frustum[0][3] /= t;
frustum[1][0] = clip[ 3] + clip[ 0]; // Extract the LEFT clipping plane
frustum[1][1] = clip[ 7] + clip[ 4];
frustum[1][2] = clip[11] + clip[ 8];
frustum[1][3] = clip[15] + clip[12];
t = (float) sqrt( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] );
if (t==0) t=1;
frustum[1][0] /= t;
frustum[1][1] /= t;
frustum[1][2] /= t;
frustum[1][3] /= t;
frustum[2][0] = clip[ 3] + clip[ 1]; // Extract the BOTTOM clipping plane
frustum[2][1] = clip[ 7] + clip[ 5];
frustum[2][2] = clip[11] + clip[ 9];
frustum[2][3] = clip[15] + clip[13];
t = (float) sqrt( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] );
if (t==0) t=1;
frustum[2][0] /= t;
frustum[2][1] /= t;
frustum[2][2] /= t;
frustum[2][3] /= t;
frustum[3][0] = clip[ 3] - clip[ 1]; // Extract the TOP clipping plane
frustum[3][1] = clip[ 7] - clip[ 5];
frustum[3][2] = clip[11] - clip[ 9];
frustum[3][3] = clip[15] - clip[13];
t = (float) sqrt( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] );
if (t==0) t=1;
frustum[3][0] /= t;
frustum[3][1] /= t;
frustum[3][2] /= t;
frustum[3][3] /= t;
frustum[4][0] = clip[ 3] - clip[ 2]; // Extract the FAR clipping plane
frustum[4][1] = clip[ 7] - clip[ 6];
frustum[4][2] = clip[11] - clip[10];
frustum[4][3] = clip[15] - clip[14];
t = (float) sqrt( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] );
if (t==0) t=1;
frustum[4][0] /= t;
frustum[4][1] /= t;
frustum[4][2] /= t;
frustum[4][3] /= t;
frustum[5][0] = clip[ 3] + clip[ 2]; // Extract the NEAR clipping plane
frustum[5][1] = clip[ 7] + clip[ 6];
frustum[5][2] = clip[11] + clip[10];
frustum[5][3] = clip[15] + clip[14];
t = (float) sqrt( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] );
if (t==0) t=1;
frustum[5][0] /= t;
frustum[5][1] /= t;
frustum[5][2] /= t;
frustum[5][3] /= t;
}
bool iFrustum::TestPoint(float x, float y, float z)
{
for (int p=0; p<6; p++)
{
if (frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= 0)
return false;
}
return true;
}
bool iFrustum::TestSphere(float x, float y, float z, float radius)
{
for (int p=0; p<6; p++)
{
if (frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= -radius)
return false;
}
return true;
}
bool iFrustum::TestCube(float x, float y, float z, float size)
{
for(int p = 0; p < 6; p++)
{
if ( frustum[p][0] * (x - size) + frustum[p][1] * (y - size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
continue;
if ( frustum[p][0] * (x + size) + frustum[p][1] * (y - size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
continue;
if ( frustum[p][0] * (x - size) + frustum[p][1] * (y + size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
continue;
if ( frustum[p][0] * (x + size) + frustum[p][1] * (y + size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 )
continue;
if ( frustum[p][0] * (x - size) + frustum[p][1] * (y - size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
continue;
if ( frustum[p][0] * (x + size) + frustum[p][1] * (y - size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
continue;
if ( frustum[p][0] * (x - size) + frustum[p][1] * (y + size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
continue;
if ( frustum[p][0] * (x + size) + frustum[p][1] * (y + size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 )
continue;
return false;
}
return true;
}