Конференция "Игры" » Проблема с камерой [Delphi, Windows]
 
  • ElectriC © (18.04.07 21:20) [0]
    Есть проблемка с камерой: Допустим, когда начинаешь вертеть мышкой по/против часовой стрелки, камера, как и положено поворачивается вверх/вниз/влево/вправо, но при этом она ещё начинает переворачивается по/против часовой стрелки? Не подскажите, в чём проблем-ка.

    P.S. Или посоветуйте что нужно улучшить.

    Код движение камеры мышкой:

    ...

    Xi, Yi : Single;
    Cursor : TPoint

    ...

    GetCursorPos(Cursor);
    SetCursorPos(800 div 2, 600 div 2);

    Xi := Xi + (Cursor.X  - 400)/100 * 0.1;
    Yi := Yi - (300 - Cursor.Y)/100 * 0.1;

    RotateLR(Xi);
    RotateUD(Yi);
    Xi := 0; Yi := 0;

    ...

    Код модуля камеры:

     SLCamera = packed record
       CameraType : (FP, FREE);//камера для первого лица/свободная камера

       View, Proj : TD3DMatrix;

       Xi, Yi     : Single;

       LR, UD,
       LK, PS     : TD3DXVECTOR3;
     end;

    var D3DDevice : IDirect3DDevice9;

    procedure GetViewMatrix;
    var X, Y, Z : Single;
    begin
     with SLCamera do
      begin
        D3DXVec3Normalize(LK, LK);

        D3DXVec3Cross    (UD, LK, LR);
        D3DXVec3Normalize(UD, UD);

        D3DXVec3Cross    (LR, UD, LK);
        D3DXVec3Normalize(LR, LR);

        X := -D3DXVec3Dot(LR, PS);
        Y := -D3DXVec3Dot(UD, PS);
        Z := -D3DXVec3Dot(LK, PS);

        with View do
         begin
           m[0, 0] := LR.x;
           m[0, 1] := UD.x;
           m[0, 2] := LK.x;
           m[0, 3] :=  0.0;

           m[1, 0] := LR.y;
           m[1, 1] := UD.y;
           m[1, 2] := LK.y;
           m[1, 3] :=  0.0;

           m[2, 0] := LR.z;
           m[2, 1] := UD.z;
           m[2, 2] := LK.z;
           m[2, 3] :=  0.0;

           m[3, 0] :=    X;
           m[3, 1] :=    Y;
           m[3, 2] :=    Z;
           m[3, 3] :=  1.0;
         end;

        D3DDevice.SetTransform(D3DTS_VIEW, View);

        D3DXMatrixPerspectiveFovLH(Proj, D3DX_PI / 4, 1.0, 1.0, 1000.0);
        D3DDevice.SetTransform(D3DTS_PROJECTION, Proj);
      end;
    end;

    { движение влево/вправо }
    procedure MoveLR(Step : Single);
    begin
     with SLCamera do
      case CameraType of
        FP   : PS := D3DXVECTOR3(PS.x + LR.x * Step,                0.0,
                                 PS.z + LR.z * Step);
        FREE : PS := D3DXVECTOR3(PS.x + LR.x * Step, PS.y + LR.y * Step,
                                 PS.z + LR.z * Step);
      end;

     GetViewMatrix;
    end;

    { движение вверх/вниз }
    procedure MoveUD(Step : Single);
    begin
     with SLCamera do
      If CameraType = FREE then
       begin
         PS.x := PS.x + UD.x * Step;
         PS.y := PS.y + UD.y * Step;
         PS.z := PS.z + UD.z * Step;
       end;

     GetViewMatrix;
    end;

    { движение вперёд/назад }
    procedure MoveFB(Step : Single);
    begin
     with SLCamera do
      case CameraType of
        FP   : PS := D3DXVECTOR3(PS.x + LK.x * Step, 0.0, PS.z + LK.z * Step);
        FREE : begin
                 PS.x := PS.x + LK.x * Step;
                 PS.y := PS.y + LK.y * Step;
                 PS.z := PS.z + LK.z * Step;
               end;
      end;

     GetViewMatrix;
    end;

    { поаорот влево/вправо }
    procedure RotateLR(Step : Single);
    var Mat : TD3DXMatrix;
    begin
     with SLCamera do
      begin
        case CameraType of
          FP   : D3DXMatrixRotationY   (Mat, Step);
          FREE : D3DXMatrixRotationAxis(Mat,   UD, Step);
        end;

        D3DXVec3TransformCoord(LR, LR, Mat);
        D3DXVec3TransformCoord(LK, LK, Mat);
     end;

     GetViewMatrix;
    end;

    { поворот вверх/вниз }
    procedure RotateUD(Step : Single);
    var Mat : TD3DXMatrix;
    begin
     with SLCamera do
      begin
        D3DXMatrixRotationAxis(Mat, LR, Step);

        D3DXVec3TransformCoord( UD, UD,  Mat);
        D3DXVec3TransformCoord( LK, LK,  Mat);
      end;

     GetViewMatrix;
    end;

    { поворот по/против часовой стрелки }
    procedure RotateUC(Step : Single);
    var Mat : TD3DXMatrix;
    begin
     with SLEngine.SLCamera do
      If CameraType = FREE then
       begin
         D3DXMatrixRotationAxis(Mat, LK, Step);

         D3DXVec3TransformCoord( LR, LR,  Mat);
         D3DXVec3TransformCoord( UD, UD,  Mat);
       end;

     GetViewMatrix;
    end;

    end.
  • Sapersky (19.04.07 14:23) [1]
    В примерах к DX SDK не вращается - видимо из-за того, что вращение там делается через кватернионы. В DX8 это класс D3DUtil.CD3DArcBall.
    В принципе, само по себе вращение не порок, оно присутствует в некоторых коммерческих CAD, например. Даже логично - крутим мышкой вокруг объекта -> поворачиваем объект относительно перпендикулярной экрану оси.
  • ElectriC © (19.04.07 15:57) [2]
    Понятно!
    Последний вопрос: Как сделать поворот камеры вокруг какого-либо объекта,
    например дома, как это сделано, допустим, в Sims'ах?
    P.S. Использование нмжеприведённого кода не предлагать:
         RotateLR( 0.02);
         MoveLR  (-0.02);
         если ошибаюсь, то
         RotateLR(-0.02);
         MoveLR  ( 0.02);
  • Sapersky (19.04.07 19:27) [3]
    Обычно формируют матрицу вращения относительно 0-й точки, потом умножают её на матрицу перемещения в точку, относительно которой нужно крутить.
    Правда, в моём тесте для достижения нужного результата пришлось перемещать в обратном направлении. То ли у меня что-то напутано, то ли действительно так и есть.
  • ElectriC © (19.04.07 19:52) [4]
    Можешь написать исходный текст?
  • Sapersky (19.04.07 21:10) [5]
    Я так понял, что в [0] как раз и есть вращение камеры вокруг объекта (толком не вникал), а проблема в том, чтобы сделать вращение относительно произвольной точки.
    Если нет... можно заранее подготовить видовую матрицу, направленную в 0 (тем же GetViewMatrix) и потом умножать её на матрицу вращения, полученную D3DXMatrixRotationAxis.
    Матрица перемещения - D3DXMatrixTranslation. Потом ещё раз D3DXMatrixMultiply, потом SetTransform(D3DTS_VIEW, ...).
  • ElectriC © (20.04.07 00:32) [6]
    Спасибо, по-экспериментируем))
  • ElectriC © (20.04.07 15:04) [7]
    Чё т не выходит! Так можешь написать исходник процедуры, которая ворочает камеру вокруг точки, плиз!
  • ElectriC © (20.04.07 18:17) [8]
    ...
  • Sapersky (20.04.07 18:44) [9]
    Нет у меня конкретной процедуры, нужно выдирать куски из разных мест, а это долго.
    Умножаешь матрицы в правильном порядке? Т.е. порядок передачи параметров в функцию имеет значение.
    И чем всё-таки CD3DArcBall не угодил? Хотя в примерах SDK он в основном применяется к матрице модели, фактически можно применять и к видовой. Рекомендация глобального характера - см. ветку про текстуры, качай книги по ссылкам, читай.
  • ElectriC © (29.04.07 21:51) [10]
    Я понял, что надо так (хотя и не работает):

    LK : TD3DXVECTOR3;
    procedure Axis(Step : Single);
    var Mat : TD3DXMatrix;
    begin
     D3DXMatrixRotationAxis(Mat,     LK, Step);
     D3DXMatrixTranslation (Mat,   Step,  0.0, 0.0);
     D3DXMatrixMultiply     (Mat,    Mat,  Mat);
     Device.SetTransform   ( D3DTS_VIEW,  Mat);
    end;
    Или нет?
  • ElectriC © (29.04.07 23:05) [11]
    Лучше, наверное, будет этот код (и он тож не работает):
    procedure Axis(Step : Single);
    var matTrans, matRot, matWorld : TD3DXMatrix;
    begin
      D3DXMatrixTranslation(matTrans, 0.0, 0.0, 10.0);
      D3DXMatrixRotationYawPitchRoll(matRot,
                                     D3DXToRadian(Step),
                                     0.0,
                                     0.0);

        matWorld.m[0, 0] := matRot.m[0, 0] * matTrans.m[0, 0];
        matWorld.m[0, 1] := matRot.m[0, 1] * matTrans.m[0, 1];
        matWorld.m[0, 2] := matRot.m[0, 2] * matTrans.m[0, 2];
        matWorld.m[0, 3] := matRot.m[0, 3] * matTrans.m[0, 3];

        matWorld.m[1, 0] := matRot.m[1, 0] * matTrans.m[1, 0];
        matWorld.m[1, 1] := matRot.m[1, 1] * matTrans.m[1, 1];
        matWorld.m[1, 2] := matRot.m[1, 2] * matTrans.m[1, 2];
        matWorld.m[1, 3] := matRot.m[1, 3] * matTrans.m[1, 3];

        matWorld.m[2, 0] := matRot.m[2, 0] * matTrans.m[2, 0];
        matWorld.m[2, 1] := matRot.m[2, 1] * matTrans.m[2, 1];
        matWorld.m[2, 2] := matRot.m[2, 2] * matTrans.m[2, 2];
        matWorld.m[2, 3] := matRot.m[2, 3] * matTrans.m[2, 3];

        matWorld.m[3, 0] := matRot.m[3, 0] * matTrans.m[3, 0];
        matWorld.m[3, 1] := matRot.m[3, 1] * matTrans.m[3, 1];
        matWorld.m[3, 2] := matRot.m[3, 2] * matTrans.m[3, 2];
        matWorld.m[3, 3] := matRot.m[3, 3] * matTrans.m[3, 3];

        Device.SetTransform(D3DTS_WORLD, matWorld);
     end;
    end;

    Пробовал изменять Device.SetTransform(D3DTS_WORLD, matWorld) на
    Device.SetTransform(D3DTS_VIEW, matWorld) => Объекты вообще исчезают(((
  • ElectriC © (30.04.07 11:29) [12]
    А, всё!!! Въехал наконец-то)))
 
Конференция "Игры" » Проблема с камерой [Delphi, Windows]
Есть новые Нет новых   [119252   +34][b:0][p:0.001]