OpenGL 投影矩阵急问

skywind 2004-01-27 05:25:11
某点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;
}
...全文
126 5 打赏 收藏 举报
写回复
5 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
ttmmdd 2004-01-28
其实不光是效率的问题.
现在用判断可视一般是将物体的包围盒或包围球和视锥求交.
而投影变换不是正交变换,也就是说立方体经过投影变换后不是立方体,球也不是球体.
所以投影后得到的形状和{-w<=x<w,-w<=y<w,-w<=z<w}这个立方体求交反而更困难.
一般还是使用投影前的形状求交.
  • 打赏
  • 举报
回复
tomb4 2004-01-27
同意ttmmdd(老孩子)的说法

实际上
[ 1 0 0 0 ]
PM = [ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 -1 0 ]

就是NEAR = 0的透视投影

2.
考虑到效率,判断M(mvp)*V(o)的三个分量显然没有判断plane.normal*V(w)与plane.dist大小来得快
  • 打赏
  • 举报
回复
skywind 2004-01-27
哦,楼上果然高手,!! 太感动了,豁然开朗~~
我想问下,立方体中,判断可视的话用视锥六面体 {-w<=x<w,-w<=y<w,-w<=z<w}这个立方体就可以判断了嘛,而ExtractFrustum函数中他求的哪个六面体求的太复杂了~~ 干嘛要求那么复杂的六面体??用要检测的点乘ModelviewMatrix和ProjectionMatrix后判断和[-w,w]这个六面体的关系就可以了嘛,干嘛要求一个变换前的六面体弄的那么复杂呢??
  • 打赏
  • 举报
回复
ttmmdd 2004-01-27
1问题1
线能画出来是因为线的宽度不是投影变换算出来的.所以不变,但实际上两个端点已经在屏幕以外了.而三角形的应为画的很近界接近无穷大,所以就满屏幕了.至于溢出,不用为OPENGL担心,他会有保护的.
2.
下面的检测没错.单个点当然可以用是否在(W,-W)之间判断,但是立方体不可.即使每个顶点都落在视锥之外,立方体仍然有可能和视锥相交,
用六个面表示视锥是通用办法
  • 打赏
  • 举报
回复
skywind 2004-01-27
大家快帮看看
  • 打赏
  • 举报
回复
相关推荐
发帖
机器视觉

4304

社区成员

图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
帖子事件
创建了帖子
2004-01-27 05:25
社区公告
暂无公告