OpenGL Math

So when learning OpenGL i decided that i would write my own Math classes instead of using a math library such as glm. I always enjoy trying to use as few library as possible and having to write it myself as a fun challenged. A lot of people ask me why i would bother, just use an existing library, for me, It’s just fun!

I have not implemented everything, only thing’s i need at the time of writing code for my OpenGL tech demos.

Vectors:

For vectors i needed to add two vectors, minus two vectors, do the usual cross and dot product.

Addition

vector3 vector3::operator+(vector3 &vec3)
{
	return vector3(x + vec3.x, y + vec3.y, z + vec3.z);
}

vector3 vector3::operator+=(vector3 &vec3)
{
	x += vec3.x;
	y += vec3.y;
	z += vec3.z;

	return *this;
}

Minus two vectors

vector3 vector3::operator-(vector3 &vec3)
{
	return vector3(x - vec3.x, y - vec3.y, z - vec3.z);
}

vector3 vector3::operator-=(vector3 &vec3)
{
	x -= vec3.x;
	y -= vec3.y;
	z -= vec3.z;

	return *this;
}

Dot Product

float vector3::dotProduct(vector3 &vec3)
{
	return x * vec3.x + y * vec3.y + z * vec3.z;
}

Cross Product

vector3 vector3::crossProduct(vector3 &vec3_One, vector3 &vec3_Two)
{
	return vector3(vec3_Two.y*vec3_One.z - vec3_Two.z*vec3_One.y, vec3_Two.z*vec3_One.x
		- vec3_Two.x*vec3_One.z, vec3_Two.x*vec3_One.y - vec3_Two.y*vec3_One.x);
}

Orthonormal Basis

void vector3::makeOrthinormalBasis(vector3 &a, vector3 &b, vector3 &c)
{
	a.normalise();
	c = a.vectorProduct(b);

	if (c.squareMagnitude() == 0.0f)
		return;

	c.normalise();
	b = c.vectorProduct(a);
}

Square Magnitude

float vector3::squareMagnitude()
{
	return (x*x + y*y + z*z);
}

Normalize

vector3 vector3::normalise()
{
	if (magnitude() > 0)
	{
		*this *= 1 / magnitude();
	}

	return *this;
}

Matrix:

In the Matrix 4×4 the data is treated like this:

|0,  1,   2,   3,|

|4,   5,   6,  7,|

|8,   9, 10, 11,|

|12, 13, 14, 15 |

The usual adding, subtracting, multiplying and assigning another matrix to another is straight forward.

Matrix4 Matrix4::operator+=(float value)
{
    data[0] += value;    data[1] += value;    data[2] += value;    data[3] += value;
    data[4] += value;    data[5] += value;    data[6] += value;    data[7] += value;
    data[8] += value;    data[9] += value;    data[10] += value;    data[11] += value;
    data[12] += value;    data[13] += value;    data[14] += value;    data[15] += value;

    return *this;
}
Matrix4 Matrix4::operator*=(Matrix4 &matrix)
{
    data[0] = data[0] * matrix.data[0] + data[1] * matrix.data[4] + data[2] * matrix.data[8] + data[3] * matrix.data[12];
    data[1] = data[0] * matrix.data[1] + data[1] * matrix.data[5] + data[2] * matrix.data[9] + data[3] * matrix.data[13];
    data[2] = data[0] * matrix.data[2] + data[1] * matrix.data[6] + data[2] * matrix.data[10] + data[3] * matrix.data[14];
    data[3] = data[0] * matrix.data[3] + data[1] * matrix.data[7] + data[2] * matrix.data[11] + data[3] * matrix.data[15];

    data[4] = data[4] * matrix.data[0] + data[5] * matrix.data[4] + data[6] * matrix.data[8] + data[7] * matrix.data[12];
    data[5] = data[4] * matrix.data[1] + data[5] * matrix.data[5] + data[6] * matrix.data[9] + data[7] * matrix.data[13];
    data[6] = data[4] * matrix.data[2] + data[5] * matrix.data[6] + data[6] * matrix.data[10] + data[7] * matrix.data[14];
    data[7] = data[4] * matrix.data[3] + data[5] * matrix.data[7] + data[6] * matrix.data[11] + data[7] * matrix.data[15];

    data[8] = data[8] * matrix.data[0] + data[9] * matrix.data[4] + data[10] * matrix.data[8] + data[11] * matrix.data[12];
    data[9] = data[8] * matrix.data[1] + data[9] * matrix.data[5] + data[10] * matrix.data[9] + data[11] * matrix.data[13];
    data[10] = data[8] * matrix.data[2] + data[9] * matrix.data[6] + data[10] * matrix.data[10] + data[11] * matrix.data[14];
    data[11] = data[8] * matrix.data[3] + data[9] * matrix.data[7] + data[10] * matrix.data[11] + data[11] * matrix.data[15];

    data[12] = data[12] * matrix.data[0] + data[13] * matrix.data[4] + data[14] * matrix.data[8] + data[15] * matrix.data[12];
    data[13] = data[12] * matrix.data[1] + data[13] * matrix.data[5] + data[14] * matrix.data[9] + data[15] * matrix.data[13];
    data[14] = data[12] * matrix.data[2] + data[13] * matrix.data[6] + data[14] * matrix.data[10] + data[15] * matrix.data[14];
    data[15] = data[12] * matrix.data[3] + data[13] * matrix.data[7] + data[14] * matrix.data[11] + data[15] * matrix.data[15];

    return *this;
}

scale_matrix_2

Matrix4 &Matrix4::scale(vector3 &scale)
{
	data[0] *= scale.x;
	data[5] *= scale.y;
	data[10] *= scale.z;

	return *this;
}

translation

Matrix4 &Matrix4::translate(vector3 &vec3)
{
	data[12] += vec3.x;
	data[13] += vec3.y;
	data[14] += vec3.z;

	return *this;
}
// Anti - clockwise rotation around a arbitrary axis.
// Where x^2 + y^2 + z^2 = 1;
Matrix4 &Matrix4::rotate(float angle, vector3 &vec3)
{
	// Normalize vector
	vec3.normalise();

	data[0] = cos(angle) + (vec3.x * vec3.x) * (1 - cos(angle));
	data[1] = (vec3.x * vec3.y) * (1 - cos(angle)) + (vec3.z * sin(angle));
	data[2] = (vec3.x * vec3.z) * (1 - cos(angle)) - (vec3.y * sin(angle));

	data[4] = (vec3.x * vec3.y) * (1 - cos(angle)) - (vec3.z * sin(angle));
	data[5] = cos(angle) + (vec3.y * vec3.y) * (1 - cos(angle));
	data[6] = (vec3.y * vec3.z) * (1 - cos(angle)) + (vec3.x * sin(angle));

	data[8] = (vec3.x * vec3.z) * (1 - cos(angle)) + (vec3.y * sin(angle));
	data[9] = (vec3.y * vec3.z) * (1 - cos(angle)) - (vec3.x * sin(angle));
	data[10] = cos(angle) + (vec3.z * vec3.z) * (1 - cos(angle));

	return *this;
}

xaxis_rotate

// Anti-clockwise rotation around the x axis.
Matrix4 &Matrix4::rotateX(float angle)
{
	data[5] = cos(angle);
	data[6] = sin(angle);
	data[9] = -sin(angle);
	data[10] = cos(angle);

	return *this;
}

yaxis_rotate

// Anti-clockwise rotation around the y axis.
Matrix4 &Matrix4::rotateY(float angle)
{
	data[0] = cos(angle);
	data[2] = -sin(angle);
	data[8] = sin(angle);
	data[10] = cos(angle);

	return *this;
}

zaxis_rotate

// Anti-clockwise rotation around the z axis.
Matrix4 &Matrix4::rotateZ(float angle)
{
	data[0] = cos(angle);
	data[1] = sin(angle);
	data[4] = -sin(angle);
	data[5] = cos(angle);

	return *this;
}
Matrix4 &Matrix4::setFrustrum(float l, float r, float b, float t, float n, float f)
{
	data[0] = (2 * n) / (r - l);
	data[5] = (2 * n) / (t - b);
	data[8] = (r + l) / (r - l);
	data[9] = (t + b) / (t - b);
	data[10] = -((f + n) / (f - n));
	data[11] = -1;
	data[14] = -((2 * n * f) / (f - n));
	data[15] = 0;	

	return *this;
}

Matrix4 &Matrix4::perspectiveProjection(float fov, float aspectRatio, float nearPlane, float farPlane)
{
	float tangent = tanf((fov * 0.5) * (PI / 180));
	float height = nearPlane * tangent;
	float width = height * aspectRatio;

	setFrustrum(-width, width, -height, height, nearPlane, farPlane);

	return *this;
}
//							Eye,			Center,				Up
Matrix4 &Matrix4::lookAt(vector3 &position, vector3 &target, vector3 &worldUp)
{
	// Camera Direction.
	vector3 zAxis = (position - target).normalise();
	// Positive right axis vector
	vector3 xAxis = (worldUp.normalise()).vectorProduct(zAxis).normalise();
	// Camera up vector.
	vector3 yAxis = zAxis.vectorProduct(xAxis);

	data[0] = xAxis.x;
	data[1] = yAxis.x;
	data[2] = zAxis.x;

	data[4] = xAxis.y;
	data[5] = yAxis.y;
	data[6] = zAxis.y;

	data[8] = xAxis.z;
	data[9] = yAxis.z;
	data[10] = zAxis.z;

	data[12] = -(xAxis.dotProduct(position));
	data[13] = -(yAxis.dotProduct(position));
	data[14] = -(zAxis.dotProduct(position));

	return *this;
}

Quaternions:

Quaternion Quaternion operator*(const Quaternion &quaternion)
{
        Quaternion result;

        result.w = w * quaternion.w - x * quaternion.x - y * quaternion.y - z * quaternion.z;
        result.x = w * quaternion.x + x * quaternion.w + z * quaternion.y - y * quaternion.z;
        result.y = w * quaternion.y + y * quaternion.w + x * quaternion.z - z * quaternion.x;
        result.z = w * quaternion.z + z * quaternion.w + y * quaternion.x - x * quaternion.y;

        return result;
}

Quaternion &Quaternion operator*=(const Quaternion &quaternion)
{
        *this = *this * quaternion;

        return *this;
}

Rotate X

void Quaternion::rotateX(float angle)
{
      w = cos(angle / 2);
      x = sin(angle / 2);
      y = 0;
      z = 0;
}

Rotate Y

void Quaternion::rotateY(float angle)
{
      w = cos(angle / 2);
      x = 0
      y = sin(angle / 2);
      z = 0;
}

Rotate Z

void Quaternion::rotateZ(float angle)
{
      w = cos(angle / 2);
      x = 0;
      y = 0;
      z = sin(angle / 2);
}

Rotate about arbitrary axis

void Quaternion::rotateAxis(float angle, vector3 axis)
{
       axis.normalize();

       w = cos(angle / 2);
       x = axis.x * sin(angle / 2);
       y = axis.y * sin(angle / 2);
       z = axis.z * sin(angle / 2);
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s