pyopengl - 在旋转过程中找到形状的边缘

pyopengl - finding the edges of a shape during rotation

这背后的想法是为监控摄像头创建一个检测区域。目前,我知道如何在函数 "matrixTransformation" 中查找和使用模型视图矩阵数据,如下所示。然后应在初始化函数中针对安全摄像机旋转的每次增加计算矩阵的值。

我想知道您如何使用矩阵找到每个安全摄像头(圆柱形)的边缘坐标。我正在使用 Pygame 1.9.2、Python 3.5 和 PyOpenGL-3.1.0。

Picture of coordinates on the security camera which need to be calculated

def matrixTransformation(x,y,z):

    matrix = (GLfloat * 16)()
    glGetFloatv(GL_MODELVIEW_MATRIX, matrix)

    xp = matrix[0] * x + matrix[4] * y + matrix[8] * z + matrix[12]
    yp = matrix[1] * x + matrix[5] * y + matrix[9] * z + matrix[13]
    zp = matrix[2] * x + matrix[6] * y + matrix[10] * z + matrix[14]
    wp = matrix[3] * x + matrix[7] * y + matrix[11] * z + matrix[15]

    xp /= wp
    yp /= wp
    zp /= wp

    return xp,yp,zp

def init():

    securityCameraRotation=380

    glEnable(GL_DEPTH_TEST)

    multipleRotations=0
    result=[]

    glPushMatrix()

    glTranslatef(-4,1.5,5.5)
    glRotate(315,1,1,1)

    while True:
        if securityCameraRotation>=380:
            clockwise=True
            multipleRotations+=1
        elif securityCameraRotation<=310:
            clockwise=False
        glRotate(securityCameraRotation,0,1,0)
        #append the transformed coordinates to result

        if clockwise==True:
            securityCameraRotation-=0.2
        elif clockwise==False:
            securityCameraRotation+=0.2
        if multipleRotations>1:
            #End the loop when one complete rotation between 310 and 380 has occured
            break

        glPopMatrix()

        return result

def securityCamera(radius, height, num_slices,frontCircleColour,backCircleColour,tubeColour):
    r = radius
    h = height
    n = float(num_slices)

    circle_pts = []
    for i in range(int(n) + 1):
        angle = 2 * math.pi * (i/n)
        x = r * math.cos(angle)
        y = r * math.sin(angle)
        pt = (x, y)
        circle_pts.append(pt)

    glBegin(GL_TRIANGLE_FAN) #drawing the back circle
    glColor(backCircleColour)
    glVertex(0, 0, h/2.0)
    for (x, y) in circle_pts:
        z = h/2.0
        glVertex(x, y, z)
    glEnd()

    glBegin(GL_TRIANGLE_FAN) #drawing the front circle
    glColor(frontCircleColour)
    glVertex(0, 0, h/2.0)
    for (x, y) in circle_pts:
        z = -h/2.0
        glVertex(x, y, z)
    glEnd()

    glBegin(GL_TRIANGLE_STRIP) #draw the tube
    glColor(tubeColour)
    for (x, y) in circle_pts:
        z = h/2.0
        glVertex(x, y, z)
        glVertex(x, y, -z)
    glEnd()

在 OpenGL 中,会发生大量变换。首先,我们将对象视为 模型 space,其中对象以原点为中心并绘制网格(在本例中为圆柱体) .然后,我们应用模型矩阵变换(我们translate/rotate/scale我们的圆柱体)和视图矩阵变换(我们移动我们的场景相对于假想的相机)。最后,我们应用 投影矩阵 ,通过使用 gluPerspective 或一些更现代的方法创建矩阵,将“3d 透视”添加到我们的场景。所有这些矩阵乘法基本上都将 3d 模型的坐标放在我们 2d 屏幕上的正确位置(有点,更详细的信息 here)。

根据模型space,你图片中突出显示的黄色点实际上只是(0, 0, -h/2.0)(0, 0, h/2.0)。如果您只是在 securityCamera 函数中使用 glBegin(GL_POINTS) 绘制黄色点,这很好。但是,您可能更感兴趣的是计算这些黄色点在 world space 中的位置(即乘以模型视图矩阵后)。

获得这些 world space 坐标的一个简单方法是乘以黄色点的 model space 坐标 模型视图矩阵 。在 (0, 0, -h/2.0)(0, 0, h/2.0) 上使用您的 matrixTransformation 函数,应该可以!

或者,正如我在评论中暗示的那样,像您的模型视图矩阵这样的矩阵实际上包含有用的信息,这些信息来自于平移、旋转和缩放矩阵的乘法累积。我指着这张图:

这些列轴中的每一个实际上对应于 numpy 数组的 (这很有趣,因为 numpy 是 row-major 而 OpenGL 是 column-major) .您可以使用以下代码段获取模型在 world spaces 中的指向轴:

mv_matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
left, up, forward, position = [v/(np.linalg.norm(v)) for v in mv_matrix[:,:3]]

请注意,我切断了 numpy 数组中的最后一行并对每个轴进行了归一化。如果您采用从那里获得的 forward 数组,您将获得特定相机指向的 world space 中的方向,而 position 数组为您提供中心的 world space 位置 (model space 等同于 (0, 0, 0 )) 的安全摄像头。将规范化的 forward 数组乘以 h/2.0 并将其添加到 position 并且您应该得到 world space 前面的位置你的安全摄像头。这对于渲染到屏幕来说不是很有用,但可以用于 "behind the scenes" 使用安全摄像头对有趣对象进行数学运算。

作为旁注,我意识到我在这一行中为气缸绘图代码犯了一个符号错误:

glBegin(GL_TRIANGLE_FAN) #drawing the front circle
glColor(frontCircleColour)
glVertex(0, 0, -h/2.0)#this was + in the original code!!!

让我知道这是否有助于您理解我之前的评论!