Our view matrix in essence defines the position and orientation of our camera in our 3D world. Well to be precise, it defines the inverse of that because we actually end up moving the entire 3D world to make our camera the center of this world.
Modifying the view matrix directly
Our first option therefor is to modify the view matrix directly. We could simply apply matrix operations onto this matrix to get the camera to move through space. We thus need to do the opposite of what we intent to do. Move the camera 10 units forward? Apply a translation to our matrix to move the world 10 units back. Rotate the camera 10 degrees to the left? We need to rotate our matrix 10 degrees to the right. Etc.
Align our view matrix with another object
Our second option is a nice one for certain types of games such as racing games. When we are sitting in the drivers seat of a car our camera is basically inside of that car. If we take the model matrix for our racing car, add a translation to move the center where the driver would be, and then inverse that matrix, we have a view matrix looking nicely out of the cars windshield. This is assuming the model of the car is properly oriented so we're not looking through the side window or the floor but that is easy to rectify.
The good old 'lookat' matrix
But the option we'll look at today is using a look-at calculation. This is a function that was available in the standard glu library and I've added to my math3d.h implementation.
The look-at calculation takes the location of your camera (or eye), the location you are looking at, and what you consider to be "up" and applies a proper view matrix.
Our changes are fairly simple. First we add our lookat and position variables to track our camera (for now globals to keep things easy):
// our camera (and view matrix) mat4 view; vec3 camera_eye = { 10.0, 20.0, 30.0 }; vec3 camera_lookat = { 0.0, 0.0, 0.0 };Next we initialize our view matrix using our lookup function in our engineLoad function:
// init our view matrix mat4Identity(&view); mat4LookAt(&view, &camera_eye, &camera_lookat, vec3Set(&upvector, 0.0, 1.0, 0.0));And that's it.
I've also removed the code that rotates the box and instead added this code to our engineUpdate function to allow basic interaction with the camera using the WASD keys:
vec3 avector, bvector, upvector; mat4 M; // handle our keys.... if (engineKeyPressedCallback(GLFW_KEY_A)) { // rotate position left // get our (reverse) looking direction vector vec3Copy(&avector, &camera_eye); vec3Sub(&avector, &camera_lookat); // rotate our looking direction vector around our up vector mat4Identity(&M); mat4Rotate(&M, 1.0, vec3Set(&bvector, view.m[0][1], view.m[1][1], view.m[2][1])); // and update our eye position accordingly mat4ApplyToVec3(&camera_eye, &avector, &M); vec3Add(&camera_eye, &camera_lookat); } else if (engineKeyPressedCallback(GLFW_KEY_D)) { // rotate position right // get our (reverse) looking direction vector vec3Copy(&avector, &camera_eye); vec3Sub(&avector, &camera_lookat); // rotate our looking direction vector around our up vector mat4Identity(&M); mat4Rotate(&M, -1.0, vec3Set(&bvector, view.m[0][1], view.m[1][1], view.m[2][1])); // and update our eye position accordingly mat4ApplyToVec3(&camera_eye, &avector, &M); vec3Add(&camera_eye, &camera_lookat); } else if (engineKeyPressedCallback(GLFW_KEY_W)) { // get our (reverse) looking direction vector vec3Copy(&avector, &camera_eye); vec3Sub(&avector, &camera_lookat); // rotate our looking direction vector around our right vector mat4Identity(&M); mat4Rotate(&M, 1.0, vec3Set(&bvector, view.m[0][0], view.m[1][0], view.m[2][0])); // and update our eye position accordingly mat4ApplyToVec3(&camera_eye, &avector, &M); vec3Add(&camera_eye, &camera_lookat); } else if (engineKeyPressedCallback(GLFW_KEY_S)) { // get our (reverse) looking direction vector vec3Copy(&avector, &camera_eye); vec3Sub(&avector, &camera_lookat); // rotate our looking direction vector around our right vector mat4Identity(&M); mat4Rotate(&M, -1.0, vec3Set(&bvector, view.m[0][0], view.m[1][0], view.m[2][0])); // and update our eye position accordingly mat4ApplyToVec3(&camera_eye, &avector, &M); vec3Add(&camera_eye, &camera_lookat); }; // update our view matrix mat4Identity(&view); mat4LookAt(&view, &camera_eye, &camera_lookat, vec3Set(&upvector, 0.0, 1.0, 0.0));Note that I am using my current view matrix to determine what my current up and right are as far as my camera is concerned and rotate around those vectors.
Well that was quick:)
Download the source here
What's next
Now that we have a camera that we can move around, it's time to start loading more complex objects instead of our hard coded cube...
No comments:
Post a Comment