I'm Back! OpenGL

Back Again!

After forgetting about this blog for quite a while, I’ve decided to come back to it and write about my most recent project about OpenGL and 3D graphics, hopefully from now on the blogs will be much more regular. Enjoy reading!

What have I done so far?

Currently I’m following a guide on OpenGL and finished learning the basics, drawing 2D objects, 3D objects, types of transformations, camera movements etc. But instead of using the GLM (a maths library for OpenGL) I was challenged by my brother to make my own functions. I studied for a few days about matrices, vectors and transformations and jumped straight back into OpenGL. At first it was quite challenging trying get a grasp of making the functions but it slowly started getting easier and easier.

Current development

I’ve delved pretty far already but as I’m writing this i’ve finished making a function to be able to rotate my camera dynamically on it’s local axis. It took a few days after searching, being dissapointed and searching again. I finally found a solution! Short explanation for those who do not want to read it in-detail: Instead of GLM’s 4x4 matrix function which multiplied a 4x4 matrix by a 4x4 rotational matrix, I made some changes and edits and made a 3x3 rotation matrix and multiplied it by a 3 length vector. Long explanation: Okay, here we go. The original GLM mat4 (4x4 matrix) function has the prerequesites of a 4x4 matrix, an angle or rotation and a normal (in form of a vec3). GLM would normalize the vec3 (basically makes the vec3 have a length of 1 but still has its original proportions) and a template vector which would allow us to rotate on its local axis. The function would then assemble a 4x4 rotational matrix which looked like this:

template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotate(mat<4, 4, T, Q> const& m, T angle, vec<3, T, Q> const& v)
{
T const a = angle;
T const c = cos(a);
T const s = sin(a);

    	vec<3, T, Q> axis(normalize(v));
    	vec<3, T, Q> temp((T(1) - c) * axis);

    	mat<4, 4, T, Q> Rotate;
    	Rotate[0][0] = c + temp[0] * axis[0];
    	Rotate[0][1] = temp[0] * axis[1] + s * axis[2];
    	Rotate[0][2] = temp[0] * axis[2] - s * axis[1];

    	Rotate[1][0] = temp[1] * axis[0] - s * axis[2];
    	Rotate[1][1] = c + temp[1] * axis[1];
    	Rotate[1][2] = temp[1] * axis[2] + s * axis[0];

    	Rotate[2][0] = temp[2] * axis[0] + s * axis[1];
    	Rotate[2][1] = temp[2] * axis[1] - s * axis[0];
    	Rotate[2][2] = c + temp[2] * axis[2];

    	mat<4, 4, T, Q> Result;
    	Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2];
    	Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2];
    	Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2];
    	Result[3] = m[3];
    	return Result;
    }

As you can see it multiplies every element of the orignal matrix with the rotational matrix individually and returns a mat4. Meanwhile, my 3 length vector rotation function has the prerequesites of: a vec3 that we want to rotate, the angle of rotation & the normal (in form of a vec3). Similar to GLM I normalized the normal (sounds weird, I know) and made a template vector. Instead of making a mat4 I made a mat3 which is called a eulear function in contrast to GLM. But instead of multiplying each element of the vector by the rotational matrix I simply used cmath to do it for me. And voila.

(Source Code):

glm::vec3 rotate(glm::vec3 vector, float angle, glm::vec3 normal) {
//result vector
glm::vec3 result;

    	//finding axis we're gonna rotate on
    	glm::vec3 axis = roml::normalize(normal);
    	glm::vec3 temp = glm::vec3((1 - cos(angle)) * axis);

    	//brief explanation; The OpenGL 'rotate' function uses a quaternian way of calculating and outputting (which outputs a mat4 in this case). Meanwhile, this rotate uses a eular way of calculating and outputting which uses a mat3 and outputs a mat3 or a mat4.
    	glm::mat3 rotMat = glm::mat3(1.0f);
    	rotMat[0] = glm::vec3(cos(angle) + temp.x * axis.x, temp.x * axis.y + sin(angle) * axis.z, temp.x * axis.z - sin(angle) * axis.y);
    	rotMat[1] = glm::vec3(temp.y * axis.x - sin(angle) * axis.z, cos(angle) + temp.y * axis.y, temp.y * axis.z + sin(angle) * axis.x);
    	rotMat[2] = glm::vec3(temp.z * axis.x + sin(angle) * axis.y, temp.z * axis.y - sin(angle) * axis.x, cos(angle) + temp.z * axis.z);

    	result = rotMat * vector;
    	return result;
    }

The result: result

Changelog:

  • None, since this is my first post about OpenGL