# HG changeset patch # User Radek Brich # Date 1193323222 -7200 # Node ID 3547b885df7e1c8e75db77422279c9762558689e initial commit, raytracer source as written year ago and unchanged since 2007-03-25 diff -r 000000000000 -r 3547b885df7e Makefile --- /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 diff -r 000000000000 -r 3547b885df7e demos/cube.obj --- /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 diff -r 000000000000 -r 3547b885df7e demos/demo.py --- /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') diff -r 000000000000 -r 3547b885df7e demos/monkey.obj --- /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 diff -r 000000000000 -r 3547b885df7e demos/sphere.obj --- /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 diff -r 000000000000 -r 3547b885df7e demos/spheres_ao.py --- /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') diff -r 000000000000 -r 3547b885df7e demos/spheres_shadow.py --- /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') diff -r 000000000000 -r 3547b885df7e demos/triangles_monkey.py --- /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') diff -r 000000000000 -r 3547b885df7e demos/triangles_sphere.py --- /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') diff -r 000000000000 -r 3547b885df7e src/kdtree.cc --- /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(); + 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 diff -r 000000000000 -r 3547b885df7e src/kdtree.h --- /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 + +#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 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 diff -r 000000000000 -r 3547b885df7e src/matrix.h --- /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 diff -r 000000000000 -r 3547b885df7e src/noise.cc --- /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 + +#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]; } +} +*/ diff -r 000000000000 -r 3547b885df7e src/noise.h --- /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 diff -r 000000000000 -r 3547b885df7e src/raytracer.cc --- /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 +#include +#include +#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::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; +} diff -r 000000000000 -r 3547b885df7e src/raytracer.h --- /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 + +#include "scene.h" + +using namespace std; + +/* axis-aligned bounding box */ +class AABB +{ +}; + +class ShapeList: public vector +{ + AABB extends() { return AABB(); }; +}; + +class Raytracer +{ + ShapeList shapes; + vector 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 diff -r 000000000000 -r 3547b885df7e src/raytracermodule.cc --- /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 +#include +#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 *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(); + + return (PyObject*)v; +} + +static void Raytracer_Destructor(PyObject* self) +{ + vector::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); +} diff -r 000000000000 -r 3547b885df7e src/scene.cc --- /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 +#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 &allts) +{ + //allts = new vector(); + + 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; +} diff -r 000000000000 -r 3547b885df7e src/scene.h --- /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 + +#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 &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 &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 &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 &allts) {return false;}; + Vector3 normal(Vector3 &) { return N; }; +}; + +#endif diff -r 000000000000 -r 3547b885df7e src/vector.h --- /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 +#include + +using namespace std; + +class Vector3 +{ +public: + // data + union { + struct { + float x, y, z; + }; + struct { + float r, g, b; + }; + float cell[3]; + }; + + // constructors + Vector3(): x(0.0f), y(0.0f), z(0.0f) {}; + Vector3(float ax, float ay, float az): x(ax), y(ay), z(az) {}; + + // index operator + float &operator[](int index) { return cell[index]; }; + + // 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 diff -r 000000000000 -r 3547b885df7e tests/vector.cc --- /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; +}