OpenGL自定义转换麻烦

时间:2011-10-01 14:25:47

标签: opengl transformation jogl

我正在尝试使用投影变换投射阴影。但似乎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

2 个答案:

答案 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定义的平面上。

希望能教会你一些新东西。如果我犯了错误,请发表评论,我会解决它。