2016-10-19 8 views
2

나는 자동차를 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에서 변수를 설정 모든 프레임을 사용하고 있습니다 매끄러운 방식으로 차를 움직이거나 차에 타이어를 회전시키는 것 (샤시와 타이어가 분리되어 렌더링되기 때문에).

변환을 수행하기 위해 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() 전화의 각 단순히 glm::translate, glm::rotate에 대한 래퍼입니다 사용자 정의 Transform 클래스를 받아, 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

일반적으로 앞 타이어는 평행하지 않습니다. 왜냐하면 한 타이어가 거리를 가로 질러지나 가기 때문입니다. 내부 타이어가 조금 더 돌았습니다. 타이어가 앞으로 나아갈 수 있다고 가정한다면 이것은 의미가 있습니다. 그러면 타이어의 축이 모두 공통점에서 만나게됩니다. 이것은 자동차의 회전 피벗 것입니다. 회전 각도는 자동차 속도에 따라 다릅니다. 따라서 피벗을 찾으면 차에 회전을 적용하기 만하면됩니다. –

+0

@NicoSchertler 간결함을 위해 자동차의 속도는 항상 0 또는 정방향/역방향으로 일정하게 유지됩니다. –

+1

그것은 원칙을 바꾸지 않습니다. 자동차의 회전 각도는 조향 방향에 따라 달라집니다. 일을 단순하게하기 위해 스티어링을 가상 중앙 전륜으로 간주 할 수 있습니다. –

답변

3

타이어는 축과 같이 공통의 피벗에 부합하도록 정렬되어야합니다 :

보시다시피

Car tires

는, 두 개의 전면 타이어는 다른 각도 있어야합니다. 그러므로 턴을 처리하는 가장 쉬운 방법은 스티어링 변수를 통해 제어하는 ​​가상 중앙 휠을 고려하는 것입니다.

이 조타를 통해 자동차가 움직여야하는 회전 원의 반지름을 계산할 수 있습니다. 이것은 차의 길이에 달려 있습니다. 이 반경이 주어지면 피벗 점을 계산할 수 있습니다. 그런 다음 자동차의 위치와 회전을 업데이트 할 때 전체 차량을 피벗에 대해 회전시켜야합니다. 회전 각은 결과로 생성 된 원 세그먼트가 주어진 프레임 시간 (예 : 1 초) 동안 자동차가 이동해야하는 방식과 동일하도록 선택해야합니다.angle * r = velocity * t, angle 라디안).

조향 장치가 없거나 거의 작동하지 않을 때 조심해야합니다. 이 경우 회전 반경은 무한대가되고 합리적인 회전을 할 수 없습니다. 이 경우 간단한 변환으로 전환하면이 문제를 해결할 수 있습니다.

+0

네 말이 맞아. 내 잘못이야. – xaxxon