此处的“破折号“作者指的矩阵采用以下格式:
$$
n_1&0&a&0 \\
0&n_2&b& 0 \\
-&-&----\\
0&0&-1&0 \\
\ end {bmatrix}
$$
我们不在乎带短划线的值是什么。如何使用提示解决此问题?我认为我们可以推断出$ a $和$ b $(比例因子)尚未确定,但是我们可以推断出$ n_1 $和$ n_2 $是什么。
#1 楼
让我尝试对完整的答案发表评论。如果您想学习理论背景,可能会发现本文[1]有用,并且可以在我的博客文章[2]中找到更多详细信息。这是我使用Mathematica的解决方案。
第一步,我将构建一个包含所有变量的符号数组。
v = Table[Symbol["m" <> ToString[i]], {i, 0, 15}];
M = ArrayReshape[v, {4, 4}]
接下来,我们写下所有顶点的坐标。
k = f/ n;
X = {
{l, t, -n, 1},
{l, b, -n, 1},
{r, b, -n, 1},
{r, t, -n, 1},
{k l, k t, -f, 1},
{k l, k b, -f, 1},
{k r, k b, -f, 1},
{k r, k t, -f, 1}};
U = {
{-1, 1, -1},
{-1, -1, -1},
{1, -1, -1},
{1, 1, -1},
{-1, 1, 1},
{-1, -1, 1},
{1, -1, 1},
{1, 1, 1}};
其中
l
,r
,b
,t
,n
和f
分别表示左,右,下,上,近和远平面,和' X'是世界空间中的坐标,
U
是NDC中的坐标。然后我们实现一个函数
Generate
为每对坐标生成一个方程:Generate[{i_, j_}] := M[[j]].X[[i]] - U[[i, j]] M[[4]].X[[i]] == 0;
因为我们不在乎第三行,所以我们只解决
partialv
中的未知数:partialv = {m0, m1, m2, m3, m4, m5, m6, m7, m12, m13, m14, m15};
现在我们可以建立我们的线性系统并解决它:
solve[subset_] := Solve[
Map[Generate, Table[{i, j}, {i, subset}, {j, 1, 2}], {2}] // Flatten,
partialv] // Simplify
让我稍微解释一下。
因为只给出了6对点,所以我们从8对点中选择了6个元素组成的
subset
。然后在此
Generate
上调用subset
函数和矩阵的前两行(我们不在乎第三行。而第四行是“同质”部分,也将被忽略。)最后,我们枚举这8对点的所有子集,并尝试找到一种解决方案:
solutions = Map[solve, Subsets[{1, 2, 3, 4, 5, 6, 7, 8}, {6}]];
我们可以通过以下方式查看一种解决方案: {array} {cccc}
\ text {m0}&0&\ frac {\ text {m0}(l + r)} {2 n}&0 \\
0&\ frac {\文本{m0}(lr)} {bt}和\ frac {\文本{m0}(lr)(b + t)} {2 n(bt)}和0 \\
\ text {m8}&\ text {m9}&\ text {m10}&\ text {m11} \\
0&0&\ frac {\ text {m0}(lr)} {2 n}& 0 \\
\ end {array}
\ right)
$$
m0
是问题陈述中提到的“未知标量因子”。 br /> 实际上,如果让
m0
等于2 n/(r - l)
,我们将获得OpenGL中使用的常规投影矩阵:
\ left(
\ begin {array} {cccc}
\ frac {2 n} {rl}&0&\ frac {l + r} {rl}&0 \\
0&-\ frac {2 n} {bt}&-\ frac {b + t} {bt}&0 \\
\ text {m8}&\ text {m9}&\ text { m10}和\ text {m11} \\
0&0&-1&0 \\
\ end {array}
\ right)
$$
[1] Heckbert,Paul S.纹理映射和图像扭曲的基础知识。硕士论文。加利福尼亚大学伯克利分校,1989年。
[2]推导投影映射推导投影映射| linearconstraints.net
评论
我曾经写过一个Mathematica脚本来推断投影矩阵(这里:blog.linearconstraints.net/2016/02/03/…),除了当时使用8个顶点来求解线性系统。我认为6个非共面顶点应该足够。我待会再试。