Конференция "Игры" » Класс камеры DIrectX [Delphi, Windows]
 
  • ElectriC © (14.04.07 19:58) [0]
    Нашёл "гибкий" класс описания камеры в DirectX.
    Т.к. в С++ не слишком силён, может кто-нибудь, помочь, перевести на Pascal'евский (aka Delphi) язык
    описание нижеприведённого кода с C++?
    P.S.   Или не подскажите где можно найти\скачать готовый класс камеры?
    P.P.S. Использование модулей DXUt, DXUtmisc и прочее не предлагать!

    class Camera
    {
    public:
        enum CameraType { LANDOBJECT, AIRCRAFT };

        Camera();
        Camera(CameraType cameraType);
        ~Camera();

        void strafe(float units); // влево/вправо
        void fly(float units);    // вверх/вниз
        void walk(float units);   // вперед/назад

        void pitch(float angle); // вращение относительно правого вектора
        void yaw(float angle);   // вращение относительно верхнего вектора
        void roll(float angle);  // вращение относительно вектора взгляда

        void getViewMatrix(D3DXMATRIX* V);
        void setCameraType(CameraType cameraType);
        void getPosition(D3DXVECTOR3* pos);
        void setPosition(D3DXVECTOR3* pos);
        void getRight(D3DXVECTOR3* right);
        void getUp(D3DXVECTOR3* up);
        void getLook(D3DXVECTOR3* look);

    private:
        CameraType  _cameraType;
        D3DXVECTOR3 _right;
        D3DXVECTOR3 _up;
        D3DXVECTOR3 _look;
        D3DXVECTOR3 _pos;
    };

    void Camera::getViewMatrix(D3DXMATRIX* V)
    {
        // Делаем оси камеры ортогональными
        D3DXVec3Normalize(&_look, &_look);

        D3DXVec3Cross(&_up, &_look, &_right);
        D3DXVec3Normalize(&_up, &_up);

        D3DXVec3Cross(&_right, &_up, &_look);
        D3DXVec3Normalize(&_right, &_right);

        // Строим матрицу вида:
        float x = -D3DXVec3Dot(&_right, &_pos);
        float y = -D3DXVec3Dot(&_up, &_pos);
        float z = -D3DXVec3Dot(&_look, &_pos);

        (*V)(0, 0) = _right.x;
        (*V)(0, 1) = _up.x;
        (*V)(0, 2) = _look.x;
        (*V)(0, 3) = 0.0f;

        (*V)(1, 0) = _right.y;
        (*V)(1, 1) = _up.y;
        (*V)(1, 2) = _look.y;
        (*V)(1, 3) = 0.0f;

        (*V)(2, 0) = _right.z;
        (*V)(2, 1) = _up.z;
        (*V)(2, 2) = _look.z;
        (*V)(2, 3) = 0.0f;

        (*V)(3, 0) = x;
        (*V)(3, 1) = y;
        (*V)(3, 2) = z;
        (*V)(3, 3) = 1.0f;
    }

    void Camera::pitch(float angle)
    {
        D3DXMATRIX T;
        D3DXMatrixRotationAxis(&T, &_right, angle);

        // Поворот векторов _up и _look относительно вектора _right
        D3DXVec3TransformCoord(&_up,&_up, &T);
        D3DXVec3TransformCoord(&_look,&_look, &T);
    }

    void Camera::yaw(float angle)
    {
        D3DXMATRIX T;

        // Для наземных объектов выполняем вращение
        // вокруг мировой оси Y (0, 1, 0)
        if(_cameraType == LANDOBJECT)
             D3DXMatrixRotationY(&T, angle);

        // Для летающих объектов выполняем вращение
        // относительно верхнего вектора
        if(_cameraType == AIRCRAFT)
             D3DXMatrixRotationAxis(&T, &_up, angle);

        // Поворот векторов _right и _look относительно
        // вектора _up или оси Y
        D3DXVec3TransformCoord(&_right, &_right, &T);
        D3DXVec3TransformCoord(&_look, &_look, &T);
    }

    void Camera::roll(float angle)
    {
        // Вращение только для летающих объектов
        if(_cameraType == AIRCRAFT)
        {
             D3DXMATRIX T;
             D3DXMatrixRotationAxis(&T, &_look, angle);

             // Поворот векторов _up и _right относительно
             // вектора _look
             D3DXVec3TransformCoord(&_right, &_right, &T);
             D3DXVec3TransformCoord(&_up, &_up, &T);
        }
    }

    void Camera::walk(float units)
    {
        // Для наземных объектов перемещение только в плоскости xz
        if(_cameraType == LANDOBJECT)
             _pos += D3DXVECTOR3(_look.x, 0.0f, _look.z) * units;

        if(_cameraType == AIRCRAFT)
             _pos += _look * units;
    }

    void Camera::strafe(float units)
    {
        // Для наземных объектов перемещение только в плоскости xz
        if(_cameraType == LANDOBJECT)
             _pos += D3DXVECTOR3(_right.x, 0.0f, _right.z) * units;

        if(_cameraType == AIRCRAFT)
             _pos += _right * units;
    }

    void Camera::fly(float units)
    {
        if(_cameraType == AIRCRAFT)
             _pos += _up * units;
    }
  • Леон © (15.04.07 18:15) [1]
    скорее всего, так:
    TCameraType = ( LANDOBJECT, AIRCRAFT );

    TCamera = class (TObject)
    public
        constructor Create;
        constructor Create(cameraType: TCameraType);
        destructor  Destroy();
        procedure strafe(units: real);
        procedure fly(units: real);
        procedure walk(units: real);
        procedure pitch(angle: real);
        procedure yaw(angle: real);
        procedure roll(angle: real);
        procedure getViewMatrix(var V: D3DXMATRIX);
        procedure setCameraType(cameraType: TCameraType);
        procedure getPosition(var pos: D3DXVECTOR3);
        procedure setPosition(var pos: D3DXVECTOR3);
        procedure getRight(var right: D3DXVECTOR3);
        procedure getUp(var up: D3DXVECTOR3);
        procedure getLook(var look: D3DXVECTOR3);
    private
        _cameraType: D3DXVECTOR3;
        _right,
        _up,
        _look,
        _pos : D3DXVECTOR3;
    end;

    procedure TCamera.getViewMatrix(var V: D3DXMATRIX);
    var x,y,z: real;
    begin   
        D3DXVec3Normalize(_look, _look);
        D3DXVec3Cross(_up, _look, _right);
        D3DXVec3Normalize(_up, _up);
        D3DXVec3Cross(_right, _up, _look);
        D3DXVec3Normalize(_right, _right);
        x := -D3DXVec3Dot(_right, _pos);
        y := -D3DXVec3Dot(_up, _pos);
        z := -D3DXVec3Dot(_look, _pos);
        V[0, 0] := _right.x;
        V[0, 1] := _up.x;
        V[0, 2] := _look.x;
        V[0, 3] := 0.0;
        V[1, 0] := _right.y;
        V[1, 1] := _up.y;
        V[1, 2] := _look.y;
        V[1, 3] := 0.0;
        V[2, 0] := _right.z;
        V[2, 1] := _up.z;
        V[2, 2] := _look.z;
        V[2, 3] := 0.0;
        V[3, 0] := x;
        V[3, 1] := y;
        V[3, 2] := z;
        V[3, 3] := 1.0;
    end;


    дальше уж сам...
  • Леон © (15.04.07 18:17) [2]
    упс..
    вместо
    private
        _cameraType: D3DXVECTOR3;


    следует
    private
        _cameraType: TCameraType;

  • ElectriC © (15.04.07 19:25) [3]
    В процедуре procedure TCamera.getViewMatrix(var V: TD3DXMATRIX) компилятор ругается: "Array type required". В чём проблема?
  • ElectriC © (15.04.07 19:35) [4]
    А, всё, нашёл! Нужно было писать V.m[0, 0] и т.д.
  • ElectriC © (15.04.07 20:54) [5]
    Подскажите, как перевести на pascal нижеприведённый код:

        if(_cameraType == LANDOBJECT)
             _pos += D3DXVECTOR3(_look.x, 0.0f, _look.z) * units;

        if(_cameraType == AIRCRAFT)
             _pos += _look * units;

    Заранее, спасибо!

    P.S. Может быть, так:
    procedure Walk(units : Single);
    begin
      If cameraType = LANDOBJECT then
         _pos := _pos + D3DXVECTOR3(_look.x, 0.0, _look.z) * units;

        If _cameraType = AIRCRAFT then
             _pos := _pos + _look * units;
     end;
    end;
    Но при этом компилятор ругается:
    "Operator not applicable to this operand type" -                                             в строке    _pos := _pos + D3DXVECTOR3(_look.x, 0.0, _look.z) * units
    и в строке _pos := _pos + _look * units;
  • Леон © (16.04.07 11:57) [6]
    Дело в том что операция * переопределена. Скорее всего в данном случае это умножение вектроа на скаляр (для 100% увереенности нужно видеть реализацию класса D3DXVECTOR3). Поэтому:

    if _cameraType = LANDOBJECT then
            _pos := _pos + D3DXVECTOR3(_look.x*units, 0.0f, _look.z*units);

  • Piroxyline © (21.04.07 18:05) [7]
    Вот полный, но немного оптимизированный мной перевод самого первого кода. Переводилось прямо в браузере, так что может не работать. Хотя оно и так работать не будет :)


    Float = Single;
    TCameraType = (LANDOBJECT, AIRCRAFT);
    TCamera = class
     private
       _CameraType: TCameraType;
       _Right, _Up, _Look, _Pos: TD3DXVector3;
     public
       constructor Create; overload;
       constructor Create(CameraType: TCameraType); overload;
       destructor Destroy;
       procedure Strafe(Units: Float);
       procedure Fly(Units: Float);
       procedure Walk(Units: Float);
       
       procedure Pitch(Angle: Float);
       procedure Yaw(Angle: Float);
       procedure Roll(Angle: Float);

       procedure GetViewMatrix(out V: TD3DXMATRIX);
       procedure SetCameraType(CameraType: TCameraType);
       procedure GetPosition(out Pos: TD3DXVector3);
       procedure SetPosition(Pos: TD3DXVector3);
       procedure GetRight(out Right: TD3DXVector3);
       procedure GetUp(out Up: TD3DXVector3);
       procedure GetLook(out Look: TD3DXVector3);
    end;

    procedure TCamera.GetViewMatrix(out V: TD3DXMATRIX);
    var
     x, y, z: Float;
    begin
     D3DXVec3Normalize(_look, _look);

     D3DXVec3Cross(_up, _look, _right);
     D3DXVec3Normalize(_up, _up);

     D3DXVec3Cross(_right, _up, _look);
     D3DXVec3Normalize(_right, _right);

     x := -D3DXVec3Dot(_right, _pos);
     y := -D3DXVec3Dot(_up, _pos);
     z := -D3DXVec3Dot(_look, _pos);

     V.m[0, 0] := _right.x;
     V.m[0, 1] := _up.x;
     V.m[0, 2] := _look.x;
     V.m[0, 3] := 0.0;

     V.m[1, 0] := _right.y;
     V.m[1, 1] := _up.y;
     V.m[1, 2] := _look.y;
     V.m[1, 3] := 0.0;

     V.m[2, 0] := _right.z;
     V.m[2, 1] := _up.z;
     V.m[2, 2] := _look.z;
     V.m[2, 3] := 0.0;

     V.m[3, 0] := x;
     V.m[3, 1] := y;
     V.m[3, 2] := z;
     V.m[3, 3] := 1.0;
    end;

    procedure TCamera.Pitch(Angle: Float);
    var
     T: TD3DXMatrix;
    begin
     D3DXMatrixRotationAxis(T, _right, Angle);
     D3DXVec3TransformCoord(_up, _up, T);
     D3DXVec3TransformCoord(_look, _look, T);
    end;

    procedure TCamera.Yaw(Angle: Float);
    var
     T: TD3DXMatrix;
    begin
     if _CameraType = LANDOBJECT then
       D3DXMatrixRotationY(T, Angle)
     else
       D3DXMatrixRotationAxis(T, _up, Angle);

     D3DXVec3TransformCoord(_right, _right, T);
     D3DXVec3TransformCoord(_look, _look, T);
    end;

    procedure TCamera.Roll(Angle: Float);
    var
     T: TD3DXMatrix;
    begin
     if CameraType = AIRCRAFT then begin
       D3DXMatrixRotationAxis(T, _look, angle);
       D3DXVec3TransformCoord(_right, _right, T);
       D3DXVec3TransformCoord(_up, _up, T);
     end;
    end;

    procedure TCamera.Walk(Units: Float);
    begin
     if CameraType = LANDOBJECT then
       _pos := D3DXVector3(_pos.x + _look.x * Units, _pos.y, _pos.z + _look.z * Units)
     else
       _pos = D3DXVector3(_pos.x + _look.x * Units, _pos.y + _look.y * Units, _pos.z + _look.z * Units);
    end;

    procedure TCamera.Strafe(Units: Float);
    begin
     if CameraType = LANDOBJECT then
       _pos := D3DXVector3(_right.x + _look.x * Units, _pos.y, _pos.z + _right.z * Units)
     else
       _pos = D3DXVector3(_pos.x + _right.x * Units, _pos.y + _right.y * Units, _right.z + _look.z * Units);
    end;

    procedure TCamera.Fly(Units: Float);
    begin
     if CameraType = AIRCRAFT then
       _pos := D3DXVector3(_right.x + _up.x * Units, _pos.y + _up.y * Units, _pos.z + _up.z * Units);
    end;

  • ElectriC © (22.04.07 00:55) [8]
    Поглядим)))
  • s1aSh (22.04.07 10:50) [9]
    Не подскажите, откуда текст на с++? И еще, почему не принимаете DXUT? Я наоборот хочу понять, как оно там устроено (в сэмплах СДК-шных выглядит все довольно симпатично, двигается хорошо). Если знаете, где можно про камеры в DXUT почитать, скажите плизз. А то второй день не могу понять, че к чему (а в хэлпе СДК-шном ни слова про камеру из примеров).

    p.s. там у них (в sdk) даже пустая заготовка выполнена через DXUT, а не как в их же туториалах.
  • ElectriC © (22.04.07 21:49) [10]

    > И еще, почему не принимаете DXUT?

    Да потому что он объёмен, т.б. добавляет уйму КБ к exe'шнику!
 
Конференция "Игры" » Класс камеры DIrectX [Delphi, Windows]
Есть новые Нет новых   [119255   +37][b:0][p:0.004]