如何从左手系统切换到右手系统?

时间:2013-10-23 04:29:58

标签: c++ opengl transformation linear-algebra perspective

我正在从头开始实施一个学术项目。我正在使用Foley,van Dam,Feiner和Hughes的“计算机图形学:原理与实践”(C语言第二版)。

我只是通过实现所有矩阵变换来实现所需的所有矩阵变换,这些变换需要进行相互转换,旋转,剪切,缩放,投影,从透视变换到平行规范视图体积和剪切。这本书显然使用了右手坐标系。然而,我最终在左手坐标系中出现了原语,我无法解释原因。

以下是我使用的矩阵:

Translation:
1, 0, 0, dx
0, 1, 0, dy
0, 0, 1, dz
0, 0, 0, 1

Rotation (to align a coordinate system (rx, ry, rz) to XYZ):
rx1, rx2, rx3, 0
ry1, ry2, ry3, 0
rz1, rz2, rz3, 0
0  , 0  , 0  , 1

Scale:
sx, 0 , 0 , 0
0 , sy, 0 , 0
0 , 0 , sz, 0
0 , 0 , 0 , 1

Shear XY:
1, 0, shx, 0
0, 1, shy, 0
0, 0, 1  , 0
0, 0, 0  , 1

Projecting onto a plane at z = d, with PRP at origin, looking in the positive z direction:
1, 0, 0  , 0
0, 1, 0  , 0
0, 0, 1  , 0
0, 0, 1/d, 0

然后给出VRP,VPN,PRP,VUP,f和b(以及投影方向),使用P将空间缩小到规范的观看体积:

rz = VPN / |VPN|
rx = (VUP x rz) / |VUP x rz|
ry = rz x rx
P = ScaleUniform(-1 / (vrp1Z + b)) * 
    Scale(-2 * vrp1Z / deltaU, -2 * vrp1Z / deltaV, 1) * 
    Shear(-dopX / dopZ, -dopY / dopZ) * 
    T(PRP) * 
    R(rx, ry, rz) * 
    T(-VRP)

其中vrp1是ShearXY * T(-PRP)*(0,0,0,1),deltaU和deltaV是观察窗口的宽度和高度。 dop计算为CW-PRP,其中CW是观察窗口的中心。

然后投影(d)* P给出投影矩阵。

我在x,y和z上投影表示单位矢量的简单线条,但我在屏幕上绘制的表示显然是左手坐标系...现在我需要在右手坐标系中工作,那么有办法知道我做错了吗?

以下是我使用的代码: 正如你所看到的,刻度矩阵的Z分量符号相反,因为裁剪不能正常工作,因为有些东西是右撇子而且是左撇子,但我无法辨别究竟是什么,所以我换了标志因为在左手系统中不需要它。

Vector rz = vpn.toUnitVector();
Vector rx = vup.cross(rz).toUnitVector();
Vector ry = rz.cross(rx).toUnitVector(); 

Vector cw  = viewWindow.getCenter();
Vector dop = cw - prp;

Matrix t1 = Matrix::traslation(-vrp[X], -vrp[Y], -vrp[Z]);
Matrix r  = Matrix::rotation(rx, ry, rz);   
Matrix t2 = Matrix::traslation(-prp[X], -prp[Y], -prp[Z]);   
Matrix partial = t2 * r * t1;

Matrix shear  = Matrix::shearXY(-dop[X] / dop[Z], -dop[Y] / dop[Z]);
Matrix inverseShear = Matrix::shearXY(dop[X] / dop[Z], dop[Y] / dop[Z]);

Vector vrp1 = shear * t2 * Vector(0, 0, 0, 1);

Matrix scale = Matrix::scale(
    2 * vrp1[Z] / ((viewWindow.xMax - viewWindow.xMin) * (vrp1[Z] + b)),
    2 * vrp1[Z] / ((viewWindow.yMax - viewWindow.yMin) * (vrp1[Z] + b)),
    1 / (vrp1[Z] + b)); // HERE <--- WAS NEGATIVE
Matrix inverseScale = Matrix::scale(
    ((viewWindow.xMax - viewWindow.xMin) * (vrp1[Z] + b)) / (2 * vrp1[Z]),
    ((viewWindow.yMax - viewWindow.yMin) * (vrp1[Z] + b)) / (2 * vrp1[Z]),
    (vrp1[Z] + b));

float zMin = -(vrp1[Z] + f) / (vrp1[Z] + b);

Matrix parallel = Perspective::toParallelCvv(zMin);
Matrix inverseParallel = Perspective::inverseToParallelCvv(zMin);
Matrix perspective = Perspective::copAtOrigin(-vrp1[Z]);

projection = perspective * shear * partial;
canonicalView = parallel * scale * shear * partial;
canonicalToProjection = perspective * inverseScale * inverseParallel;

0 个答案:

没有答案