我正在从头开始实施一个学术项目。我正在使用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;