物体不围绕相机旋转

时间:2020-07-08 04:28:41

标签: c++ matrix orthographic

最近,我一直在尝试扩大线性代数领域的知识。无论如何,在我的游戏引擎中,我当前正在创建一个正交摄影机。在这次学习冒险中,我选择实现自己的矩阵/向量库。因此,我以为一切正常,但是我意识到我的物体围绕它们的中心而不是相机的中心旋转。我试图修复它,但一切都搞砸了。我把它固定到了原来的水平。但是我不知道如何使对象绕摄像机而不是中心旋转。

Matrix4.h

#ifndef Matrix4_h
#define Matrix4_h

#include "Scalar.h"
#include "Vector4.h"

namespace Apollo
{

  class Matrix4
  {
  public:
    Vector4 RowX, RowY, RowZ, RowW;
    Scalar Elements[16];

    Matrix4(const Vector4 &r1, const Vector4 &r2, const Vector4 &r3, const Vector4 &r4)
        : RowX(r1), RowY(r2), RowZ(r3), RowW(r4) { SetArrayValues(); }

    Matrix4(Scalar scalar)
        : Matrix4({scalar, 0.0, 0.0, 0.0}, {0.0, scalar, 0.0, 0.0}, {0.0, 0.0, scalar, 0.0}, {0.0, 0.0, 0.0, scalar}) {}

    ///// Access Operations ////////////////////////////////////
    inline Vector4 &operator[](int index)
    {
      switch (index)
      {
      case 0:
        return RowX;
      case 1:
        return RowY;
      case 2:
        return RowZ;
      case 3:
        return RowW;
      default:
        return RowX;
      }
    }
    inline const Scalar *GetUniformPointer() const { return &(Elements[0]); }

    ///// Matrix Operations ////////////////////////////////////
    inline const Matrix4 Transpose() const
    {
      return Matrix4(Vector4(RowX.X, RowY.X, RowZ.X, RowW.X),
                     Vector4(RowX.Y, RowY.Y, RowZ.Y, RowW.Y),
                     Vector4(RowX.Z, RowY.Z, RowZ.Z, RowW.Z),
                     Vector4(RowX.W, RowY.W, RowZ.W, RowW.W));
    }

    ///// Math Operations //////////////////////////////////////
    inline Matrix4 Add(const Matrix4 &matrix) const { return Matrix4(RowX + matrix.RowX, RowY + matrix.RowY, RowZ + matrix.RowZ, RowW + matrix.RowW); }
    inline Matrix4 operator+(const Matrix4 &matrix) const { return Add(matrix); }

    inline Matrix4 Subtract(const Matrix4 &matrix) const { return Matrix4(RowX - matrix.RowX, RowY - matrix.RowY, RowZ - matrix.RowZ, RowW - matrix.RowW); }
    inline Matrix4 operator-(const Matrix4 &matrix) const { return Subtract(matrix); }

    inline Matrix4 Multiply(const Matrix4 &matrix) const
    {
      Matrix4 mat = matrix.Transpose();

      return Matrix4(Vector4(RowX * mat.RowX, RowX * mat.RowY, RowX * mat.RowZ, RowX * mat.RowW),
                     Vector4(RowY * mat.RowX, RowY * mat.RowY, RowY * mat.RowZ, RowY * mat.RowW),
                     Vector4(RowZ * mat.RowX, RowZ * mat.RowY, RowZ * mat.RowZ, RowZ * mat.RowW),
                     Vector4(RowW * mat.RowX, RowW * mat.RowY, RowW * mat.RowZ, RowW * mat.RowW));
    }
    inline Matrix4 operator*(const Matrix4 &matrix) const { return Multiply(matrix); }

    inline Matrix4 Scale(Scalar scalar) const { return Matrix4(RowX * scalar, RowY * scalar, RowZ * scalar, RowW * scalar); }
    inline Matrix4 operator*(Scalar scalar) const { return Scale(scalar); }

  private:
    void SetArrayValues()
    {
      Elements[0] = RowX.X; // Column 1
      Elements[1] = RowY.X;
      Elements[2] = RowZ.X;
      Elements[3] = RowW.X;

      Elements[4] = RowX.Y; // Column 2
      Elements[5] = RowY.Y;
      Elements[6] = RowZ.Y;
      Elements[7] = RowW.Y;

      Elements[8] = RowX.Z; // Column 3
      Elements[9] = RowY.Z;
      Elements[10] = RowZ.Z;
      Elements[11] = RowW.Z;

      Elements[12] = RowX.W; // Column 4
      Elements[13] = RowY.W;
      Elements[14] = RowZ.W;
      Elements[15] = RowW.W;
    }
  };

} // namespace Apollo

#endif /* end of include guard: Matrix4_h */

Vector4.h

#ifndef Vector4_h
#define Vector4_h

#include "Scalar.h"

namespace Apollo
{

  class Vector4
  {
  public:
    Scalar X, Y, Z, W;
    Scalar Elements[4];

    Vector4(float x, float y, float z, float w)
        : X(x), Y(y), Z(z), W(w) { SetArrayValues(); }

    Vector4(float x)
        : Vector4(x, x, x, x) {}

    ///// Access Operations ////////////////////////////////////
    inline Scalar &operator[](int index) { return Elements[index]; }
    inline const Scalar *GetUniformPointer() const { return &(Elements[0]); }

    ///// Math Operations //////////////////////////////////////
    inline const Vector4 Add(const Vector4 &vector) const { return Vector4(X + vector.X, Y + vector.Y, Z + vector.Z, W + vector.W); }
    inline const Vector4 operator+(const Vector4 &vector) const { return Add(vector); }

    inline const Vector4 Subtract(const Vector4 &vector) const { return Vector4(X - vector.X, Y - vector.Y, Z - vector.Z, W - vector.W); }
    inline const Vector4 operator-(const Vector4 &vector) const { return Subtract(vector); }

    inline const Scalar Multiply(const Vector4 &vector) const { return X * vector.X + Y * vector.Y + Z * vector.Z + W * vector.W; }
    inline const Scalar operator*(const Vector4 &vector) const { return Multiply(vector); }

    inline const Vector4 Scale(Scalar scalar) const { return Vector4(X * scalar, Y * scalar, Z * scalar, W * scalar); }
    inline const Vector4 operator*(Scalar scalar) const { return Scale(scalar); }

  private:
    inline void SetArrayValues()
    {
      Elements[0] = X;
      Elements[1] = Y;
      Elements[2] = Z;
      Elements[3] = W;
    }
  };

} // namespace Apollo

#endif /* end of include guard: Vector4_h */

Camera.cpp

#include "Camera.h"

#include <cmath>

namespace Apollo
{

  OrthographicCamera::OrthographicCamera(float left, float right, float bottom, float top)
      : m_Projection(1.0), m_View(1.0), m_ProjectionView(1.0), m_Position(0.0)
  {
    m_Projection = Matrix4(Vector4(2 / (right - left), 0, 0, -((right + left) / (right - left))),
                           Vector4(0, 2 / (top - bottom), 0, -((top + bottom) / (top - bottom))),
                           Vector4(0, 0, 1, 0),
                           Vector4(0, 0, 0, 1));

    CalculateProjectionView();
  }

  OrthographicCamera::~OrthographicCamera()
  {
  }

  void OrthographicCamera::SetBounds(float left, float right, float bottom, float top)
  {
    m_Projection = Matrix4(Vector4(2 / (right - left), 0, 0, -((right + left) / (right - left))),
                           Vector4(0, 2 / (top - bottom), 0, -((top + bottom) / (top - bottom))),
                           Vector4(0, 0, 1, 0),
                           Vector4(0, 0, 0, 1));

    CalculateProjectionView();
  }

  void OrthographicCamera::CalculateProjectionView()
  {
    Matrix4 translation = Matrix4(Vector4(1, 0, 0, 0),
                                  Vector4(0, 1, 0, 0),
                                  Vector4(0, 0, 1, 0),
                                  Vector4(0.5, 0.5, 0.5, 1));

    Matrix4 rotation = Matrix4(Vector4(cos(m_Rotation / 180 * M_PI), -sin(m_Rotation / 180 * M_PI), 0, 0),
                               Vector4(sin(m_Rotation / 180 * M_PI), cos(m_Rotation / 180 * M_PI), 0, 0),
                               Vector4(0, 0, 1, 0),
                               Vector4(0, 0, 0, 1));

    m_View = rotation * translation;
    m_ProjectionView = m_View * m_Projection;
  }

} // namespace Apollo

其他说明 标量只是float的typedef。每次相机更新时都会调用CalculateProjectionView。然后由渲染器将其上载到着色器。另外,可以在Github上获得完整的源代码,网址为https://github.com/James51332/Apollo,谢谢!

0 个答案:

没有答案