쿼터니언 기반 카메라를 어떻게 구현합니까?


14

업데이트 여기의 오류는 매우 간단했습니다. 나는 라디안에서도 변환을 놓쳤다. 다른 문제가 있으면 전체를 읽을 필요가 없습니다.

나는 이것에 관한 몇 가지 튜토리얼을 보았고 내가 쿼터니언 기반 카메라를 구현하려고 시도한다는 것을 알았을 때. 문제는 약 회전 후 제대로 작동하지 않는다는 것입니다. 10 도는 -10 도로 돌아갑니다. 나는 무엇이 잘못되었는지 전혀 모른다. openTK를 사용하고 있으며 이미 쿼터니언 클래스가 있습니다. 나는 opengl에서 멍청한 놈이며, 재미를 위해 이것을하고 있으며 실제로 쿼터니언을 이해하지 못하기 때문에 아마도 여기서 바보 같은 짓을하고있을 것입니다. 다음은 몇 가지 코드입니다. (vbo를로드하고 그리는 메서드를 제외한 거의 모든 코드 (vbo-s를 보여주는 OpenTK 샘플에서 가져옴))

vbo에 큐브를로드하고 카메라의 쿼터니언을 초기화합니다.

protected override void OnLoad(EventArgs e) {
    base.OnLoad(e);

    cameraPos = new Vector3(0, 0, 7);
    cameraRot = Quaternion.FromAxisAngle(new Vector3(0,0,-1), 0);

    GL.ClearColor(System.Drawing.Color.MidnightBlue);
    GL.Enable(EnableCap.DepthTest);

    vbo = LoadVBO(CubeVertices, CubeElements);
}

여기 투시 투영을로드합니다. 이것은 처음에 그리고 창 크기를 조정할 때마다로드됩니다.

protected override void OnResize(EventArgs e) {
    base.OnResize(e);

    GL.Viewport(0, 0, Width, Height);

    float aspect_ratio = Width / (float)Height;

    Matrix4 perpective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect_ratio, 1, 64);
    GL.MatrixMode(MatrixMode.Projection);
    GL.LoadMatrix(ref perpective);
}

여기에서는 마지막 회전 값을 가져 와서 마지막 회전 만 나타내는 새 쿼터니언을 만들고 카메라 쿼터니언과 곱합니다. 이 후 opengl에서 사용할 수 있도록 이것을 축 각도로 변환합니다. (이것은 여러 온라인 쿼터니언 자습서에서 이해 한 방법입니다)

protected override void OnRenderFrame(FrameEventArgs e) {
    base.OnRenderFrame(e);

    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

    double speed = 1;
    double rx = 0, ry = 0;

    if (Keyboard[Key.A]) {
        ry = -speed * e.Time;
    }

    if (Keyboard[Key.D]) {
        ry = +speed * e.Time;
    }

    if (Keyboard[Key.W]) {
        rx = +speed * e.Time;
    }

    if (Keyboard[Key.S]) {
        rx = -speed * e.Time;
    }

    Quaternion tmpQuat = Quaternion.FromAxisAngle(new Vector3(0,1,0), (float)ry);
    cameraRot = tmpQuat * cameraRot;
    cameraRot.Normalize();

    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadIdentity();

    Vector3 axis;
    float angle;

    cameraRot.ToAxisAngle(out axis, out angle);
    //////////////////////////////////////////////////////////////////////
    // THIS IS WHAT I DID WRONG: I NEED TO CONVERT FROM RADIANS TO DEGREES
    //////////////////////////////////////////////////////////////////////
    //BEFORE
    //GL.Rotate(angle, axis);
    //AFTER
    GL.Rotate(angle * (float)180.0/(float)Math.PI, axis);
    GL.Translate(-cameraPos);

    Draw(vbo);
    SwapBuffers();
}

다음은 더 나은 설명을위한 2 가지 이미지입니다.

이

이것으로 뛰어 들다

여기에 이미지 설명을 입력하십시오

도움을 주시면 감사하겠습니다.

Update1 : 파일에 쓰는 스트림 라이터에 추가합니다.

    sw.WriteLine("camerarot: X:{0} Y:{1} Z:{2} W:{3} L:{4}", cameraRot.X, cameraRot.Y, cameraRot.Z, cameraRot.W, cameraRot.Length);
    sw.WriteLine("ry: {0}", ry);

로그는 http://www.pasteall.org/26133/text에서 사용할 수 있습니다 . 770 라인에서, 큐브는 camerarot.Y가 기호를 바꿀 때 오른쪽에서 왼쪽으로 점프합니다. 이것이 정상적인 지 모르겠습니다.

업데이트 2 다음 은 완전한 프로젝트입니다.


2
문제를 이해하지 못합니다. 렌더링에 사용하는 쿼터니언을 인쇄 해 보셨습니까?
Nicol Bolas

1
동의하고 rx, ry 및 Quaternion 값을 디버깅하십시오.
감속

전체 프로젝트를 빠른 공유에 업로드하지 않겠습니까? 더 쉬울 것입니다.
bobobobo

집에 도착하면 업로드하겠습니다.
교조 쿠 도르

답변:


9

여기에서 내 가정을 확인하는 데 필요한 코드를 표시하지는 않았지만 문제가 실제로 다음 줄임을 보장 할 수 있습니다.

cameraRot.ToAxisAngle(out axis, out angle);

라디안으로 표시된 각도 값을 반환하는 동안

GL.Rotate(angle, axis);

원하는 각도 에 제공 될 정도 .

수정하려면 각도 값을 GL.Rotate ()에 전달할 때 다음과 같이 변환해야합니다 .

GL.Rotate(angle * 180.0/3.141593, axis);

예, 그게 문제였습니다. :) 고마워. 나는 Opengl이 학위를 기대한다는 것을 알고 ToAxisAngle이 학위를 반환한다고 가정했습니다. 방금 opentk 코드를 보았고 라디안입니다. BTW 마지막에 전체 소스 코드를 제공했습니다.
gyozo kudor

@NickCaplinger는 C #에는 Math.Pi상수가 있으며, 최종 계산에 사용 된 리터럴 3.141593 값보다 우선적으로 사용해야한다는 것을 올바르게 지적합니다 .
트레버 파월

1

하지마 다른 장면 객체와 같이 조작 할 수있는 카메라를 사용하는 것이 덜 어려울 수 있지만 장기적으로는 위치, 눈 방향 및 위쪽 벡터를 정의 할 수있는 카메라를 사용하는 것이 좋습니다. 특히 모션 모델 프로그래밍을 시작할 때 쿼터니언으로 작업하는 것은 정말 고통스러운 일입니다.


1
동의했다. "응용 프로그램을 발음하기 어려운 경우에는 더 나아 져야합니다"방법을 좋아하는 팬이 아닙니다. =)
Patrick Hughes

쿼터니언은 발음하기 어렵다?
notlesh

1
약간의 유머는 먼 길을 간다 = D 추론으로 나는 그것이 쿼터니언 카메라를 원하는 이유를 모르는 누군가로부터 나왔다는 것을 암시한다. 위의 깨진 코드에서 라디안 및 학위 매개 변수를 올바르게 처리하는 것과 같은 것이 올바르게 처리되지 않으면 다루기가 쉽지 않습니다.
Patrick Hughes

3
이 질문은 실제로 카메라에 관한 것이 아닙니다. 게임 코드에서 로테이션을 표현하는 방법과 이러한 게임 표현을 OpenGL이 사용할 수있는 형태로 변환하는 방법에 관한 것입니다. 완전히 합법적 인 질문이며 OP의 도메인 경험 부족을 조롱하는 것이 어떤 식 으로든 도움이되지 않는다고 생각합니다. OP가 바보 같은 실수를 저지른 것과는 다릅니다. 각도를 표현할 때 각도를 사용한다는 OpenGL의 주장은 매우 기이합니다. 누구나 OpenGL을 처음 사용하여이 실수를합니다. 당신의 높은 말, 사람들을 내려주세요. 이런.
트레버 파월

방금 쿼터니언 기반 카메라의 작동 방식을 이해하고 싶었고 다른 일이 없었던 날에이 프로젝트를 만들었습니다. 나는 이것에 대한 실제 계획이 없습니다.
gyozo kudor

0

OpenTK 내부에 대해 잘 모릅니다. 내 경험상 필자는 필요한 정밀도 (기계)를 유지하는 quat의 적절한 구현으로 수학 라이브러리를 보지 못했습니다. 모두 e ^ 2-e ^ 3 오류에 영향을 미치기 때문입니다. 따라서 당신이 보는 효과 : 정밀도 (및 엡실론 값)는 약 10 ^ -5이며, 0 근처에서 '점프'합니다. 이것은 내 추측이다 :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.