# Computing a lookAt matrix by passing a vec3 to a camera object

I am following this tutorial on how to implement a first person camera. So far I was able to implement the entire (C++) class in TypeScript and it works as it is supposed to.

### Problem

What I was not able to implement is a system which takes the camera direction only and initially orients the camera based on it. In the tutorial the author does set the camera direction to (0.0, 0.0, -1.0) but it is instantly overwritten by calling _updateCameraVectors() in the constructor. So as I see it, passing the camera direction to the class will always be ignored. Before looking at the code please note:

• In the tutorial the author referes to a variable Front, which in my case is called cameraDirection
• In the tutorial only the view matrix is being calculated by the camera class. I am calculating the view-projection matrix.

### Code

Here are the most important parts:

The constructor initializes all the important stuff, but most importantly calls _updateCameraVectors().

constructor(gl: WebGL2RenderingContext, program: WebGLProgram, position: vec3, cameraDirection = vec3.fromValues(0.0, 0.0, -1.0),
yaw = -90.0, pitch = 0.0,
aspect = gl.canvas.clientWidth / gl.canvas.clientHeight, zNear = 1, zFar = 2000) {
this.gl = gl;
this._program = program;
this._aspect = aspect;
this._zNear = zNear;
this._zFar = zFar;
this._yaw = yaw;
this._pitch = pitch;
this._cameraPosition = position;

this._updateCameraVectors();
GLHelper.setUniformLocations(this.gl, this._unifroms, this._program);
}


In _updateCameraVectors() the camera direction is being recalculated based on yaw and pitch values. Then the cameraUp vector is calculated.

protected _updateCameraVectors(): void {
const front = vec3.create();

const right = vec3.create();
vec3.cross(right, this._cameraDirection, this._worldUp); // World up is always (0,1,0)
vec3.normalize(this._cameraRight, right);
const up = vec3.create();
vec3.normalize(this._cameraUp, up);
}


Based on a requestAnimationFrame-loop the _computeviewProjectionMatrix simply calculates a view-projection matrix which is later used for rendering.

private _computeviewProjectionMatrix(): mat4 {

this._aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight;

const cameraTarget = vec3.create();

const view = mat4.create();
mat4.lookAt(view, this._cameraPosition, cameraTarget, this._cameraUp);

const projectionMatrix = mat4.create();

const viewProjectionMatrix = mat4.create();
mat4.multiply(viewProjectionMatrix, projectionMatrix, view);

return viewProjectionMatrix;
}


The _handleMouseMovement function calls _updateCameraVectors() every time the pitch and yaw values are updated via mouse movement.

private _handleMouseMovement = (event: MouseEvent): void => {

if (this._firstMouseMove) {
this._firstMouseMove = false;
return;
}

let xOffset = event.movementX;
let yOffset = event.movementY;

xOffset *= this._sensitivity;
yOffset *= this._sensitivity;

this._yaw += xOffset;

if (!this._inverseY) {
this._pitch += yOffset;
} else {
this._pitch -= yOffset;
}

if (this._pitch > 89) {
this._pitch = 89;
}
if (this._pitch < -89) {
this._pitch = -89;
}

this._updateCameraVectors();
}


Last but not least there is a _moveCamera function which updates the camera position based on WASD input. I will post only a excerpt because it is selfexplonatory.

private _moveCamera(): void {
// INFO: 'W' - Move forward
if (this._keyMap === true) {
const factor = vec3.create();
}

// ...

}


### Question

How would I modify this class to initially "lookAt" a vec3 point passed to the constructor? Note I am not really asking for code only. Suggestion, ideas and any advice would be really helpful.

• Haven't read through the entire question yet but note that just a view direction is underspecified for the full camera matrix as it does not account for the roll (aka the "up direction" of the camera. Nov 19, 2018 at 0:13

If you have front vector given, you can compute angles:
pitch = MathHelper.radToDeg(Math.asin(front));