So, in the time since my last entry a couple of things have changed;
Firstly, after fighting with D3D and R2VB I decide that D3D really can bite me and I've retreated back to OpenGL land. Don't get me wrong, D3D is fine and all that and I could use it, however as R2VB was kinda central to my whole project not being able to get it to work was kinda a bit of a punch in the crotch.
So, this means I had to retool for OpenGL, however I hit a huge period of 'meh' so didn't do a great deal for a week, I know I know, bad Phantom! bad!
However, over the weekend I finally sat down and made a camera system, something I'd been meaning todo for a while now.
While thinking about this I decided to seperate the 'camera' and the 'view' system, the idea being that you can plug any view into a camera, update the view and then ask the camera to update it's matrix information.
This should be considered 'work in progress' however it does what I need for my project which is the main thing... I'm eyeing the matrix I've constructed as I'm not 100% convinced I've got that setup correctly but it appears to work for now :)
/************************************************************************//* IWorldCamera interface for cameras used to view the world *//* *//* Base interface class for the view system, all other classes must *//* inherit from this one. *//* *//* Base class from the Resurrection Engine Project *//************************************************************************/#ifndef RESURRECTIONENGINE_IWORLDCAMERA_HPP#define RESURRECTIONENGINE_IWORLDCAMERA_HPP#include "IWorldView.hpp"namespace Resurrection{ namespace CameraSystem { class IWorldCamera { public: virtual void setView(IWorldView *view) = 0; virtual void updateViewMatrix() = 0; virtual void setMatricies() = 0; protected: private: }; }}#endif
/************************************************************************//* IWorldView interface for views into the world *//* *//* Base interface class for the view system, all other classes must *//* inherit from this one. *//* *//* Base class from the Resurrection Engine Project *//************************************************************************/#ifndef RESURRECTIONENGINE_IWORLDVIEW_HPP#define RESURRECTIONENGINE_IWORLDVIEW_HPP// this header will need redirecting unless each project maintains the base// directory layout#include "../Maths/mtxlib.h"namespace Resurrection{ namespace CameraSystem { class IWorldView { public: virtual ~IWorldView() {}; virtual matrix44 getViewMatrix() = 0; protected: private: }; }}#endif
Those two header files form the interface for the camera and view system.
/************************************************************************//* PerspectiveWorldCamera; used for a standard perspective view of the *//* world. *//* *//* Inherits from IWorldCamera and requires a view to operate *//* *//* Class from the Resurrection Engine Project *//************************************************************************/#ifndef RESURRECTIONENGINE_PERSPECTIVEWORLDCAMERA_HPP#define RESURRECTIONENGINE_PERSPECTIVEWORLDCAMERA_HPP#include "IWorldCamera.hpp"#include "../Maths/mtxlib.h"namespace Resurrection{ namespace CameraSystem { class PerspectiveWorldCamera : public IWorldCamera { public: // Constructors PerspectiveWorldCamera(float l, float r, float b, float t, float n, float f); PerspectiveWorldCamera(float fieldOfViewY, float aspect, float n, float f); PerspectiveWorldCamera(matrix44 const& projMatrix); PerspectiveWorldCamera(float *projMatrix); ~PerspectiveWorldCamera(); PerspectiveWorldCamera(PerspectiveWorldCamera const& rhs); // View Setting method void setView(IWorldView *view); // Update local matrix cache of view matrix void updateViewMatrix(); // Sets these matrices as the current perspective and model-view matrices void setMatricies(); private: matrix44 projMatrix_; matrix44 mvMatrix_; IWorldView *view_; }; }}#endif
/************************************************************************//* OrthographicWorldCamera; used for an orthographic view of the world *//* *//* Inherits from IWorldCamera and requires a view to operate *//* *//* Class from the Resurrection Engine Project *//************************************************************************/#ifndef RESURRECTIONENGINE_ORTHOGRAPHICWORLDCAMERA_HPP#define RESURRECTIONENGINE_ORTHOGRAPHICWORLDCAMERA_HPP#include "IWorldCamera.hpp"#include "../Maths/mtxlib.h"namespace Resurrection{ namespace CameraSystem { class OrthographicWorldCamera : public IWorldCamera { public: OrthographicWorldCamera(float l, float r, float b, float t, float n, float f); OrthographicWorldCamera(matrix44 const& projMatrix); OrthographicWorldCamera(float *projMatrix); virtual ~OrthographicWorldCamera(); OrthographicWorldCamera(OrthographicWorldCamera const& rhs); void setView(IWorldView *view); // Updates local cache of view matrix void updateViewMatrix(); // Sets the various matrices to allow for rendering void setMatricies(); protected: private: matrix44 projMatrix_; matrix44 mvMatrix_; IWorldView *view_; }; }}#endif
Definitions for two basic camera models; persepctive and orthographic.
/************************************************************************//* PerspectiveWorldCamera; used for a standard perspective view of the *//* world. *//* *//* Inherits from IWorldCamera and requires a view to operate *//* *//* Class from the Resurrection Engine Project *//************************************************************************/#include "PerspectiveWorldCamera.hpp"#include "../Maths/mtxlib.h"#include "../Maths/Quaternion.hpp"// This is bad!// But as we lack a 'renderer' module to act as a // go between for GL stuffs it'll do for now#include namespace Resurrection{ namespace CameraSystem { PerspectiveWorldCamera::PerspectiveWorldCamera(float l, float r, float b, float t, float n, float f) { view_ = NULL; projMatrix_ = FrustumMatrix44(l,r,b,t,n,f); }; PerspectiveWorldCamera::PerspectiveWorldCamera(float fieldOfViewY, float aspect, float n, float f) { view_ = NULL; projMatrix_ = PerspectiveMatrix44(fieldOfViewY,aspect,n,f); }; PerspectiveWorldCamera::PerspectiveWorldCamera(matrix44 const& projMatrix) : projMatrix_(projMatrix) {view_ = NULL;}; PerspectiveWorldCamera::PerspectiveWorldCamera(float *projMatrix) : projMatrix_(projMatrix) {view_ = NULL;}; PerspectiveWorldCamera::~PerspectiveWorldCamera() {}; PerspectiveWorldCamera::PerspectiveWorldCamera(PerspectiveWorldCamera const& rhs) { projMatrix_ = rhs.projMatrix_; mvMatrix_ = rhs.mvMatrix_; }; void PerspectiveWorldCamera::setView(IWorldView *view) { view_ = view;}; // Updates local cache of view matrix void PerspectiveWorldCamera::updateViewMatrix() { if(view_) mvMatrix_ = view_->getViewMatrix(); }; // Sets the various matrices to allow for rendering void PerspectiveWorldCamera::setMatricies() { float m[16]; // hard coded to OpenGL glMatrixMode(GL_PROJECTION); //glLoadMatrixf(&projMatrix_.col[0].x); // set the matrix to our projection matrix projMatrix_.getMatrix(m); glLoadMatrixf(m); glMatrixMode(GL_MODELVIEW); //glLoadMatrixf(&mvMatrix_.col[0].x); // set the matrix to our model-view matrix mvMatrix_.getMatrix(m); glLoadMatrixf(m); }; }}
/************************************************************************//* OrthographicWorldCamera; used for an orthographic view of the world *//* *//* Inherits from IWorldCamera and requires a view to operate *//* *//* Class from the Resurrection Engine Project *//************************************************************************/#include "OrthographicWorldCamera.hpp"#include "../Maths/mtxlib.h"#include "../Maths/Quaternion.hpp"// This is bad!// But as we lack a 'renderer' module to act as a // go between for GL stuffs it'll do for now#include namespace Resurrection{ namespace CameraSystem { OrthographicWorldCamera::OrthographicWorldCamera(float l, float r, float b, float t, float n, float f) { view_ = NULL; projMatrix_ = OrthoMatrix44(l,r,b,t,n,f); }; OrthographicWorldCamera::OrthographicWorldCamera(matrix44 const& projMatrix) : projMatrix_(projMatrix) {view_ = NULL;}; OrthographicWorldCamera::OrthographicWorldCamera(float *projMatrix) : projMatrix_(projMatrix) {view_ = NULL;}; OrthographicWorldCamera::~OrthographicWorldCamera() {}; OrthographicWorldCamera::OrthographicWorldCamera(OrthographicWorldCamera const& rhs) { projMatrix_ = rhs.projMatrix_; mvMatrix_ = rhs.mvMatrix_; }; void OrthographicWorldCamera::setView(IWorldView *view) { view_ = view;}; // Updates local cache of view matrix void OrthographicWorldCamera::updateViewMatrix() { if(view_) mvMatrix_ = view_->getViewMatrix(); }; // Sets the various matrices to allow for rendering void OrthographicWorldCamera::setMatricies() { float m[16]; // hard coded to OpenGL glMatrixMode(GL_PROJECTION); //glLoadMatrixf(&projMatrix_.col[0].x); // set the matrix to our projection matrix projMatrix_.getMatrix(m); glLoadMatrixf(m); glMatrixMode(GL_MODELVIEW); //glLoadMatrixf(&mvMatrix_.col[0].x); // set the matrix to our model-view matrix mvMatrix_.getMatrix(m); glLoadMatrixf(m); }; }}
And the implimentations.
Finally we have the only working view, a targeted orbiting camera. You basically give it a distance, target and angle to look at it from and it will position the camera there for you. Kinda like gluLookAt() but with only the angle needed to be supplied.
(this one lacks the namespacing as I've just realised I've not pulled it into the TLM project, heh, opps...)
class PolarOrbitView : public IWorldView{public: PolarOrbitView(vector3 const &target, vector3 const &distance, float const angle) : target_(target), distance_(distance), angle_(angle) { }; ~PolarOrbitView() {}; PolarOrbitView(const PolarOrbitView &rhs) { distance_ = rhs.distance_; target_ = rhs.target_; angle_ = rhs.angle_; } void setDistance(vector3 const &distance) { distance_ = distance; }; void setAngle(float const angle) { angle_ = angle; }; void setTarget(vector3 const &target) { target_ = target; }; matrix44 getViewMatrix() { // Camera's virtual position vector4 position(-(cos(angle_) * distance_.x), -(distance_.y), -(sin(angle_)*distance_.z), 1.0f); vector3 forward = target_ - vector3(position.x, position.y, position.z); // Vector from our position to the target forward.normalize(); vector3 upVec(0.0f,1.0f,0.0f); vector3 side = CrossProduct(forward,upVec); side.normalize(); upVec = CrossProduct(side,forward); float m[] = { side.x, upVec.x, -forward.x, 0.0f, side.y, upVec.y, -forward.y, 0.0f, side.z, upVec.z, -forward.z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; matrix44 rotMatrix(m); // rotation matrix matrix44 transMatrix = TranslateMatrix44(-position.x, -position.y, -position.z); return rotMatrix*transMatrix; };protected:private: vector3 distance_; // How far we want to be from the target vector3 target_; // What we want to look at float angle_; // Angle of rotation};
I did take a stab at a spherical camera, however it wasn't behaving as I thought it would so I'll look into that when I have spare time.
The maths lib in use comes from Game Programming Gems. While a Quaternion header is included I'm pretty sure I don't use them as yet, the Decent style camera and the FPS camera will probably use them however.
Now, all I need todo is complete the rest of the project, which isn't that much of a problem as I've got alot of support code already and it only took me an hour or two to get back to practically where I was pre-D3D biting me.
Joy.
*chuckles*