So much clean up for cameras

This commit is contained in:
Eryn Wells 2014-08-09 11:26:17 -07:00
parent d10d219eb3
commit 9645a09a6c
3 changed files with 255 additions and 164 deletions

View file

@ -3,29 +3,45 @@
* Eryn Wells <eryn@erynwells.me> * Eryn Wells <eryn@erynwells.me>
*/ */
#include "camera.h" #include "camera.hh"
#include "log.hh" #include "log.hh"
#define LOG_NAME "camera" #define LOG_NAME "camera"
#include "logModule.hh" #include "logModule.hh"
using charles::basics::Ray;
using charles::basics::Vector4;
namespace charles {
#pragma mark - Generic Camera #pragma mark - Generic Camera
/*
* charles::Camera::Camera --
*/
Camera::Camera() Camera::Camera()
: mDirection(Vector3::Z), : mDirection(0, 0, 1),
mRight(1.33, 0, 0), mRight(1.33, 0, 0),
mUp(Vector3::Y) mUp(0, 1, 0)
{ } { }
Camera::Camera(const Camera& other) /*
: mDirection(other.mDirection), * charles::Camera::Camera --
mRight(other.mRight), */
mUp(other.mUp) Camera::Camera(const Camera& rhs)
: mOrigin(rhs.mOrigin),
mDirection(rhs.mDirection),
mRight(rhs.mRight),
mUp(rhs.mUp)
{ } { }
/*
* charles::Camera::~Camera --
*/
Camera::~Camera() Camera::~Camera()
{ } { }
@ -33,7 +49,17 @@ Camera::~Camera()
/* /*
* Camera::GetOrigin -- * Camera::GetOrigin --
*/ */
const Vector3& Vector4&
Camera::GetOrigin()
{
return mOrigin;
}
/*
* Camera::GetOrigin --
*/
const Vector4&
Camera::GetOrigin() Camera::GetOrigin()
const const
{ {
@ -45,27 +71,57 @@ Camera::GetOrigin()
* Camera::SetOrigin -- * Camera::SetOrigin --
*/ */
void void
Camera::SetOrigin(const Vector3 &origin) Camera::SetOrigin(const Vector4& origin)
{ {
mOrigin = origin; mOrigin = origin;
} }
const Vector3& /*
Camera::get_direction() * Camera::GetDirection --
*/
Vector4&
Camera::GetDirection()
{
return mDirection;
}
/*
* Camera::GetDirection --
*/
const Vector4&
Camera::GetDirection()
const const
{ {
return mDirection; return mDirection;
} }
/*
* Camera::SetDirection --
*/
void void
Camera::set_direction(const Vector3 &direction) Camera::SetDirection(const Vector4& direction)
{ {
mDirection = direction; mDirection = direction;
} }
const Vector3& /*
* Camera::GetRight --
*/
Vector4&
Camera::GetRight()
{
return mRight;
}
/*
* Camera::GetRight --
*/
const Vector4&
Camera::GetRight() Camera::GetRight()
const const
{ {
@ -73,14 +129,30 @@ Camera::GetRight()
} }
/*
* Camera::SetRight --
*/
void void
Camera::SetRight(const Vector3& right) Camera::SetRight(const Vector4& right)
{ {
mRight = right; mRight = right;
} }
const Vector3& /*
* Camera::GetUp --
*/
Vector4&
Camera::GetUp()
{
return mUp;
}
/*
* Camera::GetUp --
*/
const Vector4&
Camera::GetUp() Camera::GetUp()
const const
{ {
@ -88,13 +160,19 @@ Camera::GetUp()
} }
/*
* Camera::SetUp --
*/
void void
Camera::SetUp(const Vector3& up) Camera::SetUp(const Vector4& up)
{ {
mUp = up; mUp = up;
} }
/*
* Camera::IsLeftHanded --
*/
bool bool
Camera::IsLeftHanded() Camera::IsLeftHanded()
const const
@ -110,24 +188,27 @@ Camera::IsLeftHanded()
* than 0, the vector is pointing left of the up-direction plane and the * than 0, the vector is pointing left of the up-direction plane and the
* coordinate system is left-handed. * coordinate system is left-handed.
*/ */
return mUp.cross(mDirection).dot(mRight) < 0.0; return mUp.Cross(mDirection).Dot(mRight) < 0.0;
} }
/*
* Camera::LookAt --
*/
void void
Camera::LookAt(const Vector3& pt) Camera::LookAt(const Vector4& p)
{ {
/* /*
* Precalulate these in order to preserve the aspect ratio and orientation * Precalulate these in order to preserve the aspect ratio and orientation
* of the camera across the LookAt operation. * of the camera across the LookAt operation.
*/ */
const Double directionLength = mDirection.length(); const Double directionLength = mDirection.Length();
const Double rightLength = mRight.length(); const Double rightLength = mRight.Length();
const Double upLength = mUp.length(); const Double upLength = mUp.Length();
const bool isLeftHanded = IsLeftHanded(); const bool isLeftHanded = IsLeftHanded();
/* Orient the camera towards the point. */ /* Orient the camera towards the point. */
mDirection = (pt - mOrigin).normalize(); mDirection = basics::Normalized(p - mOrigin);
/* TODO: Check for zero length direction vector. */ /* TODO: Check for zero length direction vector. */
/* /*
@ -141,8 +222,8 @@ Camera::LookAt(const Vector3& pt)
* specifies the vector along which LookAt pans and tilts the camera. It * specifies the vector along which LookAt pans and tilts the camera. It
* might be worth looking into, at some point. * might be worth looking into, at some point.
*/ */
mRight = Vector3::Y.cross(mDirection).normalize(); mRight = basics::Normalized(Vector4(0, 1, 0).Cross(mDirection));
mUp = mDirection.cross(mRight); mUp = mDirection.Cross(mRight);
/* /*
* Now, fix up the direction, right, and up vectors so that their magnitudes * Now, fix up the direction, right, and up vectors so that their magnitudes
@ -152,10 +233,13 @@ Camera::LookAt(const Vector3& pt)
mRight *= isLeftHanded ? rightLength : -rightLength; mRight *= isLeftHanded ? rightLength : -rightLength;
mUp *= upLength; mUp *= upLength;
LOG_DEBUG << "Camera is looking at " << pt; LOG_DEBUG << "Camera is looking at " << p;
} }
/*
* charles::Camera::GetTypeString --
*/
std::string std::string
Camera::GetTypeString() Camera::GetTypeString()
const const
@ -164,6 +248,9 @@ Camera::GetTypeString()
} }
/*
* charles::Camera::WriteType --
*/
void void
Camera::WriteType(std::ostream& ost) Camera::WriteType(std::ostream& ost)
const const
@ -184,7 +271,7 @@ PerspectiveCamera::PerspectiveCamera(const Camera& other)
Ray Ray
PerspectiveCamera::compute_primary_ray(const int x, PerspectiveCamera::PrimaryRay(const int x,
const int width, const int width,
const int y, const int y,
const int height) const int height)
@ -194,13 +281,13 @@ PerspectiveCamera::compute_primary_ray(const int x,
* Center x and y in the pixel and convert them to be coordinates between * Center x and y in the pixel and convert them to be coordinates between
* -0.5 and 0.5. * -0.5 and 0.5.
*/ */
double x0 = (x + 0.5) / width - 0.5; Double x0 = (x + 0.5) / width - 0.5;
double y0 = ((height - 1.0) - (y - 0.5)) / height - 0.5; Double y0 = ((height - 1.0) - (y - 0.5)) / height - 0.5;
Vector3 direction = LinearCombination(1.0, get_direction(), Vector4 direction = LinearCombination(1.0, GetDirection(),
x0, GetRight(), x0, GetRight(),
y0, GetUp()); y0, GetUp());
return Ray(GetOrigin(), direction.normalize()); return Ray(GetOrigin(), basics::Normalized(direction));
} }
@ -226,14 +313,8 @@ OrthographicCamera::OrthographicCamera(const Camera& other)
/* /*
* OrthographicCamera::compute_primary_ray -- * OrthographicCamera::compute_primary_ray --
*/ */
/**
* Compute a primary ray given an (x,y) coordinate pair. The orthographic camera
* projects rays parallel to the viewing direction through the (x,y) coordinate
* given. Thus, the size of the orthographic camera should be set to the size of
* the view into the scene.
*/
Ray Ray
OrthographicCamera::compute_primary_ray(const int x, OrthographicCamera::PrimaryRay(const int x,
const int width, const int width,
const int y, const int y,
const int height) const int height)
@ -243,13 +324,13 @@ OrthographicCamera::compute_primary_ray(const int x,
* Center x and y in the pixel and convert them to be coordinates between * Center x and y in the pixel and convert them to be coordinates between
* -0.5 and 0.5. * -0.5 and 0.5.
*/ */
double x0 = (x + 0.5) / width + 0.5; Double x0 = (x + 0.5) / width + 0.5;
double y0 = ((height - 1.0) - (y - 0.5)) / height - 0.5; Double y0 = ((height - 1.0) - (y - 0.5)) / height - 0.5;
Vector3 origin = LinearCombination(1.0, GetOrigin(), Vector4 origin = LinearCombination(1.0, GetOrigin(),
x0, GetRight(), x0, GetRight(),
y0, GetUp()); y0, GetUp());
return Ray(origin, get_direction()); return Ray(origin, GetDirection());
} }
@ -274,3 +355,5 @@ operator<<(std::ostream& ost,
<< "]"; << "]";
return ost; return ost;
} }
} /* namespace charles */

View file

@ -1,117 +0,0 @@
/* camera.h
*
* The Camera is the eye into the scene. It defines several parameters and a
* single compute_primary_ray method that generates rays with which the ray
* tracer draws the scene.
*
* Eryn Wells <eryn@erynwells.me>
*/
#ifndef __CAMERA_H__
#define __CAMERA_H__
#include <memory>
#include "basics.h"
struct Camera
{
typedef std::shared_ptr<Camera> Ptr;
Camera();
Camera(const Camera& other);
virtual ~Camera();
const Vector3& GetOrigin() const;
void SetOrigin(const Vector3& origin);
const Vector3& get_direction() const;
void set_direction(const Vector3& direction);
const Vector3& GetRight() const;
void SetRight(const Vector3& right);
const Vector3& GetUp() const;
void SetUp(const Vector3& up);
/**
* Get the camera's handedness. Left handed is the default.
*
* @returns `true` if the camera is set up for left-handed coordinates.
*/
bool IsLeftHanded() const;
/**
* Pan and tilt the camera towards the given point.
*
* @param [in] pt The point at which to face the camera
*/
void LookAt(const Vector3& pt);
virtual Ray compute_primary_ray(const int x, const int width,
const int y, const int height) const = 0;
virtual std::string GetTypeString() const;
private:
friend std::ostream& operator<<(std::ostream& ost, const Camera& camera);
void WriteType(std::ostream& ost) const;
/**
* The location of the camera in the scene. Depending on the type of camera,
* this is the point from which rays will be emitted.
*/
Vector3 mOrigin;
/** A normalized vector defining where the camera is pointed. */
Vector3 mDirection;
/**
* A vector defining the width of the camera's image plane. The ratio of
* this and mUp determine the aspect ratio of the image.
*/
Vector3 mRight;
/**
* A vector defining the height of the camera's image plane. The ratio of
* this and mRight determine the aspect ratio of the image.
*/
Vector3 mUp;
};
class PerspectiveCamera
: public Camera
{
public:
PerspectiveCamera();
PerspectiveCamera(const Camera& other);
Ray compute_primary_ray(const int x, const int width,
const int y, const int height) const;
private:
std::string GetTypeString() const;
};
class OrthographicCamera
: public Camera
{
public:
OrthographicCamera();
OrthographicCamera(const Camera& other);
Ray compute_primary_ray(const int x, const int width,
const int y, const int height) const;
private:
std::string GetTypeString() const;
};
std::ostream& operator<<(std::ostream& ost, const Camera& camera);
#endif

125
src/camera.hh Normal file
View file

@ -0,0 +1,125 @@
/* camera.hh
* vim: set tw=80:
* Eryn Wells <eryn@erynwells.me>
*/
#ifndef __CAMERA_H__
#define __CAMERA_H__
#include <memory>
#include "basics/basics.hh"
namespace charles {
/**
* The Camera is the eye into the scene. It defines several parameters and a
* single compute_primary_ray method that generates rays with which the ray
* tracer draws the scene.
*/
struct Camera
{
typedef std::shared_ptr<Camera> Ptr;
Camera();
Camera(const Camera& other);
virtual ~Camera();
basics::Vector4& GetOrigin();
const basics::Vector4& GetOrigin() const;
void SetOrigin(const basics::Vector4& origin);
basics::Vector4& GetDirection();
const basics::Vector4& GetDirection() const;
void SetDirection(const basics::Vector4& direction);
basics::Vector4& GetRight();
const basics::Vector4& GetRight() const;
void SetRight(const basics::Vector4& right);
basics::Vector4& GetUp();
const basics::Vector4& GetUp() const;
void SetUp(const basics::Vector4& up);
/** Get the camera's handedness. Left handed is the default. */
bool IsLeftHanded() const;
/** Pan and tilt the camera towards the given point. */
void LookAt(const basics::Vector4& p);
virtual basics::Ray PrimaryRay(const int x, const int width,
const int y, const int height) const = 0;
protected:
virtual std::string GetTypeString() const;
private:
friend std::ostream& operator<<(std::ostream& ost, const Camera& camera);
void WriteType(std::ostream& ost) const;
/**
* The location of the camera in the scene. Depending on the type of camera,
* this is the point from which rays will be emitted.
*/
basics::Vector4 mOrigin;
/** A vector defining where the camera is pointed. */
basics::Vector4 mDirection;
/**
* A vector defining the width of the camera's image plane. The ratio of
* this and mUp determine the aspect ratio of the image.
*/
basics::Vector4 mRight;
/**
* A vector defining the height of the camera's image plane. The ratio of
* this and mRight determine the aspect ratio of the image.
*/
basics::Vector4 mUp;
};
class PerspectiveCamera
: public Camera
{
public:
PerspectiveCamera();
PerspectiveCamera(const Camera& other);
basics::Ray PrimaryRay(const int x, const int width,
const int y, const int height) const;
private:
std::string GetTypeString() const;
};
class OrthographicCamera
: public Camera
{
public:
OrthographicCamera();
OrthographicCamera(const Camera& other);
/**
* Compute a primary ray given an (x,y) coordinate pair. The orthographic
* camera projects rays parallel to the viewing direction through the (x,y)
* coordinate given. Thus, the size of the orthographic camera should be set
* to the size of the view into the scene.
*/
basics::Ray PrimaryRay(const int x, const int width,
const int y, const int height) const;
private:
std::string GetTypeString() const;
};
std::ostream& operator<<(std::ostream& ost, const Camera& camera);
} /* namespace charles */
#endif