# HG changeset patch # User Radek Brich # Date 1208702904 -7200 # Node ID 7c3f38dff0821a9f7aa56263a99ed82b1656ed79 # Parent 4fedf72909297cafa31ac3d8dd13afdb799b5449 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 diff -r 4fedf7290929 -r 7c3f38dff082 TODO --- 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? ============ diff -r 4fedf7290929 -r 7c3f38dff082 ccdemos/common_ply.h --- 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)++; diff -r 4fedf7290929 -r 7c3f38dff082 ccdemos/common_sdl.h --- 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) { diff -r 4fedf7290929 -r 7c3f38dff082 ccdemos/realtime.cc --- 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)); diff -r 4fedf7290929 -r 7c3f38dff082 ccdemos/realtime_bunny.cc --- 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); diff -r 4fedf7290929 -r 7c3f38dff082 ccdemos/realtime_dragon.cc --- 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); diff -r 4fedf7290929 -r 7c3f38dff082 ccdemos/spheres_shadow.cc --- 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(); diff -r 4fedf7290929 -r 7c3f38dff082 ccdemos/textures.cc --- 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; diff -r 4fedf7290929 -r 7c3f38dff082 demos/SConscript --- 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: diff -r 4fedf7290929 -r 7c3f38dff082 demos/lworeader.py --- 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 diff -r 4fedf7290929 -r 7c3f38dff082 demos/render_nff.py --- /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') diff -r 4fedf7290929 -r 7c3f38dff082 demos/vector.py --- /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] diff -r 4fedf7290929 -r 7c3f38dff082 include/raytracer.h --- 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); diff -r 4fedf7290929 -r 7c3f38dff082 include/scene.h --- 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); }; diff -r 4fedf7290929 -r 7c3f38dff082 src/container.cc --- 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; } }; diff -r 4fedf7290929 -r 7c3f38dff082 src/kdtree.cc --- 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 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::iterator edge, splitedge = edges[axis].end(); - int lnum = 0, rnum = shapes->size(); - for (edge = edges[axis].begin(); edge != edges[axis].end(); edge++) + vector::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); } diff -r 4fedf7290929 -r 7c3f38dff082 src/raytracer.cc --- 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; diff -r 4fedf7290929 -r 7c3f38dff082 src/raytracermodule.cc --- 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);