坐标变换
在opengl中,主要包含下面的几个坐标空间,不做多余赘述:
1:局部空间
2:世界空间
3:观察空间
4:剪裁空间
在模型经过这些变换之后,还需要进行后续处理,但是一般为硬件进行处理,就到此为止。
后续处理
在经过剪裁空间之后,顶点变为Xc,Yc,Zc,Wc,进行透视除法除以Wc,坐标点变为X,Y,Z,1,然后进行NDC标准显示空间,在所有的X,Y,Z限制到[-1,1],按照比例进行显示出来。
反求世界的坐标
先得到窗口的X,Y坐标和深度值:
float winZ;
glReadPixels(posX,this->height()-posY,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&winZ);
由NDC空间还原:
float x=(2.0f*posX)/this->width()-1.0f;
float y=1.0f-(2.0f*posY)/this->height();
float z=winZ*2.0-1.0f;
求W:
float w = (2.0 * _near * _far) / (_far + _near - z * (_far - _near));
返回坐标:
QVector4D wolrdPostion(x,y,z,1);
wolrdPostion=w*wolrdPostion;
return view.inverted()*projection.inverted()*wolrdPostion;
在上述的流程之中,可能位移比较复杂的点W的计算,下面主要描述一下:
W的计算
设在观测矩阵乘积之后坐标点为:
X=(Xe,Ye,Ze,1)
透视矩阵为:然后进行透视除法,这里除以-Ze,也就是W,则顶点变为:
QT中的全文:
QVector4D wolrdPostion=worldPosFromViewPort(event->pos().x(), event->pos().y());
QVector4D OpenglWidget::worldPosFromViewPort(int posX, int posY)
{
float winZ;
glReadPixels(posX,this->height()-posY,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&winZ);
float x=(2.0f*posX)/this->width()-1.0f;
float y=1.0f-(2.0f*posY)/this->height();
float z=winZ*2.0-1.0f;
float w = (2.0 * _near * _far) / (_far + _near - z * (_far - _near));
//float w= _near*_far/(_near*winZ-_far*winZ+_far);
QVector4D wolrdPostion(x,y,z,1);
wolrdPostion=w*wolrdPostion;
return view.inverted()*projection.inverted()*wolrdPostion;
}