我正在尝试使用投影变换投射阴影。但似乎OpenGL不喜欢我的矩阵,因为它在glMultMatrix
之后没有绘制任何东西。弹出矩阵之后一切都还可以。
我也在使用JOGL,可能是问题所在,但我怀疑它,因为我的自定义平移和旋转矩阵工作正常。
矩阵看起来像这样:
lightPosition = {x, y, z, 1}
planeEquation = {a, b, c, d}
pl = a*x + b*y + c*z + d
a*x-pl b*x c*x d*x
a*y b*y-pl c*y d*y
a*z b*z c*z-pl d*z
a b c d-pl
现在这是我计算的矩阵,但我还在互联网上搜索了其他两种口味;一个有点不同,另一个完全像我的时代-1。 这个信息足够吗?或者我也应该提交代码吗?
也许这是我的飞机方程?
three points on plane = p0, p1, p2
v0 = p1 - p0
v1 = p2 - p0
n = {a, b, c} = v0 (cross) v1
d = -(n (dot) p0)
planeEquation = {a, b, c, d}
对任何人来说听起来都很熟悉吗?或者它只是一个代码的东西?
编辑:我正在尝试做这个测试,并且绘制带有和不带矩阵的单个顶点(对于xz平面和{0,20,0}点光源),以及正交投影矩阵。另外,我试图通过获取OpenGL的投影和模型视图矩阵并将其与它们相乘并使用w坐标进行标准化来计算自己的顶点的规范化设备坐标。
我得到的是,没有我的“阴影矩阵”,它很好地显示了这一点,似乎我对顶点的计算与我所看到的相符。但是我的“阴影矩阵”没有任何结果,尽管顶点的坐标位于所有轴的[-1,1]范围内。
这太奇怪了......
编辑:在此添加测试程序:https://gist.github.com/e0c54d5ab3cbc92dffe6
答案 0 :(得分:0)
可能,您只需将传递给OpenGL的矩阵转置。 OpenGL的矩阵索引起初有点违反直觉(但是,如果您将矩阵理解为列向量的行向量,则有意义)OpenGL索引如下:
0 4 8 c
1 5 9 d
2 6 a e
3 7 b f
与C行主要排序
相反0 1 2 3
4 5 6 7
8 9 a b
c d e f
答案 1 :(得分:0)
想出来(这是问题的作者)。这只是一个错字,我没有在正确的方向上计算飞机的法线...... 它不像我说的那样(v0 X v1)它是偶然的(v1 X v0)。你可以在代码中看到它。所以,如果飞机是以另一种方式指向的,你就不能投射它。
因为这是一个愚蠢的错误。对于你想知道平面上这个矩阵投影背后的数学的所有人,我会试着解释一下:
在开始之前,我假设对线性代数有一点粗略的了解。不需要太多。
假设我们有一个普通N的平面,其上有一个点Q.对于每个点P (P-Q).N=0
(这是一个点积),如果(并且仅当)P在平面上,因为向量(P-Q)
和N是垂直的。
现在让我们假设我们也有一个(固定的聚光灯)点S.我们想从这个聚光灯投射我们飞机上的一个点P.这意味着我们希望找到点R,它位于由点P和S定义的线上,并且也在平面上。换句话说,找到标量t,使得S+t(P-S)=R
,使得R在平面上。 (P-S)
是从聚光灯到点P的方向向量。我们在该向量上“行走”一定量t,从点S开始直到我们降落在飞机上。
从2段开始,我们学到了一个很好的技巧,可以知道一个点是否在飞机上。因此,如果我们在R上应用它,那么如果(并且仅当):
,我们就得到R在平面上N.(R-Q)=0
N.R-N.Q=0
N.R=N.Q
N.(S+t(P-S))=N.Q
N.S+tN.(P-S)=N.Q
t=(N.Q-N.S)/(N.(P-S))
现在,如果我们把它放回R:
的定义中R=S+(N.Q-N.S)*(1/(N.(P-S))*(P-S)
让我们将N.(P-S)
定义为k
kR=(N.(P-S))*S+(N.Q-N.S)*P-(N.Q-N.S)*S
kR=(N.P)*S+(N.Q-N.S)*P-(N.Q-N.S)*S-(N.S)*S
kR=(N.P)*S+(N.Q-N.S)*P-(N.Q)*S
让我们提醒自己,我们知道什么,我们不知道什么,以及我们想知道什么。我们知道N和Q和S. P给我们,我们想找到R.换句话说,我们想表达给定P的R,并使用N,Q和S.让我们继续打破这一点进一步,
kR=(N_x*P_x+N_y*P_y+N_z*P_z)*S+(N.Q-N.S)*P-(N.Q)*S
R是点,所以让我们定义它的每个坐标,坐标为P(也是S,因为我们也让他在方程的右边)。
kR_x=[N_x*S_x+(N.Q-N.S)]P_x+[N_y*S_x]P_y+[N_z*S_x]P_z-(N.Q)*S_x
kR_y=[N_x*S_y]P_x+[N_y*S_y+(N.Q-N.S)]P_y+[N_z*S_y]P_z-(N.Q)*S_y
kR_z=[N_x*S_z]P_x+[N_y*S_z]P_y+[N_z*S_z+(N.Q-N.S))]P_z-(N.Q)*S_z
看起来我们没有得到任何东西,因为我们在左侧得到了那个k,我们仍然需要除以它(并且k由P确定为没有!)。不用担心,因为OpenGL使用四个元素向量而不是三个。最后的第四个元素用于平移矩阵和透视深度插值。对于我们现在的需求,我们应该知道的是openGL将每个顶点的坐标除以它的第四个元素。这意味着可怕的k是我们的第四个元素。我们得到:
R_w=k
R_w=N.(P-S)
R_w=N.P-N.S
R_w=[N_x]P_x+[N_y]P_y+[N_z]P_z-N.S
好吧,我们使用N,S和Q定义了我们的R到P.我们把它放在矩阵M中。我们想要:
M * P = - [R
所以,
M=
N_x*S_x + (N.Q-N.S), N_y*S_x, N_z*S_x, -(N.Q)*S_x
N_x*S_y, N_y*S_y + (N.Q-N.S), N_z*S_y, -(N.Q)*S_y
N_x*S_z, N_y*S_z, N_z*S_z + (N.Q-N.S), -(N.Q)*S_z
N_x, N_y, N_z, -(N.S)
虽然盯着这个,但请记住,因为P是一个点,它的第四个元素是1.(!= 0,准确但我们可以假设它是一个设备规范化的顶点)
关于平面方程。平面方程是一个向量,它的前三个元素是法线。它的第四个要素是它与原点的距离。计算平面距原点的距离的另一种方法是:
假设平面上的点Q为正常N,则该平面与原点的距离为| N.Q |
非常简单,对吧?这是正确的,因为:
N.Q=|N|*|Q|*cos(N,Q)
和|N|=1
,给我们:
N.Q=|Q|*cos(N,Q)=|Q|*d/|Q|=d
其中d是距离原点的平面距离。或者,它是向量N的大小;和N的大小是从原点到平面的距离的大小。您可以看到,通过绘制平面,在平面上选择一些点Q,绘制从原点到达平面的法线N,并查看由两个矢量和平面所做的线制成的三角形。
在上面的矩阵中用-N替换-N.Q(平面方程中的最后一个元素),你就完成了。 (d = -N.Q)。给定点P的矩阵将从由S定义的聚光灯投影到由N和Q定义的平面上。
希望能教会你一些新东西。如果我犯了错误,请发表评论,我会解决它。