在 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)
玩得开心!
我正在尝试在 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)
玩得开心!