设置
在一张纸上画出 XY 坐标轴。沿 X 轴在其上写一个单词,使单词的中心点在 origo(一半在 X/Y 的正侧,另一半在 X/Y 的负侧)。
现在,如果你把纸倒过来,你会注意到这个词相对于 X 轴和 Y 轴都是镜像的。如果你从纸后面看,它相对于 Y 轴是镜像的。如果你从后面和倒过来看它,它是相对于 X 轴镜像的。
好的,我在 2D 平面(顶点)中有点,它们在 origo 处以类似的方式创建,我需要对它们应用完全相同的规则。为了让事情变得有趣:
- 2D 平面实际上是 3D,每个点 ( vertex ) 为 (x, y, 0)。最初,顶点定位到原点,它们的法线是Pn (0,0,1)。=> 从Pn点朝 origo看时正确看到。
- 顶点平面在 3D 世界中具有自己的旋转矩阵[Rp]和位置P (x,y,z)。在定位之前应用旋转。
- 3D 世界是“右手”的。观看者会沿着正 Z 轴从一定距离看向 origo,但世界也由旋转矩阵[Rw]定向。[Rw] * (0,0,1) 将直接指向观察者的眼睛。
从那些我需要计算顶点平面应该何时镜像以及由哪个轴镜像。镜像本身可以在应用[Rp]和P之前通过以下方式完成:
Vertices vertices = Get2DPlanePoints();
int MirrorX = 1; // -1 to mirror, 1 NOT to mirror
int MirrorY = 1; // -1 to mirror, 1 NOT to mirror
Matrix WorldRotation = GetWorldRotationMatrix();
MirrorX = GetMirrorXFactor(WorldRotation);
MirrorY = GetMirrorYFactor(WorldRotation);
foreach(Vertex v in vertices)
{
v.X = v.X * MirrorX * MirrorY;
v.Y = V.Y * MirrorY;
}
// Apply rotation...
// Add position...
问题
所以我需要 GetMirrorXFactor() 和 ..YFactor() -如果观察者的眼点在旋转和世界之后相对于顶点平面的法线大于 +-90 度的“X/Y”角度,则返回 -1 的函数方向。我已经解决了这个问题,但我正在寻找更“优雅”的数学。我知道旋转矩阵以某种方式包含有关哪个轴旋转了多少的信息,我相信可以在这里使用。
我的 MirrorX 解决方案:
// Matrix multiplications. Vectors are vertical matrices here.
Pnr = [Rp] * Pn // Rotated vertices's normal
Pur = [Rp] * (0,1,0) // Rotated vertices's "up-vector"
Wnr = [Rw] * (0,0,1) // Rotated eye-vector with world's orientation
// = vector pointing directly at the viewer's eye
// Use rotated up-vector as a normal some new plane and project viewer's
// eye on it. dot = dot product between vectors.
Wnrx = Wnr - (Wnr dot Pur) * Pur // "X-projected" eye.
// Calculate angle between eye's X-component and plane's rotated normal.
// ||V|| = V's norm.
angle = arccos( (Wnrx dot Pnr) / ( ||Wnrx|| * ||Pnr|| ) )
if (angle > PI / 2)
MirrorX = -1; // DO mirror
else
MirrorX = 1; // DON'T mirror
mirrorY 的解决方案可以使用查看器的向上和顶点平面的右向量以类似的方式完成。
更好的解决方案?