2016-10-19 12 views
2

私は車をOpenGLで半現実的なやり方で動かそうとしています。車はフロントタイヤの方向に向かっています。実際の車のタイヤ)。OpenGLでタイヤの方向に車を移動する方法

車をタイヤに近づける方法がわかりません。キーリリースの

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の変数を設定します私はこのようなSDL2を使用して、キーボード(ダウンキーとキーアップ)からの入力を取っています車を動かす/タイヤを回転させる(シャーシとタイヤは別々にレンダリングされるので)、滑らかな方法で。

私はglm-math(すなわちglm:vec3glm::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()のコールのそれぞれは、単にglm::translateのラッパーですカスタムTransformクラスを、取りglm::rotate、およびglm::scale私が指定した変換に基づいて、モデルの行列変換を表す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ベクトルでこれをしようとしていますが、それはいくつかの奇妙な結果を持っています。車は本当に回転しますが、あまりにも多くの旋回後、車はもはやタイヤが指している方法を移動しません。

私はこれがたくさんあることを知っています。何かを明確にする必要があるかどうかを教えてください。車の

+4

通常、フロントタイヤは平行ではありません。これは、路面を滑って1本のタイヤが必要になるためです。内側のタイヤはもう少し回転しています。そして、これは、タイヤが前進するだけであると仮定すると理にかなっています。そして、タイヤの軸はすべて共通点で出会うでしょう。これは車の回転ピボットになります。回転角は車の速度に依存します。あなたがピボットを見つけたら、あなたがする必要があることは車に回転を適用することだけです。 –

+0

@NicoSchertler簡単にするために、車の速度は常に0または正または逆の一定量になります。 –

+1

それは原則を変更しません。車の回転角は操舵方向に依存します。物事をシンプルにするために、ステアリングはバーチャル中央の前輪のためのものと想定することができます。 –

答えて

3

タイヤはそれらの軸がそうのような一般的なピボットで会うように整列されるべきである。

Car tires

ご覧のように、2つのフロントタイヤは異なる角度を持っている必要があります。だから、旋回を扱う最も簡単な方法は、ステアリング変数を使って角度を制御する仮想の中央ホイールを検討することです。

このステアリングでは、車が動かなければならないターンサークルの半径を計算できます。これは車の長さによって異なります。この半径を指定すると、ピボットポイントを計算できます。次に、車の位置と回転を更新するときは、車全体をピボットについて回転させるだけです。回転角は、結果として得られる円のセグメントが、所与のフレーム時間(すなわち、フレーム時間)に自動車が移動すべき方法と等しくなるように選択されるべきである。angle * r = velocity * t,angle)。

ステアリングがまったく起こらないか、ほとんど起こらないように注意する必要があります。この場合、回転半径は無限になり、妥当な回転を行うことはできません。この場合、簡単な翻訳に切り替えることでこの問題を解決できます。

+0

あなたは正しいです。私の悪い。 – xaxxon

関連する問題