I have created a basic Math Library for an assignment, involving a Matrix3 and Matrix4 class, alongside some others. For OpenGL, to project a cube onto the screen, I have created a lookAt function and a Perspective function for the Projection * View * Model algorithm that yields a proper view for the scene. They are designed to be replacements for the corresponding functions in the GLM library/other libraries, since they have to interface with my Matrix classes in the future.
The lookAt function yields correct results, the Projection function is yielding close results, with some temporary manual tweaking to get it to provide the same results. However, when I multiply them together with the Projection * View (lookat) * Model (an Identity matrix), my library yield completely different results to GLM's (the MVP Matrix4). Mine match up with a graphics calculator, the GLM one doesn't. The GLM one actually displays the cube on the screen correctly, my one looks as if the cube has imploded. The Matrices themselves have minimal to no similarity.
GLM Library
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
glm::mat4 ProjectionGLM = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
glm::mat4 ViewGLM = glm::lookAt(
glm::vec3(4, 3, 3), // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 ModelGLM = glm::mat4(1.0f); // Changes for each model !
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = ProjectionGLM * ViewGLM * ModelGLM; // Remember, matrix multiplication is the other way around
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
Output Matricies (MVP Matrix4)
Custom Library
Vector3 vectornew1(4, 3, 3);
Vector3 vectornew2(0, 0, 0);
Vector3 vectornew3(0, 1, 0);
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
Matrix4 Projection = Matrix4::Perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
Projection = Matrix4::Transpose(Projection);
// Camera matrix
Matrix4 View = Matrix4::lookAt(
vectornew1, // Camera is at (4,3,3), in World Space
vectornew2, // and looks at the origin
vectornew3 // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
Matrix4 Model = Matrix4::Identity(); // Changes for each model !
// Our ModelViewProjection : multiplication of our 3 matrices
Matrix4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP.data[0][0]);
Custom Matrix4 Multiplication code:
temp.data[0][0] = this->data[0][0] * Other.data[0][0] + this->data[0][1] * Other.data[1][0] + this->data[0][2] * Other.data[2][0] + this->data[0][3] * Other.data[3][0];
temp.data[0][1] = this->data[0][0] * Other.data[0][1] + this->data[0][1] * Other.data[1][1] + this->data[0][2] * Other.data[2][1] + this->data[0][3] * Other.data[3][1];
temp.data[0][2] = this->data[0][0] * Other.data[0][2] + this->data[0][1] * Other.data[1][2] + this->data[0][2] * Other.data[2][2] + this->data[0][3] * Other.data[3][2];
temp.data[0][3] = this->data[0][0] * Other.data[0][3] + this->data[0][1] * Other.data[1][3] + this->data[0][2] * Other.data[2][3] + this->data[0][3] * Other.data[3][3];
temp.data[1][0] = this->data[1][0] * Other.data[0][0] + this->data[1][1] * Other.data[1][0] + this->data[1][2] * Other.data[2][0] + this->data[1][3] * Other.data[3][0];
temp.data[1][1] = this->data[1][0] * Other.data[0][1] + this->data[1][1] * Other.data[1][1] + this->data[1][2] * Other.data[2][1] + this->data[1][3] * Other.data[3][1];
temp.data[1][2] = this->data[1][0] * Other.data[0][2] + this->data[1][1] * Other.data[1][2] + this->data[1][2] * Other.data[2][2] + this->data[1][3] * Other.data[3][2];
temp.data[1][3] = this->data[1][0] * Other.data[0][3] + this->data[1][1] * Other.data[1][3] + this->data[1][2] * Other.data[2][3] + this->data[1][3] * Other.data[3][3];
temp.data[2][0] = this->data[2][0] * Other.data[0][0] + this->data[2][1] * Other.data[1][0] + this->data[2][2] * Other.data[2][0] + this->data[2][3] * Other.data[3][0];
temp.data[2][1] = this->data[2][0] * Other.data[0][1] + this->data[2][1] * Other.data[1][1] + this->data[2][2] * Other.data[2][1] + this->data[2][3] * Other.data[3][1];
temp.data[2][2] = this->data[2][0] * Other.data[0][2] + this->data[2][1] * Other.data[1][2] + this->data[2][2] * Other.data[2][2] + this->data[2][3] * Other.data[3][2];
temp.data[2][3] = this->data[2][0] * Other.data[0][3] + this->data[2][1] * Other.data[1][3] + this->data[2][2] * Other.data[2][3] + this->data[2][3] * Other.data[3][3];
temp.data[3][0] = this->data[3][0] * Other.data[0][0] + this->data[3][1] * Other.data[1][0] + this->data[3][2] * Other.data[2][0] + this->data[3][3] * Other.data[3][0];
temp.data[3][1] = this->data[3][0] * Other.data[0][1] + this->data[3][1] * Other.data[1][1] + this->data[3][2] * Other.data[2][1] + this->data[3][3] * Other.data[3][1];
temp.data[3][2] = this->data[3][0] * Other.data[0][2] + this->data[3][1] * Other.data[1][2] + this->data[3][2] * Other.data[2][2] + this->data[3][3] * Other.data[3][2];
temp.data[3][3] = this->data[3][0] * Other.data[0][3] + this->data[3][1] * Other.data[1][3] + this->data[3][2] * Other.data[2][3] + this->data[3][3] * Other.data[3][3];
What could GLM be doing with the Matrix multiplication to yield vastly different results? My method matched up with graphics calculators and yields correct results with identity matrices.