3D 카메라 회전


9

용서해주세요.하지만 도움이 필요합니다. 몇 주 동안이 문제에 봉착했습니다. 나는 진전이없고 어디를 가든 다른 답을 볼 수 있습니다. 시도하는 모든 것이 효과가 없습니다. 나는 충분한 팁과 조언을 얻었으므로 이제는 이것을 이해할 수 없기 때문에 내가 거꾸로 일할 수있는 누군가를 내게 필요로합니다.

이 주제를 가장 혼란스럽게 만든 것은 모든 사람이 다른 규칙 또는 규칙 집합을 사용하는 방식이며, 답변은 자신의 규칙을 정의하지 않고 자체 규칙을 기반으로합니다.

그래서 여기에 가장 일반적이고 논리적으로 보이는 것을 기반으로 한 규칙이 있습니다.

  1. 축의 오른쪽 규칙.
  2. 양의 Y가 올랐고 양의 Z가 시청자를 향하고 양의 X가 오른쪽에 있습니다.
  3. 셰이더로 보낼 때 바뀐 행 주요 행렬.
    • 피치 : X 축을 중심으로 회전
    • 요 : y 축을 중심으로 회전
    • 롤 : z 축을 중심으로 회전
  4. 회전 순서 : Roll, Pitch, Yaw (이것이 맞습니까? 누군가 나를 확인할 수 있습니까?)
  5. 축의 양의 끝에서 내려다 보면 양의 회전 값이 시계 방향으로 회전합니다.
  6. 모든 축에서 0 회전의 기본 방향은 음의 Y를 가리키는 벡터입니다.

.. 그러한 관습이 주어지면 (잘못되면 반드시 바로 잡으십시오!), 어떻게 하는가 :

  • LookAt 함수를 작성 하시겠습니까? (lookAt (벡터 위치, 벡터 눈 초점, 벡터))
  • 회전 행렬을 계산합니다. (회전 (x, y, z))

적어도 지난 3 주 동안이 두 가지 질문에 스스로 답해 보았습니다. 최소 30 번 이상 LookAt & Rotation Matrix 기능을 다시 작성했습니다. 수십 가지 방법을 테스트 한 결과 제가 본 자료를 읽었습니다. 수백 개의 웹 사이트와 많은 답변이있는 질문을 읽고, 다른 사람들의 코드를 복사했으며, 지금까지 내가 한 것도 효과가 없었습니다. 모든 것이 잘못된 결과를 가져 왔습니다. 일부는 유쾌하게 기괴한 출력을 만들어내어 올바른 회전에 가깝지 않습니다.

나는 지난 밤을 제외하고 매일 밤이 일을 해왔다. 나는 반복적 인 실패로 너무 좌절해서 멈추고 쉬어야했다.

올바른 방법이 무엇인지 보여 주시면 거꾸로 작업하고 어떻게 작동하는지 알아낼 수 있습니다. 정답을 얻지 못하고있어 조금 미치게됩니다!

Java로 작성하고 있지만 모든 언어로 작성된 코드를 사용합니다. 대부분의 3D 렌더링 코드는 실제로 매우 훌륭하게 작동합니다. 이해할 수없는 수학 일뿐입니다.

업데이트 : 해결

도와 주셔서 감사합니다! 나는 이제 실제로 이해하고 작동하는 LookAt 기능을 가지고 있으며 더 행복해질 수 없습니다 (누군가가 그것을보고 싶다면 물어보십시오).

피치 / 요 / 롤 변수를 기반으로 회전 행렬을 다시 작성하려고 시도했지만 다시 실패하는 것처럼 보였지만 Freelook 카메라에 적합하지 않은 것처럼 오일러 각도를 사용하려고 시도했습니다. 대신 쿼터니언 클래스를 만들고 그 길을 따라 가면 운이 좋을 것입니다. 그렇지 않으면 피치 / 요를 구면 좌표로 사용하고 새로운 작업 LookAt 함수를 회전에 사용합니다.

다른 사람이 비슷한 문제에 직면하고 있고 나에게 질문을하고 싶은 경우, 부담없이 문의하십시오.

적어도 나는 더 이상 붙어 있지 않습니다, 도움을 주셔서 감사합니다!

답변:


15

당신이 찾고있는 것은이 좋은 설명에서 찾을 수 있습니다 : http://www.songho.ca/opengl/gl_transform.html

그러나 손을 잡지 않고 혼란스러워한다는 것을 알았으므로 여기에 설명하려고 노력할 것입니다.

이 시점에서 5 개의 좌표계와 이들이 서로 관련되는 방식을 고려해야합니다. 이들은 창 좌표, 정규화 된 장치 좌표, 눈 좌표, 세계 좌표 및 객체 좌표입니다.

창 좌표는 화면에서 "물리적"픽셀로 볼 수 있습니다. 이는 윈도우 시스템이 참조하는 좌표이며 모니터에서 기본 해상도로 작동하는 경우 실제로는 개별 픽셀입니다. 창 좌표계는 2D 정수이며 창을 기준으로합니다. 여기서 x +는 왼쪽이고 y +는 왼쪽 위 모서리에 원점이 표시되어 있습니다. 예를 들어 전화를 걸 때 이러한 문제가 발생합니다 glViewport.

두 번째 세트는 정규화 된 장치 좌표입니다. 활성 뷰 포트에 의한 공간 설정을 나타냅니다. 뷰 포트의 가시 영역은 -1에서 +1로 이동하여 중심에 원점이 있습니다. x +가 남아 있고 y +가 올라갑니다. 또한 z +가 장면에서 "꺼져"있습니다. 이것이 1에서 설명하는 것입니다.

정규화 된 장치 좌표에서 창 좌표로 얻는 방법을 제어 할 수 없습니다. 이는 암시 적으로 수행됩니다. 당신이 가진 유일한 컨트롤은 glViewport또는 유사합니다.

openGL로 작업 할 때 최종 결과는 항상 표준화 된 장치 좌표로 표시됩니다. 결과적으로 장면을 렌더링하는 방법에 대해 걱정할 필요가 있습니다. 투영 및 모델 뷰 행렬을 항등 행렬로 설정하면 이러한 좌표로 직접 그릴 수 있습니다. 예를 들어 전체 화면 효과를 적용 할 때 수행됩니다.

다음은 눈 좌표입니다. 이것이 카메라에서 보여지는 세상입니다. 결과적으로 원점이 카메라에 있으며 장치 좌표와 같은 축 축이 적용됩니다.

눈 좌표에서 장치 좌표로 이동하려면 투영 행렬을 만듭니다. 가장 간단한 것은 값을 적절하게 스케일링하는 직교 투영법입니다. 투시 투영은 더 복잡하며 시뮬레이션 투시도 포함됩니다.

마지막으로 세계 좌표계가 있습니다. 이것은 세계가 정의되고 카메라가이 세계의 일부인 좌표계입니다. 여기서 축 방향은 사용자가 정의한 것과 같습니다 . z +를 위로 선호한다면 완전히 괜찮습니다.

세계 좌표에서 눈 좌표로 이동하려면 뷰 매트릭스를 정의하십시오. 이것은 다음과 같은 방법으로 수행 할 수 있습니다 lookAt. 이 매트릭스가하는 것은 카메라가 원점에 있고 z 축을 내려다 보도록 월드를 "이동"하는 것입니다.

뷰 매트릭스를 계산하는 것은 놀랍도록 간단합니다. 카메라를 변형시켜야합니다. 기본적으로 다음 행렬을 공식화해야합니다.

미디엄=엑스[1]와이[1][1][1]엑스[2]와이[2][2][2]엑스[]와이[][][]0001

x, y 및 z 벡터는 카메라에서 직접 가져올 수 있습니다. 살펴보면 목표, 눈 (중심) 및 최대 값에서 파생됩니다. 이렇게 :

=영형아르 자형미디엄나는이자형(이자형와이이자형아르 자형이자형)엑스=영형아르 자형미디엄나는이자형(×)와이=엑스

그러나 만약 당신이이 값들이 단지 주위에 놓여 있다면 당신은 그것들을 그대로 가지고 갈 수 있습니다.

p를 얻는 것이 좀 더 까다 롭습니다. 월드 좌표에서의 위치가 아니라 카메라 좌표에서의 위치입니다. 여기서 간단한 해결 방법은 두 개의 행렬을 초기화하는 것입니다. 하나는 x, y 및 z 만 있고 다른 하나는 -eye를 사용하여 곱하는 것입니다. 결과는 뷰 매트릭스입니다.

이것이 코드에서 어떻게 보일 수 있는지 :

mat4 lookat(vec3 eye, vec3 target, vec3 up)
{
    vec3 zaxis = normalize(eye - target);    
    vec3 xaxis = normalize(cross(up, zaxis));
    vec3 yaxis = cross(zaxis, xaxis);     

    mat4 orientation(
       xaxis[0], yaxis[0], zaxis[0], 0,
       xaxis[1], yaxis[1], zaxis[1], 0,
       xaxis[2], yaxis[2], zaxis[2], 0,
         0,       0,       0,     1);

    mat4 translation(
              1,       0,       0, 0,
              0,       1,       0, 0, 
              0,       0,       1, 0,
        -eye[0], -eye[1], -eye[2], 1);

    return orientation * translation;
}

풀 코드

그리고 마지막으로 완전성을 위해 객체 좌표계도 있습니다. 메시가 저장되는 좌표계입니다. 모델 매트릭스의 도움으로 메쉬 좌표가 월드 좌표계로 변환됩니다. 실제로 모델 및 뷰 매트릭스는 소위 모델 뷰 매트릭스로 결합됩니다.


1
내가이 답변에 100 번 투표 할 수 있다면 내가 혼란 스러웠던 모든 것을 다루고 코드와 링크를 제공하는 철저하고 완전한 답변에 감사드립니다! 나는 하루 종일이 주제에 대한 수학 책과 당신의 대답, 예제 코드 및 링크 된 페이지를 읽었습니다. 이것이 충분하지 않다면 지금 끝내야합니다. 마지막 코드 샘플에서 한 가지 설명 만 요청할 수 있다면 행렬이 열 주요 순서이고 위의 행렬이 행 주요이라고 말하는 것이 옳습니까?
Grady

이것은 약간 혼란스럽고 행렬은 주요 열이지만 열은 행에 있습니다. 따라서 실제 수학을 코드에 매핑하려면 행렬을 전치해야합니다. github.com/rioki/glm/blob/master/src/matrix.h#l72를 참조하십시오 . 이것은 openGL에 정확하게 매핑되며 사용하는 경우의 방식 float[16]입니다.
rioki

아, 나는 그렇게 생각했지만 확신하고 싶었다. 다시 한번 감사드립니다! 당신은 큰 도움이되었습니다. 정말 고맙습니다.
Grady
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.