[eigen] Help with LHS matrices for directx

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


Hi,
i've written 2 classes that use Eigen for matrix calculations 1 for column major order (opengl) and 1 for row major order (directx)... OpenGL works as expected but directx seems to be off. How do i get the Orthographic and Perspective matrices working for left hand side, row major ordering. Also i would be nice if you guys included a matrixstack like mine that could work out of the box with directx or opengl.


Thanks for helping,
Shomari
#ifndef GGRAPHICSMATRIXSTACK_H
#define GGRAPHICSMATRIXSTACK_H


#include "GGraphicsDefines.h"

#define MAX_MATRIX_STACKS 16

/* ===============================================================
radians = ( degrees * pi ) / 180;
degrees = ( radians * 180 ) / pi;


column major -----------------------------
rightx  upx     forwardx    positionx       X
righty  upy     forwardy    positiony       Y
rightz  upz     forwardz    positionz       Z
0       0       0           1               W
------------------------------------------


row major (double check)------------------
   X          Y           Z         W
rightx      righty      rightz      0
upx         upy         upz         0
forwardx    forwardy    forwardz    0
positionx   positiony   positionz   1
------------------------------------------



 =============================================================== */


class GGraphicsMatrixStack
{
    public:
        GGraphicsMatrixStack();
        GGraphicsMatrixStack(GGraphicsMatrixOrder order);
        GGraphicsMatrixOrder GetMatrixOrder() const;
        virtual void SetMode(GGraphicsMatrixMode mode);
        virtual void Push() = 0;
        virtual void Pop() = 0;
        virtual void PopAll(GGraphicsMatrixMode mode) = 0;
        virtual void LockMode() = 0;
        virtual void UnlockMode() = 0;
        virtual void LoadIdentity() = 0;
        virtual void LoadIdentity(GGraphicsMatrixMode mode) = 0;
        virtual void SetTransform(float* trans) = 0;
        virtual void SetTransform(GGraphicsMatrixMode mode, float* trans) = 0;
        virtual float* GetTransform(GGraphicsMatrixMode mode) = 0;
        virtual float* GetTransformModelView() = 0;
        virtual float* GetTransformProjectionViewModel() = 0;
        virtual void Scale(float x, float y, float z) = 0;
        virtual void Translate(float x, float y, float z) = 0;
        virtual void Rotate(float angle, float x, float y, float z) = 0;
        virtual float* GetTranspose(GGraphicsMatrixMode mode) = 0;
        virtual void Reset() = 0;
        uint8_t GetMaxStacks() const;
        virtual void LookAt(float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz) = 0;
        virtual void Perspective(float fovy, float aspect, float near, float far) = 0;
        virtual void Ortho(double left, double right, double bottom, double top, double near, double far) = 0;
        virtual ~GGraphicsMatrixStack();

    protected:
        GGraphicsMatrixOrder    m_order;
        GGraphicsMatrixMode     m_mode;
};

#endif // GGRAPHICSMATRIXSTACK_H
#include "GGraphicsMatrixStack.h"

GGraphicsMatrixStack::GGraphicsMatrixStack() :
    m_order(GGraphicsMatrixOrder::ROW_MAJOR),
    m_mode(GGraphicsMatrixMode::VIEW)
{
    //ctor
} //end function

GGraphicsMatrixStack::GGraphicsMatrixStack(GGraphicsMatrixOrder order) :
    m_order(order),
    m_mode(GGraphicsMatrixMode::VIEW)
{
    //ctor
} //end function

GGraphicsMatrixOrder GGraphicsMatrixStack::GetMatrixOrder() const
{
    return m_order;
} //end function

void GGraphicsMatrixStack::SetMode(GGraphicsMatrixMode mode)
{
    m_mode = mode;
} //end function

GGraphicsMatrixStack::~GGraphicsMatrixStack()
{
    //dtor
} //end function
#ifndef GGRAPHICSMATRIXSTACKEIGEN_H
#define GGRAPHICSMATRIXSTACKEIGEN_H

#include "GGraphicsDefines.h"
#include "GGraphicsMatrixStack.h"
#include <stack>
#include <Eigen/Geometry>
#include <pthread.h>

using namespace Eigen;

//https://eigen.tuxfamily.org/dox/group__TutorialGeometry.html
//https://eigen.tuxfamily.org/dox/group__TopicStlContainers.html
//https://eigen.tuxfamily.org/dox/group__TopicStructHavingEigenMembers.html

/* =================================== NOTES =========================================== *
 * This is a FULL HEADER IMPLEMENTATION since templates and .cpp files don't play nicely *
 * ===================================================================================== */


#ifndef M_PI
#define M_PI		3.14159265358979323846
#endif // M_PI


template <int Order>
class GGraphicsMatrixStackEigen : public GGraphicsMatrixStack
{
    public:
        GGraphicsMatrixStackEigen();
        void SetMode(GGraphicsMatrixMode mode);
        void Push();
        void Pop();
        void PopAll(GGraphicsMatrixMode mode);
        void LockMode();
        void UnlockMode();
        void LoadIdentity();
        void LoadIdentity(GGraphicsMatrixMode mode);
        void SetTransform(float* trans);
        void SetTransform(GGraphicsMatrixMode mode, float* trans);
        float* GetTransform(GGraphicsMatrixMode mode);
        float* GetTransformModelView();
        float* GetTransformProjectionViewModel();
        void Scale(float x, float y, float z);
        void Translate(float x, float y, float z);
        void Rotate(float angle, float x, float y, float z);
        float* GetTranspose(GGraphicsMatrixMode mode);
        void Reset();
        uint8_t GetMaxStacks() const;
        void LookAt(float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz);
        void Perspective(float fovy, float aspect, float near, float far);
        void Ortho(double left, double right, double bottom, double top, double near, double far);

        virtual ~GGraphicsMatrixStackEigen();
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW //required to prevent crash when allocating from within renderer class
    private:
        std::stack<Eigen::Matrix<float, 4, 4, Order, 4, 4> >    m_matrixstack[11];
        Eigen::Matrix<float, 4, 4, Order, 4, 4>                 m_current[11];
        pthread_mutex_t                                         m_mutex;

};


template <int Order>
GGraphicsMatrixStackEigen<Order>::GGraphicsMatrixStackEigen() :
    GGraphicsMatrixStack(static_cast<GGraphicsMatrixOrder>(Order))
{
    pthread_mutex_init(&m_mutex, NULL);
    Reset();
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::SetMode(GGraphicsMatrixMode mode)
{
    if (pthread_mutex_trylock(&m_mutex) == 0)
    {
        m_mode = mode;
        pthread_mutex_unlock(&m_mutex);
    }
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::Push() ///OK
{
    if (m_matrixstack[static_cast<uint8_t>(m_mode)].size() < MAX_MATRIX_STACKS-1)
        m_matrixstack[static_cast<uint8_t>(m_mode)].push(m_current[static_cast<uint8_t>(m_mode)]);
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::Pop() ///OK
{
    if (m_matrixstack[static_cast<uint8_t>(m_mode)].size() > 0)
    {
        m_current[static_cast<uint8_t>(m_mode)] = m_matrixstack[static_cast<uint8_t>(m_mode)].top();
        m_matrixstack[static_cast<uint8_t>(m_mode)].pop();
    }
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::PopAll(GGraphicsMatrixMode mode) ///OK
{
    while (m_matrixstack[static_cast<uint8_t>(mode)].size() > 0)
    {
        m_current[static_cast<uint8_t>(mode)] = m_matrixstack[static_cast<uint8_t>(mode)].top();
        m_matrixstack[static_cast<uint8_t>(mode)].pop();
    }
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::LoadIdentity() ///OK
{
    m_current[static_cast<uint8_t>(m_mode)].setIdentity();
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::LockMode()
{
    pthread_mutex_lock(&m_mutex);
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::UnlockMode()
{
    pthread_mutex_unlock(&m_mutex);
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::LoadIdentity(GGraphicsMatrixMode mode) ///OK
{
    m_current[static_cast<uint8_t>(mode)].setIdentity();
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::SetTransform(float* trans) ///OK
{
    Eigen::Map<Eigen::Matrix<float, 4, 4, Order, 4, 4> > mapped_buffer(trans);
    m_current[static_cast<uint8_t>(m_mode)] = mapped_buffer.matrix();
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::SetTransform(GGraphicsMatrixMode mode, float* trans) ///OK
{
    Eigen::Map<Eigen::Matrix<float, 4, 4, Order, 4, 4> > mapped_buffer(trans);
    m_current[static_cast<uint8_t>(mode)] = mapped_buffer.matrix();
} //end function

template <int Order>
float* GGraphicsMatrixStackEigen<Order>::GetTransform(GGraphicsMatrixMode mode) ///OK
{
    return m_current[static_cast<uint8_t>(mode)].data();
} //end function

template <int Order>
float* GGraphicsMatrixStackEigen<Order>::GetTransformModelView()
{
    Eigen::Matrix<float, 4, 4, Order, 4, 4> prod =
        (m_current[static_cast<uint8_t>(GGraphicsMatrixMode::VIEW)] *
         m_current[static_cast<uint8_t>(GGraphicsMatrixMode::MODEL)]);
    return prod.data();
} //end function

template <int Order>
float* GGraphicsMatrixStackEigen<Order>::GetTransformProjectionViewModel()
{
    Eigen::Matrix<float, 4, 4, Order, 4, 4> prod =
        (m_current[static_cast<uint8_t>(GGraphicsMatrixMode::PROJECTION)] *
         m_current[static_cast<uint8_t>(GGraphicsMatrixMode::VIEW)] *
         m_current[static_cast<uint8_t>(GGraphicsMatrixMode::MODEL)]);
    return prod.data();
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::Scale(float x, float y, float z) ///OK
{
    Eigen::Transform<float, 3, Eigen::Affine, Order> scale(Eigen::Scaling(x, y, z));
    m_current[static_cast<uint8_t>(m_mode)] *= scale.matrix();
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::Translate(float x, float y, float z) ///OK
{
    Eigen::Transform<float, 3, Eigen::Affine, Order> trans(Eigen::Translation3f(x, y, z));
    m_current[static_cast<uint8_t>(m_mode)] *= trans.matrix();
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::Rotate(float angle, float x, float y, float z) ///OK
{
    float radians = ( angle * M_PI ) /180.f;
    Eigen::Transform<float, 3, Eigen::Affine, Order> trans(Eigen::AngleAxisf(radians, Eigen::Vector3f(x, y, z)));
    m_current[static_cast<uint8_t>(m_mode)] *= trans.matrix();
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::Reset() ///OK
{
    for (int i = 0; i < 11; i++)
        while(m_matrixstack[i].size())
            m_matrixstack[i].pop();

    for (int i = 0; i < 11; i++)
        m_current[i].setIdentity();
} //end function

template <int Order>
uint8_t GGraphicsMatrixStackEigen<Order>::GetMaxStacks() const ///OK
{
    return MAX_MATRIX_STACKS;
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::Ortho(double left, double right, double bottom, double top, double nearval, double farval) ///OK
{
    Eigen::Matrix<float, 4, 4, Order, 4, 4>& M = m_current[static_cast<uint8_t>(m_mode)];
    //if (Order == 0)
    //{
        ///Column Major Style OK OpenGL
        /*column major -----------------------------
        rightx  upx     forwardx    positionx       X
        righty  upy     forwardy    positiony       Y
        rightz  upz     forwardz    positionz       Z
        0       0       0           1               W
        ------------------------------------------  */

        M(0,0) = 2.0F / (right-left);           //rightx
        M(0,1) = 0.0F;                          //upx
        M(0,2) = 0.0F;                          //forwardx
        M(0,3) = -(right+left) / (right-left);  //positionx

        M(1,0) = 0.0F;                          //righty
        M(1,1) = 2.0F / (top-bottom);           //upy
        M(1,2) = 0.0F;                          //forwardy
        M(1,3) = -(top+bottom) / (top-bottom);  //positiony

        M(2,0) = 0.0F;                          //rightz
        M(2,1) = 0.0F;                          //upz
        M(2,2) = -2.0F / (farval-nearval);      //forwardz
        M(2,3) = -(farval+nearval) / (farval-nearval);  //positionz

        M(3,0) = 0.0F; //W
        M(3,1) = 0.0F; //W
        M(3,2) = 0.0F; //W
    /*} else
    {
        ///Row Major style
        /*row major (double check)------------------
           X          Y           Z         W
        rightx      righty      rightz      0
        upx         upy         upz         0
        forwardx    forwardy    forwardz    0
        positionx   positiony   positionz   1
        ------------------------------------------ */

        /*M(0,0) = 2.0f / (right-left);           //rightx OK
        M(0,1) = 0.0f;                          //righty OK
        M(0,2) = 0.0f;                          //rightz OK
        M(0,3) = 0.0f;                          //(0) W /// -(right+left) / (right-left);

        M(1,0) = 0.0f;                          //upx
        M(1,1) = 2.0f / (top-bottom);           //upy
        M(1,2) = 0.0f;                          //upz
        M(1,3) = 0.f;  //(0) W

        M(2,0) = 0.0f;                                  //forwardx
        M(2,1) = 0.0F;                                  //forwardy
        M(2,2) = -2.0F / (farval-nearval);              //forwardz
        M(2,3) = 0;  //(0) W

        M(3,0) = 0.0F;                                  //positionx
        M(3,1) =  -(top+bottom) / (top-bottom);         //positiony OK
        M(3,2) = -(farval+nearval) / (farval-nearval);  //positionz OK
    } */
} //end function

template <int Order>
float* GGraphicsMatrixStackEigen<Order>::GetTranspose(GGraphicsMatrixMode mode) ///OK
{
    return m_current[static_cast<uint8_t>(mode)].transpose().data();
} //end function

///------------- ensure these 2 match matrix ordering -----------------------
template <int Order>
void GGraphicsMatrixStackEigen<Order>::LookAt(float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz)
{
    Eigen::Matrix<float, 4, 4, Order, 4, 4> M;
    Eigen::Vector3f position(eyex, eyey, eyez);
    Eigen::Vector3f target(centerx, centery, centerz);
    Eigen::Vector3f up(upx, upy, upz);
    Eigen::Matrix3f R;
    R.col(2) = (position - target).normalized();
    R.col(0) = up.cross(R.col(2)).normalized();
    R.col(1) = R.col(2).cross(R.col(0));

    M.setIdentity();
    M.topLeftCorner(3,3) = R.transpose();
    M.topRightCorner(3,1) = -R.transpose() * position;
    M(3,3) = 1.0f;
    m_current[static_cast<uint8_t>(m_mode)] *= M;
} //end function

template <int Order>
void GGraphicsMatrixStackEigen<Order>::Perspective(float fovy, float aspect, float nearval, float farval)
{
    #ifdef MAD_DEBUG
    assert(aspect > 0);
    assert(farval > nearval);
    #else
    if (aspect <= 0)
        return;
    if (farval > nearval)
        return;
    #endif // MAD_DEBUG

    Eigen::Matrix<float, 4, 4, Order, 4, 4>& M = m_current[static_cast<uint8_t>(m_mode)];
    M = Matrix4f::Zero();

    if (Order == 0)
    {
        double radians = (fovy * M_PI) / 180.f;
        double tanHalfFovy = tan(radians / 2.0);

        //column major
        M(0,0) = 1.0 / (aspect * tanHalfFovy); //rightx
        M(1,1) = 1.0 / (tanHalfFovy); //upy
        M(2,2) = - (farval + nearval) / (farval - nearval); //forwardz
        M(3,2) = - 1.0f;
        M(2,3) = - (2.0f * farval * nearval) / (farval - nearval); //positionz
    } else
    {
        float w = (float)1/tan(fovy*0.5);  // 1/tan(x) == cot(x)
        //float h = (float)1/tan(fov_vert*0.5);   // 1/tan(x) == cot(x)
        float Q = farval/(farval - nearval);

        //row major
        M(0, 0) = w;
        M(1, 1) = w;
        M(2, 2) = Q;
        M(3, 2) = -Q*nearval;
        M(2, 3) = 1;
    }
} //end function
///------------- ensure these 2 match matrix ordering -----------------------

template <int Order>
GGraphicsMatrixStackEigen<Order>::~GGraphicsMatrixStackEigen()
{
    //dtor
} //end function

#endif // GGRAPHICSMATRIXSTACKEIGEN_H


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/