Матрица 3х3 с мармеладом

Я застрял на проблеме в течение нескольких часов. Мне нужно преобразовать мои матрицы 4x4 (модель, вид, проекция) в матрицы 3x3 с вектором перевода. Мне нужно сделать это, потому что API, который я использую, не имеет класса матрицы 4x4 и полностью закрытого источника.

Странно то, что их функция LookAt утверждает, что она вообще не влияет на часть перевода матрицы. Где, как у матрицы 4x4, которую я использую для рендеринга, она есть (все отрисовывается на 100% правильно).

Может кто-нибудь взглянуть на мои функции преобразования и посмотреть, что я делаю не так? Спасибо

CIwFMat ConvertToMarmaladeFormat(Matrix4& Mat)
{
    CIwFMat M;

    M.m[0][0] = Mat[0][0];
    M.m[0][1] = Mat[0][1];
    M.m[0][2] = Mat[0][2];

    M.m[1][0] = Mat[1][0];
    M.m[1][1] = Mat[1][1];
    M.m[1][2] = Mat[1][2];

    M.m[2][0] = Mat[2][0];
    M.m[2][1] = Mat[2][1];
    M.m[2][2] = Mat[2][2];

    M.t = CIwFVec3(Mat[3][0], Mat[3][1], Mat[3][2]);

    return M;
}

Matrix4 ConvertFromMarmaladeFormat(CIwFMat& M)
{
    Matrix4 Mat;
    Mat.identity();

    Mat[0][0] = M.m[0][0];
    Mat[0][1] = M.m[0][1];
    Mat[0][2] = M.m[0][2];

    Mat[1][0] = M.m[1][0];
    Mat[1][1] = M.m[1][1];
    Mat[1][2] = M.m[1][2];

    Mat[2][0] = M.m[2][0];
    Mat[2][1] = M.m[2][1];
    Mat[2][2] = M.m[2][2];

    Mat[3][0] = M.t.x;
    Mat[3][1] = M.t.y;
    Mat[3][2] = M.t.z;

    return Mat;
}

class Matrix4
{
    friend Vector4 operator*(const Vector4 &lhs, const Matrix4 &rhs);
    friend Vector3 operator*(const Vector3 &lhs, const Matrix4 &rhs);
    friend Matrix4 operator*(float scalar, const Matrix4 &rhs);

public:
    static const Matrix4 IDENTITY;
    static Matrix4 createFromAxes(const Vector3 &x, const Vector3 &y, const Vector3 &z);
    static Matrix4 createFromAxesTransposed(const Vector3 &x, const Vector3 &y, const Vector3 &z);
    static Matrix4 createFromHeadPitchRoll(float headDegrees, float pitchDegrees, float rollDegrees);
    static Matrix4 createMirror(const Vector3 &planeNormal, const Vector3 &pointOnPlane);
    static Matrix4 createOrient(const Vector3 &from, const Vector3 &to);
    static Matrix4 createRotate(const Vector3 &axis, float degrees);
    static Matrix4 createScale(float sx, float sy, float sz);
    static Matrix4 createTranslate(float tx, float ty, float tz);

    Matrix4() {}
    Matrix4(float m11, float m12, float m13, float m14,
            float m21, float m22, float m23, float m24,
            float m31, float m32, float m33, float m34,
            float m41, float m42, float m43, float m44);
    ~Matrix4() {}

    float *operator[](int row);
    const float *operator[](int row) const;

    bool operator==(const Matrix4 &rhs) const;
    bool operator!=(const Matrix4 &rhs) const;

    Matrix4 &operator+=(const Matrix4 &rhs);
    Matrix4 &operator-=(const Matrix4 &rhs);
    Matrix4 &operator*=(const Matrix4 &rhs);
    Matrix4 &operator*=(float scalar);
    Matrix4 &operator/=(float scalar);

    Matrix4 operator+(const Matrix4 &rhs) const;
    Matrix4 operator-(const Matrix4 &rhs) const;
    Matrix4 operator*(const Matrix4 &rhs) const;
    Matrix4 operator*(float scalar) const;
    Matrix4 operator/(float scalar) const;

    float determinant() const;
    void fromAxes(const Vector3 &x, const Vector3 &y, const Vector3 &z);
    void fromAxesTransposed(const Vector3 &x, const Vector3 &y, const Vector3 &z);
    void fromHeadPitchRoll(float headDegrees, float pitchDegrees, float rollDegrees);
    void identity();
    Matrix4 inverse() const;
    void orient(const Vector3 &from, const Vector3 &to);
    void rotate(const Vector3 &axis, float degrees);
    void scale(float sx, float sy, float sz);
    void toAxes(Vector3 &x, Vector3 &y, Vector3 &z) const;
    void toAxesTransposed(Vector3 &x, Vector3 &y, Vector3 &z) const;
    void toHeadPitchRoll(float &headDegrees, float &pitchDegrees, float &rollDegrees) const;
    void translate(float tx, float ty, float tz);
    Matrix4 transpose() const;

private:
    float mtx[4][4];
};

class CIwFMat
{
public:
/**
 * 3x3 rotation matrix.
 */
    float   m[3][3];
/**
 * Trans vector.
 */
    CIwFVec3    t;

...

};

1 ответ

Решение

Ваше преобразование выглядит хорошо, но проверьте, что:

  1. Мармелад использует матричную нотацию строки-столбца и правую систему координат (имейте это в виду при ваших преобразованиях)

  2. мармеладная матрица "вид" на самом деле не матрица вида, это матрица положения и ориентации камеры. Чтобы получить реальную матрицу вида, нужно сделать что-то вроде этого:

    CIwFMat MarmaladeView = IwGxGetViewMatrix();
    CIwFMat view = (CIwFMat(CIwFMat::g_Identity, -MarmaladeView.GetTrans()) * MarmaladeView.GetTranspose()); // actually it's simple matrix inversion, but CIwFMat doesn't have Inverse() method
    // in some cases your should add axis-flip transform
    
  3. marmalade IwGxGetPerspectiveMatrix () возвращает неверную матрицу проекции в случае ортографической проекции (документация ничего не говорит об этом интересном факте)

  4. Функция LookAt() просто устанавливает вращающуюся часть матрицы в соответствии с направлением между двумя точками, поэтому перевод выполняется вручную

  5. проверить свои дальние / ближние самолеты

  6. Все матрицы MVP должны быть явно установлены

    IwGxSetViewMatrix(); // sets view matrix view - camera position
    IwGxSetModelMatrix(); // sets model matrix
    IwGxSetPerspMul(); // sets perspective projection in terms of distance to view plane
    IwGxSetFarZNearZ(); // sets clipping planes
    
Другие вопросы по тегам