c++classgraphicsmatrix

What is the better Matrix4x4 class design c++ newbie


What would be better to use as a way to store matrix values?

float m1,m2,m3 ... ,m16

or

float[4][4].

I first tried float[16] but when im debugging and testing VS wont show what is inside of the array :( could implement a cout and try to read answer from a console test application.

Then i tried using float m1,m2,m3,etc under testing and debugging the values could be read in VS so it seemed easier to work with.

My question is because im fairly new with c++ what is the better design?

I find the float m1,m2 ... ,m16 easier to work with when debugging.

Would also love if someone could say from experience or has benchmark data what has better performance my gut says it shouldn't really matter because the matrix data should be laid out the same in memory right?

Edit: Some more info its a column major matrix. As far as i know i only need a 4x4 Matrix for the view transformation pipeline. So nothing bigger and so i have some constant values.

Busy writing a simple software renderer as a way to learn more c++ and get some more experiences and learn/improve my Linear algebra skills. Will probably only go to per fragment shading and some simple lighting models and so far that i have seen 4x4 matrix is the biggest i will need for rendering.

Edit2: Found out why i couldn't read the array data it was a float pointer i used and debugging menu only showed the pointer value i did discover a way to see the array value in watch where you have to do pointer, n where n = the element you want to see.

Everybody that answered thanks i will use the Vector4 m[4] answer for now.


Solution

  • You should consider a Vector4 with float [4] members, and a Matrix4 with Vector4 [4] members. With operator [], you have two useful classes, and maintain the ability to access elements with: [i][j] - the element data will be contiguous, provided you don't use virtual methods, on any platform I'm aware of.

    You can also benefit from SIMD data alignment requirements this way, e.g., in Vector4

    alignas (sizeof(float) * 4) float s_[4] = {}; // scalars
    
    float & operator [] (int i) { return s_[i]; }
    const float & operator [] (int i) const { return s_[i]; }
    

    and in Matrix4

    Vector4 m_[4]; // (row) vectors
    
    Vector4 & operator [] (int i) { return m_[i]; }
    const Vector4 & operator [] (int i) const { return m_[i]; }
    

    Feel free to decorate everything with constexpr and noexcept - though I'd only bother with the latter for constructors, and let everything else default.

    The data could be stored using std::array, but I don't see any benefit. It's just a noisy T[N] wrapper for such a specialized case. Technically, std::array could break contiguous float storage in Matrix4, but no sane implementation would do so.

    e.g., check storage requirements at compile-time:

    static_assert((sizeof(Matrix4) == sizeof(float) * 16) &&
        std::is_standard_layout_v<Matrix4>); // should be sufficient...
    

    Or, just use something like glm.