如何在 OpenGL 中将汽车朝轮胎的方向移动
How to move car towards direction of tires in OpenGL
我试图让汽车以半真实的方式在 OpenGL 中移动,汽车大致沿着前轮胎的方向行驶(前轮胎可以转动,就像真正的汽车轮胎一样)。
我不知道如何让汽车朝向轮胎。我正在使用 SDL2 从键盘输入(按下和向上键),如下所示:
case SDLK_LEFT:
car.setTireRotationSpeed(-TIRE_ROTATION_SPEED);
break;
case SDLK_RIGHT:
car.setTireRotationSpeed(TIRE_ROTATION_SPEED);
break;
case SDLK_UP:
car.setCarForwardSpeed(CAR_MOVEMENT_SPEED);
break;
case SDLK_DOWN:
car.setCarForwardSpeed(-CAR_MOVEMENT_SPEED);
break;
按键释放也类似:
case SDLK_LEFT:
if (car.getTireRotationSpeed() == -TIRE_ROTATION_SPEED)
car.setTireRotationSpeed(0);
break;
case SDLK_RIGHT:
if (car.getTireRotationSpeed() == TIRE_ROTATION_SPEED)
car.setTireRotationSpeed(0);
break;
case SDLK_UP:
if (car.getCarForwardSpeed() == CAR_MOVEMENT_SPEED)
car.setCarForwardSpeed(0);
break;
case SDLK_DOWN:
if (car.getCarForwardSpeed() == -CAR_MOVEMENT_SPEED)
car.setCarForwardSpeed(0);
break;
这会在 car
中设置变量,每一帧都会使用这些变量来平滑地移动 car/rotate 汽车上的轮胎(因为底盘和轮胎是单独渲染的)。
我正在使用 glm-math(即 glm:vec3
、glm::mat4
等)来完成转换,我正在使用着色器来绘制和纹理。
每次渲染整车,都会经过以下几个步骤:
void Car::Render(Shader & shader, Camera & camera)
{
incrementFrontTireRotation(getTireRotationSpeed());
move();
chasisTexture.Bind(0);
shader.Update(getChasisTransform(), camera);
chasisMesh.Draw();
tireTexture.Bind(0);
shader.Update(getTireTransform(Car::FRONT_RIGHT), camera);
tireMesh.Draw();
//Repeated for the other tires
}
每个 shader.Update()
调用都采用自定义 Transform
class,这只是 glm::translate
、glm::rotate
和 glm::scale
和 returns 代表模型矩阵变换的 glm::mat4
,基于我指定的变换。
incrementFrontTireRotation
方法和 move
方法是我遇到问题的地方。
void Car::incrementFrontTireRotation(float amount)
{
if (amount > 0)
{
if (frontTireRotation.y + amount <= MAX_FRONT_TIRE_TURNED)
frontTireRotation.y += amount;
else
frontTireRotation.y = MAX_FRONT_TIRE_TURNED;
}
else if (amount < 0)
{
if (frontTireRotation.y + amount >= -MAX_FRONT_TIRE_TURNED)
frontTireRotation.y += amount;
else
frontTireRotation.y = -MAX_FRONT_TIRE_TURNED;
}
if (carForwardSpeed != 0)
carRotation += glm::vec3(0, -amount, 0);
}
frontTireRotation
是一个 glm::vec3
,用于计算前轮胎的旋转,因为它们可以左右转动。 carRotation
本意是小车的旋转
void Car::move()
{
forward = glm::vec3(glm::rotate(-tireRotation, glm::vec3(0, 1.0f, 0)) * glm::vec4(forward, 1.0f));
position += forward * carForwardSpeed;
}
我的目的是让汽车朝与前轮胎相同的方向行驶。我正在尝试使用 forward
向量来执行此操作,但它产生了一些奇怪的结果。车确实转了,但是转太多之后车就不再按照轮胎指向的方向移动了。
我知道这很多。如果我需要澄清任何事情,请告诉我。
汽车的轮胎应对齐,使它们的轴线在公共枢轴处相交,如下所示:
如您所见,两个前轮胎的角度肯定不同。因此,处理转弯的最简单方法是考虑一个虚拟中央轮,其角度可通过转向变量控制。
然后,您可以通过此转向计算汽车必须行驶的转弯半径。这将取决于汽车的长度。给定此半径,您可以计算枢轴点。然后,在更新汽车的位置和旋转时,您需要做的就是围绕枢轴旋转整个汽车。旋转角度的选择应使生成的圆弧段等于汽车在给定帧时间内的行驶方式(即 angle * r = velocity * t
、angle
弧度)。
当没有或很少发生转向时,必须小心。在这种情况下,转弯半径变为无限大,无法进行合理的旋转。在这种情况下切换到简单的翻译可以解决这个问题。
我试图让汽车以半真实的方式在 OpenGL 中移动,汽车大致沿着前轮胎的方向行驶(前轮胎可以转动,就像真正的汽车轮胎一样)。
我不知道如何让汽车朝向轮胎。我正在使用 SDL2 从键盘输入(按下和向上键),如下所示:
case SDLK_LEFT:
car.setTireRotationSpeed(-TIRE_ROTATION_SPEED);
break;
case SDLK_RIGHT:
car.setTireRotationSpeed(TIRE_ROTATION_SPEED);
break;
case SDLK_UP:
car.setCarForwardSpeed(CAR_MOVEMENT_SPEED);
break;
case SDLK_DOWN:
car.setCarForwardSpeed(-CAR_MOVEMENT_SPEED);
break;
按键释放也类似:
case SDLK_LEFT:
if (car.getTireRotationSpeed() == -TIRE_ROTATION_SPEED)
car.setTireRotationSpeed(0);
break;
case SDLK_RIGHT:
if (car.getTireRotationSpeed() == TIRE_ROTATION_SPEED)
car.setTireRotationSpeed(0);
break;
case SDLK_UP:
if (car.getCarForwardSpeed() == CAR_MOVEMENT_SPEED)
car.setCarForwardSpeed(0);
break;
case SDLK_DOWN:
if (car.getCarForwardSpeed() == -CAR_MOVEMENT_SPEED)
car.setCarForwardSpeed(0);
break;
这会在 car
中设置变量,每一帧都会使用这些变量来平滑地移动 car/rotate 汽车上的轮胎(因为底盘和轮胎是单独渲染的)。
我正在使用 glm-math(即 glm:vec3
、glm::mat4
等)来完成转换,我正在使用着色器来绘制和纹理。
每次渲染整车,都会经过以下几个步骤:
void Car::Render(Shader & shader, Camera & camera)
{
incrementFrontTireRotation(getTireRotationSpeed());
move();
chasisTexture.Bind(0);
shader.Update(getChasisTransform(), camera);
chasisMesh.Draw();
tireTexture.Bind(0);
shader.Update(getTireTransform(Car::FRONT_RIGHT), camera);
tireMesh.Draw();
//Repeated for the other tires
}
每个 shader.Update()
调用都采用自定义 Transform
class,这只是 glm::translate
、glm::rotate
和 glm::scale
和 returns 代表模型矩阵变换的 glm::mat4
,基于我指定的变换。
incrementFrontTireRotation
方法和 move
方法是我遇到问题的地方。
void Car::incrementFrontTireRotation(float amount)
{
if (amount > 0)
{
if (frontTireRotation.y + amount <= MAX_FRONT_TIRE_TURNED)
frontTireRotation.y += amount;
else
frontTireRotation.y = MAX_FRONT_TIRE_TURNED;
}
else if (amount < 0)
{
if (frontTireRotation.y + amount >= -MAX_FRONT_TIRE_TURNED)
frontTireRotation.y += amount;
else
frontTireRotation.y = -MAX_FRONT_TIRE_TURNED;
}
if (carForwardSpeed != 0)
carRotation += glm::vec3(0, -amount, 0);
}
frontTireRotation
是一个 glm::vec3
,用于计算前轮胎的旋转,因为它们可以左右转动。 carRotation
本意是小车的旋转
void Car::move()
{
forward = glm::vec3(glm::rotate(-tireRotation, glm::vec3(0, 1.0f, 0)) * glm::vec4(forward, 1.0f));
position += forward * carForwardSpeed;
}
我的目的是让汽车朝与前轮胎相同的方向行驶。我正在尝试使用 forward
向量来执行此操作,但它产生了一些奇怪的结果。车确实转了,但是转太多之后车就不再按照轮胎指向的方向移动了。
我知道这很多。如果我需要澄清任何事情,请告诉我。
汽车的轮胎应对齐,使它们的轴线在公共枢轴处相交,如下所示:
如您所见,两个前轮胎的角度肯定不同。因此,处理转弯的最简单方法是考虑一个虚拟中央轮,其角度可通过转向变量控制。
然后,您可以通过此转向计算汽车必须行驶的转弯半径。这将取决于汽车的长度。给定此半径,您可以计算枢轴点。然后,在更新汽车的位置和旋转时,您需要做的就是围绕枢轴旋转整个汽车。旋转角度的选择应使生成的圆弧段等于汽车在给定帧时间内的行驶方式(即 angle * r = velocity * t
、angle
弧度)。
当没有或很少发生转向时,必须小心。在这种情况下,转弯半径变为无限大,无法进行合理的旋转。在这种情况下切换到简单的翻译可以解决这个问题。