由窗口界面坐标映射到世界空间的坐标

247 阅读2分钟

坐标变换

在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)

透视矩阵为:

图片1.png

这里使用的project矩阵的第三列为-1,和前面有一点差别,是为了方便后面的计算,本质无区别。 在经过透视矩阵之后,坐标点变为:

图片1.png

然后进行透视除法,这里除以-Ze,也就是W,则顶点变为:

图片2.png

在反求的时候,也就是返NDC之后的坐标点为(X,Y,Z),Z就是上述的对应值,就可以得到上述的对应值,有:

图片3.png

于是后续操作就可以得到对应的时间空间中的值了。

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;
}