태그 보관물: c#

c#

쿼터니언 기반 카메라를 어떻게 구현합니까? 곱합니다. 이 후

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

나는 이것에 관한 몇 가지 튜토리얼을 보았고 내가 쿼터니언 기반 카메라를 구현하려고 시도한다는 것을 알았을 때. 문제는 약 회전 후 제대로 작동하지 않는다는 것입니다. 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 다음 은 완전한 프로젝트입니다.



답변

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

cameraRot.ToAxisAngle(out axis, out angle);

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

GL.Rotate(angle, axis);

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

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

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


답변

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


답변

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


답변