# HG changeset patch # User Radek Brich # Date 1196002201 -3600 # Node ID fc18ac4833f275f9115b41b5e7798fb0a5c70c0a # Parent fbd1d2f7d94eacde2d4799d2ff8fbbf6286c5db5 replace Plane with axis-aligned Box (because infinite Plane is not usable with kd-tree) fix memory leak in KdTree::nearest_intersection rename BBox::R to BBox::H new file: common.h (Eps and Inf constants) diff -r fbd1d2f7d94e -r fc18ac4833f2 Makefile --- a/Makefile Sat Nov 24 23:55:54 2007 +0100 +++ b/Makefile Sun Nov 25 15:50:01 2007 +0100 @@ -45,7 +45,7 @@ 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 +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 raytracer.o: src/raytracer.cc src/raytracer.h src/scene.h src/vector.h src/noise.h diff -r fbd1d2f7d94e -r fc18ac4833f2 README --- a/README Sat Nov 24 23:55:54 2007 +0100 +++ b/README Sun Nov 25 15:50:01 2007 +0100 @@ -2,6 +2,11 @@ Pyrit Ray Tracer ================== +License +------- +Currently unlicensed, you may not redistribute or use this work for any purposes. +Will be MIT licensed when ready. + Pthreads -------- Threads can be used to render rows of picture paralelly. Arbitrary number diff -r fbd1d2f7d94e -r fc18ac4833f2 TODO --- a/TODO Sat Nov 24 23:55:54 2007 +0100 +++ b/TODO Sun Nov 25 15:50:01 2007 +0100 @@ -5,10 +5,10 @@ * update Python binding, new classes * rename: - Ray.a -> Ray.o or Ray.origin - - BBox.R -> H * C++ demos * more complex demos + New Classes? ============ diff -r fbd1d2f7d94e -r fc18ac4833f2 demos/demo.py --- a/demos/demo.py Sat Nov 24 23:55:54 2007 +0100 +++ b/demos/demo.py Sun Nov 25 15:50:01 2007 +0100 @@ -3,7 +3,7 @@ import sys sys.path.append("..") -from raytracer import Raytracer, Material, Plane, Sphere, Light +from raytracer import Raytracer, Material, Box, Sphere, Light #, SphericalLight import Image @@ -17,8 +17,8 @@ rt.addlight(light2) mat0 = Material(colour=(0.1, 0.2, 0.9)) -plane = Plane(normal=(0.0, 1.0, 0.0), d=1.0, material=mat0) -rt.addshape(plane) +box = Box(L=(-20.0, -1.2, -20.0), H=(20.0, -1.0, 20.0), material=mat0) +rt.addshape(box) mat1 = Material(colour=(1.0, 0.2, 0.1)) bigsphere = Sphere(centre=(2.0, 2.0, 5.0), radius=2.5, material=mat1) @@ -42,4 +42,4 @@ rendersize = (800, 600) data = rt.render(rendersize) img = Image.fromstring("RGB", rendersize, data) -img.save('out.png') +img.save('demo.png') diff -r fbd1d2f7d94e -r fc18ac4833f2 demos/spheres_ao.py --- a/demos/spheres_ao.py Sat Nov 24 23:55:54 2007 +0100 +++ b/demos/spheres_ao.py Sun Nov 25 15:50:01 2007 +0100 @@ -3,7 +3,7 @@ import sys sys.path.append("..") -from raytracer import Raytracer, Material, Plane, Sphere, Light +from raytracer import Raytracer, Material, Box, Sphere, Light import Image rt = Raytracer() @@ -19,8 +19,8 @@ mat0 = Material(colour=(0.7, 0.7, 0.7)) -plane = Plane(normal=(0.0, 1.0, 0.0), d=1.0, material=mat0) -rt.addshape(plane) +box = Box(L=(-20.0, -1.2, -20.0), H=(20.0, -1.0, 20.0), material=mat0) +rt.addshape(box) mat1 = Material(colour=(1.0, 0.0, 0.0)) bigsphere = Sphere(centre=(3.0, 2.0, 7.0), radius=3.0, material=mat1) diff -r fbd1d2f7d94e -r fc18ac4833f2 demos/spheres_shadow.py --- a/demos/spheres_shadow.py Sat Nov 24 23:55:54 2007 +0100 +++ b/demos/spheres_shadow.py Sun Nov 25 15:50:01 2007 +0100 @@ -3,7 +3,7 @@ import sys sys.path.append("..") -from raytracer import Raytracer, Material, Plane, Sphere, Light +from raytracer import Raytracer, Material, Box, Sphere, Light import Image rt = Raytracer() @@ -16,8 +16,8 @@ mat0 = Material(colour=(0.7, 0.7, 0.7)) -plane = Plane(normal=(0.0, 1.0, 0.0), d=1.0, material=mat0) -rt.addshape(plane) +box = Box(L=(-20.0, -1.2, -20.0), H=(20.0, -1.0, 20.0), material=mat0) +rt.addshape(box) mat1 = Material(colour=(1.0, 0.0, 0.0)) bigsphere = Sphere(centre=(3.0, 2.0, 7.0), radius=3.0, material=mat1) diff -r fbd1d2f7d94e -r fc18ac4833f2 src/kdtree.cc --- a/src/kdtree.cc Sat Nov 24 23:55:54 2007 +0100 +++ b/src/kdtree.cc Sun Nov 25 15:50:01 2007 +0100 @@ -70,9 +70,9 @@ if (shapebb.L.x < bbox.L.x) bbox.L.x = shapebb.L.x; if (shapebb.L.y < bbox.L.y) bbox.L.y = shapebb.L.y; if (shapebb.L.z < bbox.L.z) bbox.L.z = shapebb.L.z; - if (shapebb.R.x > bbox.R.x) bbox.R.x = shapebb.R.x; - if (shapebb.R.y > bbox.R.y) bbox.R.y = shapebb.R.y; - if (shapebb.R.z > bbox.R.z) bbox.R.z = shapebb.R.z; + if (shapebb.H.x > bbox.H.x) bbox.H.x = shapebb.H.x; + if (shapebb.H.y > bbox.H.y) bbox.H.y = shapebb.H.y; + if (shapebb.H.z > bbox.H.z) bbox.H.z = shapebb.H.z; } }; @@ -112,7 +112,7 @@ for (sh = sslist.begin(); sh != sslist.end(); sh++) { splitlist.push_back(SplitPos(sh->bbox.L.cell[axis])); - splitlist.push_back(SplitPos(sh->bbox.R.cell[axis])); + splitlist.push_back(SplitPos(sh->bbox.H.cell[axis])); } sort(splitlist.begin(), splitlist.end()); // remove duplicate splits @@ -131,9 +131,9 @@ continue; } // if shape is completely contained in split plane - if (spl->pos == sh->bbox.L.cell[axis] == sh->bbox.R.cell[axis]) + if (spl->pos == sh->bbox.L.cell[axis] == sh->bbox.H.cell[axis]) { - if (spl->pos - bbox.L.cell[axis] < bbox.R.cell[axis] - spl->pos) + if (spl->pos - bbox.L.cell[axis] < bbox.H.cell[axis] - spl->pos) { // left subcell is smaller -> if not empty, put shape here if (spl->lnum) @@ -150,13 +150,13 @@ sh->setMark(); } else // if shape is on left side of split plane - if (sh->bbox.R.cell[axis] <= spl->pos) + if (sh->bbox.H.cell[axis] <= spl->pos) { spl->lnum++; sh->setMark(); } else // if shape occupies both sides of split plane - if (sh->bbox.L.cell[axis] < spl->pos && sh->bbox.R.cell[axis] > spl->pos) + if (sh->bbox.L.cell[axis] < spl->pos && sh->bbox.H.cell[axis] > spl->pos) { spl->lnum++; spl->rnum++; @@ -181,7 +181,7 @@ for (spl = splitlist.begin(); spl != splitlist.end(); spl++) { // calculate SAH cost of this split - lbb.R.cell[axis] = spl->pos; + 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()); @@ -209,12 +209,12 @@ v.cell[(axis+2)%3] = bbox.L.cell[(axis+2)%3]; F << "v " << v.x << " " << v.y << " " << v.z << endl; v.cell[(axis+1)%3] = bbox.L.cell[(axis+1)%3]; - v.cell[(axis+2)%3] = bbox.R.cell[(axis+2)%3]; + v.cell[(axis+2)%3] = bbox.H.cell[(axis+2)%3]; F << "v " << v.x << " " << v.y << " " << v.z << endl; - v.cell[(axis+1)%3] = bbox.R.cell[(axis+1)%3]; - v.cell[(axis+2)%3] = bbox.R.cell[(axis+2)%3]; + v.cell[(axis+1)%3] = bbox.H.cell[(axis+1)%3]; + v.cell[(axis+2)%3] = bbox.H.cell[(axis+2)%3]; F << "v " << v.x << " " << v.y << " " << v.z << endl; - v.cell[(axis+1)%3] = bbox.R.cell[(axis+1)%3]; + v.cell[(axis+1)%3] = bbox.H.cell[(axis+1)%3]; v.cell[(axis+2)%3] = bbox.L.cell[(axis+2)%3]; F << "v " << v.x << " " << v.y << " " << v.z << endl; F << "f " << f+1 << " " << f+2 << " " << f+3 << " " << f+4 << endl; @@ -238,11 +238,11 @@ } if (state == 0) { - if (sh->bbox.R.cell[axis] < split) + if (sh->bbox.H.cell[axis] < split) { // left children[0].addShape(sh->shape); } else - if (sh->bbox.R.cell[axis] > split) + if (sh->bbox.H.cell[axis] > split) { if (sh->bbox.L.cell[axis] < split) { // both @@ -254,13 +254,13 @@ state = 1; } } else - { // R == split + { // H == split if (sh->bbox.L.cell[axis] < split) { // left children[0].addShape(sh->shape); } else { // contained - if (split - bbox.L.cell[axis] < bbox.R.cell[axis] - split) + if (split - bbox.L.cell[axis] < bbox.H.cell[axis] - split) { // left subcell is smaller -> if not empty, put shape here if (lnum) @@ -279,7 +279,7 @@ } } - lbb.R.cell[axis] = split; + lbb.H.cell[axis] = split; rbb.L.cell[axis] = split; children[0].subdivide(lbb, depth+1); @@ -406,6 +406,7 @@ } /* pop from the stack */ + delete enPt; enPt = exPt; /* the signed distance intervals are adjacent */ /* retrieve the pointer to the next node, it is possible that ray traversal terminates */ @@ -416,6 +417,8 @@ st.pop(); } /* while */ + delete enPt; + /* ray leaves the scene */ return NULL; } diff -r fbd1d2f7d94e -r fc18ac4833f2 src/raytracer.cc --- a/src/raytracer.cc Sat Nov 24 23:55:54 2007 +0100 +++ b/src/raytracer.cc Sun Nov 25 15:50:01 2007 +0100 @@ -11,7 +11,7 @@ #include #include -#include +#include "common.h" #include "raytracer.h" // Hammersley spherical point distribution diff -r fbd1d2f7d94e -r fc18ac4833f2 src/raytracermodule.cc --- a/src/raytracermodule.cc Sat Nov 24 23:55:54 2007 +0100 +++ b/src/raytracermodule.cc Sun Nov 25 15:50:01 2007 +0100 @@ -224,27 +224,27 @@ return Py_FindMethod(SphereMethods, self, name); } -//=========================== Plane Object =========================== +//=========================== Box Object =========================== typedef struct { PyObject_HEAD - Plane *shape; -} PlaneObject; + Box *shape; +} BoxObject; -static PyObject *Plane_Constructor(PyObject* self, PyObject* args, PyObject *kwd); -static void Plane_Destructor(PyObject* self); -static PyObject *Plane_Getattr(PyObject *self, char *name); +static PyObject *Box_Constructor(PyObject* self, PyObject* args, PyObject *kwd); +static void Box_Destructor(PyObject* self); +static PyObject *Box_Getattr(PyObject *self, char *name); -static PyTypeObject PlaneType = { +static PyTypeObject BoxType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ - "Plane", /*tp_name*/ - sizeof(PlaneObject), /*tp_basicsize*/ + "Box", /*tp_name*/ + sizeof(BoxObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ - Plane_Destructor, /*tp_dealloc*/ + Box_Destructor, /*tp_dealloc*/ 0, /*tp_print*/ - Plane_Getattr, /*tp_getattr*/ + Box_Getattr, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ @@ -254,40 +254,44 @@ 0, /*tp_hash */ }; -static PyMethodDef PlaneMethods[] = { +static PyMethodDef BoxMethods[] = { {NULL, NULL} }; -static PyObject* Plane_Constructor(PyObject* self, PyObject* args, PyObject *kwd) +static PyObject* Box_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { - PlaneObject *v; + BoxObject *v; MaterialObject *material; - static char *kwdlist[] = {"normal", "d", "material", NULL}; - PyObject *TNorm = NULL; - float nx, ny, nz, d; + static char *kwdlist[] = {"L", "H", "material", NULL}; + PyObject *TL = NULL; + PyObject *TH = NULL; + float lx, ly, lz, hx, hy, hz; - if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!fO!", kwdlist, - &PyTuple_Type, &TNorm, &d, &MaterialType, &material)) + if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!", kwdlist, + &PyTuple_Type, &TL, &PyTuple_Type, &TH, &MaterialType, &material)) return NULL; - if (!PyArg_ParseTuple(TNorm, "fff", &nx, &ny, &nz)) + if (!PyArg_ParseTuple(TL, "fff", &lx, &ly, &lz)) return NULL; - v = PyObject_New(PlaneObject, &PlaneType); - v->shape = new Plane(Vector3(nx, ny, nz), d, material->material); + if (!PyArg_ParseTuple(TH, "fff", &hx, &hy, &hz)) + return NULL; + + v = PyObject_New(BoxObject, &BoxType); + v->shape = new Box(Vector3(lx, ly, lz), Vector3(hx, hy, hz), material->material); Py_INCREF(material); return (PyObject*)v; } -static void Plane_Destructor(PyObject* self) +static void Box_Destructor(PyObject* self) { - delete ((PlaneObject *)self)->shape; + delete ((BoxObject *)self)->shape; PyObject_Del(self); } -static PyObject *Plane_Getattr(PyObject *self, char *name) +static PyObject *Box_Getattr(PyObject *self, char *name) { - return Py_FindMethod(PlaneMethods, self, name); + return Py_FindMethod(BoxMethods, self, name); } //=========================== Triangle Object =========================== @@ -479,7 +483,7 @@ return NULL; ((RaytracerObject *)self)->raytracer->addshape( - ((PlaneObject*)obj)->shape); + ((BoxObject*)obj)->shape); ((RaytracerObject *)self)->children->push_back(obj); Py_INCREF(obj); @@ -526,8 +530,8 @@ METH_VARARGS | METH_KEYWORDS, "Material object constructor."}, {"Sphere", (PyCFunction) Sphere_Constructor, METH_VARARGS | METH_KEYWORDS, "Sphere object constructor."}, - {"Plane", (PyCFunction) Plane_Constructor, - METH_VARARGS | METH_KEYWORDS, "Plane object constructor."}, + {"Box", (PyCFunction) Box_Constructor, + METH_VARARGS | METH_KEYWORDS, "Box object constructor."}, {"Triangle", (PyCFunction) Triangle_Constructor, METH_VARARGS | METH_KEYWORDS, "Triangle object constructor."}, {NULL, NULL} diff -r fbd1d2f7d94e -r fc18ac4833f2 src/scene.cc --- a/src/scene.cc Sat Nov 24 23:55:54 2007 +0100 +++ b/src/scene.cc Sun Nov 25 15:50:01 2007 +0100 @@ -6,8 +6,8 @@ */ #include -#include +#include "common.h" #include "scene.h" /* http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter3.htm */ @@ -21,13 +21,13 @@ { if (ray.dir.cell[i] == 0) { /* ray is parallel to these planes */ - if (ray.a.cell[i] < L.cell[i] || ray.a.cell[i] > R.cell[i]) + if (ray.a.cell[i] < L.cell[i] || ray.a.cell[i] > H.cell[i]) return false; } else { /* compute the intersection distance of the planes */ t1 = (L.cell[i] - ray.a.cell[i]) / ray.dir.cell[i]; - t2 = (R.cell[i] - ray.a.cell[i]) / ray.dir.cell[i]; + t2 = (H.cell[i] - ray.a.cell[i]) / ray.dir.cell[i]; if (t1 > t2) swap(t1, t2); @@ -114,32 +114,40 @@ BBox Sphere::get_bbox() { BBox bbox = BBox(); - bbox.L.x = center.x - radius; - bbox.L.y = center.y - radius; - bbox.L.z = center.z - radius; - bbox.R.x = center.x + radius; - bbox.R.y = center.y + radius; - bbox.R.z = center.z + radius; + bbox.L = center - radius; + //bbox.L.y = center.y - radius; + //bbox.L.z = center.z - radius; + bbox.H = center + radius; + //bbox.H.y = center.y + radius; + //bbox.H.z = center.z + radius; return bbox; } -bool Plane::intersect(const Ray &ray, float &dist) +bool Box::intersect(const Ray &ray, float &dist) { - float dir = dot(N, ray.dir); - if (dir != 0) - { - float newdist = -(dot(N, ray.a) + d) / dir; - if (newdist > 0 && newdist < dist) { - dist = newdist; - return true; - } - } - return false; + float b; + return get_bbox().intersect(ray, dist, b); } -BBox Plane::get_bbox() +Vector3 Box::normal(Vector3 &P) { - return BBox(); + Vector3 N(0,1,0); + /*for (int i = 0; i < 3; i++) + { + if (P.cell[i] >= L.cell[i]-Eps && P.cell[i] <= L.cell[i]+Eps) + //if (P.cell[i] == L.cell[i]) + { + N.cell[i] = -1.0; + break; + } + if (P.cell[i] >= H.cell[i]-Eps && P.cell[i] <= H.cell[i]+Eps) + //if (P.cell[i] == H.cell[i]) + { + N.cell[i] = +1.0; + break; + } + }*/ + return N; } // this initialization and following intersection methods implements @@ -233,12 +241,12 @@ if (C.y < bbox.L.y) bbox.L.y = C.y; if (B.z < bbox.L.z) bbox.L.z = B.z; if (C.z < bbox.L.z) bbox.L.z = C.z; - bbox.R = A; - if (B.x > bbox.R.x) bbox.R.x = B.x; - if (C.x > bbox.R.x) bbox.R.x = C.x; - if (B.y > bbox.R.y) bbox.R.y = B.y; - if (C.y > bbox.R.y) bbox.R.y = C.y; - if (B.z > bbox.R.z) bbox.R.z = B.z; - if (C.z > bbox.R.z) bbox.R.z = C.z; + bbox.H = A; + if (B.x > bbox.H.x) bbox.H.x = B.x; + if (C.x > bbox.H.x) bbox.H.x = C.x; + if (B.y > bbox.H.y) bbox.H.y = B.y; + if (C.y > bbox.H.y) bbox.H.y = C.y; + if (B.z > bbox.H.z) bbox.H.z = B.z; + if (C.z > bbox.H.z) bbox.H.z = C.z; return bbox; }; diff -r fbd1d2f7d94e -r fc18ac4833f2 src/scene.h --- a/src/scene.h Sat Nov 24 23:55:54 2007 +0100 +++ b/src/scene.h Sun Nov 25 15:50:01 2007 +0100 @@ -29,11 +29,12 @@ { public: Vector3 L; - Vector3 R; - BBox(): L(), R() {}; - float w() { return R.x-L.x; }; - float h() { return R.y-L.y; }; - float d() { return R.z-L.z; }; + 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); }; @@ -118,20 +119,22 @@ BBox get_bbox(); }; -class Plane: public Shape +class Box: public Shape { + Vector3 L; + Vector3 H; public: - Vector3 N; - float d; - - Plane(const Vector3 &normal, const float ad, Material *amaterial): - N(normal), d(ad) { material = amaterial; }; - Plane(const Vector3 &normal, const Vector3 &point): - N(normal), d(0) { /*TODO*/}; + 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 &) { return N; }; - BBox get_bbox(); + Vector3 normal(Vector3 &P); + BBox get_bbox() { return BBox(L, H); }; }; class Triangle: public Shape diff -r fbd1d2f7d94e -r fc18ac4833f2 src/vector.h --- a/src/vector.h Sat Nov 24 23:55:54 2007 +0100 +++ b/src/vector.h Sun Nov 25 15:50:01 2007 +0100 @@ -99,11 +99,23 @@ return Vector3(f * v.x, f * v.y, f * v.z); } - friend Vector3 operator*(const float &f, Vector3 &v) + 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) {