如何在Python中使用OpenGL让球体沿八字路径移动?

1 投票
1 回答
51 浏览
提问于 2025-04-12 21:05

我需要让一个球体在我的计算机图形课上沿着无限符号的形状移动。

我觉得我已经在下面的Python程序中成功地复现了这个球体的运动,跟任务的图示很相似。

这是我的结果:

球体沿着数字8的路径移动

但我遇到了一个问题:

我的程序需要做一些事情才能完成这个任务:

  1. 我需要画两个球体模型。一个位于(-8,4,0),另一个位于(7,-3,0)。这样做是为了把球体放在两个不同于原点的坐标周围。

  2. 我让第一个模型围绕坐标(-8,4,0)旋转,直到它转了半圈。之后,我把它换成第二个模型,那个模型的原点在(7,-3,0),它会旋转一整圈。等它转完一圈后,我再换回第一个模型,让它转一圈半。这个过程会重复,这样就形成了无限符号的轨迹。

这是我在Python程序中做的事情:

run = True
angle = 0
x_position = -8
y_position = 4
points_matrix = generate_sphere_points(x0=x_position, y0=y_position, z0=0)
points_matrix2 = generate_sphere_points(x0=-x_position-1, y0=-y_position+1, z0=0)
index = False
matrices_points = [points_matrix, points_matrix2]
delta_angle = -4
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    draw_world_axes()
    glLineWidth(1)
    glTranslatef(x_position, y_position, 0)
    glRotatef(angle, 0, 0, 1)
    plot_parametric_mesh(matrices_points[index])
    pygame.display.flip()
    pygame.time.wait(10)

    if angle <= -180 or angle >= 180:
        index = not index
        x_position = -x_position - 1
        y_position = -y_position + 1
        delta_angle *= -1

    angle += delta_angle

pygame.quit()

虽然这个方法有效,但我觉得其实只需要一个球体模型。不过,我还没弄明白怎么让一个球体或者其他物体围绕一个不同于原点(0,0,0)的坐标旋转,而不改变它的位置。我知道可以用glRotatef()*glTranslatef()让物体围绕原点旋转,但我想要的是让它围绕我指定的坐标旋转。

在这种情况下,我想让一个球体模型围绕一个坐标旋转,然后再把它的中心换到另一个坐标,整个8的循环都这样重复。

有没有人知道怎么用变换矩阵(translatef和rotatef)让一个球体围绕一个坐标旋转,而不需要在它的参数方程中改变球体的中心,并且只用一个球体模型来完成8的循环,而不是交换两个模型?

1 个回答

2

我觉得你想要的其实是一个利萨如曲线。这个曲线是通过对两个轴进行不同角度的变换来生成的。如果两个角度相同,你就会得到一个圆。如果一个角度是另一个角度的两倍,你就会得到一个8字形:

import pygame
from OpenGL.GL import *
import math

pygame.init()
display = (400, 400)
screen = pygame.display.set_mode(display, pygame.DOUBLEBUF | pygame.OPENGL)
clock = pygame.time.Clock()

run = True
angle1 = 0
angle2 = 0
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    x = math.cos(angle1) * 0.8
    y = math.sin(angle2) * 0.4
    glTranslatef(x, y, 0)
    angle1 += 0.01
    angle2 += 0.02
    glBegin(GL_QUADS)
    glVertex2f(-0.1, -0.1)
    glVertex2f(0.1, -0.1)
    glVertex2f(0.1, 0.1)
    glVertex2f(-0.1, 0.1)
    glEnd()

    clock.tick(100)
    pygame.display.flip()

pygame.quit()

撰写回答