Sign in to follow this  
OandO

CORRECT gluLookAt clone

Recommended Posts

OandO    1566

While searching for information on how gluLookAt works, I found out that a lot of the code floating around on the internet is based on incorrect assumptions about how the modelview matrix works, and I didn't find anything that produced the correct result. In case anyone else runs into this at any point, I've written a correct version, that produces an identical matrix to gluLookAt:

void flor_Cam_LookAt(mat4x4_t matrix, vec3_t eyePos, vec3_t lookAt, vec3_t up)
{
vec3_t side;
vec3_t forward;
vec3_t newUp;
double length;
 
flor_Maths_Vec3Normalise(up, up);
forward[0] = lookAt[0] - eyePos[0];
forward[1] = lookAt[1] - eyePos[1];
forward[2] = lookAt[2] - eyePos[2];
length = sqrt((forward[0]*forward[0])+(forward[1]*forward[1])+(forward[2]*forward[2]));
forward[0]/=length; // Saves on an additional sqrt performed by flor_Maths_Vec3Normalise()
forward[1]/=length;
forward[2]/=length;
flor_Maths_Vec3CrossProduct(forward, up, side);
flor_Maths_Vec3Normalise(side, side);
flor_Maths_Vec3CrossProduct(side, forward, newUp);
flor_Maths_Vec3Normalise(newUp, newUp);
 
matrix[0] = side[0];
matrix[4] = side[1];
matrix[8] = side[2];
matrix[1] = newUp[0];
matrix[5] = newUp[1];
matrix[9] = newUp[2];
matrix[2] = -forward[0];
matrix[6] = -forward[1];
matrix[10] = -forward[2];
matrix[3] = matrix[7] = matrix[11] = 0.0;
 
matrix[12] = 0.0;
matrix[13] = 0.0;
matrix[14] = 0.0;
matrix[15] = 1.0;
 
matrix[12]=matrix[0]*-eyePos[0]+matrix[4]*-eyePos[1]+matrix[8]*-eyePos[2]+matrix[12];
matrix[13]=matrix[1]*-eyePos[0]+matrix[5]*-eyePos[1]+matrix[9]*-eyePos[2]+matrix[13];
matrix[14]=matrix[2]*-eyePos[0]+matrix[6]*-eyePos[1]+matrix[10]*-eyePos[2]+matrix[14];
matrix[15]=matrix[3]*-eyePos[0]+matrix[7]*-eyePos[1]+matrix[11]*-eyePos[2]+matrix[15];
}

Matrices are column-major arrays, and vectors are just arrays too, hopefully it's reasonably easy to understand.

Edited by OandO

Share this post


Link to post
Share on other sites
cireNeikual    388

Here is some code from my engine. The two versions are inverses of each other, one intended for camera look at and the other for object look at.

Matrix4x4f Matrix4x4f::DirectionMatrix(const Vec3f &direction, const Vec3f &up)
{
	Vec3f tangent_0 = direction.Cross(up);

	tangent_0.NormalizeThis();

	Vec3f tangent_1(direction.Cross(tangent_0).Normalize());

	Matrix4x4f mat;

	mat.m_elements[0] = direction.x;
	mat.m_elements[1] = direction.y;
	mat.m_elements[2] = direction.z;
	mat.m_elements[3] = 0.0f;

	mat.m_elements[4] = tangent_1.x;
	mat.m_elements[5] = tangent_1.y;
	mat.m_elements[6] = tangent_1.z;
	mat.m_elements[7] = 0.0f;

	mat.m_elements[8] = tangent_0.x;
	mat.m_elements[9] = tangent_0.y;
	mat.m_elements[10] = tangent_0.z;
	mat.m_elements[11] = 0.0f;

	mat.m_elements[12] = 0.0f;
	mat.m_elements[13] = 0.0f;
	mat.m_elements[14] = 0.0f;
	mat.m_elements[15] = 1.0f;

	return mat;
}
Matrix4x4f Matrix4x4f::CameraDirectionMatrix(const Vec3f &direction, const Vec3f &up)
{
	Vec3f tangent_0 = direction.Cross(up);

	tangent_0.NormalizeThis();

	Vec3f tangent_1(tangent_0.Cross(direction).Normalize());

	Matrix4x4f mat;

	mat.m_elements[0] = tangent_0.x;
	mat.m_elements[4] = tangent_0.y;
	mat.m_elements[8] = tangent_0.z;
	mat.m_elements[12] = 0.0f;

	mat.m_elements[1] = tangent_1.x;
	mat.m_elements[5] = tangent_1.y;
	mat.m_elements[9] = tangent_1.z;
	mat.m_elements[13] = 0.0f;

	mat.m_elements[2] = -direction.x;
	mat.m_elements[6] = -direction.y;
	mat.m_elements[10] = -direction.z;
	mat.m_elements[14] = 0.0f;

	mat.m_elements[3] = 0.0f;
	mat.m_elements[7] = 0.0f;
	mat.m_elements[11] = 0.0f;
	mat.m_elements[15] = 1.0f;

	return mat;
}
Edited by CireNeikual

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this