2
votes

I have a 4x4 matrix class that holds the values as 2d float array : float mat[4][4]; and I overloaded the [] operator

inline float *Matrix4::operator[](int row) { return mat[row]; }

and I have an uniform mat4 in my shader (uniform mat4 Bones[64];) which i will upload my data onto. And I hold the bones as a Matrix4 pointer (Matrix4 *finalBones) which is a matrix array, containing numJoints elements. and this is what i use to upload the data :

glUniformMatrix4fv(shader.getLocation("Bones"),numJoints,false,finalBones[0][0]);

I am totally unsure about what is going to happen, so i need to ask that if this will work or i need to extract everything into 16*numJoints sized float arrays which seems to be expensive for each tick.

edit this is what i have done which seems really expensive for each draw operation

void MD5Loader::uploadToGPU()
{
float* finalmat=new float[16*numJoints];
for (int i=0; i < numJoints; i++)
    for (int j=0; j < 4; j++)
        for(int k=0; k < 4; k++)
            finalmat[16*i + j*4 + k] = finalBones[i][j][k];


glUniformMatrix4fv(shader.getLocation("Bones"),numJoints,false,finalmat);

delete[] finalmat;
}
2

2 Answers

5
votes

It depends on two things. Assuming your compiler is C++03, (and you care about standards compliance), then your Matrix class must be a POD type. It must, in particular, have no constructors. C++11 relaxes these rules significantly.

The other thing is that your matrix appears to be row-major. I say this because your operator[] seems to think that your 2D array is row-major. The first coordinate is the row rather than the column, so it's row-major storage order.

If you're going to give OpenGL row-major matrices, you need to tell it that they are row-major:

glUniformMatrix4fv(shader.getLocation("Bones"), numJoints, GL_TRUE, finalBones[0][0]);

1
votes

With C++11, a class with standard layout can be cast to a pointer, addressing its first member, and back again. With a sizeof check, you then have a guarantee of contiguous matrix data:

#include <type_traits>

static_assert((sizeof(Matrix4) == (sizeof(GLfloat) * 16)) &&
              (std::is_standard_layout<Matrix4>::value),
              "Matrix4 does not satisfy contiguous storage requirements");

Trivial (or POD) layouts are just too restrictive once you have non-trivial constructors, etc. Your post suggests you will need to set the transpose parameter to GL_TRUE.