include/scene.h
author Radek Brich <radek.brich@devl.cz>
Tue, 04 Dec 2007 08:58:05 +0100
branchpyrit
changeset 23 7e258561a690
parent 22 76b7bd51d64a
child 24 d0d76e8a5203
permissions -rw-r--r--
fix a bug in KdNode::subdivide and remove some extra variables realtime.cc - use SW surface

/*
 * C++ RayTracer
 * file: scene.h
 *
 * Radek Brich, 2006
 */

#ifndef SCENE_H
#define SCENE_H

#include <vector>

#include "noise.h"

#include "vector.h"

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) = 0;

	// all intersections (only for CSG)
	virtual bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) = 0;

	// normal at point P
	virtual Vector3 normal(Vector3 &P) = 0;

	virtual BBox get_bbox() = 0;
};

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);
	bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts);
	Vector3 normal(Vector3 &P) { return (P - center) * inv_radius; };
	BBox get_bbox();
};

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);
	bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) {return false;};
	Vector3 normal(Vector3 &P);
	BBox get_bbox() { return BBox(L, H); };
};

class Triangle: public Shape
{
	int k; // dominant axis
	Float nu, nv, nd;
	Float bnu, bnv;
	Float cnu, cnv;
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);
	bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) {return false;};
	Vector3 normal(Vector3 &) { return N; };
	BBox get_bbox();
};

#endif