initial commit, raytracer source as written year ago and unchanged since 2007-03-25 pyrit
authorRadek Brich <radek.brich@devl.cz>
Thu, 25 Oct 2007 16:40:22 +0200
branchpyrit
changeset 0 3547b885df7e
child 1 e74bf781067e
initial commit, raytracer source as written year ago and unchanged since 2007-03-25
Makefile
demos/cube.obj
demos/demo.py
demos/monkey.obj
demos/sphere.obj
demos/spheres_ao.py
demos/spheres_shadow.py
demos/triangles_monkey.py
demos/triangles_sphere.py
src/kdtree.cc
src/kdtree.h
src/matrix.h
src/noise.cc
src/noise.h
src/raytracer.cc
src/raytracer.h
src/raytracermodule.cc
src/scene.cc
src/scene.h
src/vector.h
tests/vector.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,57 @@
+CCFLAGS=-Wall -O3 -I./src
+LDFLAGS=
+
+ifeq ($(OS), Windows_NT)
+  CCFLAGS+=-I"C:/Program Files/Python25/include"
+  LDFLAGS+=-L"C:\Program Files\Python25\libs" -lpython25
+  MODULENAME=raytracer.pyd
+else
+  CCFLAGS+=-fPIC -I/usr/include/python2.4
+  MODULENAME=raytracermodule.so
+endif
+
+# optimisations
+#CCFLAGS+=-pipe -fomit-frame-pointer -ffast-math -msse3
+
+
+# TARGETS
+#########
+
+all: python-module
+
+python-module: $(MODULENAME)
+
+tests: testvector testmatrix
+
+clean:
+	rm -f *.o $(MODULENAME) testvector testmatrix
+
+
+# RULES
+#######
+
+%.o: src/%.cc
+	$(CXX) -c -o $@ src/$*.cc $(CCFLAGS)
+
+test%: tests/%.cc 
+	$(CXX) -o $@ tests/$*.cc $(CCFLAGS) 
+	./$@
+
+
+# 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
+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
+	$(CXX) $^ -shared -o $@ $(LDFLAGS)
+
+# library tests
+testvector: tests/vector.cc src/vector.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/cube.obj	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,27 @@
+# Blender v242 OBJ File: bow.blend
+# www.blender3d.org
+mtllib cube.mtl
+o Cube_Cube.001
+v -0.156446 0.619376 -1.609937
+v 1.108605 -0.823246 -1.045591
+v -0.353969 -1.695493 0.003248
+v -1.619020 -0.252870 -0.561099
+v 0.353969 1.695493 -0.003248
+v 1.619020 0.252870 0.561099
+v 0.156445 -0.619376 1.609937
+v -1.108605 0.823246 1.045591
+usemtl (null)
+usemtl (null)
+s off
+f 5 1 8
+f 1 4 8
+f 3 7 8
+f 3 8 4
+f 2 6 3
+f 6 7 3
+f 1 5 2
+f 5 6 2
+f 5 8 7
+f 5 7 6
+f 1 2 3
+f 1 3 4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/demo.py	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,45 @@
+#!/usr/bin/python2.4
+
+import sys
+sys.path.append("../")
+
+from raytracer import Raytracer, Material, Plane, Sphere, Light
+#, SphericalLight
+import Image
+
+rt = Raytracer()
+
+light1 = Light(position=(0.0, 5.0, 3.0), colour=(0.9, 0.3, 0.6))
+rt.addlight(light1)
+
+#light2 = SphericalLight(position=(-2.0, 5.0, 1.0), radius=3.0, colour=(0.7, 1.0, 0.3))
+light2 = Light(position=(-2.0, -5.0, 1.0), colour=(0.7, 1.0, 0.3))
+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)
+
+mat1 = Material(colour=(1.0, 0.2, 0.1))
+bigsphere = Sphere(centre=(2.0, 2.0, 5.0), radius=2.5, material=mat1)
+#      reflection=0.6)
+rt.addshape(bigsphere)
+
+mat2 = Material(colour=(0.1, 0.7, 1.0))
+smallsphere = Sphere(centre=(-5.5, 1.5, 8.0), radius=2.0, material=mat2)
+#      reflection=1.0, diffuse=0.1)
+rt.addshape(smallsphere)
+
+mat3 = Material(colour=(0.9, 0.9, 0.1))
+tinysphere = Sphere(centre=(-0.5, 0.0, 2.0), radius=0.5, material=mat3)
+#      reflection=1.0, diffuse=0.1)
+rt.addshape(tinysphere)
+
+#for i in range(100):
+#      sph=Sphere((-5.5+i/10.0, -0.5, 7.0), 2.0)
+#      rt.addshape(sph)
+
+rendersize = (800, 600)
+data = rt.render(rendersize)
+img = Image.fromstring("RGB", rendersize, data)
+img.save('out.png')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/monkey.obj	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,1482 @@
+# Blender v242 OBJ File: untitled.blend
+# www.blender3d.org
+mtllib monkey2.mtl
+o monkey_Suzanne_Suzanne
+v -0.351562 0.242188 -0.828125
+v -0.445312 0.156250 -0.781250
+v -0.476562 0.242188 -0.773438
+v 0.476562 0.242188 -0.773438
+v 0.445312 0.156250 -0.781250
+v 0.351562 0.242188 -0.828125
+v -0.351562 0.117188 -0.804688
+v 0.351562 0.117188 -0.804688
+v -0.265625 0.156250 -0.820312
+v 0.265625 0.156250 -0.820312
+v -0.226562 0.242188 -0.820312
+v 0.226562 0.242188 -0.820312
+v -0.265625 0.335938 -0.820312
+v 0.265625 0.335938 -0.820312
+v -0.351562 0.375000 -0.804688
+v 0.351562 0.375000 -0.804688
+v -0.445312 0.335938 -0.781250
+v 0.445312 0.335938 -0.781250
+v -0.093750 -0.750000 -0.664062
+v -0.046875 -0.851562 -0.632812
+v -0.093750 -0.812500 -0.640625
+v 0.093750 -0.812500 -0.640625
+v 0.046875 -0.851562 -0.632812
+v 0.093750 -0.750000 -0.664062
+v -0.000000 0.406250 -0.601562
+v -0.109375 0.460938 -0.609375
+v -0.000000 0.570312 -0.570312
+v 0.109375 0.460938 -0.609375
+v -0.218750 -0.281250 -0.429688
+v -0.210938 -0.390625 -0.164062
+v -0.406250 -0.171875 -0.148438
+v 0.406250 -0.171875 -0.148438
+v 0.210938 -0.390625 -0.164062
+v 0.218750 -0.281250 -0.429688
+v -0.437500 -0.093750 -0.468750
+v -0.203125 -0.171875 -0.500000
+v -0.210938 -0.226562 -0.468750
+v 0.210938 -0.226562 -0.468750
+v 0.203125 -0.171875 -0.500000
+v 0.437500 -0.093750 -0.468750
+v -0.335938 0.054688 0.664062
+v -0.484375 0.023438 0.546875
+v -0.343750 -0.148438 0.539062
+v 0.343750 -0.148438 0.539062
+v 0.484375 0.023438 0.546875
+v 0.335938 0.054688 0.664062
+v -0.726562 0.000000 0.070312
+v -0.718750 -0.023438 0.171875
+v -0.718750 0.039062 0.187500
+v 0.718750 0.039062 0.187500
+v 0.718750 -0.023438 0.171875
+v 0.726562 0.000000 0.070312
+v -1.039062 0.328125 0.414062
+v -1.085938 0.273438 0.390625
+v -1.187500 0.343750 0.484375
+v 1.187500 0.343750 0.484375
+v 1.085938 0.273438 0.390625
+v 1.039062 0.328125 0.414062
+v -1.250000 0.468750 0.546875
+v -1.367188 0.296875 0.500000
+v -1.312500 0.054688 0.531250
+v 1.312500 0.054688 0.531250
+v 1.367188 0.296875 0.500000
+v 1.250000 0.468750 0.546875
+v 0.789062 -0.125000 0.328125
+v 0.640625 -0.007812 0.429688
+v 0.593750 -0.125000 0.164062
+v 0.773438 -0.140625 0.125000
+v -0.593750 -0.125000 0.164062
+v -0.640625 -0.007812 0.429688
+v -0.789062 -0.125000 0.328125
+v -0.773438 -0.140625 0.125000
+v 0.859375 0.382812 0.382812
+v 0.773438 0.265625 0.437500
+v -0.773438 0.265625 0.437500
+v -0.859375 0.382812 0.382812
+v 0.890625 0.406250 0.234375
+v 0.820312 0.328125 0.203125
+v -0.820312 0.328125 0.203125
+v -0.890625 0.406250 0.234375
+v 1.023438 0.437500 0.484375
+v 1.039062 -0.085938 0.492188
+v -1.023438 0.437500 0.484375
+v -1.039062 -0.085938 0.492188
+v 1.023438 0.476562 0.312500
+v -1.023438 0.476562 0.312500
+v 1.234375 0.507812 0.421875
+v -1.234375 0.507812 0.421875
+v 1.351562 0.320312 0.421875
+v -1.351562 0.320312 0.421875
+v 1.281250 0.054688 0.429688
+v -1.281250 0.054688 0.429688
+v 1.039062 -0.101562 0.328125
+v -1.039062 -0.101562 0.328125
+v 1.109375 0.210938 0.390625
+v 1.257812 0.242188 0.492188
+v -1.109375 0.210938 0.390625
+v -1.257812 0.242188 0.492188
+v 1.054688 0.187500 0.382812
+v 1.210938 0.085938 0.484375
+v -1.210938 0.085938 0.484375
+v -1.054688 0.187500 0.382812
+v 1.000000 0.125000 0.367188
+v 1.046875 0.000000 0.421875
+v -1.046875 0.000000 0.421875
+v -1.000000 0.125000 0.367188
+v 0.937500 0.062500 0.335938
+v 0.882812 -0.015625 0.265625
+v -0.937500 0.062500 0.335938
+v -0.882812 -0.015625 0.265625
+v 0.851562 0.015625 0.320312
+v 0.812500 -0.015625 0.320312
+v -0.812500 -0.015625 0.320312
+v -0.851562 0.015625 0.320312
+v 0.843750 0.171875 0.320312
+v 0.890625 0.109375 0.328125
+v 0.828125 0.078125 0.320312
+v 0.765625 0.093750 0.320312
+v -0.828125 0.078125 0.320312
+v -0.890625 0.109375 0.328125
+v -0.843750 0.171875 0.320312
+v -0.765625 0.093750 0.320312
+v 0.960938 0.171875 0.351562
+v 0.890625 0.234375 0.320312
+v -0.890625 0.234375 0.320312
+v -0.960938 0.171875 0.351562
+v 1.015625 0.234375 0.375000
+v 0.953125 0.289062 0.343750
+v -0.953125 0.289062 0.343750
+v -1.015625 0.234375 0.375000
+v 1.039062 0.000000 0.367188
+v 0.882812 -0.023438 0.210938
+v -0.882812 -0.023438 0.210938
+v -1.039062 0.000000 0.367188
+v 1.187500 0.093750 0.445312
+v -1.187500 0.093750 0.445312
+v 1.234375 0.250000 0.445312
+v -1.234375 0.250000 0.445312
+v 1.171875 0.359375 0.437500
+v -1.171875 0.359375 0.437500
+v 1.023438 0.343750 0.359375
+v -1.023438 0.343750 0.359375
+v 0.945312 0.304688 0.289062
+v -0.945312 0.304688 0.289062
+v 0.812500 -0.015625 0.273438
+v -0.812500 -0.015625 0.273438
+v 0.843750 0.015625 0.273438
+v -0.843750 0.015625 0.273438
+v 0.820312 0.085938 0.273438
+v -0.820312 0.085938 0.273438
+v 0.757812 0.093750 0.273438
+v -0.757812 0.093750 0.273438
+v 0.835938 0.171875 0.273438
+v -0.835938 0.171875 0.273438
+v 0.890625 0.242188 0.265625
+v -0.890625 0.242188 0.265625
+v 0.796875 0.203125 0.210938
+v 0.859375 0.320312 0.046875
+v -0.859375 0.320312 0.046875
+v -0.796875 0.203125 0.210938
+v 0.843750 0.289062 0.210938
+v -0.843750 0.289062 0.210938
+v 0.921875 0.359375 0.218750
+v -0.921875 0.359375 0.218750
+v 0.828125 -0.070312 0.132812
+v -0.828125 -0.070312 0.132812
+v 0.734375 -0.046875 -0.070312
+v 0.851562 0.234375 -0.054688
+v -0.851562 0.234375 -0.054688
+v -0.734375 -0.046875 -0.070312
+v 1.015625 0.414062 0.289062
+v -1.015625 0.414062 0.289062
+v 1.187500 0.437500 0.390625
+v -1.187500 0.437500 0.390625
+v 1.265625 0.289062 0.406250
+v -1.265625 0.289062 0.406250
+v 1.210938 0.078125 0.406250
+v -1.210938 0.078125 0.406250
+v 1.031250 -0.039062 0.304688
+v -1.031250 -0.039062 0.304688
+v 0.429688 -0.195312 0.210938
+v 0.296875 -0.312500 0.265625
+v -0.296875 -0.312500 0.265625
+v -0.429688 -0.195312 0.210938
+v 0.617188 0.328125 0.585938
+v 0.460938 0.437500 0.703125
+v -0.460938 0.437500 0.703125
+v -0.617188 0.328125 0.585938
+v 0.601562 0.000000 -0.414062
+v -0.601562 0.000000 -0.414062
+v 0.796875 0.617188 0.117188
+v 0.796875 0.539062 0.359375
+v -0.796875 0.539062 0.359375
+v -0.796875 0.617188 0.117188
+v 0.796875 0.562500 -0.125000
+v -0.796875 0.562500 -0.125000
+v 0.726562 0.406250 -0.335938
+v -0.726562 0.406250 -0.335938
+v 0.773438 0.164062 -0.375000
+v 0.796875 0.406250 -0.460938
+v -0.796875 0.406250 -0.460938
+v -0.773438 0.164062 -0.375000
+v 0.460938 0.523438 -0.429688
+v 0.484375 0.554688 -0.554688
+v -0.484375 0.554688 -0.554688
+v -0.460938 0.523438 -0.429688
+v 0.335938 0.687500 -0.593750
+v 0.195312 0.664062 -0.617188
+v -0.195312 0.664062 -0.617188
+v -0.335938 0.687500 -0.593750
+v 0.453125 0.851562 -0.234375
+v -0.000000 0.898438 -0.289062
+v -0.453125 0.851562 -0.234375
+v 0.632812 0.453125 -0.281250
+v 0.679688 0.453125 -0.492188
+v -0.679688 0.453125 -0.492188
+v -0.632812 0.453125 -0.281250
+v 0.640625 0.703125 -0.054688
+v -0.640625 0.703125 -0.054688
+v 0.453125 0.929688 0.070312
+v 0.640625 0.750000 0.195312
+v -0.453125 0.929688 0.070312
+v -0.640625 0.750000 0.195312
+v 0.453125 0.867188 0.382812
+v 0.640625 0.679688 0.445312
+v -0.453125 0.867188 0.382812
+v -0.640625 0.679688 0.445312
+v 0.000000 0.898438 0.546875
+v 0.000000 0.562500 0.851562
+v 0.000000 0.984375 0.078125
+v 0.000000 0.070312 0.828125
+v 0.179688 -0.414062 -0.257812
+v 0.234375 -0.351562 -0.406250
+v -0.234375 -0.351562 -0.406250
+v -0.179688 -0.414062 -0.257812
+v -0.000000 -0.460938 -0.187500
+v -0.000000 -0.484375 -0.281250
+v 0.000000 -0.382812 0.351562
+v 0.000000 -0.195312 0.671875
+v 0.437500 -0.140625 -0.531250
+v 0.203125 -0.187500 -0.562500
+v -0.203125 -0.187500 -0.562500
+v -0.437500 -0.140625 -0.531250
+v 0.234375 -0.250000 -0.554688
+v -0.234375 -0.250000 -0.554688
+v 0.257812 -0.312500 -0.554688
+v 0.312500 -0.437500 -0.570312
+v -0.312500 -0.437500 -0.570312
+v -0.257812 -0.312500 -0.554688
+v 0.250000 -0.500000 -0.390625
+v 0.351562 -0.695312 -0.570312
+v -0.351562 -0.695312 -0.570312
+v -0.250000 -0.500000 -0.390625
+v 0.125000 -0.539062 -0.359375
+v -0.125000 -0.539062 -0.359375
+v 0.164062 -0.945312 -0.437500
+v 0.328125 -0.914062 -0.398438
+v 0.140625 -0.757812 -0.367188
+v 0.289062 -0.710938 -0.382812
+v -0.289062 -0.710938 -0.382812
+v -0.328125 -0.914062 -0.398438
+v -0.140625 -0.757812 -0.367188
+v -0.164062 -0.945312 -0.437500
+v 0.367188 -0.890625 -0.531250
+v -0.367188 -0.890625 -0.531250
+v 0.328125 -0.945312 -0.523438
+v -0.328125 -0.945312 -0.523438
+v 0.179688 -0.968750 -0.554688
+v -0.179688 -0.968750 -0.554688
+v -0.000000 -0.976562 -0.460938
+v -0.000000 -0.984375 -0.578125
+v -0.000000 -0.804688 -0.343750
+v -0.000000 -0.570312 -0.320312
+v 0.632812 -0.039062 -0.539062
+v -0.632812 -0.039062 -0.539062
+v 0.828125 0.148438 -0.445312
+v -0.828125 0.148438 -0.445312
+v 0.859375 0.429688 -0.593750
+v -0.859375 0.429688 -0.593750
+v 0.710938 0.484375 -0.625000
+v -0.710938 0.484375 -0.625000
+v 0.492188 0.601562 -0.687500
+v -0.492188 0.601562 -0.687500
+v 0.320312 0.757812 -0.734375
+v -0.320312 0.757812 -0.734375
+v 0.156250 0.718750 -0.757812
+v -0.156250 0.718750 -0.757812
+v 0.062500 0.492188 -0.750000
+v -0.062500 0.492188 -0.750000
+v -0.000000 0.429688 -0.742188
+v 0.203125 0.171875 -0.750000
+v 0.187500 0.156250 -0.773438
+v 0.171875 0.218750 -0.781250
+v 0.195312 0.226562 -0.750000
+v -0.171875 0.218750 -0.781250
+v -0.187500 0.156250 -0.773438
+v -0.203125 0.171875 -0.750000
+v -0.195312 0.226562 -0.750000
+v 0.179688 0.296875 -0.781250
+v 0.195312 0.296875 -0.757812
+v -0.179688 0.296875 -0.781250
+v -0.195312 0.296875 -0.757812
+v 0.210938 0.375000 -0.781250
+v 0.234375 0.359375 -0.757812
+v -0.210938 0.375000 -0.781250
+v -0.234375 0.359375 -0.757812
+v 0.242188 0.125000 -0.757812
+v 0.226562 0.109375 -0.781250
+v -0.226562 0.109375 -0.781250
+v -0.242188 0.125000 -0.757812
+v 0.375000 0.085938 -0.726562
+v 0.375000 0.062500 -0.742188
+v -0.375000 0.062500 -0.742188
+v -0.375000 0.085938 -0.726562
+v 0.460938 0.117188 -0.703125
+v 0.476562 0.101562 -0.718750
+v -0.476562 0.101562 -0.718750
+v -0.460938 0.117188 -0.703125
+v 0.546875 0.210938 -0.671875
+v 0.578125 0.195312 -0.679688
+v -0.578125 0.195312 -0.679688
+v -0.546875 0.210938 -0.671875
+v 0.554688 0.281250 -0.671875
+v 0.585938 0.289062 -0.687500
+v -0.585938 0.289062 -0.687500
+v -0.554688 0.281250 -0.671875
+v 0.531250 0.335938 -0.679688
+v 0.562500 0.351562 -0.695312
+v -0.562500 0.351562 -0.695312
+v -0.531250 0.335938 -0.679688
+v 0.414062 0.390625 -0.750000
+v 0.421875 0.398438 -0.773438
+v -0.421875 0.398438 -0.773438
+v -0.414062 0.390625 -0.750000
+v 0.335938 0.406250 -0.750000
+v 0.335938 0.429688 -0.757812
+v -0.335938 0.429688 -0.757812
+v -0.335938 0.406250 -0.750000
+v 0.281250 0.398438 -0.765625
+v 0.273438 0.421875 -0.773438
+v -0.273438 0.421875 -0.773438
+v -0.281250 0.398438 -0.765625
+v 0.164062 0.414062 -0.773438
+v 0.250000 0.468750 -0.757812
+v -0.250000 0.468750 -0.757812
+v -0.164062 0.414062 -0.773438
+v 0.328125 0.476562 -0.742188
+v -0.328125 0.476562 -0.742188
+v 0.429688 0.437500 -0.718750
+v -0.429688 0.437500 -0.718750
+v 0.601562 0.375000 -0.664062
+v -0.601562 0.375000 -0.664062
+v 0.640625 0.296875 -0.648438
+v -0.640625 0.296875 -0.648438
+v 0.625000 0.187500 -0.648438
+v -0.625000 0.187500 -0.648438
+v 0.492188 0.062500 -0.671875
+v -0.492188 0.062500 -0.671875
+v 0.375000 0.015625 -0.703125
+v -0.375000 0.015625 -0.703125
+v 0.203125 0.093750 -0.742188
+v -0.203125 0.093750 -0.742188
+v 0.164062 0.140625 -0.750000
+v -0.164062 0.140625 -0.750000
+v 0.125000 0.304688 -0.765625
+v -0.125000 0.304688 -0.765625
+v 0.132812 0.210938 -0.757812
+v -0.132812 0.210938 -0.757812
+v -0.000000 -0.859375 -0.632812
+v -0.000000 -0.781250 -0.656250
+v -0.000000 -0.773438 -0.718750
+v 0.093750 -0.742188 -0.726562
+v -0.093750 -0.742188 -0.726562
+v 0.093750 -0.820312 -0.710938
+v -0.093750 -0.820312 -0.710938
+v 0.046875 -0.867188 -0.687500
+v -0.046875 -0.867188 -0.687500
+v -0.000000 -0.875000 -0.687500
+v 0.062500 -0.882812 -0.695312
+v -0.000000 -0.890625 -0.687500
+v -0.062500 -0.882812 -0.695312
+v 0.117188 -0.835938 -0.710938
+v -0.117188 -0.835938 -0.710938
+v 0.109375 -0.718750 -0.734375
+v -0.109375 -0.718750 -0.734375
+v -0.000000 -0.765625 -0.734375
+v 0.164062 -0.242188 -0.710938
+v 0.125000 -0.101562 -0.812500
+v -0.125000 -0.101562 -0.812500
+v -0.164062 -0.242188 -0.710938
+v 0.179688 -0.312500 -0.710938
+v -0.179688 -0.312500 -0.710938
+v 0.210938 -0.445312 -0.710938
+v -0.210938 -0.445312 -0.710938
+v 0.078125 -0.445312 -0.750000
+v 0.085938 -0.289062 -0.742188
+v -0.085938 -0.289062 -0.742188
+v -0.078125 -0.445312 -0.750000
+v 0.125000 -0.226562 -0.750000
+v -0.125000 -0.226562 -0.750000
+v 0.101562 -0.148438 -0.742188
+v -0.101562 -0.148438 -0.742188
+v -0.000000 -0.140625 -0.742188
+v -0.000000 0.046875 -0.726562
+v 0.078125 -0.250000 -0.804688
+v -0.000000 -0.289062 -0.804688
+v -0.000000 -0.203125 -0.828125
+v 0.109375 -0.226562 -0.828125
+v -0.078125 -0.250000 -0.804688
+v -0.109375 -0.226562 -0.828125
+v 0.093750 -0.156250 -0.812500
+v 0.046875 -0.148438 -0.812500
+v -0.046875 -0.148438 -0.812500
+v -0.093750 -0.156250 -0.812500
+v 0.132812 -0.226562 -0.796875
+v 0.093750 -0.273438 -0.781250
+v -0.132812 -0.226562 -0.796875
+v -0.093750 -0.273438 -0.781250
+v 0.109375 -0.132812 -0.781250
+v -0.109375 -0.132812 -0.781250
+v 0.039062 -0.125000 -0.781250
+v -0.039062 -0.125000 -0.781250
+v -0.000000 -0.187500 -0.796875
+v -0.000000 -0.320312 -0.781250
+v -0.000000 -0.328125 -0.742188
+v -0.000000 -0.195312 -0.750000
+v 0.117188 -0.687500 -0.734375
+v -0.000000 -0.679688 -0.734375
+v -0.117188 -0.687500 -0.734375
+v -0.000000 -0.445312 -0.750000
+v 0.250000 -0.703125 -0.687500
+v 0.265625 -0.820312 -0.664062
+v -0.265625 -0.820312 -0.664062
+v -0.250000 -0.703125 -0.687500
+v 0.234375 -0.914062 -0.632812
+v -0.234375 -0.914062 -0.632812
+v 0.164062 -0.929688 -0.632812
+v -0.164062 -0.929688 -0.632812
+v -0.000000 -0.945312 -0.640625
+v -0.000000 0.210938 -0.765625
+v -0.000000 0.351562 -0.820312
+v 0.101562 0.429688 -0.843750
+v -0.101562 0.429688 -0.843750
+v 0.398438 -0.046875 -0.671875
+v -0.398438 -0.046875 -0.671875
+v 0.617188 0.054688 -0.625000
+v -0.617188 0.054688 -0.625000
+v 0.726562 0.203125 -0.601562
+v -0.726562 0.203125 -0.601562
+v 0.742188 0.375000 -0.656250
+v -0.742188 0.375000 -0.656250
+v 0.687500 0.414062 -0.726562
+v -0.687500 0.414062 -0.726562
+v 0.437500 0.546875 -0.796875
+v -0.437500 0.546875 -0.796875
+v 0.312500 0.640625 -0.835938
+v -0.312500 0.640625 -0.835938
+v 0.203125 0.617188 -0.851562
+v -0.203125 0.617188 -0.851562
+v 0.468750 0.242188 -0.757812
+v 0.437500 0.164062 -0.765625
+v -0.437500 0.164062 -0.765625
+v -0.468750 0.242188 -0.757812
+v 0.351562 0.132812 -0.781250
+v -0.351562 0.132812 -0.781250
+v 0.273438 0.164062 -0.796875
+v -0.273438 0.164062 -0.796875
+v 0.242188 0.242188 -0.796875
+v -0.242188 0.242188 -0.796875
+v 0.273438 0.328125 -0.796875
+v -0.273438 0.328125 -0.796875
+v 0.351562 0.359375 -0.781250
+v -0.351562 0.359375 -0.781250
+v 0.437500 0.328125 -0.765625
+v -0.437500 0.328125 -0.765625
+v 0.562500 0.242188 -0.671875
+v 0.500000 0.390625 -0.687500
+v -0.500000 0.390625 -0.687500
+v -0.562500 0.242188 -0.671875
+v 0.625000 0.242188 -0.562500
+v 0.546875 0.437500 -0.578125
+v -0.546875 0.437500 -0.578125
+v -0.625000 0.242188 -0.562500
+v 0.351562 0.515625 -0.617188
+v 0.351562 0.453125 -0.718750
+v -0.351562 0.453125 -0.718750
+v -0.351562 0.515625 -0.617188
+v 0.203125 0.390625 -0.742188
+v -0.203125 0.390625 -0.742188
+v 0.156250 0.437500 -0.648438
+v -0.156250 0.437500 -0.648438
+v 0.078125 0.242188 -0.656250
+v 0.140625 0.242188 -0.742188
+v -0.140625 0.242188 -0.742188
+v -0.078125 0.242188 -0.656250
+v 0.203125 0.093750 -0.742188
+v -0.203125 0.093750 -0.742188
+v 0.156250 0.054688 -0.648438
+v -0.156250 0.054688 -0.648438
+v 0.351562 0.031250 -0.718750
+v 0.351562 -0.023438 -0.617188
+v -0.351562 0.031250 -0.718750
+v -0.351562 -0.023438 -0.617188
+v 0.500000 0.093750 -0.687500
+v -0.500000 0.093750 -0.687500
+v 0.546875 0.054688 -0.578125
+v -0.546875 0.054688 -0.578125
+usemtl (null)
+usemtl (null)
+s 1
+f 1 2 3
+f 4 5 6
+f 2 1 7
+f 6 5 8
+f 1 9 7
+f 8 10 6
+f 1 11 9
+f 10 12 6
+f 1 13 11
+f 12 14 6
+f 1 15 13
+f 14 16 6
+f 1 17 15
+f 16 18 6
+f 1 3 17
+f 18 4 6
+f 19 20 21
+f 22 23 24
+f 25 26 27
+f 27 28 25
+f 29 30 31
+f 32 33 34
+f 35 36 37
+f 38 39 40
+f 41 42 43
+f 44 45 46
+f 47 48 49
+f 50 51 52
+f 53 54 55
+f 56 57 58
+f 59 60 61
+f 62 63 64
+f 65 66 67
+f 65 67 68
+f 69 70 71
+f 69 71 72
+f 65 73 74
+f 65 74 66
+f 75 76 71
+f 75 71 70
+f 77 78 73
+f 78 74 73
+f 75 79 76
+f 79 80 76
+f 62 64 81
+f 62 81 82
+f 83 59 61
+f 83 61 84
+f 65 82 73
+f 82 81 73
+f 83 84 76
+f 84 71 76
+f 81 85 73
+f 85 77 73
+f 80 86 76
+f 86 83 76
+f 64 87 81
+f 87 85 81
+f 86 88 83
+f 88 59 83
+f 63 89 64
+f 89 87 64
+f 88 90 59
+f 90 60 59
+f 62 91 63
+f 91 89 63
+f 90 92 60
+f 92 61 60
+f 82 93 91
+f 82 91 62
+f 92 94 84
+f 92 84 61
+f 65 68 93
+f 65 93 82
+f 94 72 71
+f 94 71 84
+f 95 57 56
+f 95 56 96
+f 55 54 97
+f 55 97 98
+f 99 95 100
+f 95 96 100
+f 98 97 101
+f 97 102 101
+f 103 99 104
+f 99 100 104
+f 101 102 105
+f 102 106 105
+f 107 103 104
+f 107 104 108
+f 105 106 109
+f 105 109 110
+f 107 108 111
+f 108 112 111
+f 113 110 114
+f 110 109 114
+f 115 116 117
+f 115 117 118
+f 119 120 121
+f 119 121 122
+f 116 115 123
+f 115 124 123
+f 125 121 126
+f 121 120 126
+f 127 123 128
+f 123 124 128
+f 125 126 129
+f 126 130 129
+f 127 128 58
+f 127 58 57
+f 53 129 130
+f 53 130 54
+f 95 99 57
+f 99 127 57
+f 130 102 54
+f 102 97 54
+f 99 103 123
+f 99 123 127
+f 126 106 102
+f 126 102 130
+f 103 107 123
+f 107 116 123
+f 120 109 126
+f 109 106 126
+f 107 111 116
+f 111 117 116
+f 119 114 120
+f 114 109 120
+f 104 131 108
+f 131 132 108
+f 133 134 110
+f 134 105 110
+f 100 135 104
+f 135 131 104
+f 134 136 105
+f 136 101 105
+f 96 137 100
+f 137 135 100
+f 136 138 101
+f 138 98 101
+f 56 139 137
+f 56 137 96
+f 138 140 55
+f 138 55 98
+f 58 141 139
+f 58 139 56
+f 140 142 53
+f 140 53 55
+f 128 143 141
+f 128 141 58
+f 142 144 129
+f 142 129 53
+f 108 132 145
+f 108 145 112
+f 146 133 110
+f 146 110 113
+f 112 145 147
+f 112 147 111
+f 148 146 113
+f 148 113 114
+f 111 147 117
+f 147 149 117
+f 150 148 119
+f 148 114 119
+f 117 149 118
+f 149 151 118
+f 152 150 122
+f 150 119 122
+f 118 151 153
+f 118 153 115
+f 154 152 122
+f 154 122 121
+f 115 153 124
+f 153 155 124
+f 156 154 125
+f 154 121 125
+f 124 155 143
+f 124 143 128
+f 144 156 125
+f 144 125 129
+f 50 52 157
+f 52 158 157
+f 159 47 160
+f 47 49 160
+f 161 157 78
+f 157 158 78
+f 159 160 79
+f 160 162 79
+f 155 161 143
+f 161 163 143
+f 164 162 144
+f 162 156 144
+f 153 157 155
+f 157 161 155
+f 162 160 156
+f 160 154 156
+f 50 157 151
+f 157 153 151
+f 154 160 152
+f 160 49 152
+f 147 50 151
+f 147 151 149
+f 152 49 148
+f 152 148 150
+f 51 50 145
+f 50 147 145
+f 148 49 146
+f 49 48 146
+f 145 132 165
+f 145 165 51
+f 166 133 146
+f 166 146 48
+f 163 161 78
+f 163 78 77
+f 79 162 164
+f 79 164 80
+f 52 167 168
+f 52 168 158
+f 169 170 47
+f 169 47 159
+f 165 68 51
+f 68 67 51
+f 69 72 48
+f 72 166 48
+f 51 67 52
+f 67 167 52
+f 170 69 47
+f 69 48 47
+f 143 163 171
+f 143 171 141
+f 172 164 144
+f 172 144 142
+f 139 141 173
+f 141 171 173
+f 172 142 174
+f 142 140 174
+f 137 139 175
+f 139 173 175
+f 174 140 176
+f 140 138 176
+f 135 137 177
+f 137 175 177
+f 176 138 178
+f 138 136 178
+f 131 135 177
+f 131 177 179
+f 178 136 134
+f 178 134 180
+f 132 131 179
+f 132 179 165
+f 180 134 133
+f 180 133 166
+f 165 179 93
+f 165 93 68
+f 94 180 166
+f 94 166 72
+f 179 177 93
+f 177 91 93
+f 92 178 94
+f 178 180 94
+f 177 175 91
+f 175 89 91
+f 90 176 92
+f 176 178 92
+f 175 173 89
+f 173 87 89
+f 88 174 90
+f 174 176 90
+f 173 171 85
+f 173 85 87
+f 86 172 174
+f 86 174 88
+f 163 77 171
+f 77 85 171
+f 86 80 172
+f 80 164 172
+f 45 44 181
+f 44 182 181
+f 183 43 184
+f 43 42 184
+f 45 181 66
+f 181 67 66
+f 69 184 70
+f 184 42 70
+f 45 185 46
+f 185 186 46
+f 187 188 41
+f 188 42 41
+f 45 66 185
+f 66 74 185
+f 75 70 188
+f 70 42 188
+f 34 38 40
+f 34 40 32
+f 35 37 29
+f 35 29 31
+f 32 40 189
+f 32 189 167
+f 190 35 31
+f 190 31 170
+f 181 32 67
+f 32 167 67
+f 170 31 69
+f 31 184 69
+f 181 182 32
+f 182 33 32
+f 30 183 31
+f 183 184 31
+f 191 192 78
+f 192 74 78
+f 75 193 79
+f 193 194 79
+f 191 78 158
+f 191 158 195
+f 159 79 194
+f 159 194 196
+f 195 158 168
+f 195 168 197
+f 169 159 196
+f 169 196 198
+f 168 199 197
+f 199 200 197
+f 201 202 198
+f 202 169 198
+f 203 204 28
+f 203 28 27
+f 26 205 206
+f 26 206 27
+f 207 208 204
+f 208 28 204
+f 26 209 205
+f 209 210 205
+f 211 203 212
+f 203 27 212
+f 27 206 212
+f 206 213 212
+f 214 215 203
+f 215 204 203
+f 205 216 206
+f 216 217 206
+f 214 203 211
+f 214 211 218
+f 213 206 217
+f 213 217 219
+f 218 211 220
+f 218 220 221
+f 222 213 219
+f 222 219 223
+f 221 220 224
+f 221 224 225
+f 226 222 223
+f 226 223 227
+f 225 224 186
+f 225 186 185
+f 187 226 227
+f 187 227 188
+f 225 185 192
+f 185 74 192
+f 75 188 193
+f 188 227 193
+f 192 191 221
+f 192 221 225
+f 223 194 193
+f 223 193 227
+f 191 195 218
+f 191 218 221
+f 219 196 194
+f 219 194 223
+f 195 197 214
+f 195 214 218
+f 217 198 196
+f 217 196 219
+f 197 200 215
+f 197 215 214
+f 216 201 198
+f 216 198 217
+f 186 224 228
+f 186 228 229
+f 228 226 187
+f 228 187 229
+f 224 220 230
+f 224 230 228
+f 230 222 226
+f 230 226 228
+f 220 211 230
+f 211 212 230
+f 212 213 230
+f 213 222 230
+f 46 186 231
+f 186 229 231
+f 229 187 231
+f 187 41 231
+f 167 189 199
+f 167 199 168
+f 202 190 170
+f 202 170 169
+f 33 232 34
+f 232 233 34
+f 234 235 29
+f 235 30 29
+f 232 33 236
+f 232 236 237
+f 236 30 235
+f 236 235 237
+f 33 182 238
+f 33 238 236
+f 238 183 30
+f 238 30 236
+f 182 44 238
+f 44 239 238
+f 239 43 238
+f 43 183 238
+f 44 46 239
+f 46 231 239
+f 231 41 239
+f 41 43 239
+f 40 39 240
+f 39 241 240
+f 242 36 243
+f 36 35 243
+f 38 244 39
+f 244 241 39
+f 242 245 36
+f 245 37 36
+f 34 233 246
+f 233 247 246
+f 248 234 249
+f 234 29 249
+f 38 34 244
+f 34 246 244
+f 249 29 245
+f 29 37 245
+f 250 251 247
+f 250 247 233
+f 248 252 253
+f 248 253 234
+f 254 250 232
+f 250 233 232
+f 234 253 235
+f 253 255 235
+f 256 257 258
+f 257 259 258
+f 260 261 262
+f 261 263 262
+f 254 258 259
+f 254 259 250
+f 260 262 255
+f 260 255 253
+f 259 264 251
+f 259 251 250
+f 252 265 260
+f 252 260 253
+f 257 266 264
+f 257 264 259
+f 265 267 261
+f 265 261 260
+f 256 268 266
+f 256 266 257
+f 267 269 263
+f 267 263 261
+f 270 271 268
+f 270 268 256
+f 269 271 270
+f 269 270 263
+f 258 272 256
+f 272 270 256
+f 270 272 263
+f 272 262 263
+f 254 273 258
+f 273 272 258
+f 272 273 262
+f 273 255 262
+f 232 237 254
+f 237 273 254
+f 273 237 255
+f 237 235 255
+f 40 240 274
+f 40 274 189
+f 275 243 35
+f 275 35 190
+f 189 274 276
+f 189 276 199
+f 277 275 190
+f 277 190 202
+f 199 276 200
+f 276 278 200
+f 279 277 201
+f 277 202 201
+f 200 278 280
+f 200 280 215
+f 281 279 201
+f 281 201 216
+f 215 280 204
+f 280 282 204
+f 283 281 205
+f 281 216 205
+f 204 282 207
+f 282 284 207
+f 285 283 210
+f 283 205 210
+f 207 284 208
+f 284 286 208
+f 287 285 209
+f 285 210 209
+f 208 286 288
+f 208 288 28
+f 289 287 209
+f 289 209 26
+f 28 288 290
+f 28 290 25
+f 290 289 26
+f 290 26 25
+f 291 292 293
+f 291 293 294
+f 295 296 297
+f 295 297 298
+f 294 293 299
+f 294 299 300
+f 301 295 298
+f 301 298 302
+f 300 299 303
+f 300 303 304
+f 305 301 302
+f 305 302 306
+f 307 308 292
+f 307 292 291
+f 296 309 310
+f 296 310 297
+f 311 312 307
+f 312 308 307
+f 309 313 310
+f 313 314 310
+f 315 316 311
+f 316 312 311
+f 313 317 314
+f 317 318 314
+f 319 320 316
+f 319 316 315
+f 317 321 322
+f 317 322 318
+f 323 324 319
+f 324 320 319
+f 321 325 322
+f 325 326 322
+f 327 328 324
+f 327 324 323
+f 325 329 330
+f 325 330 326
+f 331 332 327
+f 332 328 327
+f 329 333 330
+f 333 334 330
+f 335 336 331
+f 336 332 331
+f 333 337 334
+f 337 338 334
+f 339 340 336
+f 339 336 335
+f 337 341 342
+f 337 342 338
+f 304 303 340
+f 304 340 339
+f 341 305 306
+f 341 306 342
+f 303 343 344
+f 303 344 340
+f 345 346 305
+f 345 305 341
+f 340 344 347
+f 340 347 336
+f 348 345 341
+f 348 341 337
+f 336 347 349
+f 336 349 332
+f 350 348 337
+f 350 337 333
+f 332 349 328
+f 349 351 328
+f 352 350 329
+f 350 333 329
+f 328 351 324
+f 351 353 324
+f 354 352 325
+f 352 329 325
+f 324 353 355
+f 324 355 320
+f 356 354 325
+f 356 325 321
+f 320 355 357
+f 320 357 316
+f 358 356 321
+f 358 321 317
+f 316 357 359
+f 316 359 312
+f 360 358 317
+f 360 317 313
+f 312 359 361
+f 312 361 308
+f 362 360 313
+f 362 313 309
+f 308 361 292
+f 361 363 292
+f 364 362 296
+f 362 309 296
+f 299 365 303
+f 365 343 303
+f 346 366 305
+f 366 301 305
+f 293 367 365
+f 293 365 299
+f 366 368 295
+f 366 295 301
+f 292 363 367
+f 292 367 293
+f 368 364 296
+f 368 296 295
+f 23 369 370
+f 23 370 24
+f 370 369 20
+f 370 20 19
+f 370 371 24
+f 371 372 24
+f 373 371 19
+f 371 370 19
+f 24 372 374
+f 24 374 22
+f 375 373 19
+f 375 19 21
+f 22 374 376
+f 22 376 23
+f 377 375 21
+f 377 21 20
+f 23 376 369
+f 376 378 369
+f 378 377 369
+f 377 20 369
+f 376 379 380
+f 376 380 378
+f 380 381 377
+f 380 377 378
+f 374 382 379
+f 374 379 376
+f 381 383 375
+f 381 375 377
+f 372 384 382
+f 372 382 374
+f 383 385 373
+f 383 373 375
+f 371 386 372
+f 386 384 372
+f 385 386 373
+f 386 371 373
+f 387 388 241
+f 387 241 244
+f 242 389 390
+f 242 390 245
+f 387 244 391
+f 244 246 391
+f 249 245 392
+f 245 390 392
+f 391 246 393
+f 246 247 393
+f 248 249 394
+f 249 392 394
+f 393 395 391
+f 395 396 391
+f 397 398 392
+f 398 394 392
+f 391 396 387
+f 396 399 387
+f 400 397 390
+f 397 392 390
+f 387 399 401
+f 387 401 388
+f 402 400 390
+f 402 390 389
+f 388 401 403
+f 388 403 404
+f 403 402 389
+f 403 389 404
+f 405 406 407
+f 405 407 408
+f 407 406 409
+f 407 409 410
+f 411 408 412
+f 408 407 412
+f 407 410 413
+f 410 414 413
+f 405 408 415
+f 405 415 416
+f 417 410 409
+f 417 409 418
+f 408 411 415
+f 411 419 415
+f 420 414 417
+f 414 410 417
+f 411 412 421
+f 411 421 419
+f 422 413 414
+f 422 414 420
+f 412 407 423
+f 412 423 421
+f 423 407 413
+f 423 413 422
+f 405 416 406
+f 416 424 406
+f 424 418 406
+f 418 409 406
+f 416 396 424
+f 396 425 424
+f 425 397 424
+f 397 418 424
+f 421 423 403
+f 423 426 403
+f 426 423 403
+f 423 422 403
+f 419 421 401
+f 421 403 401
+f 403 422 402
+f 422 420 402
+f 415 419 399
+f 419 401 399
+f 402 420 400
+f 420 417 400
+f 416 415 399
+f 416 399 396
+f 400 417 418
+f 400 418 397
+f 427 384 428
+f 384 386 428
+f 386 385 428
+f 385 429 428
+f 430 395 428
+f 395 427 428
+f 429 398 428
+f 398 430 428
+f 430 425 395
+f 425 396 395
+f 397 425 398
+f 425 430 398
+f 431 432 384
+f 431 384 427
+f 385 433 434
+f 385 434 429
+f 427 395 393
+f 427 393 431
+f 394 398 429
+f 394 429 434
+f 435 382 432
+f 382 384 432
+f 385 383 433
+f 383 436 433
+f 437 379 382
+f 437 382 435
+f 383 381 438
+f 383 438 436
+f 439 380 379
+f 439 379 437
+f 381 380 439
+f 381 439 438
+f 367 363 440
+f 363 404 440
+f 404 364 440
+f 364 368 440
+f 440 441 365
+f 440 365 367
+f 366 441 440
+f 366 440 368
+f 441 442 365
+f 442 343 365
+f 346 443 366
+f 443 441 366
+f 404 363 361
+f 404 361 388
+f 362 364 404
+f 362 404 389
+f 444 388 361
+f 444 361 359
+f 362 389 445
+f 362 445 360
+f 446 444 357
+f 444 359 357
+f 360 445 358
+f 445 447 358
+f 448 446 355
+f 446 357 355
+f 358 447 356
+f 447 449 356
+f 450 448 353
+f 448 355 353
+f 356 449 354
+f 449 451 354
+f 452 450 351
+f 450 353 351
+f 354 451 352
+f 451 453 352
+f 454 452 349
+f 452 351 349
+f 352 453 350
+f 453 455 350
+f 456 454 347
+f 454 349 347
+f 350 455 348
+f 455 457 348
+f 456 347 344
+f 456 344 458
+f 345 348 457
+f 345 457 459
+f 458 344 442
+f 344 343 442
+f 346 345 443
+f 345 459 443
+f 441 290 442
+f 290 288 442
+f 289 290 443
+f 290 441 443
+f 442 288 458
+f 288 286 458
+f 287 289 459
+f 289 443 459
+f 458 286 456
+f 286 284 456
+f 285 287 457
+f 287 459 457
+f 456 284 282
+f 456 282 454
+f 283 285 457
+f 283 457 455
+f 454 282 452
+f 282 280 452
+f 281 283 453
+f 283 455 453
+f 452 280 450
+f 280 278 450
+f 279 281 451
+f 281 453 451
+f 450 278 448
+f 278 276 448
+f 277 279 449
+f 279 451 449
+f 448 276 274
+f 448 274 446
+f 275 277 449
+f 275 449 447
+f 446 274 444
+f 274 240 444
+f 243 275 445
+f 275 447 445
+f 444 240 241
+f 444 241 388
+f 242 243 445
+f 242 445 389
+f 431 393 247
+f 431 247 251
+f 248 394 434
+f 248 434 252
+f 432 431 251
+f 432 251 264
+f 252 434 433
+f 252 433 265
+f 435 432 264
+f 435 264 266
+f 265 433 436
+f 265 436 267
+f 437 435 268
+f 435 266 268
+f 267 436 269
+f 436 438 269
+f 439 437 271
+f 437 268 271
+f 269 438 271
+f 438 439 271
+f 4 460 461
+f 4 461 5
+f 462 463 3
+f 462 3 2
+f 5 461 464
+f 5 464 8
+f 465 462 2
+f 465 2 7
+f 8 464 466
+f 8 466 10
+f 467 465 7
+f 467 7 9
+f 10 466 468
+f 10 468 12
+f 469 467 9
+f 469 9 11
+f 12 468 14
+f 468 470 14
+f 471 469 13
+f 469 11 13
+f 14 470 16
+f 470 472 16
+f 473 471 15
+f 471 13 15
+f 16 472 18
+f 472 474 18
+f 475 473 17
+f 473 15 17
+f 18 474 4
+f 474 460 4
+f 463 475 3
+f 475 17 3
+f 476 460 477
+f 460 474 477
+f 475 463 478
+f 463 479 478
+f 480 476 481
+f 476 477 481
+f 478 479 482
+f 479 483 482
+f 481 477 484
+f 477 485 484
+f 486 478 487
+f 478 482 487
+f 477 474 485
+f 474 472 485
+f 473 475 486
+f 475 478 486
+f 485 472 488
+f 472 470 488
+f 471 473 489
+f 473 486 489
+f 484 485 490
+f 485 488 490
+f 489 486 491
+f 486 487 491
+f 490 488 492
+f 488 493 492
+f 494 489 495
+f 489 491 495
+f 488 470 468
+f 488 468 493
+f 469 471 489
+f 469 489 494
+f 493 468 496
+f 468 466 496
+f 467 469 497
+f 469 494 497
+f 492 493 498
+f 493 496 498
+f 497 494 499
+f 494 495 499
+f 498 496 500
+f 498 500 501
+f 502 497 499
+f 502 499 503
+f 496 466 464
+f 496 464 500
+f 465 467 497
+f 465 497 502
+f 500 464 461
+f 500 461 504
+f 462 465 502
+f 462 502 505
+f 501 500 504
+f 501 504 506
+f 505 502 503
+f 505 503 507
+f 506 504 476
+f 506 476 480
+f 479 505 507
+f 479 507 483
+f 504 461 460
+f 504 460 476
+f 463 462 505
+f 463 505 479
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/sphere.obj	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,128 @@
+# Blender v242 OBJ File: bow.blend
+# www.blender3d.org
+mtllib sphere.mtl
+v -0.024294 0.961141 -0.274988
+v 0.683332 0.290993 -0.669598
+v -0.332322 0.192749 -0.923249
+v -0.903742 0.422154 -0.070949
+v -0.241221 0.662176 0.709446
+v 0.739635 0.581112 0.339455
+v 0.241221 -0.662176 -0.709446
+v -0.739635 -0.581112 -0.339455
+v -0.683332 -0.290993 0.669598
+v 0.332322 -0.192749 0.923249
+v 0.903742 -0.422154 0.070949
+v 0.024294 -0.961141 0.274988
+v 0.387374 0.735988 -0.555215
+v -0.209614 0.678242 -0.704308
+v 0.206320 0.284339 -0.936260
+v 0.420468 0.906516 0.037893
+v 0.836404 0.512613 -0.194054
+v -0.545486 0.813080 -0.203337
+v -0.726545 0.361433 -0.584379
+v -0.156067 0.954165 0.255369
+v -0.672997 0.637357 0.375302
+v 0.292963 0.730793 0.616534
+v 0.965959 0.093434 0.241231
+v 0.932865 -0.077095 -0.351879
+v 0.543447 -0.218179 -0.810594
+v -0.053548 -0.275925 -0.959686
+v -0.630090 -0.228277 -0.742210
+v -0.965959 -0.093434 -0.241231
+v -0.932865 0.077095 0.351879
+v -0.543447 0.218179 0.810594
+v 0.053548 0.275925 0.959686
+v 0.630090 0.228277 0.742210
+v 0.672997 -0.637357 -0.375302
+v -0.292963 -0.730793 -0.616534
+v -0.836404 -0.512613 0.194054
+v -0.206320 -0.284339 0.936260
+v 0.726545 -0.361433 0.584379
+v 0.545486 -0.813080 0.203337
+v 0.156067 -0.954165 -0.255369
+v -0.420468 -0.906516 -0.037893
+v -0.387374 -0.735988 0.555215
+v 0.209614 -0.678242 0.704308
+usemtl (null)
+usemtl (null)
+s off
+f 15 13 2
+f 13 15 14
+f 3 14 15
+f 14 1 13
+f 17 2 13
+f 13 16 17
+f 6 17 16
+f 13 1 16
+f 19 14 3
+f 14 19 18
+f 4 18 19
+f 18 1 14
+f 21 18 4
+f 18 21 20
+f 5 20 21
+f 20 1 18
+f 22 20 5
+f 20 22 16
+f 6 16 22
+f 16 1 20
+f 24 2 17
+f 17 23 24
+f 11 24 23
+f 23 17 6
+f 26 3 15
+f 15 25 26
+f 7 26 25
+f 25 15 2
+f 28 4 19
+f 19 27 28
+f 8 28 27
+f 27 19 3
+f 30 5 21
+f 21 29 30
+f 9 30 29
+f 29 21 4
+f 32 6 22
+f 22 31 32
+f 10 32 31
+f 31 22 5
+f 33 24 11
+f 24 33 25
+f 7 25 33
+f 25 2 24
+f 34 26 7
+f 26 34 27
+f 8 27 34
+f 27 3 26
+f 35 28 8
+f 28 35 29
+f 9 29 35
+f 29 4 28
+f 36 30 9
+f 30 36 31
+f 10 31 36
+f 31 5 30
+f 37 32 10
+f 32 37 23
+f 11 23 37
+f 23 6 32
+f 39 7 33
+f 33 38 39
+f 12 39 38
+f 38 33 11
+f 40 8 34
+f 34 39 40
+f 12 40 39
+f 39 34 7
+f 41 9 35
+f 35 40 41
+f 12 41 40
+f 40 35 8
+f 42 10 36
+f 36 41 42
+f 12 42 41
+f 41 36 9
+f 38 11 37
+f 37 42 38
+f 12 38 42
+f 42 37 10
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/spheres_ao.py	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,40 @@
+#!/usr/bin/python2.4
+
+import sys
+sys.path.append("../")
+
+from raytracer import Raytracer, Material, Plane, Sphere, Light
+import Image
+
+rt = Raytracer()
+rt.ambientocclusion(samples=60, distance=6.0, angle=0.5)
+
+light1 = Light(position=(0.0, 5.0, 5.0), colour=(0.7, 0.3, 0.6))
+light1.castshadows(False)
+rt.addlight(light1)
+
+light2 = Light(position=(-2.0, 10.0, 2.0), colour=(0.4, 0.6, 0.3))
+light2.castshadows(False)
+rt.addlight(light2)
+
+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)
+
+mat1 = Material(colour=(1.0, 0.0, 0.0))
+bigsphere = Sphere(centre=(3.0, 2.0, 7.0), radius=3.0, material=mat1)
+rt.addshape(bigsphere)
+
+mat2 = Material(colour=(0.0, 1.0, 0.0))
+smallsphere = Sphere(centre=(-5.5, 1.5, 8.0), radius=2.0, material=mat2)
+rt.addshape(smallsphere)
+
+mat3 = Material(colour=(0.0, 0.0, 1.0))
+tinysphere = Sphere(centre=(-1.2, 0.0, 2.0), radius=0.5, material=mat3)
+rt.addshape(tinysphere)
+
+imagesize = (800, 600)
+data = rt.render(imagesize)
+img = Image.fromstring("RGB", imagesize, data)
+img.save('spheres_ao.png')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/spheres_shadow.py	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,37 @@
+#!/usr/bin/python2.4
+
+import sys
+sys.path.append("../")
+
+from raytracer import Raytracer, Material, Plane, Sphere, Light
+import Image
+
+rt = Raytracer()
+
+light1 = Light(position=(0.0, 5.0, 5.0), colour=(0.7, 0.3, 0.6))
+rt.addlight(light1)
+
+light2 = Light(position=(-2.0, 10.0, 2.0), colour=(0.4, 0.6, 0.3))
+rt.addlight(light2)
+
+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)
+
+mat1 = Material(colour=(1.0, 0.0, 0.0))
+bigsphere = Sphere(centre=(3.0, 2.0, 7.0), radius=3.0, material=mat1)
+rt.addshape(bigsphere)
+
+mat2 = Material(colour=(0.0, 1.0, 0.0))
+smallsphere = Sphere(centre=(-5.5, 1.5, 8.0), radius=2.0, material=mat2)
+rt.addshape(smallsphere)
+
+mat3 = Material(colour=(0.0, 0.0, 1.0))
+tinysphere = Sphere(centre=(-1.2, 0.0, 2.0), radius=0.5, material=mat3)
+rt.addshape(tinysphere)
+
+imagesize = (800, 600)
+data = rt.render(imagesize)
+img = Image.fromstring("RGB", imagesize, data)
+img.save('spheres_shadow.png')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/triangles_monkey.py	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,35 @@
+#!/usr/bin/python2.4
+
+import sys
+sys.path.append("../")
+
+from raytracer import Raytracer, Light, Sphere, Triangle, Material
+import Image
+
+def LoadWavefrontObjFile(rt, mat, filename):
+	vertices = []
+	fp = file(filename)
+	while True:
+		ln = fp.readline()
+		if ln == "":
+			break;
+		ln = ln.split()
+		if ln[0] == "v":
+			v = [1.5*float(x) for x in ln[1:4]]
+			vertices.append(tuple(v))
+		if ln[0] == "f":
+			f = [vertices[int(x)-1] for x in ln[1:4]]
+			face = Triangle(f[0], f[1], f[2], mat)
+			rt.addshape(face)
+
+rt = Raytracer()
+mat = Material(colour=(0.9, 0.9, 0.9))
+LoadWavefrontObjFile(rt, mat, "monkey.obj")
+
+light = Light(position=(-5.0, 2.0, -8.0), colour=(0.9, 0.3, 0.6))
+rt.addlight(light)
+
+imagesize = (800, 600)
+data = rt.render(imagesize)
+img = Image.fromstring("RGB", imagesize, data)
+img.save('triangles_monkey.png')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/triangles_sphere.py	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,40 @@
+#!/usr/bin/python2.4
+
+import sys
+sys.path.append("../")
+
+from raytracer import Raytracer, Light, Sphere, Triangle, Material
+import Image
+
+def LoadWavefrontObjFile(rt, mat, filename):
+	vertices = []
+	fp = file(filename)
+	while True:
+		ln = fp.readline()
+		if ln == "":
+			break;
+		ln = ln.split()
+		if ln[0] == "v":
+			v = [1.5*float(x) for x in ln[1:4]]
+			vertices.append(tuple(v))
+		if ln[0] == "f":
+			f = [vertices[int(x)-1] for x in ln[1:4]]
+			face = Triangle(f[0], f[1], f[2], mat)
+			rt.addshape(face)
+
+rt = Raytracer()
+mat = Material(colour=(0.9, 0.9, 0.9))
+LoadWavefrontObjFile(rt, mat, "sphere.obj")
+
+light1 = Light(position=(0.0, 2.0, -5.0), colour=(0.9, 0.3, 0.6))
+light1.castshadows(False);
+rt.addlight(light1)
+
+light2 = Light(position=(-2.0, -5.0, -7.0), colour=(0.7, 1.0, 0.3))
+light2.castshadows(False);
+rt.addlight(light2)
+
+imagesize = (800, 600)
+data = rt.render(imagesize)
+img = Image.fromstring("RGB", imagesize, data)
+img.save('triangles_sphere.png')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/kdtree.cc	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,36 @@
+#include "kdtree.cc"
+
+void KdTree::KdTree(ShapeList &shapelist):
+{
+	root = new KdNode();
+	shapes = new vector<Shape*>();
+	ShapeList::iterator shape;
+	for (shape = shapelist.begin(); shape != shapes.end(); shape++)
+		addShape(*shape);
+
+	rebuild();
+}
+
+void KdTree::Subdivide(KdNode* node, AABB& bbox, int depth, int count)
+{
+	
+	/*if (stopcriterionmet()) return
+	splitpos = findoptimalsplitposition()
+	leftnode = new Node()
+	rightnode = new Node()
+	for (all primitives in node)
+	{
+		if (node->intersectleftnode()) leftnode->addprimitive( primitive )
+		if (node->intersectrightnode()) rightnode->addprimitive( primitive )
+	}
+	buildkdtree( leftnode )
+		buildkdtree( rightnode )*/
+}
+
+void KdTree::rebuild()
+{
+	int count = shapes->size();
+	AABB bbox = shapes->extends();
+
+	Subdivide(root, bbox, 0, count);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/kdtree.h	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,51 @@
+#ifndef KDTREE_H
+#define KDTREE_H
+
+#include <vector>
+
+#include "scene.h"
+
+class SpaceDivider
+{
+	ShapeList *shapes;
+public:
+	SpaceDivider(ShapeList &shapelist): shapes(shapelist) {};
+};
+
+class KdNode:
+{
+	float split;
+	bool leaf; /* is this node a leaf? */
+	char axis; /* 0,1,2 => x,y,z */
+	KdNode *leftchild, *rightchild;
+public:
+	vector<Shape*> shapes;
+
+	KdNode() : leaf(true), axis(0), shapes() {};
+
+	setAxis(char aAxis) { axis = aAxis; };
+	char getAxis() { return axis; };
+
+	setSplit(float aSplit) { split = aSplit; };
+	float getSplit() { return split; };
+
+	setLeaf(bool aLeaf) { leaf = aLeaf; };
+	bool isLeaf() { return leaf; };
+
+	setLeftChild(KdNode *aLeft) { leftchild = aLeft; };
+	KdNode *getLeftChild() { return leftchild; };
+	setRightChild(KdNode *aRight) { rightchild = aRight; };
+	KdNode *getRightChild() { return rightchild; };
+
+	addShape(Shape* aShape) { shapes.push_back(aShape); };
+};
+
+class KdTree: public SpaceDivider
+{
+	KdNote *root;
+public:
+	KdTree(ShapeList &shapelist);
+	rebuild();
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/matrix.h	Thu Oct 25 16:40:22 2007 +0200
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/noise.cc	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,134 @@
+/*
+Based on
+JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE
+by KEN PERLIN (COPYRIGHT 2002)
+*/
+
+#include <math.h>
+
+#include "noise.h"
+
+double fade(double t)
+{
+      return t * t * t * (t * (t * 6 - 15) + 10);
+}
+
+double lerp(double t, double a, double b)
+{
+      return a + t * (b - a);
+}
+
+double grad(unsigned char hash, double x, double y, double z)
+{
+      unsigned char h = hash & 15;            // CONVERT LO 4 BITS OF HASH CODE
+      double 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);
+}
+
+unsigned char p[512] = { 151,160,137,91,90,15,
+   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
+
+   151,160,137,91,90,15,
+   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
+   };
+
+
+double perlin(double x, double y, double z)
+{
+      int X = (int)floor(x) & 255,                  // FIND UNIT CUBE THAT
+          Y = (int)floor(y) & 255,                  // CONTAINS POINT.
+          Z = (int)floor(z) & 255;
+      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
+             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
+          B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;      // THE 8 CUBE CORNERS,
+
+      return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ),  // AND ADD
+                                     grad(p[BA  ], x-1, y  , z   )), // BLENDED
+                             lerp(u, grad(p[AB  ], x  , y-1, z   ),  // RESULTS
+                                     grad(p[BB  ], x-1, y-1, z   ))),// FROM  8
+                     lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  // CORNERS
+                                     grad(p[BA+1], x-1, y  , z-1 )), // OF CUBE
+                             lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
+                                     grad(p[BB+1], x-1, y-1, z-1 ))));
+}
+
+
+/*
+// JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN.
+
+public final class ImprovedNoise {
+   static public double noise(double x, double y, double z) {
+      int X = (int)Math.floor(x) & 255,                  // FIND UNIT CUBE THAT
+          Y = (int)Math.floor(y) & 255,                  // CONTAINS POINT.
+          Z = (int)Math.floor(z) & 255;
+      x -= Math.floor(x);                                // FIND RELATIVE X,Y,Z
+      y -= Math.floor(y);                                // OF POINT IN CUBE.
+      z -= Math.floor(z);
+      double 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
+          B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;      // THE 8 CUBE CORNERS,
+
+      return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ),  // AND ADD
+                                     grad(p[BA  ], x-1, y  , z   )), // BLENDED
+                             lerp(u, grad(p[AB  ], x  , y-1, z   ),  // RESULTS
+                                     grad(p[BB  ], x-1, y-1, z   ))),// FROM  8
+                     lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  // CORNERS
+                                     grad(p[BA+1], x-1, y  , z-1 )), // OF CUBE
+                             lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
+                                     grad(p[BB+1], x-1, y-1, z-1 ))));
+   }
+   static double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); }
+   static double lerp(double t, double a, double b) { return a + t * (b - a); }
+   static double grad(int hash, double x, double y, double z) {
+      int h = hash & 15;                      // CONVERT LO 4 BITS OF HASH CODE
+      double 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);
+   }
+   static final int p[] = new int[512], permutation[] = { 151,160,137,91,90,15,
+   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
+   };
+   static { for (int i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i]; }
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/noise.h	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,6 @@
+#ifndef NOISE_H
+#define NOISE_H
+
+double perlin(double x, double y, double z);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/raytracer.cc	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,245 @@
+/*
+ * C++ RayTracer
+ * file: raytracer.cc
+ *
+ * Radek Brich, 2006
+ */
+
+#include <stdio.h>
+#include <malloc.h>
+#include <float.h>
+#include "raytracer.h"
+
+// 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)
+{
+	float p, t, st, phi, phirad;
+	int kk;
+
+	t = 0;
+	for (p=0.5, kk=i; kk; p*=0.5, kk>>=1)
+	if (kk & 1)
+		t += p;
+	t = 1.0 + (t - 1.0)*extent;
+
+	phi = (i + 0.5) / n;
+	phirad =  phi * 2.0 * M_PI;
+
+	st = sqrt(1.0 - t*t);
+
+	float x, y, z, xx, yy, zz, q;
+	x = st * cos(phirad);
+	y = st * sin(phirad);
+	z = t;
+
+	// rotate against Y axis
+	q = acos(normal.z);
+	zz = z*cos(q) - x*sin(q);
+	xx = z*sin(q) + x*cos(q);
+	yy = y;
+
+	// rotate against Z axis
+	q = atan2f(normal.y, normal.x);
+	x = xx*cos(q) - yy*sin(q);
+	y = xx*sin(q) + yy*cos(q);
+	z = zz;
+
+	return Vector3(x, y, z);
+}
+
+inline Shape *Raytracer::nearest_intersection(const Shape *origin_shape, const Ray &ray,
+	float &nearest_distance)
+{
+	Shape *nearest_shape = NULL;
+	ShapeList::iterator shape;
+	for (shape = shapes.begin(); shape != shapes.end(); shape++)
+		if (*shape != origin_shape && (*shape)->intersect(ray, nearest_distance))
+			nearest_shape = *shape;
+	return nearest_shape;
+}
+
+// ---- tyto dve funkce budou v budouci verzi metody objektu PhongShader
+
+// calculate shader function
+// P is point of intersection, N normal in this point
+Colour PhongShader_ambient(Material &mat, Vector3 &P)
+{
+	Colour col = mat.texture.colour; //mat.texture.evaluate(P);
+
+	// ambient
+	return mat.ambient * col;
+}
+
+/*
+ P is point of intersection,
+ N normal in this point,
+ R direction of reflected ray,
+ V direction to the viewer
+*/
+Colour PhongShader_calculate(Material &mat, Vector3 &P, Vector3 &N, Vector3 &R, Vector3 &V,
+	Light &light)
+{
+	Colour I = Colour();
+	Vector3 L = light.pos - P;
+	L.normalize();
+	float L_dot_N = dot(L, N);
+	float R_dot_V = dot(R, V);
+
+	Colour col = mat.texture.colour; //mat.texture.evaluate(P);
+
+	// diffuse
+	I = mat.diffuse * col * light.colour * L_dot_N;
+
+	// specular
+	if (R_dot_V > 0)
+		I += mat.specular * light.colour * powf(R_dot_V, mat.shininess);
+	return I;
+}
+
+Colour Raytracer::raytrace(Ray &ray, int depth, Shape *origin_shape)
+{
+	float nearest_distance = FLT_MAX; //Infinity
+	Shape *nearest_shape = nearest_intersection(origin_shape, ray, nearest_distance);
+
+	if (nearest_shape == NULL) {
+		return bg_colour;
+	} else {
+		Colour acc = Colour();
+		Vector3 P = ray.a + ray.dir * nearest_distance; // point of intersection
+		Vector3 normal = nearest_shape->normal(P);
+		acc = PhongShader_ambient(*nearest_shape->material, P);
+
+		vector<Light*>::iterator light;
+		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);
+			if (L_dot_N > 0) {
+				// test if this light is occluded (sharp shadows)
+				if ((*light)->shadows) {
+					Ray shadow_ray = Ray(P, L);
+					float dist = FLT_MAX;
+					if (nearest_intersection(nearest_shape, shadow_ray, dist))
+						continue;
+				}
+
+				// shading function
+				Vector3 R = L - 2.0 * L_dot_N * normal;
+				acc += PhongShader_calculate(*nearest_shape->material,
+					P, normal, R, ray.dir, **light);
+			}
+		}
+
+		// reflection
+		int trace_max_depth = 4;
+		Vector3 newdir = ray.dir - 2.0 * dot(ray.dir, normal) * normal;
+		if (depth < trace_max_depth && nearest_shape->material->reflection > 0.01) {
+			Ray newray = Ray(P, newdir);
+			Colour refl_col = raytrace(newray, depth + 1, nearest_shape);
+			acc += nearest_shape->material->reflection * refl_col;
+		}
+
+		// refraction
+		/* ... */
+
+		// ambient occlusion
+		if (ao_samples)
+		{
+			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;
+				Shape *shape_in_way = 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;
+			acc = acc * ao_intensity;
+		}
+
+		return acc;
+	}
+}
+
+float *Raytracer::render(int w, int h)
+{
+	int x, y;
+	float *data, *iter;
+
+	data = (float *) malloc(w*h*3*sizeof(float));
+	if (!data)
+		return NULL;
+
+	float startx = -1.0 * 4, starty = (float)h/w * 4;
+	float dx = -2*startx/w, dy = -2*starty/h;
+	float vx, vy;
+
+	//srand(time(NULL));
+
+	// eye - viewing point
+	Vector3 eye(0, 0, -5);
+
+	// for each pixel...
+	iter = data;
+	for (vy = starty, y = 0; y < h; y++) {
+		vx = startx;
+		for (x = 0; x < w; x++) {
+			// generate a ray from eye passing through this pixel
+#if 1
+			// no oversampling
+			Vector3 dir = Vector3(vx, vy, 0) - eye;
+			dir.normalize();
+			Ray ray(eye, dir);
+			Colour c = raytrace(ray, 0, NULL);
+#else
+			// 5x oversampling
+			Vector3 dir = Vector3();
+			Colour c = Colour();
+
+			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};
+				dir = Vector3(vx + osax[i]*dx,
+					vy + osay[i]*dy , 0) - eye;
+				dir.normalize();
+				Ray ray(eye, dir);
+				c += raytrace(ray, 0, NULL);
+			}
+			c = c * (1./5);
+#endif
+			*iter++ = c.r;
+			*iter++ = c.g;
+			*iter++ = c.b;
+			vx += dx;
+		}
+		vy += dy;
+		printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%2d%% done (row %4d)", y*100/(h-1), y);
+	}
+	printf("\n");
+	return data;
+}
+
+void Raytracer::addshape(Shape *shape)
+{
+	shapes.push_back(shape);
+}
+
+void Raytracer::addlight(Light *light)
+{
+	lights.push_back(light);
+}
+
+void Raytracer::ambientocclusion(int samples, float distance, float angle)
+{
+	ao_samples = samples;
+	ao_distance = distance;
+	ao_angle = angle;
+	if (ao_distance == 0)
+		/* 0 ==> Inf */
+		ao_distance = FLT_MAX;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/raytracer.h	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,49 @@
+/*
+ * C++ RayTracer
+ * file: raytracer.h
+ *
+ * Radek Brich, 2006
+ */
+
+#ifndef RAYTRACER_H
+#define RAYTRACER_H
+
+#include <vector>
+
+#include "scene.h"
+
+using namespace std;
+
+/* axis-aligned bounding box */
+class AABB
+{
+};
+
+class ShapeList: public vector<Shape*>
+{
+	AABB extends() { return AABB(); };
+};
+
+class Raytracer
+{
+	ShapeList shapes;
+	vector<Light*> lights;
+	Colour bg_colour;
+	int ao_samples;
+	float ao_distance, ao_angle;
+
+	Vector3 SphereDistribute(int i, int n, float extent, Vector3 &normal);
+	inline Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray,
+		float &nearest_distance);
+	Colour raytrace(Ray &ray, int depth, Shape *origin_shape);
+public:
+	Raytracer(): shapes(), lights(), bg_colour(0.0, 0.0, 0.0), ao_samples(0) {};
+	~Raytracer() {};
+	float *render(int w, int h);
+	void addshape(Shape *shape);
+	void addlight(Light *light);
+
+	void ambientocclusion(int samples, float distance, float angle);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/raytracermodule.cc	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,539 @@
+/*
+ * C++ RayTracer
+ * Module for Python
+ * file: raytracermodule.cc
+ *
+ * Radek Brich, 2006
+ */
+
+#include <Python.h>
+#include <vector>
+#include "scene.h"
+#include "raytracer.h"
+
+//=========================== Light Source Object ===========================
+
+typedef struct {
+	PyObject_HEAD
+	Light *light;
+} LightObject;
+
+static PyObject *Light_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Light_Destructor(PyObject* self);
+static PyObject *Light_Getattr(PyObject *self, char *name);
+static PyObject *Light_castshadows(PyObject* self, PyObject* args);
+
+static PyTypeObject LightType = {
+	PyObject_HEAD_INIT(NULL)
+	0,				/*ob_size*/
+	"Light",			/*tp_name*/
+	sizeof(LightObject),		/*tp_basicsize*/
+	0,				/*tp_itemsize*/
+	/* methods */
+	Light_Destructor,		/*tp_dealloc*/
+	0,				/*tp_print*/
+	Light_Getattr,			/*tp_getattr*/
+	0,				/*tp_setattr*/
+	0,				/*tp_compare*/
+	0,				/*tp_repr*/
+	0,				/*tp_as_number*/
+	0,				/*tp_as_sequence*/
+	0,				/*tp_as_mapping*/
+	0,				/*tp_hash */
+};
+
+static PyMethodDef LightMethods[] = {
+	{"castshadows", (PyCFunction)Light_castshadows, METH_VARARGS, "Enable or disable shadows from this light."},
+	{NULL, NULL}
+};
+
+static PyObject* Light_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+	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;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!|O!", kwdlist,
+		&PyTuple_Type, &TPos, &PyTuple_Type, &TCol))
+		return NULL;
+
+	if (!PyArg_ParseTuple(TPos, "fff", &px, &py, &pz))
+		return NULL;
+	if (TCol && !PyArg_ParseTuple(TCol, "fff", &cr, &cg, &cb))
+		return NULL;
+
+	v = PyObject_New(LightObject, &LightType);
+	v->light = new Light(Vector3(px, py, pz), Colour(cr, cg, cb));
+	return (PyObject*)v;
+}
+
+static void Light_Destructor(PyObject* self)
+{
+	delete ((LightObject *)self)->light;
+	PyObject_Del(self);
+}
+
+static PyObject *Light_Getattr(PyObject *self, char *name)
+{
+	return Py_FindMethod(LightMethods, self, name);
+}
+
+static PyObject *Light_castshadows(PyObject* self, PyObject* args)
+{
+	int shadows = 1;
+
+	if (!PyArg_ParseTuple(args, "i", &shadows))
+		return NULL;
+
+	((LightObject *)self)->light->castshadows(shadows);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+//=========================== Material Object ===========================
+
+typedef struct {
+	PyObject_HEAD
+	Material *material;
+} MaterialObject;
+
+static PyObject *Material_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Material_Destructor(PyObject* self);
+static PyObject *Material_Getattr(PyObject *self, char *name);
+
+static PyTypeObject MaterialType = {
+	PyObject_HEAD_INIT(NULL)
+	0,				/*ob_size*/
+	"Material",			/*tp_name*/
+	sizeof(MaterialObject),		/*tp_basicsize*/
+	0,				/*tp_itemsize*/
+	/* methods */
+	Material_Destructor,		/*tp_dealloc*/
+	0,				/*tp_print*/
+	Material_Getattr,			/*tp_getattr*/
+	0,				/*tp_setattr*/
+	0,				/*tp_compare*/
+	0,				/*tp_repr*/
+	0,				/*tp_as_number*/
+	0,				/*tp_as_sequence*/
+	0,				/*tp_as_mapping*/
+	0,				/*tp_hash */
+};
+
+static PyMethodDef MaterialMethods[] = {
+	{NULL, NULL}
+};
+
+static PyObject* Material_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+	MaterialObject *v;
+	static char *kwdlist[] = {"colour", NULL};
+	PyObject *TCol = NULL;
+	float cr=1.0, cg=1.0, cb=1.0;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwd, "|O!", kwdlist,
+		&PyTuple_Type, &TCol))
+		return NULL;
+
+	if (!PyArg_ParseTuple(TCol, "fff", &cr, &cg, &cb))
+		return NULL;
+
+	v = PyObject_New(MaterialObject, &MaterialType);
+	v->material = new Material(Colour(cr, cg, cb));
+	return (PyObject*)v;
+}
+
+static void Material_Destructor(PyObject* self)
+{
+	delete ((MaterialObject *)self)->material;
+	PyObject_Del(self);
+}
+
+static PyObject *Material_Getattr(PyObject *self, char *name)
+{
+	return Py_FindMethod(MaterialMethods, self, name);
+}
+
+//=========================== Sphere Object ===========================
+
+typedef struct {
+	PyObject_HEAD
+	Sphere *shape;
+} SphereObject;
+
+static PyObject *Sphere_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Sphere_Destructor(PyObject* self);
+static PyObject *Sphere_Getattr(PyObject *self, char *name);
+
+static PyTypeObject SphereType = {
+	PyObject_HEAD_INIT(NULL)
+	0,				/*ob_size*/
+	"Sphere",			/*tp_name*/
+	sizeof(SphereObject),		/*tp_basicsize*/
+	0,				/*tp_itemsize*/
+	/* methods */
+	Sphere_Destructor,		/*tp_dealloc*/
+	0,				/*tp_print*/
+	Sphere_Getattr,			/*tp_getattr*/
+	0,				/*tp_setattr*/
+	0,				/*tp_compare*/
+	0,				/*tp_repr*/
+	0,				/*tp_as_number*/
+	0,				/*tp_as_sequence*/
+	0,				/*tp_as_mapping*/
+	0,				/*tp_hash */
+};
+
+static PyMethodDef SphereMethods[] = {
+	{NULL, NULL}
+};
+
+static PyObject* Sphere_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+	SphereObject *v;
+	MaterialObject *material;
+	static char *kwdlist[] = {"centre", "radius", "material", NULL};
+	PyObject *TCentre = NULL;
+	float cx, cy, cz, radius;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!fO!", kwdlist,
+		&PyTuple_Type, &TCentre, &radius, &MaterialType, &material))
+		return NULL;
+
+	if (!PyArg_ParseTuple(TCentre, "fff", &cx, &cy, &cz))
+		return NULL;
+
+	v = PyObject_New(SphereObject, &SphereType);
+	v->shape = new Sphere(Vector3(cx, cy, cz), radius, material->material);
+	Py_INCREF(material);
+	return (PyObject*)v;
+}
+
+static void Sphere_Destructor(PyObject* self)
+{
+	delete ((SphereObject *)self)->shape;
+	PyObject_Del(self);
+}
+
+static PyObject *Sphere_Getattr(PyObject *self, char *name)
+{
+	return Py_FindMethod(SphereMethods, self, name);
+}
+
+//=========================== Plane Object ===========================
+
+typedef struct {
+	PyObject_HEAD
+	Plane *shape;
+} PlaneObject;
+
+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 PyTypeObject PlaneType = {
+	PyObject_HEAD_INIT(NULL)
+	0,				/*ob_size*/
+	"Plane",			/*tp_name*/
+	sizeof(PlaneObject),		/*tp_basicsize*/
+	0,				/*tp_itemsize*/
+	/* methods */
+	Plane_Destructor,		/*tp_dealloc*/
+	0,				/*tp_print*/
+	Plane_Getattr,			/*tp_getattr*/
+	0,				/*tp_setattr*/
+	0,				/*tp_compare*/
+	0,				/*tp_repr*/
+	0,				/*tp_as_number*/
+	0,				/*tp_as_sequence*/
+	0,				/*tp_as_mapping*/
+	0,				/*tp_hash */
+};
+
+static PyMethodDef PlaneMethods[] = {
+	{NULL, NULL}
+};
+
+static PyObject* Plane_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+	PlaneObject *v;
+	MaterialObject *material;
+	static char *kwdlist[] = {"normal", "d", "material", NULL};
+	PyObject *TNorm = NULL;
+	float nx, ny, nz, d;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!fO!", kwdlist,
+		&PyTuple_Type, &TNorm, &d, &MaterialType, &material))
+		return NULL;
+
+	if (!PyArg_ParseTuple(TNorm, "fff", &nx, &ny, &nz))
+		return NULL;
+
+	v = PyObject_New(PlaneObject, &PlaneType);
+	v->shape = new Plane(Vector3(nx, ny, nz), d, material->material);
+	Py_INCREF(material);
+	return (PyObject*)v;
+}
+
+static void Plane_Destructor(PyObject* self)
+{
+	delete ((PlaneObject *)self)->shape;
+	PyObject_Del(self);
+}
+
+static PyObject *Plane_Getattr(PyObject *self, char *name)
+{
+	return Py_FindMethod(PlaneMethods, self, name);
+}
+
+//=========================== Triangle Object ===========================
+
+typedef struct {
+	PyObject_HEAD
+	Triangle *shape;
+} TriangleObject;
+
+static PyObject *Triangle_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Triangle_Destructor(PyObject* self);
+static PyObject *Triangle_Getattr(PyObject *self, char *name);
+
+static PyTypeObject TriangleType = {
+	PyObject_HEAD_INIT(NULL)
+	0,				/*ob_size*/
+	"Triangle",			/*tp_name*/
+	sizeof(TriangleObject),		/*tp_basicsize*/
+	0,				/*tp_itemsize*/
+	/* methods */
+	Triangle_Destructor,		/*tp_dealloc*/
+	0,				/*tp_print*/
+	Triangle_Getattr,			/*tp_getattr*/
+	0,				/*tp_setattr*/
+	0,				/*tp_compare*/
+	0,				/*tp_repr*/
+	0,				/*tp_as_number*/
+	0,				/*tp_as_sequence*/
+	0,				/*tp_as_mapping*/
+	0,				/*tp_hash */
+};
+
+static PyMethodDef TriangleMethods[] = {
+	{NULL, NULL}
+};
+
+static PyObject* Triangle_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+	TriangleObject *v;
+	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;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!O!", kwdlist,
+		&PyTuple_Type, &A, &PyTuple_Type, &B, &PyTuple_Type, &C,
+		&MaterialType, &material))
+		return NULL;
+
+	if (!PyArg_ParseTuple(A, "fff", &ax, &ay, &az))
+		return NULL;
+
+	if (!PyArg_ParseTuple(B, "fff", &bx, &by, &bz))
+		return NULL;
+
+	if (!PyArg_ParseTuple(C, "fff", &cx, &cy, &cz))
+		return NULL;
+
+	v = PyObject_New(TriangleObject, &TriangleType);
+	v->shape = new Triangle(Vector3(ax, ay, az), Vector3(bx, by, bz),
+		Vector3(cx, cy, cz), material->material);
+	Py_INCREF(material);
+	return (PyObject*)v;
+}
+
+static void Triangle_Destructor(PyObject* self)
+{
+	delete ((TriangleObject *)self)->shape;
+	PyObject_Del(self);
+}
+
+static PyObject *Triangle_Getattr(PyObject *self, char *name)
+{
+	return Py_FindMethod(TriangleMethods, self, name);
+}
+
+//=========================== Raytracer Object ===========================
+
+typedef struct {
+	PyObject_HEAD
+	Raytracer *raytracer;
+	vector<PyObject*> *children;
+} RaytracerObject;
+
+static PyObject *Raytracer_Constructor(PyObject* self, PyObject* args);
+static void Raytracer_Destructor(PyObject* self);
+static PyObject *Raytracer_Getattr(PyObject *self, char *name);
+static PyObject *Raytracer_render(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);
+
+static PyTypeObject RaytracerType = {
+	PyObject_HEAD_INIT(NULL)
+	0,				/*ob_size*/
+	"Raytracer",			/*tp_name*/
+	sizeof(RaytracerObject),	/*tp_basicsize*/
+	0,				/*tp_itemsize*/
+	/* methods */
+	Raytracer_Destructor,		/*tp_dealloc*/
+	0,				/*tp_print*/
+	Raytracer_Getattr,		/*tp_getattr*/
+	0,				/*tp_setattr*/
+	0,				/*tp_compare*/
+	0,				/*tp_repr*/
+	0,				/*tp_as_number*/
+	0,				/*tp_as_sequence*/
+	0,				/*tp_as_mapping*/
+	0,				/*tp_hash */
+};
+
+static PyMethodDef RaytracerMethods[] = {
+	{"render", (PyCFunction)Raytracer_render, METH_VARARGS, "Render scene and return image data."},
+	{"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,
+		"Set ambient occlusion parametrs - samples: int (0 = disable), distance: float, angle: float."},
+	{NULL, NULL}
+};
+
+static PyObject* Raytracer_Constructor(PyObject* self, PyObject* args)
+{
+	RaytracerObject *v;
+
+	if(!PyArg_ParseTuple(args, ""))
+		return NULL;
+
+	v = PyObject_New(RaytracerObject, &RaytracerType);
+	v->raytracer = new Raytracer();
+	v->children = new vector<PyObject*>();
+
+	return (PyObject*)v;
+}
+
+static void Raytracer_Destructor(PyObject* self)
+{
+	vector<PyObject*>::iterator o;
+	for (o = ((RaytracerObject *)self)->children->begin();
+		o != ((RaytracerObject *)self)->children->end(); o++)
+		Py_DECREF(*o);
+	delete ((RaytracerObject *)self)->raytracer;
+	PyObject_Del(self);
+}
+
+static PyObject *Raytracer_Getattr(PyObject *self, char *name)
+{
+	return Py_FindMethod(RaytracerMethods, self, name);
+}
+
+static PyObject* Raytracer_render(PyObject* self, PyObject* args)
+{
+	int w = 0, h = 0;
+	char *chardata;
+	float *data;
+	PyObject *o;
+
+	if (!PyArg_ParseTuple(args, "(ii)", &w, &h))
+		return NULL;
+
+	printf("[PyRit] Raytracing...\n");
+	data = ((RaytracerObject *)self)->raytracer->render(w, h);
+	if (!data) {
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+
+	// convert data to char
+	printf("[PyRit] Converting image data (float to char)...\n");
+	chardata = (char *) malloc(w*h*3);
+	float *d = data;
+	for (char *c = chardata; c != chardata + w*h*3; c++, d++) {
+		if (*d > 1.0)
+			*c = 255;
+		else
+			*c = (unsigned char)(*d * 255.0);
+	}
+	free(data);
+	o = Py_BuildValue("s#", chardata, w*h*3);
+	free(chardata);
+	printf("[PyRit] Done.\n");
+	return o;
+}
+
+static PyObject* Raytracer_addshape(PyObject* self, PyObject* args)
+{
+	PyObject *obj;
+
+	if (!PyArg_ParseTuple(args, "O", &obj))
+		return NULL;
+
+	((RaytracerObject *)self)->raytracer->addshape(
+		((PlaneObject*)obj)->shape);
+
+	((RaytracerObject *)self)->children->push_back(obj);
+	Py_INCREF(obj);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject* Raytracer_addlight(PyObject* self, PyObject* args)
+{
+	LightObject *lightobj;
+
+	if (!PyArg_ParseTuple(args, "O!", &LightType, &lightobj))
+		return NULL;
+	((RaytracerObject *)self)->raytracer->addlight(lightobj->light);
+	((RaytracerObject *)self)->children->push_back((PyObject*)lightobj);
+	Py_INCREF(lightobj);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject* Raytracer_ambientocclusion(PyObject* self, PyObject* args, PyObject *kwd)
+{
+	int samples = 0;
+	float distance = 0.0, angle = 0.0;
+	static char *kwdlist[] = {"samples", "distance", "angle", NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwd, "iff", kwdlist,
+		&samples, &distance, &angle))
+		return NULL;
+
+	((RaytracerObject *)self)->raytracer->ambientocclusion(samples, distance, angle);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+//=========================== Module Methods ===========================
+
+static PyMethodDef ModuleMethods[] = {
+	{"Raytracer", (PyCFunction) Raytracer_Constructor,
+		METH_VARARGS, "Raytracer object constructor."},
+	{"Light", (PyCFunction) Light_Constructor,
+		METH_VARARGS | METH_KEYWORDS, "Light source object constructor."},
+	{"Material", (PyCFunction) Material_Constructor,
+		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."},
+	{"Triangle", (PyCFunction) Triangle_Constructor,
+		METH_VARARGS | METH_KEYWORDS, "Triangle object constructor."},
+	{NULL, NULL}
+};
+
+
+extern "C" void initraytracer(void)
+{
+	Py_InitModule("raytracer", ModuleMethods);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/scene.cc	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,167 @@
+/*
+ * C++ RayTracer
+ * file: scene.cc
+ *
+ * Radek Brich, 2006
+ */
+
+#include <math.h>
+#include "scene.h"
+
+bool Sphere::intersect(const Ray &ray, float &dist)
+{
+	Vector3 V = ((Ray)ray).a - center;
+
+	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;
+		if (t1 > 0)
+		{
+			if (t1 < dist) {
+				dist = t1;
+				return true;
+			}
+		} else {
+			float t2 = Vd + Det;
+			if (t2 > 0)
+			{
+				// ray from inside of the sphere
+				dist = t2;
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+bool Sphere::intersect_all(const Ray &ray, float dist, vector<float> &allts)
+{
+	//allts = new vector<float>();
+
+	Vector3 V = ((Ray)ray).a - center;
+	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;
+		if (t1 < 0)
+		{
+			if (t2 > 0)
+			{
+				// ray from inside of the sphere
+				allts.push_back(0.0);
+				allts.push_back(t2);
+				return true;
+			}
+			else
+				return false;
+		}
+		else
+		{
+			allts.push_back(t1);
+			allts.push_back(t2);
+			return true;
+		}
+	}
+	return false;
+}
+
+bool Plane::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;
+}
+
+// this initialization and following intersection methods implements
+// Fast Triangle Intersection algorithm from
+// http://www.mpi-inf.mpg.de/~wald/PhD/
+Triangle::Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial)
+	: A(aA), B(aB), C(aC)
+{
+	material = amaterial;
+	Vector3 c = B - A;
+	Vector3 b = C - A;
+
+	N = cross(c, b);
+
+	if (fabsf(N.x) > fabsf(N.y))
+	{
+		if (fabsf(N.x) > fabsf(N.z))
+			k = 0;
+		else
+			k = 2;
+	}
+	else
+	{
+		if (fabsf(N.y) > fabsf(N.z))
+			k = 1;
+		else
+			k = 2;
+	}
+
+	int u = (k + 1) % 3;
+	int v = (k + 2) % 3;
+
+	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]);
+	bnu = b[u] * reci;
+	bnv = -b[v] * reci;
+
+	// second line equation
+	cnu = c[v] * reci;
+	cnv = -c[u] * reci;
+
+	// finalize normal
+	N.normalize();
+}
+
+// see comment for previous method
+bool Triangle::intersect(const Ray &ray, float &dist)
+{
+	Vector3 O = ray.a;
+	Vector3 D = ray.dir;
+
+	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;
+
+	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;
+
+	if (beta < 0)
+		return false;
+
+	float gamma = hu * cnu + hv * cnv;
+	if (gamma < 0)
+		return false;
+
+	if ((beta + gamma) > 1)
+		return false;
+
+	dist = t;
+	return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/scene.h	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,135 @@
+/*
+ * C++ RayTracer
+ * file: scene.h
+ *
+ * Radek Brich, 2006
+ */
+
+#ifndef SCENE_H
+#define SCENE_H
+
+#include <vector>
+
+#include "noise.h"
+
+#include "vector.h"
+
+using namespace std;
+
+class Ray
+{
+public:
+	Vector3 a, dir;
+	Ray(const Vector3 &aa, const Vector3 &adir):
+		a(aa), dir(adir) {};
+};
+
+class Light
+{
+public:
+	Vector3 pos;
+	Colour colour;
+	int shadows;
+
+	Light(const Vector3 &position, const Colour &acolour):
+		pos(position), colour(acolour), shadows(1) {};
+	void castshadows(bool ashadows) { shadows = ashadows; };
+};
+
+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 = 1.0;
+		shininess = 20.0;
+		reflection = 0.5;
+	}
+};
+
+class Shape
+{
+public:
+	Material *material;
+	Shape() {};
+	virtual ~Shape() {};
+
+	// first intersection point
+	virtual bool intersect(const Ray &ray, float &dist) = 0;
+
+	// all intersections (only for CSG)
+	virtual bool intersect_all(const Ray &ray, float dist, vector<float> &allts) = 0;
+
+	// normal at point P
+	virtual Vector3 normal(Vector3 &P) = 0;
+};
+
+class Sphere: public Shape
+{
+	float sqr_radius;
+	float inv_radius;
+public:
+	Vector3 center;
+	float radius;
+
+	Sphere(const Vector3 &acenter, const float aradius, Material *amaterial):
+		sqr_radius(aradius*aradius), inv_radius(1.0f/aradius),
+		center(acenter), radius(aradius) { material = amaterial; }
+	bool intersect(const Ray &ray, float &dist);
+	bool intersect_all(const Ray &ray, float dist, vector<float> &allts);
+	Vector3 normal(Vector3 &P) { return (P - center) * inv_radius; };
+};
+
+class Plane: public Shape
+{
+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*/};
+	bool intersect(const Ray &ray, float &dist);
+	bool intersect_all(const Ray &ray, float dist, vector<float> &allts) {return false;};
+	Vector3 normal(Vector3 &) { return N; };
+};
+
+class Triangle: public Shape
+{
+	int k; // dominant axis
+	float nu, nv, nd;
+	float bnu, bnv;
+	float cnu, cnv;
+public:
+	Vector3 A, B, C, N;
+
+	Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial);
+	bool intersect(const Ray &ray, float &dist);
+	bool intersect_all(const Ray &ray, float dist, vector<float> &allts) {return false;};
+	Vector3 normal(Vector3 &) { return N; };
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/vector.h	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,122 @@
+/*
+ * C++ RayTracer
+ * file: vector.h
+ *
+ * Radek Brich, 2006
+ */
+
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#include <math.h>
+#include <iostream>
+
+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]; };
+
+	// 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
+	Vector3 operator*(const float &f)
+	{
+		return Vector3(f * x, f * y, f * z);
+	}
+
+	friend Vector3 operator*(const float &f, Vector3 &v)
+	{
+		return v * 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/vector.cc	Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,23 @@
+#include "vector.h"
+
+int main() {
+	Vector3 a(1, 2, 3);
+	cout << "=== Vector3 test ===" << endl;
+	cout << "a = " << a << endl;
+	Vector3 b(2, 3, 2);
+	cout << "b = " << b << endl;
+	
+	cout << "a + b = " << a + b << endl;
+	cout << "b - a = " << b - a << endl;
+	cout << "dot(a,b) = " << dot(a,b) << endl;
+	cout << "cross(a,b) = " << cross(a,b) << endl;
+	cout << "a * 2 = " << a * 2 << endl;
+	cout << "3 * b = " << 3 * b << endl;
+	cout << "-a = " << -a << endl;
+
+	cout << "a.mag() = " << a.mag() << endl;
+	cout << "a.unit() = " << a.unit() << endl;
+	cout << "a.unit().mag() = " << a.unit().mag() << endl;
+
+	return 0;
+}