在 PyOpenGL 中制作 3D 汽车动画

Animating a 3D car in PyOpenGL

我正在尝试在 PyOpenGL 中制作 3D 汽车的动画,使其沿着八字形轨道移动。问题是我好像没有找到让车子沿着赛道曲线转弯的最佳方法。

我尝试过的方法是让汽车在 x 轴和 z 轴上平移,以及制作 glRotate 来旋转汽车,但这似乎不是最好的方法。

我的代码如下所示:

 # Values for all the animation process, including translate and rotate
 angulo = 0.0
 traslacion = 0.0
 giroXl = 0.0
 giroZl = 0.0

 ...

 # The display function, where the 3D car model recieves the intructions for 
 # the movement along the track
 def display():
     ...
     glTranslate(0, 0, traslacion)  # Moves the car along a straight line, this works just fine

     # This is where I try to turn the car along the track curve, this is where I'm stuck
     if bandRecta == True:
        glTranslate(giroXl, 0, giroZl)
        glRotate(angulo, 0.0, 1.0, 0.0)

 # The glutTimerFunc, where the values get manipulated
 def movimiento():
     ...
     angulo = angulo + (1.0 if angulo < 180.0 else 0.0)
     traslacion = traslacion + (1.0 if traslacion < 100.0 else 0.0)

     if traslacion == 50:
          bandRecta = True 
          giroXl = giroXl + (1.0 if giroXl < 50.0 else 0.0)
          giroZl = giroZl + (1.0 if giroZl < 50.0 else 0.0)

你们能给我一些关于如何使汽车转向的建议吗?谢谢。

我可以想到两种方法来做到这一点。 (我不是 python 程序员,所以这不会是完整的语法。)

细分

我猜你的轨道在 Z 方向前进 R 个单位,然后穿过半径为 R 的圆的 3/4。

使旋转围绕点 -R,0,R 而不是 0,0,0。这涉及在 rotate() 之前和之后额外的 translate()。

将 T 视为沿着轨道的总距离 (traslacion)。不要在 translate() 中直接使用 T。将曲目分成这样的片段:

if (T<=R)
    theta = 0
    Z = T
    X = 0
else if (T < R * (1 + 3/2 * PI))
    theta = (T/R-1)
    Z = R # limit of straight travel
    X = 0
else if (T < R * (3 + 3/2 * PI))
    theta = 3/2 * PI
    Z = R
    X = T - R * (1 + 3/2 * PI)) # now travelling straight in X
else # you work out the other pole of the track

轨道第一杆绘制:

glTranslate(0, 0, Z) # add Z from straight portion of track

# rotate about pole at -R, 0, R
glTranslate(R, 0, -R)
glRotate(180 * theta / PI), 0, 1, 0)
glTranslate(-R, 0, R)

# add X from after the curve
glTranslate(X, 0, 0) 

这将使您到达第二个回合(将有一个不同的中心)。

备注

PI = math.pi

使用参数函数

我能想到的第二种方法是使用参数函数 Fx,z (T)

要旋转小车,需要知道导数Fx1和Fz1,用atan算出航向。

如果你定义

Fx = cos(T * K) 
Fz = sin(T * L) 

你可以有一个 K=0.5 和 L=1 的八字形。

但是数学和绘图很简单:

Fx1 = -K * sin(T * K)
Fz1 = L * cos ( T * L)
theta = atan(Fz1/Fx1) if Fx1 != 0 else sign(Fz1)*PI/2
glRotate(180 * theta / PI, 0, 1, 0)
glTranslate(Fx, 0, Fz)

玩得开心!