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

时间:2017-02-01 20:36:06

标签: python opengl pyopengl

这背后的想法是为安全摄像头创建一个检测区域。目前,我知道如何在函数" 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()

1 个答案:

答案 0 :(得分:0)

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

模型空间而言,您在图片中突出显示的黄点实际上只是(0, 0, -h/2.0)(0, 0, h/2.0)。如果您只是在glBegin(GL_POINTS)函数中使用securityCamera绘制黄点,这样就可以了。但是,您可能更感兴趣的是计算这些黄点在世界空间中的位置(即,在乘以模型视图矩阵之后)。

获取这些世界空间坐标的一种简单方法是将黄色点'模型空间坐标乘以模型视图矩阵。使用matrixTransformation(0, 0, -h/2.0)上的(0, 0, h/2.0)功能,该功能应该有效!

或者,正如我在评论中所暗示的那样,像你的模型视图矩阵这样的矩阵实际上包含了有用的信息,这些信息是由平移,旋转和缩放矩阵的乘法累加产生的。我指着这张照片:

enter image description here

这些列轴中的每一个实际上都对应于numpy数组的(这很有趣,因为numpy是行主要的,而OpenGL是列主要的)。您可以使用以下代码段获取模型指向世界空间的以下轴:

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

请注意,我切断了numpy数组中的最后一行并规范化了每个轴。如果您从那里获取forward数组,则可以在世界空间中获取该特定相机所指向的方向,而position数组则为您提供世界空间安全摄像头的中心位置(模型空间相当于(0,0,0))。将规范化的forward数组乘以h/2.0并将其添加到position,您应该获得安全摄像头前端的世界空间位置。这对于渲染到屏幕来说不是太有用,但可以用于安全摄像头的有趣对象的“幕后”数学。

作为旁注,我意识到我在圆柱体绘图代码的这一行中出现了一个符号错误:

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

请告诉我这是否有助于您理解我之前的评论!