OpenGL中的太阳系,相机位置

时间:2018-11-04 12:53:40

标签: python numpy opengl coordinate-transformation pyopengl

我想用四个摄像头在OpenGL中制作简单的太阳系。

我想要的很简单,只需将相机放置在地球的一侧即可。

在以下代码中,我通过>>> a = np.random.rand(4, 4) array([[0.55197876, 0.95840616, 0.88332771, 0.97894739], [0.06717366, 0.39165116, 0.10248439, 0.42335457], [0.73611318, 0.09655115, 0.79041814, 0.40971255], [0.34336608, 0.39239233, 0.14236677, 0.92172401]]) >>> reduce(a.copy()) array([[0.00292008, 0.05290198, 0.00467298, 0.00045746], [0.06717366, 0.02161831, 0.10248439, 0.00019783], [0.00494474, 0.09655115, 0.00170875, 0.00419891], [0.00016979, 0.00019403, 0.14236677, 0.0001575 ]]) >>> reduce_(a.copy()) array([[0.02161831, 0.03753609, 0.03459563, 0.01003268], [0.06717366, 0.00401381, 0.10248439, 0.00433872], [0.02882996, 0.09655115, 0.03095682, 0.00419891], [0.00331524, 0.00378859, 0.14236677, 0.00285336]]) 得到了>>> a = np.random.rand(3, 2) array([[0.17246979, 0.42743388], [0.1911065 , 0.41250723], [0.73389051, 0.22333497]]) >>> reduce(a.copy()) array([[0.17246979, 0.00737194], [0.1911065 , 0.0071145 ], [0.01402513, 0.22333497]]) >>> reduce_(a.copy()) # same as a because there are no cells with 8 neighbors array([[0.17246979, 0.42743388], [0.1911065 , 0.41250723], [0.73389051, 0.22333497]]) (第116行)

因此,我认为MODELVIEW_MATRIX在世界坐标系中获得了行星的原点。

但是它不能很好地工作,因此我需要一些帮助。

glGetFloatv(GL_MODELVIEW_MATRIX)

1 个答案:

答案 0 :(得分:0)

*运算符没有执行您期望的操作,它是数组乘法,而不是矩阵乘法。它将对元素执行按组件的乘法。参见how does multiplication differ for NumPy Matrix vs Array classes?Numerical operations on arrays

使用numpy.dotnumpy.matmul通过矩阵变换向量。
通过4 * 4矩阵对4分量向量(Homogeneous coordinates)进行转换的结果仍然是4分量向量。通常,转换后必须执行perspective divide。但是模型视图矩阵是Orthogonal matrix,因此使用结果的前3个分量就足够了,因为第4个分量始终为1:

pos = np.array( [0,0,0,1] )
pos = np.dot( pos, t )
earthPosition = pos[0:3]

但是请注意,坐标(0,0,0,1)的视图空间位置是模型视图矩阵的平移部分(第4行):

earthPosition = t[3][0:3]

可悲的是,这不是您想要执行的操作,因为您想知道地球的世界位置,而不是视图位置。 由于glGetFloatv(GL_MODELVIEW_MATRIX)返回模型视图矩阵,因此变换将计算视图位置,而不是世界位置。 您必须按模型矩阵进行变换,而不必按模型视图矩阵进行变换。由于您无法将模型矩阵与模型视图矩阵分开,所以这并不是那么容易。 您可以获得的是视图矩阵。使用视图矩阵和模型视图矩阵,您可以获得世界排名。 通过模型矩阵进行的转换与通过模型视图矩阵和逆视图矩阵进行的转换相同:

p_world = inverse(view_matrix) * model_view_matrix * p_model

我建议在通过Cam进行设置之后,立即在lookAt类中获取视图矩阵并计算逆模型视图矩阵。逆矩阵可以通过numpy.linalg.inv来计算:

def applyCamera(self):
    gluLookAt(self.loc[0], self.loc[1], self.loc[2],
              self.tar[0], self.tar[1], self.tar[2],
              self.up [0], self.up [1], self.up [2])
    self.viewmat = glGetFloatv(GL_MODELVIEW_MATRIX)
    self.inv_viewmat = np.linalg.inv(self.viewmat)

最后,世界位置是模型视图矩阵的第四行通过逆视图矩阵的简单转换:

global plutoCamera, earthPosition, Cam

.....

model_view = glGetFloatv(GL_MODELVIEW_MATRIX)

if(shape == "satellite"):
    glScalef(0.4,0.4,0.4)
    glutSolidTetrahedron()
    glScalef(2.5,2.5,2.5)

elif(shape == "earth"):
    glutWireCube(1)

    pos = np.dot( model_view[3], Cam.inv_viewmat )
    earthPosition = pos[0:3]

elif(shape == "pluto"):
    glScalef(0.4,0.4,0.4)
    glutWireOctahedron()
    glScalef(2.5,2.5,2.5)

    pos = np.dot( model_view[3], Cam.inv_viewmat )
    plutoCamera = pos[0:3]

预览: