/*
* C++ RayTracer
* file: scene.h
*
* Radek Brich, 2006
*/
#ifndef SCENE_H
#define SCENE_H
#include <vector>
#include "noise.h"
#include "vector.h"
/*
triangle intersection alghoritm
chooses are:
TRI_PLUCKER
TRI_BARI
TRI_BARI_PRE
*/
#if !defined(TRI_PLUCKER) && !defined(TRI_BARI) && !defined(TRI_BARI_PRE)
# define TRI_BARI_PRE
#endif
using namespace std;
class Ray
{
public:
Vector3 o, dir;
Ray(const Vector3 &ao, const Vector3 &adir):
o(ao), dir(adir) {};
};
class Quaternion
{
public:
Float a,b,c,d;
Quaternion(): a(0), b(0), c(0), d(0) {};
Quaternion(const Float aa, const Float ab, const Float ac, const Float ad):
a(aa), b(ab), c(ac), d(ad) {};
Quaternion(const Vector3& v): a(1), b(v.x), c(v.y), d(v.z) {};
Vector3 toVector() { return Vector3(b/a, c/a, d/a); };
Quaternion normalize()
{
Float f = 1.0f / sqrtf(a * a + b * b + c * c + d * d);
a *= f;
b *= f;
c *= f;
d *= f;
return *this;
};
friend Quaternion operator*(const Quaternion &q1, const Quaternion &q2)
{
return Quaternion(
q1.a*q2.a - q1.b*q2.b - q1.c*q2.c - q1.d*q2.d,
q1.a*q2.b + q1.b*q2.a + q1.c*q2.d - q1.d*q2.c,
q1.a*q2.c + q1.c*q2.a + q1.d*q2.b - q1.b*q2.d,
q1.a*q2.d + q1.d*q2.a + q1.b*q2.c - q1.c*q2.b);
};
friend Quaternion conjugate(const Quaternion &q)
{
return Quaternion(q.a, -q.b, -q.c, -q.d);
}
};
class Camera
{
public:
Vector3 eye, p, u, v;
Float f;
Camera(): eye(0,0,10), p(0,0,-1), u(-1,0,0), v(0,1,0), f(3.14/4.0) {};
Camera(const Vector3 &C, const Vector3 &ap, const Vector3 &au, const Vector3 &av):
eye(C), p(ap), u(au), v(av), f(3.14/4.0) {};
void setEye(const Vector3 &aeye) { eye = aeye; };
void setFocalLength(const Float af) { f = af; };
void rotate(const Quaternion &q);
void move(const Float fw, const Float left, const Float up);
};
/* axis-aligned bounding box */
class BBox
{
public:
Vector3 L;
Vector3 H;
BBox(): L(), H() {};
BBox(const Vector3 aL, const Vector3 aH): L(aL), H(aH) {};
Float w() { return H.x-L.x; };
Float h() { return H.y-L.y; };
Float d() { return H.z-L.z; };
bool intersect(const Ray &ray, Float &a, Float &b);
};
class Light
{
public:
Vector3 pos;
Colour colour;
bool cast_shadows;
Light(const Vector3 &position, const Colour &acolour):
pos(position), colour(acolour), cast_shadows(true) {};
void castShadows(bool cast) { cast_shadows = cast; };
};
class Texture
{
public:
Colour colour;
Colour evaluate(Vector3 point)
{
Float sum = 0.0;
for (int i = 1; i < 5; i++)
sum += fabsf(perlin(point.x*i, point.y*i, point.z*i))/i;
Float value = sinf(point.x + sum)/2 + 0.5;
return Colour(value*colour.r, value*colour.g, value*colour.b);
};
};
class Material
{
public:
Float ambient, diffuse, specular, shininess; // Phong constants
Float reflection; // how much reflectife is the surface
Float refraction; // refraction index
Float transmitivity;
Texture texture;
Material(const Colour &acolour) {
texture.colour = acolour;
ambient = 0.1;
diffuse = 0.5;
specular = 0.1;
shininess = 0.5;
reflection = 0.5;
}
};
class Shape
{
public:
Material *material;
Shape() {};
virtual ~Shape() {};
// first intersection point
virtual bool intersect(const Ray &ray, Float &dist) const = 0;
// all intersections (only for CSG)
virtual bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const = 0;
// normal at point P
virtual Vector3 normal(Vector3 &P) const = 0;
virtual BBox get_bbox() const = 0;
};
class ShapeList: public vector<Shape*>
{
};
class Sphere: public Shape
{
Float sqr_radius;
Float inv_radius;
public:
Vector3 center;
Float radius;
Sphere(const Vector3 &acenter, const Float aradius, Material *amaterial):
sqr_radius(aradius*aradius), inv_radius(1.0f/aradius),
center(acenter), radius(aradius) { material = amaterial; }
bool intersect(const Ray &ray, Float &dist) const;
bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const;
Vector3 normal(Vector3 &P) const { return (P - center) * inv_radius; };
BBox get_bbox() const;
};
class Box: public Shape
{
Vector3 L;
Vector3 H;
public:
Box(const Vector3 &aL, const Vector3 &aH, Material *amaterial): L(aL), H(aH)
{
for (int i = 0; i < 3; i++)
if (L.cell[i] > H.cell[i])
swap(L.cell[i], H.cell[i]);
material = amaterial;
};
bool intersect(const Ray &ray, Float &dist) const;
bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const { return false; };
Vector3 normal(Vector3 &P) const;
BBox get_bbox() const { return BBox(L, H); };
};
class Triangle: public Shape
{
#ifdef TRI_BARI_PRE
Float nu, nv, nd;
int k; // dominant axis
Float bnu, bnv;
Float cnu, cnv;
#endif
#ifdef TRI_BARI
int k; // dominant axis
#endif
#ifdef TRI_PLUCKER
Float pla[6], plb[6], plc[6];
#endif
public:
Vector3 A, B, C, N;
Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial);
bool intersect(const Ray &ray, Float &dist) const;
bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const {return false;};
Vector3 normal(Vector3 &) const { return N; };
BBox get_bbox() const;
};
#endif