kd-tree building - check all axes for best split, add additional shape-bbox check
extent Container bounds by Eps to fix invisible triangles on borders
new Camera constructor with more intuitive lookat/up vectors
fix camera axes (mirrored images)
better camera angle-of-view
change capitalization of addShape and addLight
--- a/TODO Sat Apr 19 18:00:27 2008 +0200
+++ b/TODO Sun Apr 20 16:48:24 2008 +0200
@@ -10,7 +10,7 @@
* kd-tree:
- optimize structures
- optimize construction: use box-shape intersection instead of bounding boxes of shapes
- - optimize traversal -- no std::vector
+ - optimize traversal -- no std::vector, no dynamic memory allocation
- save/load
* textures (3D procedural, pixmaps)
* update Python binding: Camera, other new classes
@@ -18,7 +18,7 @@
* absorbtion of refracted rays in dense materials (can be computed using shape distance and some 'absorbance' constant)
* implement efficient AABB-ray intersection using Plucker coordinates
* generalization: Camera "shader" (ray generator), surface shader and maybe light & background shaders
-
+ * unify capitalization of method names in C++ and Python
New Classes?
============
--- a/ccdemos/common_ply.h Sat Apr 19 18:00:27 2008 +0200
+++ b/ccdemos/common_ply.h Sun Apr 20 16:48:24 2008 +0200
@@ -58,7 +58,7 @@
}
f >> v1 >> v2 >> v3;
face = new Triangle(vertices.at(v1), vertices.at(v3), vertices.at(v2), mat);
- rt.addshape(face);
+ rt.addShape(face);
normals.at(v1) += face->getNormal();
vertex_face_num.at(v1)++;
--- a/ccdemos/common_sdl.h Sat Apr 19 18:00:27 2008 +0200
+++ b/ccdemos/common_sdl.h Sun Apr 20 16:48:24 2008 +0200
@@ -94,11 +94,11 @@
break;
}
if (event.key.keysym.sym == SDLK_LEFT) {
- roty = -0.01;
+ roty = +0.01;
break;
}
if (event.key.keysym.sym == SDLK_RIGHT) {
- roty = +0.01;
+ roty = -0.01;
break;
}
if (event.key.keysym.sym == SDLK_DOWN) {
--- a/ccdemos/realtime.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/ccdemos/realtime.cc Sun Apr 20 16:48:24 2008 +0200
@@ -16,16 +16,16 @@
Light light1(Vector3(2.0, -5.0, -5.0), Colour(0.7, 0.3, 0.6));
light1.castShadows(false);
- rt.addlight(&light1);
+ rt.addLight(&light1);
Light light2(Vector3(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3));
light2.castShadows(false);
- rt.addlight(&light2);
+ rt.addLight(&light2);
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)rand()/RAND_MAX*5.0, y*2-10), 0.45, &mat_sph));
+ rt.addShape(new Sphere(Vector3(x*2-10, (Float)rand()/RAND_MAX*5.0, y*2-10), 0.45, &mat_sph));
rt.setCamera(&cam);
cam.setEye(Vector3(0,0,10));
--- a/ccdemos/realtime_bunny.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/ccdemos/realtime_bunny.cc Sun Apr 20 16:48:24 2008 +0200
@@ -15,11 +15,11 @@
Light light1(Vector3(-5.0, 2.0, 8.0), Colour(0.9, 0.3, 0.6));
light1.castShadows(false);
- rt.addlight(&light1);
+ rt.addLight(&light1);
//Light light2(Vector3(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3));
//light2.castShadows(false);
- //rt.addlight(&light2);
+ //rt.addLight(&light2);
Material mat(Colour(0.9, 0.9, 0.9));
mat.setSmooth(true);
--- a/ccdemos/realtime_dragon.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/ccdemos/realtime_dragon.cc Sun Apr 20 16:48:24 2008 +0200
@@ -15,7 +15,7 @@
Light light1(Vector3(-5.0, 2.0, 8.0), Colour(0.9, 0.3, 0.6));
light1.castShadows(false);
- rt.addlight(&light1);
+ rt.addLight(&light1);
//Light light2(Vector3(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3));
//light2.castShadows(false);
--- a/ccdemos/spheres_shadow.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/ccdemos/spheres_shadow.cc Sun Apr 20 16:48:24 2008 +0200
@@ -18,7 +18,7 @@
if (lz != 0.0)
light.pos.z += lz;
if (cf != 0.0)
- cam.f += cf;
+ cam.F += cf;
}
void key_callback(int key, int down)
@@ -60,35 +60,35 @@
Octree top;
rt.setTop(&top);
- rt.addlight(&light);
+ rt.addLight(&light);
//Light light2;
//light2.colour = Colour(0.7, 0.3, 0.6);
- //rt.addlight(&light2);
+ //rt.addLight(&light2);
Material mat0a(Colour(0.7, 0.7, 0.7));
mat0a. setReflectivity(0.0);
Box box(Vector3(-10.0, -1.2, -20.0), Vector3(10.0, -1.0, 0.0), &mat0a);
- rt.addshape(&box);
+ rt.addShape(&box);
Material mat0b(Colour(0.1, 0.7, 0.8));
mat0b.setReflectivity(0.7);
Box box2(Vector3(-10.0, -1.2, -20.0), Vector3(10.0, 10.0, -20.2), &mat0b);
- rt.addshape(&box2);
+ rt.addShape(&box2);
Material mat1(Colour(1.0, 0.0, 0.0));
Sphere bigsphere(Vector3(3.0, 2.0, -7.0), 3.0, &mat1);
- rt.addshape(&bigsphere);
+ rt.addShape(&bigsphere);
Material mat2(Colour(0.0, 1.0, 0.0));
Sphere smallsphere(Vector3(-5.5, 1.5, -8.0), 2.0, &mat2);
- rt.addshape(&smallsphere);
+ rt.addShape(&smallsphere);
Material mat3(Colour(0.0, 0.0, 1.0));
mat3.setReflectivity(0.1);
mat3.setTransmissivity(0.8, 1.5);
Sphere tinysphere(Vector3(-1.2, 0.0, -2.0), 0.7, &mat3);
- rt.addshape(&tinysphere);
+ rt.addShape(&tinysphere);
top.optimize();
--- a/ccdemos/textures.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/ccdemos/textures.cc Sun Apr 20 16:48:24 2008 +0200
@@ -4,7 +4,7 @@
#include "image.h"
#include "common_sdl.h"
-Camera cam;
+Camera cam(Vector3(0.,6.,6.), Vector3(0.,2.,-7.), Vector3(0.,0.,-1.));
Light light(Vector3(-2.0, 10.0, -2.0), Colour(0.9, 0.9, 0.9));
Float lx, ly, lz, cf;
@@ -149,7 +149,7 @@
if (lz != 0.0)
light.pos.z += lz;
if (cf != 0.0)
- cam.f += cf;
+ cam.F += cf;
}
void key_callback(int key, int down)
@@ -189,62 +189,63 @@
Raytracer rt;
Octree top;
+ rt.setCamera(&cam);
rt.setTop(&top);
- rt.addlight(&light);
+ rt.addLight(&light);
light.castShadows(false);
Material mat0a(Colour(0.7, 0.7, 0.7));
mat0a. setReflectivity(0.0);
Box box(Vector3(-12.0, -1.2, -20.0), Vector3(12.0, -1.0, 0.0), &mat0a);
- rt.addshape(&box);
+ rt.addShape(&box);
Material mat0b(Colour(0.1, 0.7, 0.8));
mat0b.setReflectivity(0.7);
Box box2(Vector3(-12.0, -1.2, -10.0), Vector3(12.0, 10.0, -10.2), &mat0b);
- rt.addshape(&box2);
+ rt.addShape(&box2);
// spheres
Material mat1(Colour(1.0, 1.0, 1.0));
- mat1.texture = new PlanarMapTexture(Vector3(4.0, 2.0, -7.0));
- Sphere sphere1(Vector3(4.0, 2.0, -7.0), 1.0, &mat1);
- rt.addshape(&sphere1);
+ mat1.texture = new PlanarMapTexture(Vector3(-4.5, 2.0, -7.0));
+ Sphere sphere1(Vector3(-4.5, 2.0, -7.0), 1.0, &mat1);
+ rt.addShape(&sphere1);
Material mat2(Colour(1.0, 1.0, 1.0));
- mat2.texture = new CubicMapTexture(Vector3(1.0, 2.0, -7.0));
- Sphere sphere2(Vector3(1.0, 2.0, -7.0), 1.0, &mat2);
- rt.addshape(&sphere2);
+ mat2.texture = new CubicMapTexture(Vector3(-1.5, 2.0, -7.0));
+ Sphere sphere2(Vector3(-1.5, 2.0, -7.0), 1.0, &mat2);
+ rt.addShape(&sphere2);
Material mat3(Colour(1.0, 1.0, 1.0));
- mat3.texture = new CylinderMapTexture(Vector3(-2.0, 2.0, -7.0));
- Sphere sphere3(Vector3(-2.0, 2.0, -7.0), 1.0, &mat3);
- rt.addshape(&sphere3);
+ mat3.texture = new CylinderMapTexture(Vector3(1.5, 2.0, -7.0));
+ Sphere sphere3(Vector3(1.5, 2.0, -7.0), 1.0, &mat3);
+ rt.addShape(&sphere3);
Material mat4(Colour(1.0, 1.0, 1.0));
- mat4.texture = new SphereMapTexture(Vector3(-5.0, 2.0, -7.0));
- Sphere sphere4(Vector3(-5.0, 2.0, -7.0), 1.0, &mat4);
- rt.addshape(&sphere4);
+ mat4.texture = new SphereMapTexture(Vector3(4.5, 2.0, -7.0));
+ Sphere sphere4(Vector3(4.5, 2.0, -7.0), 1.0, &mat4);
+ rt.addShape(&sphere4);
// cubes
Material mat5(Colour(1.0, 1.0, 1.0));
- mat5.texture = new PlanarMapTexture(Vector3(4.0, 0.0, -7.0));
- Box cube1(Vector3(4.0, 0.0, -7.0)-1.0, Vector3(4.0, 0.0, -7.0)+1.0, &mat5);
- rt.addshape(&cube1);
+ mat5.texture = new PlanarMapTexture(Vector3(-4.5, 0.0, -7.0));
+ Box cube1(Vector3(-4.5, 0.0, -7.0)-1.0, Vector3(-4.5, 0.0, -7.0)+1.0, &mat5);
+ rt.addShape(&cube1);
Material mat6(Colour(1.0, 1.0, 1.0));
- mat6.texture = new CubicMapTexture(Vector3(1.0, 0.0, -7.0));
- Box cube2(Vector3(1.0, 0.0, -7.0)-1.0, Vector3(1.0, 0.0, -7.0)+1.0, &mat6);
- rt.addshape(&cube2);
+ mat6.texture = new CubicMapTexture(Vector3(-1.5, 0.0, -7.0));
+ Box cube2(Vector3(-1.5, 0.0, -7.0)-1.0, Vector3(-1.5, 0.0, -7.0)+1.0, &mat6);
+ rt.addShape(&cube2);
Material mat7(Colour(1.0, 1.0, 1.0));
- mat7.texture = new CylinderMapTexture(Vector3(-2.0, 0.0, -7.0));
- Box cube3(Vector3(-2.0, 0.0, -7.0)-1.0, Vector3(-2.0, 0.0, -7.0)+1.0, &mat7);
- rt.addshape(&cube3);
+ mat7.texture = new CylinderMapTexture(Vector3(1.5, 0.0, -7.0));
+ Box cube3(Vector3(1.5, 0.0, -7.0)-1.0, Vector3(1.5, 0.0, -7.0)+1.0, &mat7);
+ rt.addShape(&cube3);
Material mat8(Colour(1.0, 1.0, 1.0));
- mat8.texture = new SphereMapTexture(Vector3(-5.0, 0.0, -7.0));
- Box cube4(Vector3(-5.0, 0.0, -7.0)-1.0, Vector3(-5.0, 0.0, -7.0)+1.0, &mat8);
- rt.addshape(&cube4);
+ mat8.texture = new SphereMapTexture(Vector3(4.5, 0.0, -7.0));
+ Box cube4(Vector3(4.5, 0.0, -7.0)-1.0, Vector3(4.5, 0.0, -7.0)+1.0, &mat8);
+ rt.addShape(&cube4);
mat1.setReflectivity(0);
mat2.setReflectivity(0);
@@ -257,12 +258,6 @@
top.optimize();
- cam.setEye(Vector3(-0.530505, 11.0964, 11.2208));
- cam.p = Vector3(-4.18144e-08, -0.461779, -0.886995);
- cam.u = Vector3(-1, 0, 6.3393e-11);
- cam.v = Vector3(3.19387e-08, 0.886995, -0.461779);
- rt.setCamera(&cam);
-
w = 1024;
h = 600;
--- a/demos/SConscript Sat Apr 19 18:00:27 2008 +0200
+++ b/demos/SConscript Sun Apr 20 16:48:24 2008 +0200
@@ -6,7 +6,8 @@
'boxes.py', 'buddha.py', 'bunny.py', 'car.py', 'dragon.py',
'spheres_ao.py', 'spheres_glass.py', 'spheres_shadow.py',
'triangles_monkey.py', 'triangles_sphere.py',
- 'objreader.py', 'plyreader.py', 'lworeader.py']
+ 'objreader.py', 'plyreader.py', 'lworeader.py',
+ 'vector.py', 'render_nff.py']
l = []
for file in files:
--- a/demos/lworeader.py Sat Apr 19 18:00:27 2008 +0200
+++ b/demos/lworeader.py Sun Apr 20 16:48:24 2008 +0200
@@ -3,6 +3,7 @@
from math import *
from struct import *
from raytracer import Triangle, NormalVertex, Material
+from vector import dot
def read_int4(f):
return unpack('>i', f.read(4))[0]
@@ -153,12 +154,6 @@
(ID,size) = read_chunk(f)
return (points, faces, tags, surfaces)
-def dot(a,b):
- sum = 0
- for i in range(min(len(a),len(b))):
- sum += a[i]*b[i]
- return sum
-
def LoadLightwaveLwoFile(rt, filename, scale=(1,1,1), trans=(0,0,0)):
if (type(scale) == float or type(scale) == int):
scale = (scale,)*3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/render_nff.py Sun Apr 20 16:48:24 2008 +0200
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+# read nff data from standart input and render image to render_nff.png
+# see http://tog.acm.org/resources/SPD/
+# only spheres and triangles are implemented
+
+from raytracer import Raytracer, Camera, Light, Material, Sphere, NormalVertex, Triangle
+from math import pi
+import sys, Image
+
+rt = Raytracer()
+imagesize = (800, 600)
+
+mat = Material(colour=(1.0, 1.0, 1.0))
+
+f = sys.stdin
+while True:
+ line = f.readline()
+ if line == "":
+ break;
+ ln = line.split()
+ if ln[0] == 'v': # Viewpoint location
+ # from
+ ln = f.readline().split()
+ assert ln[0] == 'from'
+ eye = (float(ln[1]), float(ln[2]), float(ln[3]))
+ # at
+ ln = f.readline().split()
+ assert ln[0] == 'at'
+ lookat = (float(ln[1]), float(ln[2]), float(ln[3]))
+ # up
+ ln = f.readline().split()
+ assert ln[0] == 'up'
+ up = (float(ln[1]), float(ln[2]), float(ln[3]))
+ # angle
+ ln = f.readline().split()
+ assert ln[0] == 'angle'
+ angle = float(ln[1])
+ # hither
+ ln = f.readline().split()
+ assert ln[0] == 'hither'
+ hither = float(ln[1])
+ # resolution
+ ln = f.readline().split()
+ assert ln[0] == 'resolution'
+ imagesize = (int(ln[1]), int(ln[2]))
+ # set camera as specified
+ cam = Camera(eye=eye, lookat=lookat, up=up)
+ cam.setAngle(angle/180*pi)
+ rt.setcamera(cam)
+ elif ln[0] == 'b': # Background color
+ rt.setbgcolour((float(ln[1]), float(ln[2]), float(ln[3])))
+ elif ln[0] == 'l': # Light
+ pos = (float(ln[1]), float(ln[2]), float(ln[3]))
+ rt.addlight(Light(position=pos))
+ elif ln[0] == 'f': # Fill color and shading parameters
+ colour = (float(ln[1]), float(ln[2]), float(ln[3]))
+ mat = Material(colour=colour)
+ mat.setPhong(0,float(ln[4]),float(ln[5]),float(ln[6]))
+ mat.setTransmissivity(float(ln[7]),float(ln[8]))
+ elif ln[0] == 's': # Sphere
+ center = (float(ln[1]), float(ln[2]), float(ln[3]))
+ radius = float(ln[4])
+ rt.addshape(Sphere(centre=center, radius=radius, material=mat))
+ elif ln[0] == 'p': # Polygon
+ vertex_count = int(ln[1])
+ vertices = []
+ for i in range(vertex_count):
+ ln = f.readline().split()
+ vertex = (float(ln[0]), float(ln[1]), float(ln[2]))
+ vertices.append(NormalVertex(vertex))
+ rt.addshape(Triangle(vertices[0], vertices[1], vertices[2], mat))
+ for i in range(vertex_count)[3:]:
+ rt.addshape(Triangle(vertices[0], vertices[i-1], vertices[i], mat))
+ else:
+ print "Not implemented:", line
+f.close()
+
+data = rt.render(imagesize)
+img = Image.fromstring("RGB", imagesize, data)
+img.save('render_nff.png')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/vector.py Sun Apr 20 16:48:24 2008 +0200
@@ -0,0 +1,24 @@
+from math import *
+
+def dot(a,b):
+ sum = 0
+ for i in range(min(len(a),len(b))):
+ sum += a[i]*b[i]
+ return sum
+
+def cross(a,b):
+ return (
+ a[1]*b[2] - a[2]*b[1],
+ a[2]*b[0] - a[0]*b[2],
+ a[0]*b[1] - a[1]*b[0]
+ )
+
+def unit(a):
+ m = mag(a)
+ return (a[0]/m, a[1]/m, a[2]/m)
+
+def mag(a):
+ return sqrt(mag2(a))
+
+def mag2(a):
+ return a[0]*a[0] + a[1]*a[1] + a[2]*a[2]
--- a/include/raytracer.h Sat Apr 19 18:00:27 2008 +0200
+++ b/include/raytracer.h Sun Apr 20 16:48:24 2008 +0200
@@ -70,7 +70,7 @@
static void *raytrace_worker(void *d);
public:
- Raytracer(): top(NULL), camera(NULL), lights(), bg_colour(0.0, 0.0, 0.0),
+ Raytracer(): top(NULL), camera(NULL), lights(), bg_colour(0., 0., 0.),
ao_samples(0), num_threads(2), max_depth(3)
{
pthread_mutex_init(&sample_queue_mutex, NULL);
@@ -88,13 +88,14 @@
void render();
Colour raytrace(Ray &ray, int depth, Shape *origin_shape);
- void addshape(Shape *shape) { top->addShape(shape); };
- void addlight(Light *light);
+ void addShape(Shape *shape) { top->addShape(shape); };
+ void addLight(Light *light) { lights.push_back(light); };
void setSampler(Sampler *sampl) { sampler = sampl; };
void setCamera(Camera *cam) { camera = cam; };
void setTop(Container *atop) { top = atop; };
Container *getTop() { return top; };
+ void setBgColour(const Colour &bg) { bg_colour = bg; };
void setMaxDepth(int newdepth) { max_depth = newdepth; };
void ambientocclusion(int samples, Float distance, Float angle);
--- a/include/scene.h Sat Apr 19 18:00:27 2008 +0200
+++ b/include/scene.h Sun Apr 20 16:48:24 2008 +0200
@@ -64,19 +64,26 @@
{
public:
Vector3 eye, p, u, v;
- Float f,F;
+ Float F;
- Camera(): eye(0,0,10), p(0,0,-1), u(-1,0,0), v(0,1,0), f(3.14/4.0), F(0.5/f) {};
+ Camera(): eye(0,0,10), p(0,0,-1), u(-1,0,0), v(0,1,0), F(0.7071) {};
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), F(0.5/f) {};
+ eye(C), p(ap), u(au), v(av), F(0.7071) {};
+ Camera(const Vector3 &from, const Vector3 &lookat, const Vector3 &up):
+ eye(from), F(0.7071)
+ {
+ p = lookat - from; u = cross(up, p);
+ p.normalize(); u.normalize();
+ v = cross(p, u);
+ };
void setEye(const Vector3 &aeye) { eye = aeye; };
- void setFocalLength(const Float af) { f = af; F = 0.5/f; };
+ void setAngle(const Float angle) { F = sin(angle); };
void rotate(const Quaternion &q);
void move(const Float fw, const Float left, const Float up);
Ray makeRay(Sample &samp)
{
- Vector3 dir = p + (u*samp.x - v*samp.y)*F;
+ Vector3 dir = p - (u*samp.x + v*samp.y)*F;
dir.normalize();
return Ray(eye, dir);
};
--- a/src/container.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/src/container.cc Sun Apr 20 16:48:24 2008 +0200
@@ -33,15 +33,17 @@
if (shapes.size() == 0) {
/* initialize bounding box */
bbox = aShape->get_bbox();
+ Vector3 eps(Eps,Eps,Eps);
+ bbox = BBox(bbox.L - eps, bbox.H + eps);
} else {
/* adjust bounding box */
BBox shapebb = aShape->get_bbox();
- 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.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;
+ if (shapebb.L.x - Eps < bbox.L.x) bbox.L.x = shapebb.L.x - Eps;
+ if (shapebb.L.y - Eps < bbox.L.y) bbox.L.y = shapebb.L.y - Eps;
+ if (shapebb.L.z - Eps < bbox.L.z) bbox.L.z = shapebb.L.z - Eps;
+ if (shapebb.H.x + Eps > bbox.H.x) bbox.H.x = shapebb.H.x + Eps;
+ if (shapebb.H.y + Eps > bbox.H.y) bbox.H.y = shapebb.H.y + Eps;
+ if (shapebb.H.z + Eps > bbox.H.z) bbox.H.z = shapebb.H.z + Eps;
}
};
--- a/src/kdtree.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/src/kdtree.cc Sun Apr 20 16:48:24 2008 +0200
@@ -78,60 +78,65 @@
}
// choose split axis
- axis = 0;
+ /*axis = 0;
if (bounds.h() > bounds.w() && bounds.h() > bounds.d())
axis = 1;
if (bounds.d() > bounds.w() && bounds.d() > bounds.h())
axis = 2;
-
+*/
// create sorted list of shape bounds (= find all posible splits)
vector<ShapeBound> edges[3];
ShapeList::iterator shape;
for (shape = shapes->begin(); shape != shapes->end(); shape++)
{
BBox shapebounds = (*shape)->get_bbox();
- // for (int ax = 0; ax < 3; ax++)
- // {
- edges[axis].push_back(ShapeBound(*shape, shapebounds.L[axis], 0));
- edges[axis].push_back(ShapeBound(*shape, shapebounds.H[axis], 1));
- // }
+ for (int ax = 0; ax < 3; ax++)
+ {
+ edges[ax].push_back(ShapeBound(*shape, shapebounds.L[ax], 0));
+ edges[ax].push_back(ShapeBound(*shape, shapebounds.H[ax], 1));
+ }
}
- sort(edges[axis].begin(), edges[axis].end());
+ for (int ax = 0; ax < 3; ax++)
+ sort(edges[ax].begin(), edges[ax].end());
// choose best split pos
const Float K = 1.4; // constant, K = cost of traversal / cost of ray-triangle intersection
Float SAV = (bounds.w()*bounds.h() + // surface area of node
bounds.w()*bounds.d() + bounds.h()*bounds.d());
Float cost = SAV * (K + shapes->size()); // initial cost = non-split cost
- BBox lbb = bounds;
- BBox rbb = bounds;
- vector<ShapeBound>::iterator edge, splitedge = edges[axis].end();
- int lnum = 0, rnum = shapes->size();
- for (edge = edges[axis].begin(); edge != edges[axis].end(); edge++)
+ vector<ShapeBound>::iterator edge, splitedge = edges[2].end();
+ for (int ax = 0; ax < 3; ax++)
{
- if (edge->end)
- rnum--;
+ int lnum = 0, rnum = shapes->size();
+ BBox lbb = bounds;
+ BBox rbb = bounds;
+ for (edge = edges[ax].begin(); edge != edges[ax].end(); edge++)
+ {
+ if (edge->end)
+ rnum--;
- // calculate SAH cost of this split
- lbb.H.cell[axis] = edge->pos;
- rbb.L.cell[axis] = edge->pos;
- Float SAL = (lbb.w()*lbb.h() + lbb.w()*lbb.d() + lbb.h()*lbb.d());
- Float SAR = (rbb.w()*rbb.h() + rbb.w()*rbb.d() + rbb.h()*rbb.d());
- Float splitcost = K*SAV + SAL*(K + lnum) + SAR*(K + rnum);
+ // calculate SAH cost of this split
+ lbb.H.cell[ax] = edge->pos;
+ rbb.L.cell[ax] = edge->pos;
+ Float SAL = (lbb.w()*lbb.h() + lbb.w()*lbb.d() + lbb.h()*lbb.d());
+ Float SAR = (rbb.w()*rbb.h() + rbb.w()*rbb.d() + rbb.h()*rbb.d());
+ Float splitcost = K*SAV + SAL*(K + lnum) + SAR*(K + rnum);
- if (splitcost < cost)
- {
- splitedge = edge;
- cost = splitcost;
- split = edge->pos;
+ if (splitcost < cost)
+ {
+ axis = ax;
+ splitedge = edge;
+ cost = splitcost;
+ split = edge->pos;
+ }
+
+ if (!edge->end)
+ lnum++;
}
-
- if (!edge->end)
- lnum++;
}
- if (splitedge == edges[axis].end())
+ if (splitedge == edges[2].end())
{
setLeaf();
return;
@@ -162,17 +167,19 @@
// split this node
delete shapes;
+ BBox lbb = bounds;
+ BBox rbb = bounds;
+ lbb.H.cell[axis] = split;
+ rbb.L.cell[axis] = split;
children = new KdNode[2];
+
for (edge = edges[axis].begin(); edge != splitedge; edge++)
- if (!edge->end)
+ if (!edge->end && edge->shape->intersect_bbox(lbb))
children[0].addShape(edge->shape);
for (edge = splitedge; edge < edges[axis].end(); edge++)
- if (edge->end)
+ if (edge->end && edge->shape->intersect_bbox(rbb))
children[1].addShape(edge->shape);
- lbb.H.cell[axis] = split;
- rbb.L.cell[axis] = split;
-
children[0].subdivide(lbb, maxdepth-1);
children[1].subdivide(rbb, maxdepth-1);
}
--- a/src/raytracer.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/src/raytracer.cc Sun Apr 20 16:48:24 2008 +0200
@@ -544,11 +544,6 @@
delete[] sample_queue;
}
-void Raytracer::addlight(Light *light)
-{
- lights.push_back(light);
-}
-
void Raytracer::ambientocclusion(int samples, Float distance, Float angle)
{
ao_samples = samples;
--- a/src/raytracermodule.cc Sat Apr 19 18:00:27 2008 +0200
+++ b/src/raytracermodule.cc Sun Apr 20 16:48:24 2008 +0200
@@ -73,7 +73,7 @@
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 cr = 0.9, cg = 0.9, cb = 0.9;
if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!|O!", kwdlist,
&PyTuple_Type, &TPos, &PyTuple_Type, &TCol))
@@ -124,6 +124,7 @@
static void Camera_Destructor(PyObject* self);
static PyObject *Camera_Getattr(PyObject *self, char *name);
static PyObject *Camera_setEye(PyObject* self, PyObject* args);
+static PyObject *Camera_setAngle(PyObject* self, PyObject* args);
static PyObject *Camera_rotate(PyObject* self, PyObject* args);
static PyTypeObject CameraType = {
@@ -147,6 +148,7 @@
static PyMethodDef CameraMethods[] = {
{"setEye", (PyCFunction)Camera_setEye, METH_VARARGS, "Set eye of the camera."},
+ {"setAngle", (PyCFunction)Camera_setAngle, METH_VARARGS, "Set vertical angle of view."},
{"rotate", (PyCFunction)Camera_rotate, METH_VARARGS, "Rotate camera with a quaternion."},
{NULL, NULL}
};
@@ -154,21 +156,33 @@
static PyObject* Camera_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
{
CameraObject *v;
- static char *kwdlist[] = {"eye", "p", "u", "v", NULL};
- PyObject *TEye = NULL, *Tp = NULL, *Tu = NULL, *Tv = NULL;
+ static char *kwdlist[] = {"eye", "lookat", "up", "p", "u", "v", NULL};
+ PyObject *TEye = NULL, *TLookAt = NULL, *TUp = NULL,
+ *Tp = NULL, *Tu = NULL, *Tv = NULL;
Float ex=0.0, ey=0.0, ez=10.0;
+ Float lax=0.0, lay=0.0, laz=0.0;
+ Float upx=0.0, upy=1.0, upz=0.0;
Float px=0.0, py=0.0, pz=-1.0;
Float ux=-1.0, uy=0.0, uz=0.0;
Float vx=0.0, vy=1.0, vz=0.0;
- if (!PyArg_ParseTupleAndKeywords(args, kwd, "|O!O!O!O!", kwdlist,
- &PyTuple_Type, &TEye, &PyTuple_Type, &Tp, &PyTuple_Type, &Tu, &PyTuple_Type, &Tv))
+ if (!PyArg_ParseTupleAndKeywords(args, kwd, "|O!O!O!O!O!O!", kwdlist,
+ &PyTuple_Type, &TEye, &PyTuple_Type, &TLookAt, &PyTuple_Type, &TUp,
+ &PyTuple_Type, &Tp, &PyTuple_Type, &Tu, &PyTuple_Type, &Tv))
return NULL;
if (TEye)
if (!PyArg_ParseTuple(TEye, "fff", &ex, &ey, &ez))
return NULL;
+ if (TLookAt)
+ if (!PyArg_ParseTuple(TLookAt, "fff", &lax, &lay, &laz))
+ return NULL;
+
+ if (TUp)
+ if (!PyArg_ParseTuple(TUp, "fff", &upx, &upy, &upz))
+ return NULL;
+
if (Tp)
if (!PyArg_ParseTuple(Tp, "fff", &px, &py, &pz))
return NULL;
@@ -182,8 +196,12 @@
return NULL;
v = PyObject_New(CameraObject, &CameraType);
- v->camera = new Camera(Vector3(ex, ey, ez),
- Vector3(px, py, pz), Vector3(ux, uy, uz), Vector3(vx, vy, vz));
+ if (TLookAt)
+ v->camera = new Camera(Vector3(ex, ey, ez),
+ Vector3(lax, lay, laz), Vector3(upx, upy, upz));
+ else
+ v->camera = new Camera(Vector3(ex, ey, ez),
+ Vector3(px, py, pz), Vector3(ux, uy, uz), Vector3(vx, vy, vz));
return (PyObject*)v;
}
@@ -217,6 +235,19 @@
return Py_None;
}
+static PyObject *Camera_setAngle(PyObject* self, PyObject* args)
+{
+ Float angle;
+
+ if (!PyArg_ParseTuple(args, "f", &angle))
+ return NULL;
+
+ ((CameraObject *)self)->camera->setAngle(angle);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
static PyObject *Camera_rotate(PyObject* self, PyObject* args)
{
PyObject *Tq = NULL;
@@ -684,6 +715,7 @@
static PyObject *Raytracer_Getattr(PyObject *self, char *name);
static PyObject *Raytracer_render(PyObject* self, PyObject* args);
static PyObject *Raytracer_setcamera(PyObject* self, PyObject* args);
+static PyObject *Raytracer_setbgcolour(PyObject* self, PyObject* args);
static PyObject *Raytracer_addshape(PyObject* self, PyObject* args);
static PyObject *Raytracer_addlight(PyObject* self, PyObject* args);
static PyObject *Raytracer_ambientocclusion(PyObject* self, PyObject* args, PyObject *kwd);
@@ -710,6 +742,7 @@
static PyMethodDef RaytracerMethods[] = {
{"render", (PyCFunction)Raytracer_render, METH_VARARGS, "Render scene and return image data."},
{"setcamera", (PyCFunction)Raytracer_setcamera, METH_VARARGS, "Set camera for the scene."},
+ {"setbgcolour", (PyCFunction)Raytracer_setbgcolour, METH_VARARGS, "Set background colour."},
{"addshape", (PyCFunction)Raytracer_addshape, METH_VARARGS, "Add new shape to scene."},
{"addlight", (PyCFunction)Raytracer_addlight, METH_VARARGS, "Add new light source to scene."},
{"ambientocclusion", (PyCFunction)Raytracer_ambientocclusion, METH_VARARGS | METH_KEYWORDS,
@@ -800,6 +833,19 @@
return Py_None;
}
+static PyObject* Raytracer_setbgcolour(PyObject* self, PyObject* args)
+{
+ Float r,g,b;
+
+ if (!PyArg_ParseTuple(args, "(fff)", &r, &g, &b))
+ return NULL;
+
+ ((RaytracerObject *)self)->raytracer->setBgColour(Colour(r,g,b));
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
static PyObject* Raytracer_addshape(PyObject* self, PyObject* args)
{
PyObject *obj;
@@ -807,7 +853,7 @@
if (!PyArg_ParseTuple(args, "O", &obj))
return NULL;
- ((RaytracerObject *)self)->raytracer->addshape(
+ ((RaytracerObject *)self)->raytracer->addShape(
((BoxObject*)obj)->shape);
((RaytracerObject *)self)->children->push_back(obj);
@@ -822,7 +868,7 @@
if (!PyArg_ParseTuple(args, "O!", &LightType, &lightobj))
return NULL;
- ((RaytracerObject *)self)->raytracer->addlight(lightobj->light);
+ ((RaytracerObject *)self)->raytracer->addLight(lightobj->light);
((RaytracerObject *)self)->children->push_back((PyObject*)lightobj);
Py_INCREF(lightobj);
Py_INCREF(Py_None);