# HG changeset patch # User Radek Brich # Date 1196642963 -3600 # Node ID 76b7bd51d64aa8569cc4c52fa59c8a54f45dc19a # Parent 79b516a3803d92a01b52850b2cd124a5ae766be5 new make infrastructure generalize floats to Floats, allow compiling as both double/float diff -r 79b516a3803d -r 76b7bd51d64a .bzrignore --- a/.bzrignore Fri Nov 30 00:44:51 2007 +0100 +++ b/.bzrignore Mon Dec 03 01:49:23 2007 +0100 @@ -1,6 +1,8 @@ +demos/ModulePath demos/*.png demos/kdtree.obj demos/*.ply ccdemos/*.png ccdemos/spheres_shadow ccdemos/realtime +bin/* \ No newline at end of file diff -r 79b516a3803d -r 76b7bd51d64a Makefile --- a/Makefile Fri Nov 30 00:44:51 2007 +0100 +++ b/Makefile Mon Dec 03 01:49:23 2007 +0100 @@ -1,39 +1,38 @@ -CCFLAGS=-I./src -Wall -Wno-write-strings -fno-strict-aliasing -DPTHREADS -LDFLAGS= +ROOT=$(shell pwd) +include config.mk + +all: python-module demos ccdemos + +python-module: libs-float + $(MAKE) -C src python-module + +demos: python-module + $(MAKE) -C demos -ifeq ($(OS), Windows_NT) - CCFLAGS+=-I"C:/Program Files/Python25/include" - LDFLAGS+=-L"C:\Program Files\Python25\libs" -lpython25 -lpthreadGC2 - MODULENAME=raytracer.pyd -else - CCFLAGS+=-pthread -fPIC `python-config --includes` - MODULENAME=raytracermodule.so -endif +ccdemos: libs-float libs-double + $(MAKE) -C ccdemos + +libs-float: + $(MAKE) -C src libs-float -# optimizations -#CCFLAGS+=-g -O0 -CCFLAGS+=-O3 -pipe -fomit-frame-pointer -ffast-math -msse3 +libs-double: + $(MAKE) -C src libs-double + +clean: + $(MAKE) -C src clean + $(MAKE) -C demos clean + $(MAKE) -C ccdemos clean # TARGETS ######### -all: python-module - -python-module: $(MODULENAME) - tests: testvector testmatrix -clean: - rm -f *.o $(MODULENAME) - # RULES ####### -%.o: src/%.cc - $(CXX) -c -o $@ src/$*.cc $(CCFLAGS) - test%: tests/%.cc $(CXX) -o $@ tests/$*.cc $(CCFLAGS) ./$@ @@ -42,18 +41,6 @@ # DEPENDENCIES ############## -# C++ raytracer -vector.o: src/vector.cc src/vector.h -matrix.o: src/matrix.cc src/matrix.h src/vector.h -noise.o: src/noise.cc src/noise.h -scene.o: src/scene.cc src/scene.h src/vector.h src/noise.h src/common.h -kdtree.o: src/kdtree.cc src/kdtree.h src/scene.h -raytracer.o: src/raytracer.cc src/raytracer.h src/scene.h src/vector.h src/noise.h - -# python module -raytracermodule.o: src/raytracermodule.cc src/raytracer.h src/scene.h src/vector.h -$(MODULENAME): raytracermodule.o raytracer.o scene.o noise.o kdtree.o - $(CXX) $^ -shared -o $@ $(LDFLAGS) # library tests testvector: tests/vector.cc src/vector.h diff -r 79b516a3803d -r 76b7bd51d64a ccdemos/Makefile --- a/ccdemos/Makefile Fri Nov 30 00:44:51 2007 +0100 +++ b/ccdemos/Makefile Mon Dec 03 01:49:23 2007 +0100 @@ -1,28 +1,33 @@ -CCFLAGS=-g -O3 -I../src -LDFLAGS=-L.. -pthread -RGBLIB_LDFLAGS=$(LDFLAGS) -lpng -SDL_CCFLAGS=$(CCFLAGS) $(shell sdl-config --cflags) -SDL_LDFLAGS=$(LDFLAGS) $(shell sdl-config --libs) -PYRIT_OBJS=$(shell ls ../*.o | grep -v raytracermodule) +ifndef $(ROOT) + ROOT=$(shell pwd)/.. +endif + +include $(ROOT)/config.mk + + +### Targets ### +all: realtime spheres_shadow + +realtime: realtime.o libs-double + $(CXX) -o $@ $(ROOT)/bin/libs-double/*.o $< $(LDFLAGS) $(SDL_LDFLAGS) -all: spheres_shadow realtime +spheres_shadow: spheres_shadow.o image.o libs-float + $(CXX) -o $@ $(ROOT)/bin/libs-float/*.o $< image.o $(LDFLAGS) -lpng + +libs-float: + $(MAKE) -C ../src libs-float -%.o: %.c +libs-double: + $(MAKE) -C ../src libs-double + +realtime.o: realtime.cc + $(CXX) -c -o $@ $(CCFLAGS) $(SDL_CCFLAGS) $< $(DEFS) -DPYRIT_DOUBLE + +image.o: image.c $(CXX) -c -o $@ $*.c -%.o: %.cc - $(CXX) -c -o $@ $*.cc $(CCFLAGS) - -%: %.o - (cd .. && make) - $(CXX) -o $@ $(PYRIT_OBJS) $^ $(RGBLIB_LDFLAGS) - -image.o: image.c spheres_shadow.o: spheres_shadow.cc -spheres_shadow: spheres_shadow.o image.o - -realtime: realtime.cc - $(CXX) -o $@ $@.cc $(SDL_CCFLAGS) -L.. $(PYRIT_OBJS) $(SDL_LDFLAGS) + $(CXX) -c -o $@ $*.cc $(CCFLAGS) $(DEFS) clean: rm -f spheres_shadow realtime *.o diff -r 79b516a3803d -r 76b7bd51d64a ccdemos/realtime.cc --- a/ccdemos/realtime.cc Fri Nov 30 00:44:51 2007 +0100 +++ b/ccdemos/realtime.cc Mon Dec 03 01:49:23 2007 +0100 @@ -4,7 +4,7 @@ int w = 480; int h = 288; -float *render_buffer; +Float *render_buffer; Raytracer rt; Camera cam; @@ -19,7 +19,7 @@ Uint32 *bufp = (Uint32 *)screen->pixels; unsigned char c[3]; - for (float *fd = render_buffer; fd != render_buffer + w*h*3; fd += 3) + for (Float *fd = render_buffer; fd != render_buffer + w*h*3; fd += 3) { for (int i = 0; i < 3; i++) { @@ -60,10 +60,10 @@ } /* initialize raytracer and prepare scene */ - render_buffer = (float *) malloc(w*h*3*sizeof(float)); + render_buffer = (Float *) malloc(w*h*3*sizeof(Float)); rt.setThreads(2); - rt.setMaxDepth(1); + rt.setMaxDepth(3); KdTree top; rt.setTop(&top); @@ -79,7 +79,7 @@ Material mat_sph(Colour(1.0, 1.0, 1.0)); for (int y=0; y<10; y++) for (int x=0; x<10; x++) - rt.addshape(new Sphere(Vector3(x*2-10, (float)random()/RAND_MAX*5.0, y*2-10), 0.45, &mat_sph)); + rt.addshape(new Sphere(Vector3(x*2-10, (Float)random()/RAND_MAX*5.0, y*2-10), 0.45, &mat_sph)); rt.setCamera(&cam); cam.setEye(Vector3(0,0,10)); @@ -91,7 +91,7 @@ /* loop... */ SDL_Event event; bool quit = false; - float roty = 0.0, rotx = 0.0, move = 0.0; + Float roty = 0.0, rotx = 0.0, move = 0.0; while (!quit) { while (SDL_PollEvent(&event)) @@ -100,7 +100,7 @@ case SDL_VIDEORESIZE: w = event.resize.w; h = event.resize.h; - render_buffer = (float *) realloc(render_buffer, w*h*3*sizeof(float)); + render_buffer = (Float *) realloc(render_buffer, w*h*3*sizeof(Float)); screen = SDL_SetVideoMode(w, h, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE); break; case SDL_KEYDOWN: diff -r 79b516a3803d -r 76b7bd51d64a ccdemos/spheres_shadow.cc --- a/ccdemos/spheres_shadow.cc Fri Nov 30 00:44:51 2007 +0100 +++ b/ccdemos/spheres_shadow.cc Mon Dec 03 01:49:23 2007 +0100 @@ -4,7 +4,10 @@ int main() { Raytracer rt; - rt.setThreads(1); + rt.setThreads(2); + + KdTree top; + rt.setTop(&top); Light light1(Vector3(0.0, 5.0, -5.0), Colour(0.7, 0.3, 0.6)); rt.addlight(&light1); @@ -29,19 +32,21 @@ Sphere tinysphere(Vector3(-1.2, 0.0, -2.0), 0.5, &mat3); rt.addshape(&tinysphere); + top.optimize(); + Camera cam; cam.setEye(Vector3(0,0,15)); rt.setCamera(&cam); int w = 800; int h = 600; - float *fdata = (float *) malloc(w*h*3*sizeof(float)); + Float *fdata = (Float *) malloc(w*h*3*sizeof(Float)); rt.render(w, h, fdata); struct image *img; new_image(&img, w, h, 3); - float *fd = fdata; + Float *fd = fdata; for (char *cd = img->data; cd != img->data + w*h*3; cd++, fd++) { if (*fd > 1.0) *cd = 255; diff -r 79b516a3803d -r 76b7bd51d64a config.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config.mk Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,25 @@ +DEFS=-DPTHREADS + +CCFLAGS=-Wall -Wno-write-strings -fno-strict-aliasing -I$(ROOT)/include +LDFLAGS= + +PY_CCFLAGS=$(shell python-config --includes) +PY_LDFLAGS=$(shell python-config --libs) + +SDL_CCFLAGS=$(shell sdl-config --cflags) +SDL_LDFLAGS=$(shell sdl-config --libs) + +ifeq ($(OS), Windows_NT) + LDFLAGS+=-lpthreadGC2 + PY_CCFLAGS=-I"C:/Program Files/Python25/include" + PY_LDFLAGS=-L"C:\Program Files\Python25\libs" -lpython25 + MODULENAME=raytracer.pyd +else + CCFLAGS+=-pthread -fPIC + LDFLAGS+=-pthread + MODULENAME=raytracermodule.so +endif + +# optimizations +CCFLAGS+=-g -O0 +#CCFLAGS+=-O3 -pipe -fomit-frame-pointer -ffast-math -msse3 diff -r 79b516a3803d -r 76b7bd51d64a demos/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demos/Makefile Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,16 @@ +ifndef $(ROOT) + ROOT=$(shell pwd)/.. +endif + + +all: ModulePath reqs models + +ModulePath: + echo "$(ROOT)/bin/python-module" > ModulePath + +reqs: + $(MAKE) -C .. libs-float python-module + +models: ; + +clean: ; diff -r 79b516a3803d -r 76b7bd51d64a demos/spheres_ao.py --- a/demos/spheres_ao.py Fri Nov 30 00:44:51 2007 +0100 +++ b/demos/spheres_ao.py Mon Dec 03 01:49:23 2007 +0100 @@ -1,7 +1,7 @@ #!/usr/bin/python import sys -sys.path.append("..") +sys.path.append(open('ModulePath').read().strip()) from raytracer import Raytracer, Material, Box, Sphere, Light import Image diff -r 79b516a3803d -r 76b7bd51d64a demos/spheres_shadow.py --- a/demos/spheres_shadow.py Fri Nov 30 00:44:51 2007 +0100 +++ b/demos/spheres_shadow.py Mon Dec 03 01:49:23 2007 +0100 @@ -1,7 +1,7 @@ #!/usr/bin/python import sys -sys.path.append("..") +sys.path.append(open('ModulePath').read().strip()) from raytracer import Raytracer, Material, Box, Sphere, Light import Image diff -r 79b516a3803d -r 76b7bd51d64a demos/triangles_monkey.py --- a/demos/triangles_monkey.py Fri Nov 30 00:44:51 2007 +0100 +++ b/demos/triangles_monkey.py Mon Dec 03 01:49:23 2007 +0100 @@ -1,7 +1,7 @@ #!/usr/bin/python import sys -sys.path.append("..") +sys.path.append(open('ModulePath').read().strip()) from raytracer import Raytracer, Light, Sphere, Triangle, Material import Image diff -r 79b516a3803d -r 76b7bd51d64a demos/triangles_sphere.py --- a/demos/triangles_sphere.py Fri Nov 30 00:44:51 2007 +0100 +++ b/demos/triangles_sphere.py Mon Dec 03 01:49:23 2007 +0100 @@ -1,7 +1,7 @@ #!/usr/bin/python import sys -sys.path.append("..") +sys.path.append(open('ModulePath').read().strip()) from raytracer import Raytracer, Light, Sphere, Triangle, Material import Image diff -r 79b516a3803d -r 76b7bd51d64a include/common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/common.h Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,28 @@ +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include + +#ifdef PYRIT_DOUBLE +# define Float double +# define Eps DBL_EPSILON +# define Inf DBL_MAX +#else +# define Float float +# define Eps 1e-6 +# define Inf FLT_MAX +#endif + +inline void infomsg(const char *format, ...) +{ +#ifndef PYRIT_QUIET + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +#endif +} + +#endif diff -r 79b516a3803d -r 76b7bd51d64a include/kdtree.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/kdtree.h Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,79 @@ +#ifndef KDTREE_H +#define KDTREE_H + +#include +#include +#include + +#include "scene.h" + +using namespace std; + +class ShapeList: public vector +{ +}; + +class Container +{ +protected: + BBox bbox; +public: + ShapeList shapes; + Container(): bbox(), shapes() {}; + virtual ~Container() {}; + virtual void addShape(Shape* aShape); + //void addShapeNoExtend(Shape* aShape) { shapes.push_back(aShape); }; + virtual Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, + Float &nearest_distance); + virtual void optimize() {}; +}; + +class KdNode +{ + Float split; + short axis; /* 0,1,2 => x,y,z; 3 => leaf */ +public: + union { + KdNode *children; + ShapeList *shapes; + }; + + KdNode() : axis(3) { shapes = new ShapeList(); }; + ~KdNode(); + + void setAxis(short aAxis) { axis = aAxis; }; + short getAxis() { return axis; }; + + void setSplit(Float aSplit) { split = aSplit; }; + Float getSplit() { return split; }; + + void setLeaf() { axis = 3; }; + bool isLeaf() { return axis == 3; }; + + KdNode *getLeftChild() { return children; }; + KdNode *getRightChild() { return children+1; }; + + void addShape(Shape* aShape) { shapes->push_back(aShape); }; + + void subdivide(BBox bbox, int depth); +}; + +class KdTree: public Container +{ + KdNode *root; + bool built; + int max_depth; +public: + KdTree() : Container(), root(NULL), built(false), max_depth(32) {}; + ~KdTree() { if (root) delete root; }; + void addShape(Shape* aShape) { Container::addShape(aShape); built = false; }; + Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, + Float &nearest_distance); + void optimize() { build(); }; + void build(); + void save(ostream &str, KdNode *node = NULL); + void load(istream &str, KdNode *node = NULL); + void setMaxDepth(int md) { max_depth = md; }; +}; + +#endif diff -r 79b516a3803d -r 76b7bd51d64a include/matrix.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/matrix.h Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,94 @@ +/* + * C++ RayTracer + * file: matrix.h + * + * Radek Brich, 2006 + */ + +/* not used at this time */ + +#ifndef MATRIX_H +#define MATRIX_H + +#include "vector.h" + +using namespace std; + +class Matrix +{ +public: + Float data[4][4]; + + Matrix(): {}; + + // sum + friend Matrix operator+(const Matrix &a, const Matrix &b) + { + Matrix m = Matrix(); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + m.data[i][j] = a.data[i][j] + b.data[i][j]; + return m; + } + + // difference + friend Matrix operator-(const Matrix &a, const Matrix &b) + { + Matrix m = Matrix(); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + m.data[i][j] = a.data[i][j] - b.data[i][j]; + return m; + } + + // product + friend Matrix operator*(const Matrix &a, const Matrix &b) + { + Matrix m = Matrix(); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + m.data[i][j] = + a.data[i][0] * b.data[0][j] + + a.data[i][1] * b.data[1][j] + + a.data[i][2] * b.data[2][j] + + a.data[i][3] * b.data[3][j]; + return m; + } + + // negative + Matrix operator-() + { + Matrix m = Matrix(); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + m.data[i][j] = -data[i][j]; + return m; + } + + // product of matrix and scalar + Matrix operator*(const Float &f) + { + Matrix m = Matrix(); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + m.data[i][j] = data[i][j] * f; + return m; + } + + friend Matrix operator*(const Float &f, Matrix &m) { return m * f; }; + + // product of matrix and vector + Vector3 operator*(const Vector3 &v) + { + Vector3 u = Vector3(); + u.x = data[0][0] * v.x + data[0][1] * v.y + data[0][2] * v.z + data[0][3] * v.w; + u.y = data[1][0] * v.x + data[1][1] * v.y + data[1][2] * v.z + data[1][3] * v.w; + u.z = data[2][0] * v.x + data[2][1] * v.y + data[2][2] * v.z + data[2][3] * v.w; + u.w = data[3][0] * v.x + data[3][1] * v.y + data[3][2] * v.z + data[3][3] * v.w; + return u; + } + + friend Matrix operator*(const Vector3 &v, Matrix &m) { return m * v; }; +}; + +#endif diff -r 79b516a3803d -r 76b7bd51d64a include/noise.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/noise.h Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,8 @@ +#ifndef NOISE_H +#define NOISE_H + +#include "common.h" + +Float perlin(Float x, Float y, Float z); + +#endif diff -r 79b516a3803d -r 76b7bd51d64a include/raytracer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/raytracer.h Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,57 @@ +/* + * C++ RayTracer + * file: raytracer.h + * + * Radek Brich, 2006 + */ + +#ifndef RAYTRACER_H +#define RAYTRACER_H + +#include + +#include "common.h" +#include "kdtree.h" +#include "scene.h" + +using namespace std; + +class Raytracer; +struct RenderrowData { + Raytracer *rt; + int w; + Vector3 eye, dfix, dx, dy; + Float *iter; +}; + +class Raytracer +{ + Container *top; + Camera *camera; + vector lights; + Colour bg_colour; + int ao_samples; + Float ao_distance, ao_angle; + int num_threads; + int subsample; + int max_depth; + + Vector3 SphereDistribute(int i, int n, Float extent, Vector3 &normal); +public: + Raytracer(): top(NULL), camera(NULL), lights(), bg_colour(0.0, 0.0, 0.0), + ao_samples(0), num_threads(4), subsample(8), max_depth(4) {}; + void render(int w, int h, Float *buffer); + Colour raytrace(Ray &ray, int depth, Shape *origin_shape); + void addshape(Shape *shape) { top->addShape(shape); }; + void addlight(Light *light); + void setCamera(Camera *cam) { camera = cam; }; + void setTop(Container *atop) { top = atop; }; + Container *getTop() { return top; }; + int getSubsample() { return subsample; }; + void setMaxDepth(int newdepth) { max_depth = newdepth; }; + + void ambientocclusion(int samples, Float distance, Float angle); + void setThreads(int num) { num_threads = num; }; +}; + +#endif diff -r 79b516a3803d -r 76b7bd51d64a include/scene.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/scene.h Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,205 @@ +/* + * C++ RayTracer + * file: scene.h + * + * Radek Brich, 2006 + */ + +#ifndef SCENE_H +#define SCENE_H + +#include + +#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 &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 &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 &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 &allts) {return false;}; + Vector3 normal(Vector3 &) { return N; }; + BBox get_bbox(); +}; + +#endif diff -r 79b516a3803d -r 76b7bd51d64a include/vector.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vector.h Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,136 @@ +/* + * C++ RayTracer + * file: vector.h + * + * Radek Brich, 2006 + */ + +#ifndef VECTOR_H +#define VECTOR_H + +#include +#include + +using namespace std; + +class Vector3 +{ +public: + // data + union { + struct { + Float x, y, z; + }; + struct { + Float r, g, b; + }; + Float cell[3]; + }; + + // constructors + Vector3(): x(0.0f), y(0.0f), z(0.0f) {}; + Vector3(Float ax, Float ay, Float az): x(ax), y(ay), z(az) {}; + + // index operator + Float &operator[](int index) { return cell[index]; }; + + bool operator==(Vector3 &v) { return x==v.x && y==v.y && z==v.z; }; + + // normalize + Vector3 normalize() + { + Float f = 1.0f / mag(); + x *= f; + y *= f; + z *= f; + return *this; + } + + // get normalized copy + Vector3 unit() + { + Vector3 u(*this); + return u.normalize();; + } + + // square magnitude, magnitude + Float mag2() { return x * x + y * y + z * z; } + Float mag() { return sqrtf(mag2()); } + + // negative + Vector3 operator-() { return Vector3(-x, -y, -z); } + + // accumulate + Vector3 operator+=(const Vector3 &v) + { + x += v.x; + y += v.y; + z += v.z; + return *this; + }; + + // sum + friend Vector3 operator+(const Vector3 &a, const Vector3 &b) + { + return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); + }; + + // difference + friend Vector3 operator-(const Vector3 &a, const Vector3 &b) + { + return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); + }; + + // dot product + friend Float dot(const Vector3 &a, const Vector3 &b) + { + return a.x * b.x + a.y * b.y + a.z * b.z; + }; + + // cross product + friend Vector3 cross(const Vector3 &a, const Vector3 &b) + { + return Vector3(a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x); + }; + + // product of vector and scalar + friend Vector3 operator*(const Vector3 &v, const Float &f) + { + return Vector3(f * v.x, f * v.y, f * v.z); + } + + friend Vector3 operator*(const Float &f, const Vector3 &v) + { + return v * f; + }; + + // vector plus scalar + friend Vector3 operator+(const Vector3 &v, const Float &f) + { + return Vector3(v.x + f, v.y + f, v.z + f); + } + + // vector minus scalar + friend Vector3 operator-(const Vector3 &v, const Float &f) + { + return Vector3(v.x - f, v.y - f, v.z - f); + } + + // cell by cell product (only usable for colours) + friend Vector3 operator*(const Vector3 &a, const Vector3 &b) + { + return Vector3(a.x * b.x, a.y * b.y, a.z * b.z); + }; + + // print + friend ostream & operator<<(ostream &st, const Vector3 &v) + { + return st << "(" << v.x << ", " << v.y << ", " << v.z << ")"; + } +}; + +typedef Vector3 Colour; + +#endif diff -r 79b516a3803d -r 76b7bd51d64a src/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Makefile Mon Dec 03 01:49:23 2007 +0100 @@ -0,0 +1,50 @@ +ifndef $(ROOT) + ROOT=$(shell pwd)/.. +endif + +include $(ROOT)/config.mk + +vpath %.cc $(ROOT)/src +vpath %.h $(ROOT)/include +LIBOBJS=raytracer.o scene.o noise.o kdtree.o +CCFLAGS+=-I$(ROOT)/include + +### Targets ### +all: libs-float libs-double python-module + +libs-float: + mkdir -p $(ROOT)/bin/$@ + $(MAKE) -C $(ROOT)/bin/$@ -f $(ROOT)/src/Makefile libs ROOT="$(ROOT)" + +libs-double: + mkdir -p $(ROOT)/bin/$@ + $(MAKE) -C $(ROOT)/bin/$@ -f $(ROOT)/src/Makefile libs ROOT="$(ROOT)" DEFS="$(DEFS) -DPYRIT_DOUBLE" + +libs: $(LIBOBJS) + +python-module: libs-float + mkdir -p $(ROOT)/bin/$@ + $(MAKE) -C $(ROOT)/bin/$@ -f $(ROOT)/src/Makefile $(MODULENAME) ROOT="$(ROOT)" + +$(MODULENAME): raytracermodule.o + $(CXX) -shared -o $@ $< $(ROOT)/bin/libs-float/*.o $(LDFLAGS) $(PY_LDFLAGS) + +clean: + rm -rf $(ROOT)/bin/libs-* + rm -rf $(ROOT)/bin/python-module + + +### Rules ### +%.o: %.cc + $(CXX) -c -o $@ $(DEFS) $(CCFLAGS) $< + + +### Dependencies ### +matrix.o: matrix.cc matrix.h vector.h common.h +noise.o: noise.cc noise.h common.h +scene.o: scene.cc scene.h vector.h noise.h common.h +kdtree.o: kdtree.cc kdtree.h scene.h common.h +raytracer.o: raytracer.cc raytracer.h scene.h vector.h noise.h common.h + +raytracermodule.o: raytracermodule.cc raytracer.h scene.h vector.h common.h + $(CXX) -c -o $@ $(DEFS) $(CCFLAGS) $(PY_CCFLAGS) $< diff -r 79b516a3803d -r 76b7bd51d64a src/common.h --- a/src/common.h Fri Nov 30 00:44:51 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#include -#include -#include - -#define Eps 1e-6 -#define Inf FLT_MAX - -inline void infomsg(const char *format, ...) -{ -#ifndef PYRIT_QUITE - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); -#endif -} - -#endif diff -r 79b516a3803d -r 76b7bd51d64a src/kdtree.cc --- a/src/kdtree.cc Fri Nov 30 00:44:51 2007 +0100 +++ b/src/kdtree.cc Mon Dec 03 01:49:23 2007 +0100 @@ -35,10 +35,10 @@ class SplitPos { public: - float pos; + Float pos; int lnum, rnum; SplitPos(): pos(0.0), lnum(0), rnum(0) {}; - SplitPos(float &aPos): pos(aPos), lnum(0), rnum(0) {}; + SplitPos(Float &aPos): pos(aPos), lnum(0), rnum(0) {}; friend bool operator<(const SplitPos& a, const SplitPos& b) { return a.pos < b.pos; }; friend bool operator==(const SplitPos& a, const SplitPos& b) @@ -54,9 +54,9 @@ { public: KdNode* node; /* pointer to far child */ - float t; /* the entry/exit signed distance */ + Float t; /* the entry/exit signed distance */ Vector3 pb; /* the coordinates of entry/exit point */ - StackElem(KdNode *anode, const float &at, const Vector3 &apb): + StackElem(KdNode *anode, const Float &at, const Vector3 &apb): node(anode), t(at), pb(apb) {}; }; @@ -81,7 +81,7 @@ }; Shape *Container::nearest_intersection(const Shape *origin_shape, const Ray &ray, - float &nearest_distance) + Float &nearest_distance) { Shape *nearest_shape = NULL; ShapeList::iterator shape; @@ -183,9 +183,9 @@ } // choose best split pos - const float K = 1.4; // constant, K = cost of traversal / cost of ray-triangle intersection - float SAV = 2*(bbox.w()*bbox.h() + bbox.w()*bbox.d() + bbox.h()*bbox.d()); // surface area of node - float cost = SAV * (K + shapes->size()); // initial cost = non-split cost + const Float K = 1.4; // constant, K = cost of traversal / cost of ray-triangle intersection + Float SAV = 2*(bbox.w()*bbox.h() + bbox.w()*bbox.d() + bbox.h()*bbox.d()); // surface area of node + Float cost = SAV * (K + shapes->size()); // initial cost = non-split cost SplitPos *splitpos = NULL; bool leaf = true; BBox lbb = bbox; @@ -195,9 +195,9 @@ // calculate SAH cost of this split lbb.H.cell[axis] = spl->pos; rbb.L.cell[axis] = spl->pos; - float SAL = 2*(lbb.w()*lbb.h() + lbb.w()*lbb.d() + lbb.h()*lbb.d()); - float SAR = 2*(rbb.w()*rbb.h() + rbb.w()*rbb.d() + rbb.h()*rbb.d()); - float splitcost = K + SAL/SAV*(K+spl->lnum) + SAR/SAV*(K+spl->rnum); + Float SAL = 2*(lbb.w()*lbb.h() + lbb.w()*lbb.d() + lbb.h()*lbb.d()); + Float SAR = 2*(rbb.w()*rbb.h() + rbb.w()*rbb.d() + rbb.h()*rbb.d()); + Float splitcost = K + SAL/SAV*(K+spl->lnum) + SAR/SAV*(K+spl->rnum); if (splitcost < cost) { @@ -237,8 +237,8 @@ #endif split = splitpos->pos; - float lnum = splitpos->lnum; - float rnum = splitpos->rnum; + Float lnum = splitpos->lnum; + Float rnum = splitpos->rnum; // split this node delete shapes; @@ -315,10 +315,10 @@ /* algorithm by Vlastimil Havran, Heuristic Ray Shooting Algorithms, appendix C */ Shape *KdTree::nearest_intersection(const Shape *origin_shape, const Ray &ray, - float &nearest_distance) + Float &nearest_distance) { - float a, b; /* entry/exit signed distance */ - float t; /* signed distance to the splitting plane */ + Float a, b; /* entry/exit signed distance */ + Float t; /* signed distance to the splitting plane */ /* if we have no tree, fall back to naive test */ if (!built) @@ -352,7 +352,7 @@ while (!node->isLeaf()) { /* retrieve position of splitting plane */ - float splitVal = node->getSplit(); + Float splitVal = node->getSplit(); short axis = node->getAxis(); if (enPt->pb[axis] <= splitVal) @@ -401,7 +401,7 @@ /* "intersect ray with each object in the object list, discarding " "those lying before stack[enPt].t or farther than stack[exPt].t" */ Shape *nearest_shape = NULL; - float dist = exPt->t; + Float dist = exPt->t; ShapeList::iterator shape; for (shape = node->shapes->begin(); shape != node->shapes->end(); shape++) if (*shape != origin_shape && (*shape)->intersect(ray, dist) diff -r 79b516a3803d -r 76b7bd51d64a src/kdtree.h --- a/src/kdtree.h Fri Nov 30 00:44:51 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -#ifndef KDTREE_H -#define KDTREE_H - -#include -#include -#include - -#include "scene.h" - -using namespace std; - -class ShapeList: public vector -{ -}; - -class Container -{ -protected: - BBox bbox; -public: - ShapeList shapes; - Container(): bbox(), shapes() {}; - virtual ~Container() {}; - virtual void addShape(Shape* aShape); - //void addShapeNoExtend(Shape* aShape) { shapes.push_back(aShape); }; - virtual Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, - float &nearest_distance); - virtual void optimize() {}; -}; - -class KdNode -{ - float split; - short axis; /* 0,1,2 => x,y,z; 3 => leaf */ -public: - union { - KdNode *children; - ShapeList *shapes; - }; - - KdNode() : axis(3) { shapes = new ShapeList(); }; - ~KdNode(); - - void setAxis(short aAxis) { axis = aAxis; }; - short getAxis() { return axis; }; - - void setSplit(float aSplit) { split = aSplit; }; - float getSplit() { return split; }; - - void setLeaf() { axis = 3; }; - bool isLeaf() { return axis == 3; }; - - KdNode *getLeftChild() { return children; }; - KdNode *getRightChild() { return children+1; }; - - void addShape(Shape* aShape) { shapes->push_back(aShape); }; - - void subdivide(BBox bbox, int depth); -}; - -class KdTree: public Container -{ - KdNode *root; - bool built; - int max_depth; -public: - KdTree() : Container(), root(NULL), built(false), max_depth(32) {}; - ~KdTree() { if (root) delete root; }; - void addShape(Shape* aShape) { Container::addShape(aShape); built = false; }; - Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, - float &nearest_distance); - void optimize() { build(); }; - void build(); - void save(ostream &str, KdNode *node = NULL); - void load(istream &str, KdNode *node = NULL); - void setMaxDepth(int md) { max_depth = md; }; -}; - -#endif diff -r 79b516a3803d -r 76b7bd51d64a src/matrix.h --- a/src/matrix.h Fri Nov 30 00:44:51 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * C++ RayTracer - * file: matrix.h - * - * Radek Brich, 2006 - */ - -/* not used at this time */ - -#ifndef MATRIX_H -#define MATRIX_H - -#include "vector.h" - -using namespace std; - -class Matrix -{ -public: - float data[4][4]; - - Matrix(): {}; - - // sum - friend Matrix operator+(const Matrix &a, const Matrix &b) - { - Matrix m = Matrix(); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - m.data[i][j] = a.data[i][j] + b.data[i][j]; - return m; - } - - // difference - friend Matrix operator-(const Matrix &a, const Matrix &b) - { - Matrix m = Matrix(); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - m.data[i][j] = a.data[i][j] - b.data[i][j]; - return m; - } - - // product - friend Matrix operator*(const Matrix &a, const Matrix &b) - { - Matrix m = Matrix(); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - m.data[i][j] = - a.data[i][0] * b.data[0][j] + - a.data[i][1] * b.data[1][j] + - a.data[i][2] * b.data[2][j] + - a.data[i][3] * b.data[3][j]; - return m; - } - - // negative - Matrix operator-() - { - Matrix m = Matrix(); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - m.data[i][j] = -data[i][j]; - return m; - } - - // product of matrix and scalar - Matrix operator*(const float &f) - { - Matrix m = Matrix(); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - m.data[i][j] = data[i][j] * f; - return m; - } - - friend Matrix operator*(const float &f, Matrix &m) { return m * f; }; - - // product of matrix and vector - Vector3 operator*(const Vector3 &v) - { - Vector3 u = Vector3(); - u.x = data[0][0] * v.x + data[0][1] * v.y + data[0][2] * v.z + data[0][3] * v.w; - u.y = data[1][0] * v.x + data[1][1] * v.y + data[1][2] * v.z + data[1][3] * v.w; - u.z = data[2][0] * v.x + data[2][1] * v.y + data[2][2] * v.z + data[2][3] * v.w; - u.w = data[3][0] * v.x + data[3][1] * v.y + data[3][2] * v.z + data[3][3] * v.w; - return u; - } - - friend Matrix operator*(const Vector3 &v, Matrix &m) { return m * v; }; -}; - -#endif diff -r 79b516a3803d -r 76b7bd51d64a src/noise.cc --- a/src/noise.cc Fri Nov 30 00:44:51 2007 +0100 +++ b/src/noise.cc Mon Dec 03 01:49:23 2007 +0100 @@ -8,20 +8,20 @@ #include "noise.h" -double fade(double t) +Float fade(Float t) { return t * t * t * (t * (t * 6 - 15) + 10); } -double lerp(double t, double a, double b) +Float lerp(Float t, Float a, Float b) { return a + t * (b - a); } -double grad(unsigned char hash, double x, double y, double z) +Float grad(unsigned char hash, Float x, Float y, Float z) { unsigned char h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE - double u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS. + Float u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS. v = h<4 ? y : h==12||h==14 ? x : z; return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); } @@ -56,7 +56,7 @@ }; -double perlin(double x, double y, double z) +Float perlin(Float x, Float y, Float z) { int X = (int)floor(x) & 255, // FIND UNIT CUBE THAT Y = (int)floor(y) & 255, // CONTAINS POINT. @@ -64,7 +64,7 @@ x -= floor(x); // FIND RELATIVE X,Y,Z y -= floor(y); // OF POINT IN CUBE. z -= floor(z); - double u = fade(x), // COMPUTE FADE CURVES + Float u = fade(x), // COMPUTE FADE CURVES v = fade(y), // FOR EACH OF X,Y,Z. w = fade(z); int A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, // HASH COORDINATES OF diff -r 79b516a3803d -r 76b7bd51d64a src/noise.h --- a/src/noise.h Fri Nov 30 00:44:51 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -#ifndef NOISE_H -#define NOISE_H - -double perlin(double x, double y, double z); - -#endif diff -r 79b516a3803d -r 76b7bd51d64a src/raytracer.cc --- a/src/raytracer.cc Fri Nov 30 00:44:51 2007 +0100 +++ b/src/raytracer.cc Mon Dec 03 01:49:23 2007 +0100 @@ -15,9 +15,9 @@ // Hammersley spherical point distribution // http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html -Vector3 Raytracer::SphereDistribute(int i, int n, float extent, Vector3 &normal) +Vector3 Raytracer::SphereDistribute(int i, int n, Float extent, Vector3 &normal) { - float p, t, st, phi, phirad; + Float p, t, st, phi, phirad; int kk; t = 0; @@ -31,7 +31,7 @@ st = sqrt(1.0 - t*t); - float x, y, z, xx, yy, zz, q; + Float x, y, z, xx, yy, zz, q; x = st * cos(phirad); y = st * sin(phirad); z = t; @@ -75,8 +75,8 @@ Colour I = Colour(); Vector3 L = light.pos - P; L.normalize(); - float L_dot_N = dot(L, N); - float R_dot_V = dot(R, V); + Float L_dot_N = dot(L, N); + Float R_dot_V = dot(R, V); Colour col = mat.texture.colour; //mat.texture.evaluate(P); @@ -91,7 +91,7 @@ Colour Raytracer::raytrace(Ray &ray, int depth, Shape *origin_shape) { - float nearest_distance = FLT_MAX; //Infinity + Float nearest_distance = Inf; Shape *nearest_shape = top->nearest_intersection(origin_shape, ray, nearest_distance); if (nearest_shape == NULL) { @@ -106,12 +106,12 @@ for (light = lights.begin(); light != lights.end(); light++) { Vector3 jo, L = (*light)->pos - P; // direction vector to light L.normalize(); - float L_dot_N = dot(L, normal); + Float L_dot_N = dot(L, normal); if (L_dot_N > 0) { // test if this light is occluded (sharp shadows) if ((*light)->cast_shadows) { Ray shadow_ray = Ray(P, L); - float dist = FLT_MAX; + Float dist = FLT_MAX; if (top->nearest_intersection(nearest_shape, shadow_ray, dist)) continue; } @@ -137,18 +137,18 @@ // ambient occlusion if (ao_samples) { - float miss = 0; + Float miss = 0; for (int i = 0; i < ao_samples; i++) { Vector3 dir = SphereDistribute(i, ao_samples, ao_angle, normal); Ray ao_ray = Ray(P, dir); - float dist = ao_distance; + Float dist = ao_distance; Shape *shape_in_way = top->nearest_intersection(nearest_shape, ao_ray, dist); if (shape_in_way == NULL) miss += 1.0; else miss += dist / ao_distance; } - float ao_intensity = miss / ao_samples; + Float ao_intensity = miss / ao_samples; acc = acc * ao_intensity; } @@ -160,7 +160,7 @@ { RenderrowData *d = (RenderrowData*) data; int subsample = d->rt->getSubsample(); - float subsample2 = 1.0/(subsample*subsample); + Float subsample2 = 1.0/(subsample*subsample); int ww = d->w*3; Vector3 dir = d->dfix; for (int x = 0; x < d->w; x += subsample) { @@ -171,8 +171,8 @@ for (int i = 0; i < 5; i++) { - float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4}; - float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4}; + Float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4}; + Float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4}; Vector3 tmpdir = dir + osax[i]*d->dx + osay[i]*d->dy; tmpdir.normalize(); Ray ray(d->eye, tmpdir); @@ -204,14 +204,14 @@ ray.dir = tmpdir; Colour c3 = d->rt->raytrace(ray, 0, NULL); // are the colors similar? - float m = (c-c2).mag2(); + Float m = (c-c2).mag2(); m = max(m, (c2-c3).mag2()); m = max(m, (c3-c4).mag2()); m = max(m, (c4-c).mag2()); if (m < 0.001) { // interpolate - float *i = d->iter; + Float *i = d->iter; for (int x = 0; x < subsample; x++) { for (int y = 0; y < subsample; y++) @@ -302,14 +302,14 @@ return (void *)d; } -void Raytracer::render(int w, int h, float *buffer) +void Raytracer::render(int w, int h, Float *buffer) { if (!camera || !top || !buffer) return; RenderrowData *d; - float S = 0.5/w; + Float S = 0.5/w; Vector3 dfix = camera->u*(-w/2.0*S/camera->f) + camera->v*(h/2.0*S/camera->f) + camera->p; Vector3 dx = camera->u * (S/camera->f); @@ -372,7 +372,7 @@ lights.push_back(light); } -void Raytracer::ambientocclusion(int samples, float distance, float angle) +void Raytracer::ambientocclusion(int samples, Float distance, Float angle) { ao_samples = samples; ao_distance = distance; diff -r 79b516a3803d -r 76b7bd51d64a src/raytracer.h --- a/src/raytracer.h Fri Nov 30 00:44:51 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * C++ RayTracer - * file: raytracer.h - * - * Radek Brich, 2006 - */ - -#ifndef RAYTRACER_H -#define RAYTRACER_H - -#include - -#include "common.h" -#include "kdtree.h" -#include "scene.h" - -using namespace std; - -class Raytracer; -struct RenderrowData { - Raytracer *rt; - int w; - Vector3 eye, dfix, dx, dy; - float *iter; -}; - -class Raytracer -{ - Container *top; - Camera *camera; - vector lights; - Colour bg_colour; - int ao_samples; - float ao_distance, ao_angle; - int num_threads; - int subsample; - int max_depth; - - Vector3 SphereDistribute(int i, int n, float extent, Vector3 &normal); -public: - Raytracer(): top(NULL), camera(NULL), lights(), bg_colour(0.0, 0.0, 0.0), - ao_samples(0), num_threads(4), subsample(8), max_depth(4) {}; - void render(int w, int h, float *buffer); - Colour raytrace(Ray &ray, int depth, Shape *origin_shape); - void addshape(Shape *shape) { top->addShape(shape); }; - void addlight(Light *light); - void setCamera(Camera *cam) { camera = cam; }; - void setTop(Container *atop) { top = atop; }; - Container *getTop() { return top; }; - int getSubsample() { return subsample; }; - void setMaxDepth(int newdepth) { max_depth = newdepth; }; - - void ambientocclusion(int samples, float distance, float angle); - void setThreads(int num) { num_threads = num; }; -}; - -#endif diff -r 79b516a3803d -r 76b7bd51d64a src/raytracermodule.cc --- a/src/raytracermodule.cc Fri Nov 30 00:44:51 2007 +0100 +++ b/src/raytracermodule.cc Mon Dec 03 01:49:23 2007 +0100 @@ -53,8 +53,8 @@ LightObject *v; static char *kwdlist[] = {"position", "colour", NULL}; PyObject *TPos, *TCol = NULL; - float px, py, pz; - float cr = 1.0, cg = 1.0, cb = 1.0; + Float px, py, pz; + Float cr = 1.0, cg = 1.0, cb = 1.0; if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!|O!", kwdlist, &PyTuple_Type, &TPos, &PyTuple_Type, &TCol)) @@ -133,7 +133,7 @@ MaterialObject *v; static char *kwdlist[] = {"colour", NULL}; PyObject *TCol = NULL; - float cr=1.0, cg=1.0, cb=1.0; + Float cr=1.0, cg=1.0, cb=1.0; if (!PyArg_ParseTupleAndKeywords(args, kwd, "|O!", kwdlist, &PyTuple_Type, &TCol)) @@ -198,7 +198,7 @@ MaterialObject *material; static char *kwdlist[] = {"centre", "radius", "material", NULL}; PyObject *TCentre = NULL; - float cx, cy, cz, radius; + Float cx, cy, cz, radius; if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!fO!", kwdlist, &PyTuple_Type, &TCentre, &radius, &MaterialType, &material)) @@ -265,7 +265,7 @@ static char *kwdlist[] = {"L", "H", "material", NULL}; PyObject *TL = NULL; PyObject *TH = NULL; - float lx, ly, lz, hx, hy, hz; + Float lx, ly, lz, hx, hy, hz; if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!", kwdlist, &PyTuple_Type, &TL, &PyTuple_Type, &TH, &MaterialType, &material)) @@ -334,7 +334,7 @@ MaterialObject *material; static char *kwdlist[] = {"A", "B", "C", "material", NULL}; PyObject *A = NULL, *B = NULL, *C = NULL; - float ax, ay, az, bx, by, bz, cx, cy, cz; + Float ax, ay, az, bx, by, bz, cx, cy, cz; if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!O!", kwdlist, &PyTuple_Type, &A, &PyTuple_Type, &B, &PyTuple_Type, &C, @@ -447,7 +447,7 @@ { int w = 0, h = 0; char *chardata; - float *data; + Float *data; PyObject *o; if (!PyArg_ParseTuple(args, "(ii)", &w, &h)) @@ -455,7 +455,7 @@ printf("[pyrit] Raytracing...\n"); ((RaytracerObject *)self)->raytracer->getTop()->optimize(); - data = (float *) malloc(w*h*3*sizeof(float)); + data = (Float *) malloc(w*h*3*sizeof(Float)); ((RaytracerObject *)self)->raytracer->render(w, h, data); if (!data) { Py_INCREF(Py_None); @@ -465,7 +465,7 @@ // convert data to char printf("[pyrit] Converting image data (float to char)...\n"); chardata = (char *) malloc(w*h*3); - float *d = data; + Float *d = data; for (char *c = chardata; c != chardata + w*h*3; c++, d++) { if (*d > 1.0) *c = 255; @@ -511,7 +511,7 @@ static PyObject* Raytracer_ambientocclusion(PyObject* self, PyObject* args, PyObject *kwd) { int samples = 0; - float distance = 0.0, angle = 0.0; + Float distance = 0.0, angle = 0.0; static char *kwdlist[] = {"samples", "distance", "angle", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwd, "iff", kwdlist, diff -r 79b516a3803d -r 76b7bd51d64a src/scene.cc --- a/src/scene.cc Fri Nov 30 00:44:51 2007 +0100 +++ b/src/scene.cc Mon Dec 03 01:49:23 2007 +0100 @@ -24,16 +24,16 @@ */ // optimized - float t2 = q.a*q.b; - float t3 = q.a*q.c; - float t4 = q.a*q.d; - float t5 = -q.b*q.b; - float t6 = q.b*q.c; - float t7 = q.b*q.d; - float t8 = -q.c*q.c; - float t9 = q.c*q.d; - float t10 = -q.d*q.d; - float x,y,z; + Float t2 = q.a*q.b; + Float t3 = q.a*q.c; + Float t4 = q.a*q.d; + Float t5 = -q.b*q.b; + Float t6 = q.b*q.c; + Float t7 = q.b*q.d; + Float t8 = -q.c*q.c; + Float t9 = q.c*q.d; + Float t10 = -q.d*q.d; + Float x,y,z; x = 2*( (t8 + t10)*p.x + (t6 - t4)*p.y + (t3 + t7)*p.z ) + p.x; y = 2*( (t4 + t6)*p.x + (t5 + t10)*p.y + (t9 - t2)*p.z ) + p.y; z = 2*( (t7 - t3)*p.x + (t2 + t9)*p.y + (t5 + t8)*p.z ) + p.z; @@ -51,17 +51,17 @@ v.normalize(); } -void Camera::move(const float fw, const float left, const float up) +void Camera::move(const Float fw, const Float left, const Float up) { eye = eye + fw*p + left*u + up*v; } /* http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter3.htm */ -bool BBox::intersect(const Ray &ray, float &a, float &b) +bool BBox::intersect(const Ray &ray, Float &a, Float &b) { - float tnear = -FLT_MAX; - float tfar = FLT_MAX; - float t1, t2; + Float tnear = -FLT_MAX; + Float tfar = FLT_MAX; + Float t1, t2; for (int i = 0; i < 3; i++) { @@ -94,11 +94,11 @@ return true; } -bool Sphere::intersect(const Ray &ray, float &dist) +bool Sphere::intersect(const Ray &ray, Float &dist) { Vector3 V = ray.o - center; - register float d = -dot(V, ray.dir); - register float Det = d * d - (dot(V,V) - sqr_radius); + register Float d = -dot(V, ray.dir); + register Float Det = d * d - (dot(V,V) - sqr_radius); if (Det > 0) { d -= sqrtf(Det); if (d > 0 && d < dist) @@ -110,18 +110,18 @@ return false; } -bool Sphere::intersect_all(const Ray &ray, float dist, vector &allts) +bool Sphere::intersect_all(const Ray &ray, Float dist, vector &allts) { - //allts = new vector(); + //allts = new vector(); Vector3 V = ((Ray)ray).o - center; - float Vd = - dot(V, ray.dir); - float Det = Vd * Vd - (dot(V,V) - sqr_radius); + Float Vd = - dot(V, ray.dir); + Float Det = Vd * Vd - (dot(V,V) - sqr_radius); if (Det > 0) { Det = sqrtf(Det); - float t1 = Vd - Det; - float t2 = Vd + Det; + Float t1 = Vd - Det; + Float t2 = Vd + Det; if (t1 < 0) { if (t2 > 0) @@ -152,9 +152,9 @@ return bbox; } -bool Box::intersect(const Ray &ray, float &dist) +bool Box::intersect(const Ray &ray, Float &dist) { - float a,b; + Float a,b; bool res = get_bbox().intersect(ray, a, b); if (res && a < dist) { @@ -216,13 +216,13 @@ int u = (k + 1) % 3; int v = (k + 2) % 3; - float krec = 1.0f / N[k]; + Float krec = 1.0f / N[k]; nu = N[u] * krec; nv = N[v] * krec; nd = dot(N, A) * krec; // first line equation - float reci = 1.0f / (b[u] * c[v] - b[v] * c[u]); + Float reci = 1.0f / (b[u] * c[v] - b[v] * c[u]); bnu = b[u] * reci; bnv = -b[v] * reci; @@ -235,7 +235,7 @@ } // see comment for previous method -bool Triangle::intersect(const Ray &ray, float &dist) +bool Triangle::intersect(const Ray &ray, Float &dist) { Vector3 O = ray.o; Vector3 D = ray.dir; @@ -243,20 +243,20 @@ const int modulo3[5] = {0,1,2,0,1}; const int ku = modulo3[k+1]; const int kv = modulo3[k+2]; - const float lnd = 1.0f / (D[k] + nu * D[ku] + nv * D[kv]); - const float t = (nd - O[k] - nu * O[ku] - nv * O[kv]) * lnd; + const Float lnd = 1.0f / (D[k] + nu * D[ku] + nv * D[kv]); + const Float t = (nd - O[k] - nu * O[ku] - nv * O[kv]) * lnd; if (!(t < dist && t > 0)) return false; - float hu = O[ku] + t * D[ku] - A[ku]; - float hv = O[kv] + t * D[kv] - A[kv]; - float beta = hv * bnu + hu * bnv; + Float hu = O[ku] + t * D[ku] - A[ku]; + Float hv = O[kv] + t * D[kv] - A[kv]; + Float beta = hv * bnu + hu * bnv; if (beta < 0) return false; - float gamma = hu * cnu + hv * cnv; + Float gamma = hu * cnu + hv * cnv; if (gamma < 0) return false; diff -r 79b516a3803d -r 76b7bd51d64a src/scene.h --- a/src/scene.h Fri Nov 30 00:44:51 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -/* - * C++ RayTracer - * file: scene.h - * - * Radek Brich, 2006 - */ - -#ifndef SCENE_H -#define SCENE_H - -#include - -#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 &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 &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 &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 &allts) {return false;}; - Vector3 normal(Vector3 &) { return N; }; - BBox get_bbox(); -}; - -#endif diff -r 79b516a3803d -r 76b7bd51d64a src/vector.h --- a/src/vector.h Fri Nov 30 00:44:51 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -/* - * C++ RayTracer - * file: vector.h - * - * Radek Brich, 2006 - */ - -#ifndef VECTOR_H -#define VECTOR_H - -#include -#include - -using namespace std; - -class Vector3 -{ -public: - // data - union { - struct { - float x, y, z; - }; - struct { - float r, g, b; - }; - float cell[3]; - }; - - // constructors - Vector3(): x(0.0f), y(0.0f), z(0.0f) {}; - Vector3(float ax, float ay, float az): x(ax), y(ay), z(az) {}; - - // index operator - float &operator[](int index) { return cell[index]; }; - - bool operator==(Vector3 &v) { return x==v.x && y==v.y && z==v.z; }; - - // normalize - Vector3 normalize() - { - float f = 1.0f / mag(); - x *= f; - y *= f; - z *= f; - return *this; - } - - // get normalized copy - Vector3 unit() - { - Vector3 u(*this); - return u.normalize();; - } - - // square magnitude, magnitude - float mag2() { return x * x + y * y + z * z; } - float mag() { return sqrtf(mag2()); } - - // negative - Vector3 operator-() { return Vector3(-x, -y, -z); } - - // accumulate - Vector3 operator+=(const Vector3 &v) - { - x += v.x; - y += v.y; - z += v.z; - return *this; - }; - - // sum - friend Vector3 operator+(const Vector3 &a, const Vector3 &b) - { - return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); - }; - - // difference - friend Vector3 operator-(const Vector3 &a, const Vector3 &b) - { - return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); - }; - - // dot product - friend float dot(const Vector3 &a, const Vector3 &b) - { - return a.x * b.x + a.y * b.y + a.z * b.z; - }; - - // cross product - friend Vector3 cross(const Vector3 &a, const Vector3 &b) - { - return Vector3(a.y * b.z - a.z * b.y, - a.z * b.x - a.x * b.z, - a.x * b.y - a.y * b.x); - }; - - // product of vector and scalar - friend Vector3 operator*(const Vector3 &v, const float &f) - { - return Vector3(f * v.x, f * v.y, f * v.z); - } - - friend Vector3 operator*(const float &f, const Vector3 &v) - { - return v * f; - }; - - // vector plus scalar - friend Vector3 operator+(const Vector3 &v, const float &f) - { - return Vector3(v.x + f, v.y + f, v.z + f); - } - - // vector minus scalar - friend Vector3 operator-(const Vector3 &v, const float &f) - { - return Vector3(v.x - f, v.y - f, v.z - f); - } - - // cell by cell product (only usable for colours) - friend Vector3 operator*(const Vector3 &a, const Vector3 &b) - { - return Vector3(a.x * b.x, a.y * b.y, a.z * b.z); - }; - - // print - friend ostream & operator<<(ostream &st, const Vector3 &v) - { - return st << "(" << v.x << ", " << v.y << ", " << v.z << ")"; - } -}; - -typedef Vector3 Colour; - -#endif