A Camera Class for OpenGL John McGuiness October 2006.

33
A Camera Class for A Camera Class for OpenGL OpenGL John McGuiness John McGuiness October 2006 October 2006

Transcript of A Camera Class for OpenGL John McGuiness October 2006.

Page 1: A Camera Class for OpenGL John McGuiness October 2006.

A Camera Class for A Camera Class for OpenGLOpenGL

John McGuinessJohn McGuiness

October 2006October 2006

Page 2: A Camera Class for OpenGL John McGuiness October 2006.

Necessity for a Camera ClassNecessity for a Camera Class

Existing available camera tool - gluLookAt()Existing available camera tool - gluLookAt() Basic utility which encapsulates a series of rotate and Basic utility which encapsulates a series of rotate and

translate commandstranslate commands Allows viewing along an arbitrary line of sight with an “Up” Allows viewing along an arbitrary line of sight with an “Up”

vector definedvector defined Need extra transformations to provide greater Need extra transformations to provide greater

flexibilityflexibility Need to modify “Forward” and “Along” vectors as Need to modify “Forward” and “Along” vectors as

well as “Up” to improve on gluLookAt()well as “Up” to improve on gluLookAt() Camera class may be built to encapsulate commands Camera class may be built to encapsulate commands

for greater ease of usefor greater ease of use

Page 3: A Camera Class for OpenGL John McGuiness October 2006.

““Up”, “Forward” and “Along”Up”, “Forward” and “Along” The three camera view vectors are defined as shown:The three camera view vectors are defined as shown:

Page 4: A Camera Class for OpenGL John McGuiness October 2006.

Proposed Camera FeaturesProposed Camera Features The camera class should:The camera class should:

Provide motion along the view vectors as well as arbitrary Provide motion along the view vectors as well as arbitrary axes (in some cases)axes (in some cases)

Provide rotation about the view vectors as well as arbitrary Provide rotation about the view vectors as well as arbitrary axes (in some cases)axes (in some cases)

Maintain the camera’s own orientation by keeping the Maintain the camera’s own orientation by keeping the viewing vectors orthogonal to each otherviewing vectors orthogonal to each other

Need to define motion for two possible types of Need to define motion for two possible types of camera:camera: Land camera – e.g. for road vehicles simulationLand camera – e.g. for road vehicles simulation Air camera – e.g. for flight simulationAir camera – e.g. for flight simulation

Page 5: A Camera Class for OpenGL John McGuiness October 2006.

Camera MotionCamera Motion WalkingWalking

This is motion along the This is motion along the ForwardForward vector (or Z-axis): vector (or Z-axis):

Page 6: A Camera Class for OpenGL John McGuiness October 2006.

Camera MotionCamera Motion StrafingStrafing

This is side to side motion on the This is side to side motion on the AlongAlong vector (or X-axis): vector (or X-axis):

Page 7: A Camera Class for OpenGL John McGuiness October 2006.

Camera MotionCamera Motion FlyingFlying

This is vertical motion on the This is vertical motion on the UpUp vector (or Y-axis): vector (or Y-axis):

Page 8: A Camera Class for OpenGL John McGuiness October 2006.

Camera RotationCamera Rotation PitchingPitching

This is rotation about the This is rotation about the AlongAlong vector – looking up and down vector – looking up and down

Page 9: A Camera Class for OpenGL John McGuiness October 2006.

Camera RotationCamera Rotation YawingYawing

This is rotation about the This is rotation about the UpUp vector – looking left and right vector – looking left and right

Page 10: A Camera Class for OpenGL John McGuiness October 2006.

Camera RotationCamera Rotation RollingRolling

This is rotation about the This is rotation about the ForwardForward vector – twisting left and right vector – twisting left and right

Page 11: A Camera Class for OpenGL John McGuiness October 2006.

Camera Class DeclarationCamera Class Declaration The camera class uses a type called Vector3D The camera class uses a type called Vector3D

which provides storage and common operations which provides storage and common operations (e.g. dot product, cross product etc.) for vectors(e.g. dot product, cross product etc.) for vectors

#include "Vector3D.h"#include "Vector3D.h"

The enumerated type defined below is used to The enumerated type defined below is used to distinguish between the two types of cameradistinguish between the two types of camera

enum CAM_TYPE { LAND_CAM, AIR_CAM };enum CAM_TYPE { LAND_CAM, AIR_CAM };

Page 12: A Camera Class for OpenGL John McGuiness October 2006.

Camera Class DeclarationCamera Class Declaration First, we need private variables for each view First, we need private variables for each view

vector as well as the camera type and current vector as well as the camera type and current position:position:

class Camera {class Camera {

private:private:

CAM_TYPE CameraType;CAM_TYPE CameraType;

Vector3D Position;Vector3D Position;

Vector3D Along;Vector3D Along;

Vector3D Up;Vector3D Up;

Vector3D Forward;Vector3D Forward;

......

Page 13: A Camera Class for OpenGL John McGuiness October 2006.

Camera Class DeclarationCamera Class Declaration Various construction/destruction, update and Various construction/destruction, update and

control functions are then declared publically:control functions are then declared publically:

class Camera {class Camera {

......

public:public:

Camera(CAM_TYPE ct = LAND_CAM); // Default: landCamera(CAM_TYPE ct = LAND_CAM); // Default: land

virtual ~Camera();virtual ~Camera();

void SetCameraType(CAM_TYPE ct);void SetCameraType(CAM_TYPE ct);

Vector3D GetPosition();Vector3D GetPosition();

void Reset();void Reset();

void Update();void Update();

......

Page 14: A Camera Class for OpenGL John McGuiness October 2006.

Camera Class DeclarationCamera Class Declaration Finally, the motion and rotation functions are declared.Finally, the motion and rotation functions are declared. The boolean array, The boolean array, Wall[4]Wall[4], is an extra feature which , is an extra feature which

modifies the motion of land cameras if they have to modifies the motion of land cameras if they have to slide against walls (as opposed to going through them)slide against walls (as opposed to going through them)class Camera {class Camera {

......

public:public:

......

void Pitch(GLfloat theta);void Pitch(GLfloat theta);

void Yaw(GLfloat theta);void Yaw(GLfloat theta);

void Roll(GLfloat theta);void Roll(GLfloat theta);

void Walk(GLfloat delta, bool Wall[4]);void Walk(GLfloat delta, bool Wall[4]);

void Strafe(GLfloat delta, bool Wall[4]);void Strafe(GLfloat delta, bool Wall[4]);

void Fly(GLfloat delta);void Fly(GLfloat delta);

};};

Page 15: A Camera Class for OpenGL John McGuiness October 2006.

Setup and Control FunctionsSetup and Control Functions

The code listing on the following two slides is The code listing on the following two slides is fairly self-explanatoryfairly self-explanatory

It comprises the basic constructor and destructor It comprises the basic constructor and destructor as well as a function to alter the camera typeas well as a function to alter the camera type

The Reset() function sets the camera position to The Reset() function sets the camera position to (0,0,0) and aligns the viewing axes with the local (0,0,0) and aligns the viewing axes with the local drawing coordinate systemdrawing coordinate system

Note that the default Forward vector points along Note that the default Forward vector points along the negative Z-axisthe negative Z-axis

Page 16: A Camera Class for OpenGL John McGuiness October 2006.

Setup and Control FunctionsSetup and Control Functions

Camera::Camera(CAM_TYPE ct) {Camera::Camera(CAM_TYPE ct) {

SetCameraType(ct);SetCameraType(ct);

Reset();Reset();

}}

Camera::~Camera() {Camera::~Camera() {

}}

void Camera::SetCameraType(CAM_TYPEct) {void Camera::SetCameraType(CAM_TYPEct) {

CameraType = ct;CameraType = ct;

}}

Page 17: A Camera Class for OpenGL John McGuiness October 2006.

Setup and Control FunctionsSetup and Control Functions

Vector3D Camera::GetPosition() {Vector3D Camera::GetPosition() {

return Position;return Position;

}}

void Camera::Reset() {void Camera::Reset() {

Position = Vector3D(0.0, 0.0, 0.0);Position = Vector3D(0.0, 0.0, 0.0);

Along = Vector3D(1.0, 0.0, 0.0);Along = Vector3D(1.0, 0.0, 0.0);

Up = Vector3D(0.0, 1.0, 0.0);Up = Vector3D(0.0, 1.0, 0.0);

Forward = Vector3D(0.0, 0.0, -1.0);Forward = Vector3D(0.0, 0.0, -1.0);

Update();Update();

}}

Page 18: A Camera Class for OpenGL John McGuiness October 2006.

Building the View MatrixBuilding the View Matrix The last function called by Reset() is probably the The last function called by Reset() is probably the

most importantmost important The Update() function applies all changes made to The Update() function applies all changes made to

the viewing axes and camera position, and updates the viewing axes and camera position, and updates the view in MODELVIEW modethe view in MODELVIEW mode

In actual fact, as with gluLookAt(), the perception of In actual fact, as with gluLookAt(), the perception of camera motion is achieved by moving the objects camera motion is achieved by moving the objects around the scene while keeping the camera at a around the scene while keeping the camera at a fixed positionfixed position

Instead of using translations and rotations, a view Instead of using translations and rotations, a view matrix may be built, meaning that just one OpenGL matrix may be built, meaning that just one OpenGL function call is needed – glLoadMatrix()function call is needed – glLoadMatrix()

Page 19: A Camera Class for OpenGL John McGuiness October 2006.

Building the View MatrixBuilding the View Matrix

First we obtain the camera virtual position First we obtain the camera virtual position coordinates using the dot product of pairs of the coordinates using the dot product of pairs of the view vectors:view vectors:

void Camera::Update() {void Camera::Update() {

GLfloat x = DotProduct(Along, Position);GLfloat x = DotProduct(Along, Position);

GLfloat y = DotProduct(Up, Position);GLfloat y = DotProduct(Up, Position);

GLfloat z = DotProduct(Forward, Position);GLfloat z = DotProduct(Forward, Position);

......

These will be used to translate the camera (or These will be used to translate the camera (or rather, the scene) to its correct positionrather, the scene) to its correct position

Page 20: A Camera Class for OpenGL John McGuiness October 2006.

Building the View MatrixBuilding the View Matrix The translation part of the view matrix is shown below:The translation part of the view matrix is shown below:

1 0 0 01 0 0 0

T =T = 0 1 0 00 1 0 0

0 0 1 00 0 1 0

––x –y z 1x –y z 1

Note that we must remember to make z positive, since Note that we must remember to make z positive, since for convenience we have taken “Forward” as meaning for convenience we have taken “Forward” as meaning the direction the direction intointo the screen which is opposite to the screen which is opposite to OpenGL convention (Z-axis is positive outwards)OpenGL convention (Z-axis is positive outwards)

Page 21: A Camera Class for OpenGL John McGuiness October 2006.

Building the View MatrixBuilding the View Matrix The rotation part of the view matrix is built from The rotation part of the view matrix is built from

the view vectors as shown:the view vectors as shown:

A.x U.x –F.xA.x U.x –F.x

R =R = A.y U.y –F.yA.y U.y –F.y

A.z U.z –F.zA.z U.z –F.z

Again, the Forward vector is reversedAgain, the Forward vector is reversed

Page 22: A Camera Class for OpenGL John McGuiness October 2006.

Building the View MatrixBuilding the View Matrix Combining these two matrices, we get:Combining these two matrices, we get:

1 0 0 01 0 0 0 A.x U.x –F.x A.x U.x –F.x00 A.x U.x –F.x A.x U.x –F.x00

V =V = 0 1 0 0 .0 1 0 0 . A.y U.y –F.y A.y U.y –F.y0 =0 = A.y U.y –F.y A.y U.y –F.y00

0 0 1 00 0 1 0 A.z U.z –F.z A.z U.z –F.z 00 A.z U.z – A.z U.z –F.zF.z 00

––x –y z 1x –y z 1 0 0 0 0 0 0 11 –x –y z 1 –x –y z 1

The code on the following slides shows the rest of The code on the following slides shows the rest of the implemented functionthe implemented function

Page 23: A Camera Class for OpenGL John McGuiness October 2006.

Building the View MatrixBuilding the View Matrixvoid Camera::Update() {void Camera::Update() {

......

Glfloat ViewMatrix[4][4];Glfloat ViewMatrix[4][4];

ViewMatrix[0][0] = Along.x;ViewMatrix[0][0] = Along.x;

ViewMatrix[0][1] = Up.x;ViewMatrix[0][1] = Up.x;

ViewMatrix[0][2] = -Forward.x;ViewMatrix[0][2] = -Forward.x;

ViewMatrix[0][3] = 0.0;ViewMatrix[0][3] = 0.0;

ViewMatrix[1][0] = Along.y;ViewMatrix[1][0] = Along.y;

ViewMatrix[1][1] = Up.y;ViewMatrix[1][1] = Up.y;

ViewMatrix[1][2] = -Forward.y;ViewMatrix[1][2] = -Forward.y;

ViewMatrix[1][3] = 0.0;ViewMatrix[1][3] = 0.0;

......

Page 24: A Camera Class for OpenGL John McGuiness October 2006.

Building the View MatrixBuilding the View Matrix......

ViewMatrix[2][0] = Along.z;ViewMatrix[2][0] = Along.z;

ViewMatrix[2][1] = Up.z;ViewMatrix[2][1] = Up.z;

ViewMatrix[2][2] = -Forward.z;ViewMatrix[2][2] = -Forward.z;

ViewMatrix[2][3] = 0.0;ViewMatrix[2][3] = 0.0;

ViewMatrix[3][0] = -x;ViewMatrix[3][0] = -x;

ViewMatrix[3][1] = -y;ViewMatrix[3][1] = -y;

ViewMatrix[3][2] = z;ViewMatrix[3][2] = z;

ViewMatrix[3][3] = 1.0;ViewMatrix[3][3] = 1.0;

glMatrixMode(GL_MODELVIEW);glMatrixMode(GL_MODELVIEW);

glLoadMatrixf((GLfloat *)&ViewMatrix);glLoadMatrixf((GLfloat *)&ViewMatrix);

}}

Page 25: A Camera Class for OpenGL John McGuiness October 2006.

Camera Rotation FunctionsCamera Rotation Functions

The Pitch(), Yaw() and Roll() functions change the direction of the The Pitch(), Yaw() and Roll() functions change the direction of the Forward, Along and Up vectors respectivelyForward, Along and Up vectors respectively

In each case, the rotation will result in the alteration of a second In each case, the rotation will result in the alteration of a second view vector, leaving one unchangedview vector, leaving one unchanged

The second modified vector is found by calculating the cross The second modified vector is found by calculating the cross product of the other two vectorsproduct of the other two vectors

This means that mutual orthognality is maintained for the three This means that mutual orthognality is maintained for the three vectorsvectors

Page 26: A Camera Class for OpenGL John McGuiness October 2006.

Camera Rotation FunctionsCamera Rotation Functions Looking at a yaw from above, we can see how to Looking at a yaw from above, we can see how to

calculate the new direction of the Along vector:calculate the new direction of the Along vector:

Page 27: A Camera Class for OpenGL John McGuiness October 2006.

Camera Rotation FunctionsCamera Rotation Functions

Thus, for the Yaw function definition, we have:Thus, for the Yaw function definition, we have:

void Camera::Yaw(GLfloat theta) {void Camera::Yaw(GLfloat theta) {

Along = Along * cos(theta * DEG2RAD)Along = Along * cos(theta * DEG2RAD)

+ Forward * sin(theta * DEG2RAD);+ Forward * sin(theta * DEG2RAD);

Along.Normalize();Along.Normalize();

Forward = CrossProduct(Along, Up) * -1.0;Forward = CrossProduct(Along, Up) * -1.0;

Update();Update();

}}

Pitch() and Roll() on the following slide look very Pitch() and Roll() on the following slide look very similarsimilar

Page 28: A Camera Class for OpenGL John McGuiness October 2006.

Camera Rotation FunctionsCamera Rotation Functionsvoid Camera::Pitch(GLfloat theta) {void Camera::Pitch(GLfloat theta) {

// Invert UP/DOWN for air cameras// Invert UP/DOWN for air cameras

if(CameraType == AIR_CAM) theta = -theta;if(CameraType == AIR_CAM) theta = -theta;

Forward = Forward * cos(theta * DEG2RAD)Forward = Forward * cos(theta * DEG2RAD)

+ Up * sin(theta * DEG2RAD);+ Up * sin(theta * DEG2RAD);

Forward.Normalize();Forward.Normalize();

Up = CrossProduct(Forward, Along) * -1.0;Up = CrossProduct(Forward, Along) * -1.0;

Update();Update();

}}

void Camera::Roll(GLfloat theta) {void Camera::Roll(GLfloat theta) {

if(CameraType == LAND_CAM) return; // Not for land camsif(CameraType == LAND_CAM) return; // Not for land cams

Up = Up * cos(theta * DEG2RAD)Up = Up * cos(theta * DEG2RAD)

- Along * sin(theta * DEG2RAD);- Along * sin(theta * DEG2RAD);

Up.Normalize();Up.Normalize();

Along = CrossProduct(Forward, Up);Along = CrossProduct(Forward, Up);

Update();Update();

}}

Page 29: A Camera Class for OpenGL John McGuiness October 2006.

Camera Motion FunctionsCamera Motion Functions Walk(), Strafe() and Fly() are a little easier to implementWalk(), Strafe() and Fly() are a little easier to implement In each case, all we have to do is add the correct scaled In each case, all we have to do is add the correct scaled

vector to the camera’s Position vector and updatevector to the camera’s Position vector and update As with rotation functions, motion functions work slightly As with rotation functions, motion functions work slightly

differently depending on the type of camera being useddifferently depending on the type of camera being used For example, when walking forward with a land camera, if For example, when walking forward with a land camera, if

the view has been pitched upwards, we do not want to the view has been pitched upwards, we do not want to move up the camera’s forward vector, but rather along a move up the camera’s forward vector, but rather along a modified vector with the Y componet set to 0 – this will modified vector with the Y componet set to 0 – this will achieve the effect of staying on the ground rather than achieve the effect of staying on the ground rather than taking off into the air.taking off into the air.

Page 30: A Camera Class for OpenGL John McGuiness October 2006.

Camera Rotation FunctionsCamera Rotation Functions The Walk function with wall handling also The Walk function with wall handling also

implemented:implemented:

void Camera::Walk(GLfloat delta, bool Wall[4]) {void Camera::Walk(GLfloat delta, bool Wall[4]) {

if(CameraType == LAND_CAM)if(CameraType == LAND_CAM)

Position -= Vector3D(Forward.x *Position -= Vector3D(Forward.x *

!(Wall[0] && Forward.x * delta > 0.0 ||!(Wall[0] && Forward.x * delta > 0.0 ||

Wall[1] && Forward.x * delta < 0.0),Wall[1] && Forward.x * delta < 0.0),

0.0, Forward.z *0.0, Forward.z *

!(Wall[2] && Forward.z * delta > 0.0 ||!(Wall[2] && Forward.z * delta > 0.0 ||

Wall[3] && Forward.z * delta < 0.0))Wall[3] && Forward.z * delta < 0.0))

* delta;* delta;

else Position -= Forward * delta; // Air cameraelse Position -= Forward * delta; // Air camera

Update();Update();

}}

Page 31: A Camera Class for OpenGL John McGuiness October 2006.

Camera Rotation FunctionsCamera Rotation Functions Similarly, the Strafe function is defined as follows:Similarly, the Strafe function is defined as follows:

void Camera::Strafe(GLfloat delta, bool Wall[4]) {void Camera::Strafe(GLfloat delta, bool Wall[4]) {

if(CameraType == LAND_CAM)if(CameraType == LAND_CAM)

Position -= Vector3D(Along.x *Position -= Vector3D(Along.x *

!(Wall[0] && Along.x * delta > 0.0 ||!(Wall[0] && Along.x * delta > 0.0 ||

Wall[1] && Along.x * delta < 0.0),Wall[1] && Along.x * delta < 0.0),

0.0, Along.z *0.0, Along.z *

!(Wall[2] && Along.z * delta > 0.0 ||!(Wall[2] && Along.z * delta > 0.0 ||

Wall[3] && Along.z * delta < 0.0))Wall[3] && Along.z * delta < 0.0))

* delta;* delta;

else Position += Along * delta; // Air cameraelse Position += Along * delta; // Air camera

Update();Update();

}}

Page 32: A Camera Class for OpenGL John McGuiness October 2006.

Camera Rotation FunctionsCamera Rotation Functions Finally, flying is, of course, only allowed for air Finally, flying is, of course, only allowed for air

cameras:cameras:

void Camera::Fly(GLfloat delta, bool Wall[4]) {void Camera::Fly(GLfloat delta, bool Wall[4]) {

// Don't allow for land cameras// Don't allow for land cameras

if(CameraType == LAND_CAM) return;if(CameraType == LAND_CAM) return;

Position += Up * delta;Position += Up * delta;

Update();Update();

}}

Although flying through walls has been allowed Although flying through walls has been allowed here, this would be implemented in the same here, this would be implemented in the same manner as the previous two functionsmanner as the previous two functions

Page 33: A Camera Class for OpenGL John McGuiness October 2006.

ReferencesReferences

Frank D. Luna, 2003, Frank D. Luna, 2003, Introduction to 3D Game Introduction to 3D Game Programming with DirectX 9.0Programming with DirectX 9.0, Wordware , Wordware Publishing, Inc.Publishing, Inc.

Silicon Graphics Inc., 1997, Silicon Graphics Inc., 1997, OpenGL Programming OpenGL Programming Guide, Chapter 3 – ViewingGuide, Chapter 3 – Viewing, Addison-Wesley , Addison-Wesley Publishing CompanyPublishing Company

Philipp Crocoll, The Advanced CodeColony Philipp Crocoll, The Advanced CodeColony Camera, Camera, http://http://www.codecolony.de/www.codecolony.de/