# HG changeset patch # User Radek Brich # Date 1209504668 -7200 # Node ID f6a72eb996317e53bc4972ccb30abeef7d45d97e # Parent fcf1487b398b2223dde61174c2efb20f9f3f7c6e rename Python module from 'raytracer' to 'pyrit' improve Python binding: - new objects: Container, Octree, KdTree, Shape, Pixmap, Sampler, DefaultSampler - all shapes are now subclasses of Shape - clean, remove redundant Getattr's - Raytracer render method now just wraps C++ method without doing any additional work adjust all demos for changes in Python binding, remove PIL dependency add demo_PIL.py as a example of pyrit + PIL usage render_nff.py now either loads file given as a argument or reads input from stdin otherwise fix bug in pixmap float to char conversion diff -r fcf1487b398b -r f6a72eb99631 ccdemos/common_sdl.h --- a/ccdemos/common_sdl.h Tue Apr 29 13:56:29 2008 +0200 +++ b/ccdemos/common_sdl.h Tue Apr 29 23:31:08 2008 +0200 @@ -41,9 +41,9 @@ } *bufp = SDL_MapRGB(screen->format, c[0], c[1], c[2]); #else - __m64 m = _mm_cvtps_pi8(_mm_mul_ps(_mm_set_ps1(255.0), + __m64 m = _mm_cvtps_pi16(_mm_mul_ps(_mm_set_ps1(255.0), _mm_min_ps(mOne, _mm_set_ps(0, fd[2],fd[1],fd[0])))); - *bufp = SDL_MapRGB(screen->format, ((char*)&m)[0], ((char*)&m)[1], ((char*)&m)[2]); + *bufp = SDL_MapRGB(screen->format, ((char*)&m)[0], ((char*)&m)[2], ((char*)&m)[4]); #endif bufp++; } diff -r fcf1487b398b -r f6a72eb99631 demos/SConscript --- a/demos/SConscript Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/SConscript Tue Apr 29 23:31:08 2008 +0200 @@ -7,7 +7,7 @@ 'spheres_ao.py', 'spheres_glass.py', 'spheres_shadow.py', 'triangles_monkey.py', 'triangles_sphere.py', 'objreader.py', 'plyreader.py', 'lworeader.py', - 'vector.py', 'render_nff.py'] + 'vector.py', 'render_nff.py', 'demo_PIL.py'] l = [] for file in files: diff -r fcf1487b398b -r f6a72eb99631 demos/boxes.py --- a/demos/boxes.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/boxes.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,9 +1,11 @@ #!/usr/bin/python -from raytracer import Raytracer, Material, Box, Light -import Image +from pyrit import * rt = Raytracer() +top = Octree() +rt.setTop(top) +rt.setCamera(Camera()) light1 = Light(position=(0.0, 5.0, -5.0), colour=(0.7, 0.3, 0.6)) rt.addLight(light1) @@ -19,7 +21,9 @@ box = Box(L=(-4.3+x, -4.6+y, -8.6+z), H=(-3.7+x, -4.0+y, -8.0+z), material=mat0) rt.addShape(box) -imagesize = (800, 600) -data = rt.render(imagesize) -img = Image.fromstring("RGB", imagesize, data) -img.save('boxes.png') +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('boxes.png') diff -r fcf1487b398b -r f6a72eb99631 demos/buddha.py --- a/demos/buddha.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/buddha.py Tue Apr 29 23:31:08 2008 +0200 @@ -3,20 +3,24 @@ # this demo needs buddha model from # http://graphics.stanford.edu/data/3Dscanrep/ -from raytracer import Raytracer, Light, Sphere, Triangle, Material +from pyrit import * from plyreader import LoadStanfordPlyFile -import Image rt = Raytracer() +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) + +light = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.6)) +rt.addLight(light) + mat = Material(colour=(0.9, 0.9, 0.9)) mat.setSmooth(True) LoadStanfordPlyFile(rt, "../models/ply/happy/happy_vrip_res2.ply", mat, scale=20.0, trans=(0,-3,0)) - -light = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.6)) -rt.addLight(light) +top.optimize() -imagesize = (800, 600) -data = rt.render(imagesize) -img = Image.fromstring("RGB", imagesize, data) -img.save('buddha.png') +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('buddha.png') diff -r fcf1487b398b -r f6a72eb99631 demos/bunny.py --- a/demos/bunny.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/bunny.py Tue Apr 29 23:31:08 2008 +0200 @@ -3,11 +3,14 @@ # this demo needs bunny model from # http://graphics.stanford.edu/data/3Dscanrep/ -from raytracer import Raytracer, Light, Box, Triangle, Material +from pyrit import * from plyreader import LoadStanfordPlyFile -import Image rt = Raytracer() +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) + #rt.ambientocclusion(samples=100, distance=16.0, angle=0.5) mat = Material(colour=(0.9, 0.9, 0.9)) @@ -33,7 +36,9 @@ #light2.castshadows(0) rt.addLight(light2) -imagesize = (800, 600) -data = rt.render(imagesize) -img = Image.fromstring("RGB", imagesize, data) -img.save('bunny.png') +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('bunny.png') diff -r fcf1487b398b -r f6a72eb99631 demos/car.py --- a/demos/car.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/car.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,12 +1,12 @@ #!/usr/bin/python -from raytracer import Raytracer, Light, Sphere, Triangle, Material, Camera +from pyrit import * from lworeader import LoadLightwaveLwoFile -import Image from math import * rt = Raytracer() - +top = KdTree() +rt.setTop(top) cam = Camera(eye=(0.,2.,8.)) rotx=0.15 cam.rotate((cos(rotx),-sin(rotx),0.,0.)) @@ -19,7 +19,9 @@ light2 = Light(position=(5.0, 10.0, 10.0), colour=(0.9, 0.7, 0.7)) rt.addLight(light2) -imagesize = (800, 600) -data = rt.render(imagesize) -img = Image.fromstring("RGB", imagesize, data) -img.save('car.png') +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('car.png') diff -r fcf1487b398b -r f6a72eb99631 demos/demo_PIL.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demos/demo_PIL.py Tue Apr 29 23:31:08 2008 +0200 @@ -0,0 +1,42 @@ +#!/usr/bin/python + +from pyrit import * +import Image + +rt = Raytracer() +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) + +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)) + +box = Box(L=(-20.0, -1.2, -20.0), H=(20.0, -1.0, 20.0), material=mat0) +rt.addShape(box) + +mat1 = Material(colour=(1.0, 0.0, 0.0)) +bigsphere = Sphere(centre=(3.0, 2.0, -7.0), radius=3.0, material=mat1) +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) + +top.optimize() +imagesize = (800, 600) +sampler = DefaultSampler(imagesize) +rt.setSampler(sampler) +rt.render() +pixmap = sampler.getPixmap() +data = pixmap.getCharData() +img = Image.fromstring("RGB", imagesize, data) +img.save('demo_PIL.png') diff -r fcf1487b398b -r f6a72eb99631 demos/dragon.py --- a/demos/dragon.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/dragon.py Tue Apr 29 23:31:08 2008 +0200 @@ -3,11 +3,14 @@ # this demo needs dragon model from # http://graphics.stanford.edu/data/3Dscanrep/ -from raytracer import Raytracer, Light, Sphere, Triangle, Material +from pyrit import * from plyreader import LoadStanfordPlyFile -import Image rt = Raytracer() +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) + mat = Material(colour=(0.9, 0.9, 0.9)) mat.setSmooth(True) LoadStanfordPlyFile(rt, "../models/ply/dragon/dragon_vrip_res2.ply", @@ -19,7 +22,9 @@ light2 = Light(position=(3.0, 0.0, 9.0), colour=(0.0, 1.0, 0.2)) rt.addLight(light2) -imagesize = (800, 600) -data = rt.render(imagesize) -img = Image.fromstring("RGB", imagesize, data) -img.save('dragon.png') +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('dragon.png') diff -r fcf1487b398b -r f6a72eb99631 demos/lworeader.py --- a/demos/lworeader.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/lworeader.py Tue Apr 29 23:31:08 2008 +0200 @@ -2,7 +2,7 @@ from math import * from struct import * -from raytracer import Triangle, NormalVertex, Material +from pyrit import Triangle, NormalVertex, Material from vector import dot def read_int4(f): diff -r fcf1487b398b -r f6a72eb99631 demos/objreader.py --- a/demos/objreader.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/objreader.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,6 +1,6 @@ # Wavefron .obj file loader -from raytracer import Triangle, NormalVertex +from pyrit import Triangle, NormalVertex def LoadWavefrontObjFile(rt, filename, mat, scale): vertices = [] diff -r fcf1487b398b -r f6a72eb99631 demos/plyreader.py --- a/demos/plyreader.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/plyreader.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,6 +1,6 @@ # Stanford .ply file loader -from raytracer import Triangle, NormalVertex +from pyrit import Triangle, NormalVertex def LoadStanfordPlyFile(rt, filename, mat, scale=(1,1,1), trans=(0,0,0)): if (type(scale) == float or type(scale) == int): diff -r fcf1487b398b -r f6a72eb99631 demos/render_nff.py --- a/demos/render_nff.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/render_nff.py Tue Apr 29 23:31:08 2008 +0200 @@ -4,16 +4,25 @@ # see http://tog.acm.org/resources/SPD/ # cylinders are not implemented -from raytracer import Raytracer, Camera, Light, Material, Sphere, NormalVertex, Triangle +from pyrit import * from math import pi -import sys, Image +import sys rt = Raytracer() +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) + imagesize = (800, 600) mat = Material(colour=(1.0, 1.0, 1.0)) f = sys.stdin +fbase = "render_nff" +if len(sys.argv) > 1: + f = open(sys.argv[1]) + fbase = sys.argv[1].rsplit('.',1)[0] + while True: line = f.readline() if line == "": @@ -90,6 +99,9 @@ print "Not implemented:", line f.close() -data = rt.render(imagesize) -img = Image.fromstring("RGB", imagesize, data) -img.save('render_nff.png') +top.optimize() + +sampler = DefaultSampler(imagesize) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG(fbase+'.png') diff -r fcf1487b398b -r f6a72eb99631 demos/spheres_ao.py --- a/demos/spheres_ao.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/spheres_ao.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,9 +1,11 @@ #!/usr/bin/python -from raytracer import Raytracer, Material, Box, Sphere, Light -import Image +from pyrit import * rt = Raytracer() +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) rt.ambientOcclusion(samples=100, distance=16.0, angle=0.5) light1 = Light(position=(0.0, 5.0, -5.0), colour=(0.7, 0.3, 0.6)) @@ -31,7 +33,9 @@ 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') +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('spheres_ao.png') diff -r fcf1487b398b -r f6a72eb99631 demos/spheres_glass.py --- a/demos/spheres_glass.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/spheres_glass.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,10 +1,11 @@ #!/usr/bin/python -from raytracer import Raytracer, Material, Box, Sphere, Light -#, SphericalLight -import Image +from pyrit import * rt = Raytracer() +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) light1 = Light(position=(0.0, 4.0, -3.0), colour=(0.9, 0.3, 0.6)) rt.addLight(light1) @@ -38,7 +39,9 @@ sph = Sphere(centre=(-5.0+i, -1.5, -4.0), radius=0.5, material=mat3) rt.addShape(sph) -rendersize = (800, 600) -data = rt.render(rendersize) -img = Image.fromstring("RGB", rendersize, data) -img.save('spheres_glass.png') +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('spheres_glass.png') diff -r fcf1487b398b -r f6a72eb99631 demos/spheres_shadow.py --- a/demos/spheres_shadow.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/spheres_shadow.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,9 +1,11 @@ #!/usr/bin/python -from raytracer import Raytracer, Material, Box, Sphere, Light -import Image +from pyrit import * rt = Raytracer() +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) light1 = Light(position=(0.0, 5.0, -5.0), colour=(0.7, 0.3, 0.6)) rt.addLight(light1) @@ -28,7 +30,9 @@ 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') +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('spheres_shadow.png') diff -r fcf1487b398b -r f6a72eb99631 demos/triangles_monkey.py --- a/demos/triangles_monkey.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/triangles_monkey.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,17 +1,21 @@ #!/usr/bin/python -from raytracer import Raytracer, Light, Sphere, Triangle, NormalVertex, Material +from pyrit import * from objreader import LoadWavefrontObjFile -import Image rt = Raytracer() -mat = Material(colour=(0.9, 0.9, 0.9)) -LoadWavefrontObjFile(rt, "../models/obj/monkey.obj", mat, 1.5) +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) 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') +mat = Material(colour=(0.9, 0.9, 0.9)) +LoadWavefrontObjFile(rt, "../models/obj/monkey.obj", mat, 1.5) +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('triangles_monkey.png') diff -r fcf1487b398b -r f6a72eb99631 demos/triangles_sphere.py --- a/demos/triangles_sphere.py Tue Apr 29 13:56:29 2008 +0200 +++ b/demos/triangles_sphere.py Tue Apr 29 23:31:08 2008 +0200 @@ -1,12 +1,12 @@ #!/usr/bin/python -from raytracer import Raytracer, Light, Sphere, Triangle, NormalVertex, Material +from pyrit import * from objreader import LoadWavefrontObjFile -import Image rt = Raytracer() -mat = Material(colour=(0.9, 0.9, 0.9)) -LoadWavefrontObjFile(rt, "../models/obj/sphere.obj", mat, 1.5) +top = KdTree() +rt.setTop(top) +rt.setCamera(Camera()) light1 = Light(position=(0.0, 2.0, 6.0), colour=(0.9, 0.3, 0.6)) light1.castShadows(False); @@ -16,7 +16,11 @@ light2.castShadows(False); rt.addLight(light2) -imagesize = (800, 600) -data = rt.render(imagesize) -img = Image.fromstring("RGB", imagesize, data) -img.save('triangles_sphere.png') +mat = Material(colour=(0.9, 0.9, 0.9)) +LoadWavefrontObjFile(rt, "../models/obj/sphere.obj", mat, 1.5) +top.optimize() + +sampler = DefaultSampler(800, 600) +rt.setSampler(sampler) +rt.render() +sampler.getPixmap().writePNG('triangles_sphere.png') diff -r fcf1487b398b -r f6a72eb99631 include/pixmap.h --- a/include/pixmap.h Tue Apr 29 13:56:29 2008 +0200 +++ b/include/pixmap.h Tue Apr 29 23:31:08 2008 +0200 @@ -53,8 +53,8 @@ void setData(Float *afdata, int aw, int ah) { fdata = afdata; w = aw; h = ah; }; Colour get(int x, int y) { return data[y*w + x]; }; - const int &getWidth() { return w; }; - const int &getHeight() { return h; }; + const int &getWidth() const { return w; }; + const int &getHeight() const { return h; }; Float*& getFloatData() { return fdata; }; unsigned char *getCharData() const; int writePNG(const char *fname) const; diff -r fcf1487b398b -r f6a72eb99631 include/raytracer.h --- a/include/raytracer.h Tue Apr 29 13:56:29 2008 +0200 +++ b/include/raytracer.h Tue Apr 29 23:31:08 2008 +0200 @@ -93,9 +93,11 @@ void addShape(Shape *shape) { top->addShape(shape); }; void addLight(Light *light) { lights.push_back(light); }; void setSampler(Sampler *sampl) { sampler = sampl; }; + Sampler *&getSampler() { return sampler; }; void setCamera(Camera *cam) { camera = cam; }; + Camera *&getCamera() { return camera; }; void setTop(Container *atop) { top = atop; }; - Container *getTop() { return top; }; + Container *&getTop() { return top; }; void setBgColour(const Colour &bg) { bg_colour = bg; }; void setMaxDepth(int newdepth) { max_depth = newdepth; }; diff -r fcf1487b398b -r f6a72eb99631 include/sampler.h --- a/include/sampler.h Tue Apr 29 13:56:29 2008 +0200 +++ b/include/sampler.h Tue Apr 29 23:31:08 2008 +0200 @@ -73,7 +73,7 @@ virtual bool nextSample(Sample *s) = 0; virtual void saveSample(Sample &samp, Colour &col) = 0; bool packetableSamples() { return packetable; }; - const Pixmap &getPixmap() { return pixmap; }; + const Pixmap &getPixmap() const { return pixmap; }; }; /** diff -r fcf1487b398b -r f6a72eb99631 src/SConscript --- a/src/SConscript Tue Apr 29 13:56:29 2008 +0200 +++ b/src/SConscript Tue Apr 29 23:31:08 2008 +0200 @@ -26,7 +26,7 @@ objs.append( env.Object(src) ) shared_objs.append( env.SharedObject(src) ) -pymodule = pyenv.SharedLibrary('raytracer', +pymodule = pyenv.SharedLibrary('pyrit', ['raytracermodule.cc']+shared_objs, SHLIBPREFIX = '', CCFLAGS = '$CCFLAGS -Wno-write-strings') diff -r fcf1487b398b -r f6a72eb99631 src/pixmap.cc --- a/src/pixmap.cc Tue Apr 29 13:56:29 2008 +0200 +++ b/src/pixmap.cc Tue Apr 29 23:31:08 2008 +0200 @@ -48,9 +48,10 @@ __m64 m; for (unsigned char *cd = cdata; cd < cdata + w*h*3; cd += 4, fd += 4) { - m = _mm_cvtps_pi8(_mm_mul_ps(cmax, + m = _mm_cvtps_pi16(_mm_mul_ps(cmax, _mm_min_ps(mOne, _mm_set_ps(fd[3],fd[2],fd[1],fd[0])))); - memcpy(cd, &m, 4); + for (int i = 0; i < 4; i++) + cd[i] = ((unsigned char *)&m)[i<<1]; } #endif diff -r fcf1487b398b -r f6a72eb99631 src/raytracer.cc --- a/src/raytracer.cc Tue Apr 29 13:56:29 2008 +0200 +++ b/src/raytracer.cc Tue Apr 29 23:31:08 2008 +0200 @@ -372,7 +372,7 @@ } } - dbgmsg(2, "phase %d: 0%% done", phase); + dbgmsg(2, "- phase %d: 0%% done", phase); pthread_mutex_lock(&sampler_mutex); diff -r fcf1487b398b -r f6a72eb99631 src/raytracermodule.cc --- a/src/raytracermodule.cc Tue Apr 29 13:56:29 2008 +0200 +++ b/src/raytracermodule.cc Tue Apr 29 23:31:08 2008 +0200 @@ -28,8 +28,53 @@ #include #include "raytracer.h" +#include "octree.h" #include "kdtree.h" +#define TYPE_OBJECT(name, basicsize, dealloc, flags, doc, methods, members, base, init) \ +{ \ + PyObject_HEAD_INIT(NULL) \ + 0, /* ob_size */ \ + (name), /* tp_name */ \ + (basicsize), /* tp_basicsize*/ \ + 0, /* tp_itemsize*/ \ + (dealloc), /* tp_dealloc*/ \ + 0, /* tp_print*/\ + 0, /* 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 */\ + 0, /* tp_call*/\ + 0, /* tp_str*/\ + PyObject_GenericGetAttr, /* tp_getattro*/\ + 0, /* tp_setattro*/\ + 0, /* tp_as_buffer*/\ + (flags), /* tp_flags*/\ + (doc), /* tp_doc */\ + 0, /* tp_traverse */\ + 0, /* tp_clear */\ + 0, /* tp_richcompare */\ + 0, /* tp_weaklistoffset */\ + 0, /* tp_iter */\ + 0, /* tp_iternext */\ + (methods), /* tp_methods */\ + (members), /* tp_members */\ + 0, /* tp_getset */\ + (base), /* tp_base */\ + 0, /* tp_dict */ \ + 0, /* tp_descr_get */ \ + 0, /* tp_descr_set */ \ + 0, /* tp_dictoffset */ \ + (init), /* tp_init */ \ + 0, /* tp_alloc */ \ + 0, /* tp_new */ \ + 0, /* tp_free */ \ +} + //=========================== Light Source Object =========================== typedef struct { @@ -39,33 +84,26 @@ 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 PyTypeObject LightType = +TYPE_OBJECT( + "Light", /* tp_name */ + sizeof(LightObject), /* tp_basicsize */ + Light_Destructor, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Light type", /* tp_doc */ + LightMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + static PyObject* Light_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { LightObject *v; @@ -91,12 +129,7 @@ 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); + self->ob_type->tp_free(self); } static PyObject *Light_castShadows(PyObject* self, PyObject* args) @@ -121,30 +154,10 @@ static PyObject *Camera_Constructor(PyObject* self, PyObject* args, PyObject *kwd); static void Camera_Destructor(PyObject* self); -static PyObject *Camera_Getattr(PyObject *self, char *name); static PyObject *Camera_setEye(PyObject* self, PyObject* args); static PyObject *Camera_setAngle(PyObject* self, PyObject* args); static PyObject *Camera_rotate(PyObject* self, PyObject* args); -static PyTypeObject CameraType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Camera", /*tp_name*/ - sizeof(CameraObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - Camera_Destructor, /*tp_dealloc*/ - 0, /*tp_print*/ - Camera_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 CameraMethods[] = { {"setEye", (PyCFunction)Camera_setEye, METH_VARARGS, "Set eye of the camera."}, {"setAngle", (PyCFunction)Camera_setAngle, METH_VARARGS, "Set vertical angle of view."}, @@ -152,6 +165,19 @@ {NULL, NULL} }; +static PyTypeObject CameraType = +TYPE_OBJECT( + "Camera", /* tp_name */ + sizeof(CameraObject), /* tp_basicsize */ + Camera_Destructor, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Camera type", /* tp_doc */ + CameraMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + static PyObject* Camera_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { CameraObject *v; @@ -207,15 +233,9 @@ static void Camera_Destructor(PyObject* self) { delete ((CameraObject *)self)->camera; - PyObject_Del(self); + self->ob_type->tp_free(self); } -static PyObject *Camera_Getattr(PyObject *self, char *name) -{ - return Py_FindMethod(CameraMethods, self, name); -} - - static PyObject *Camera_setEye(PyObject* self, PyObject* args) { PyObject *TEye = NULL; @@ -274,31 +294,11 @@ 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 PyObject *Material_setPhong(PyObject* self, PyObject* args); static PyObject *Material_setReflectivity(PyObject* self, PyObject* args); static PyObject *Material_setTransmissivity(PyObject* self, PyObject* args); static PyObject *Material_setSmooth(PyObject* self, PyObject* args); -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[] = { {"setPhong", (PyCFunction)Material_setPhong, METH_VARARGS, "Set ambient, diffuse, specular and shininess Phong model constants."}, {"setReflectivity", (PyCFunction)Material_setReflectivity, METH_VARARGS, "Set reflectivity."}, @@ -307,6 +307,19 @@ {NULL, NULL} }; +static PyTypeObject MaterialType = +TYPE_OBJECT( + "Material", /* tp_name */ + sizeof(MaterialObject), /* tp_basicsize */ + Material_Destructor, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Material type", /* tp_doc */ + MaterialMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + static PyObject* Material_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { MaterialObject *v; @@ -330,12 +343,7 @@ 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); + self->ob_type->tp_free(self); } static PyObject *Material_setPhong(PyObject* self, PyObject* args) @@ -400,33 +408,26 @@ static PyObject *NormalVertex_Constructor(PyObject* self, PyObject* args, PyObject *kwd); static void NormalVertex_Destructor(PyObject* self); -static PyObject *NormalVertex_Getattr(PyObject *self, char *name); static PyObject *NormalVertex_setNormal(PyObject* self, PyObject* args); -static PyTypeObject NormalVertexType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "NormalVertex", /*tp_name*/ - sizeof(NormalVertexObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - NormalVertex_Destructor, /*tp_dealloc*/ - 0, /*tp_print*/ - NormalVertex_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 NormalVertexMethods[] = { {"setNormal", (PyCFunction)NormalVertex_setNormal, METH_VARARGS, "Set normal of this vertex."}, {NULL, NULL} }; +static PyTypeObject NormalVertexType = +TYPE_OBJECT( + "NormalVertex", /* tp_name */ + sizeof(NormalVertexObject), /* tp_basicsize */ + NormalVertex_Destructor, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "NormalVertex type", /* tp_doc */ + NormalVertexMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + static PyObject* NormalVertex_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { NormalVertexObject *v; @@ -462,12 +463,7 @@ static void NormalVertex_Destructor(PyObject* self) { delete ((NormalVertexObject *)self)->nvertex; - PyObject_Del(self); -} - -static PyObject *NormalVertex_Getattr(PyObject *self, char *name) -{ - return Py_FindMethod(NormalVertexMethods, self, name); + self->ob_type->tp_free(self); } static PyObject *NormalVertex_setNormal(PyObject* self, PyObject* args) @@ -487,40 +483,121 @@ return Py_None; } +//=========================== Shape Object (abstract) =========================== + +typedef struct { + PyObject_HEAD + Shape *shape; +} ShapeObject; + +static void Shape_Destructor(PyObject* self); + +static PyMethodDef ShapeMethods[] = { + {NULL, NULL} +}; + +static PyTypeObject ShapeType = +TYPE_OBJECT( + "Shape", /* tp_name */ + sizeof(ShapeObject), /* tp_basicsize */ + Shape_Destructor, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Shape type (abstract)", /* tp_doc */ + ShapeMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + +static void Shape_Destructor(PyObject* self) +{ + delete ((ShapeObject *)self)->shape; + self->ob_type->tp_free(self); +} + +//=========================== Triangle Object =========================== + +typedef struct { + ShapeObject shape; +} TriangleObject; + +static PyObject *Triangle_Constructor(PyObject* self, PyObject* args, PyObject *kwd); +static PyObject *Triangle_getNormal(PyObject* self, PyObject* args); + +static PyMethodDef TriangleMethods[] = { + {"getNormal", (PyCFunction)Triangle_getNormal, METH_NOARGS, "Get normal of whole triangle."}, + {NULL, NULL} +}; + +static PyTypeObject TriangleType = +TYPE_OBJECT( + "Triangle", /* tp_name */ + sizeof(TriangleObject), /* tp_basicsize */ + 0, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Triangle type", /* tp_doc */ + TriangleMethods, /* tp_methods */ + 0, /* tp_members */ + &ShapeType, /* tp_base */ + 0 /* tp_init */ +); + +static PyObject* Triangle_Constructor(PyObject* self, PyObject* args, PyObject *kwd) +{ + TriangleObject *v; + MaterialObject *material; + static char *kwdlist[] = {"A", "B", "C", "material", NULL}; + NormalVertexObject *A, *B, *C; + + if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!O!", kwdlist, + &NormalVertexType, &A, &NormalVertexType, &B, &NormalVertexType, &C, + &MaterialType, &material)) + return NULL; + + v = PyObject_New(TriangleObject, &TriangleType); + v->shape.shape = new Triangle(A->nvertex, B->nvertex, C->nvertex, material->material); + Py_INCREF(material); + Py_INCREF(A); + Py_INCREF(B); + Py_INCREF(C); + return (PyObject*)v; +} + +static PyObject* Triangle_getNormal(PyObject* self, PyObject* args) +{ + PyObject *obj; + + Vector3 N = ((Triangle*)((TriangleObject *)self)->shape.shape)->getNormal(); + + obj = Py_BuildValue("(fff)", N.x, N.y, N.z); + return obj; +} + //=========================== Sphere Object =========================== typedef struct { - PyObject_HEAD - Sphere *shape; + ShapeObject 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 PyTypeObject SphereType = +TYPE_OBJECT( + "Sphere", /* tp_name */ + sizeof(SphereObject), /* tp_basicsize */ + 0, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Sphere type", /* tp_doc */ + SphereMethods, /* tp_methods */ + 0, /* tp_members */ + &ShapeType, /* tp_base */ + 0 /* tp_init */ +); + static PyObject* Sphere_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { SphereObject *v; @@ -537,56 +614,36 @@ return NULL; v = PyObject_New(SphereObject, &SphereType); - v->shape = new Sphere(Vector3(cx, cy, cz), radius, material->material); + v->shape.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); -} - //=========================== Box Object =========================== typedef struct { - PyObject_HEAD - Box *shape; + ShapeObject shape; } BoxObject; static PyObject *Box_Constructor(PyObject* self, PyObject* args, PyObject *kwd); -static void Box_Destructor(PyObject* self); -static PyObject *Box_Getattr(PyObject *self, char *name); - -static PyTypeObject BoxType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Box", /*tp_name*/ - sizeof(BoxObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - Box_Destructor, /*tp_dealloc*/ - 0, /*tp_print*/ - Box_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 BoxMethods[] = { {NULL, NULL} }; +static PyTypeObject BoxType = +TYPE_OBJECT( + "Box", /* tp_name */ + sizeof(BoxObject), /* tp_basicsize */ + 0, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Box type", /* tp_doc */ + BoxMethods, /* tp_methods */ + 0, /* tp_members */ + &ShapeType, /* tp_base */ + 0 /* tp_init */ +); + static PyObject* Box_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { BoxObject *v; @@ -607,98 +664,325 @@ return NULL; v = PyObject_New(BoxObject, &BoxType); - v->shape = new Box(Vector3(lx, ly, lz), Vector3(hx, hy, hz), material->material); + v->shape.shape = new Box(Vector3(lx, ly, lz), Vector3(hx, hy, hz), material->material); Py_INCREF(material); return (PyObject*)v; } -static void Box_Destructor(PyObject* self) +//=========================== Pixmap Object =========================== + +typedef struct { + PyObject_HEAD + const Pixmap *pixmap; +} PixmapObject; + +static PyObject* Pixmap_Constructor(PyObject* self, PyObject* args, PyObject *kwd); +static PyObject* Pixmap_getWidth(PyObject* self, PyObject* args); +static PyObject* Pixmap_getHeight(PyObject* self, PyObject* args); +static PyObject* Pixmap_getCharData(PyObject* self, PyObject* args); +static PyObject* Pixmap_writePNG(PyObject* self, PyObject* args); + +static PyMethodDef PixmapMethods[] = { + {"getWidth", (PyCFunction)Pixmap_getWidth, METH_NOARGS, "Get width of pixmap."}, + {"getHeight", (PyCFunction)Pixmap_getHeight, METH_NOARGS, "Get height of pixmap."}, + {"getCharData", (PyCFunction)Pixmap_getCharData, METH_NOARGS, "Get raw byte data."}, + {"writePNG", (PyCFunction)Pixmap_writePNG, METH_VARARGS, "Write pixmap to PNG file."}, + {NULL, NULL} +}; + +static PyTypeObject PixmapType = +TYPE_OBJECT( + "Pixmap", /* tp_name */ + sizeof(PixmapObject), /* tp_basicsize */ + 0, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Pixmap type", /* tp_doc */ + PixmapMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + +static PyObject* Pixmap_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { - delete ((BoxObject *)self)->shape; - PyObject_Del(self); + int w = 0, h = 0; + PixmapObject *v; + + if (!PyArg_ParseTuple(args, "(ii)", &w, &h)) + return NULL; + + v = PyObject_New(PixmapObject, &PixmapType); + v->pixmap = new Pixmap(w, h); + return (PyObject*)v; } -static PyObject *Box_Getattr(PyObject *self, char *name) +static PyObject* Pixmap_getWidth(PyObject* self, PyObject* args) { - return Py_FindMethod(BoxMethods, self, name); + return Py_BuildValue("i", ((PixmapObject *)self)->pixmap->getWidth()); +} + +static PyObject* Pixmap_getHeight(PyObject* self, PyObject* args) +{ + return Py_BuildValue("i", ((PixmapObject *)self)->pixmap->getHeight()); } -//=========================== Triangle Object =========================== +static PyObject *Pixmap_getCharData(PyObject* self, PyObject* args) +{ + unsigned char *chardata; + int w,h; + PyObject *o; + + chardata = ((PixmapObject *)self)->pixmap->getCharData(); + w = ((PixmapObject *)self)->pixmap->getWidth(); + h = ((PixmapObject *)self)->pixmap->getHeight(); + o = Py_BuildValue("s#", chardata, w*h*3); + delete[] chardata; + return o; +} + +static PyObject *Pixmap_writePNG(PyObject* self, PyObject* args) +{ + const char *fname; + int res; + + if (!PyArg_ParseTuple(args, "s", &fname)) + return NULL; + + res = ((PixmapObject *)self)->pixmap->writePNG(fname); + return Py_BuildValue("i", res); +} + +//=========================== Sampler Object (abstract) =========================== typedef struct { PyObject_HEAD - Triangle *triangle; -} 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 PyObject *Triangle_getNormal(PyObject* self, PyObject* args); + Sampler *sampler; +} SamplerObject; -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 void Sampler_Destructor(PyObject* self); +static PyObject* Sampler_getPixmap(PyObject* self, PyObject* args); + +static PyMethodDef SamplerMethods[] = { + {"getPixmap", (PyCFunction)Sampler_getPixmap, METH_NOARGS, "Get sampler's pixmap."}, + {NULL, NULL} }; -static PyMethodDef TriangleMethods[] = { - {"getNormal", (PyCFunction)Triangle_getNormal, METH_NOARGS, "Get normal of whole triangle."}, +static PyTypeObject SamplerType = +TYPE_OBJECT( + "Sampler", /* tp_name */ + sizeof(SamplerObject), /* tp_basicsize */ + Sampler_Destructor, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Sampler type (abstract)", /* tp_doc */ + SamplerMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + +static void Sampler_Destructor(PyObject* self) +{ + delete ((SamplerObject *)self)->sampler; + self->ob_type->tp_free(self); +} + +static PyObject* Sampler_getPixmap(PyObject* self, PyObject* args) +{ + PixmapObject *v = PyObject_New(PixmapObject, &PixmapType); + v->pixmap = &((SamplerObject *)self)->sampler->getPixmap(); + return (PyObject*)v; +} + +//=========================== DefaultSampler Object =========================== + +typedef struct { + SamplerObject sampler; +} DefaultSamplerObject; + +static PyObject *DefaultSampler_Constructor(PyObject* self, PyObject* args, PyObject *kwd); +static PyObject* DefaultSampler_setSubsample(PyObject* self, PyObject* args); +static PyObject* DefaultSampler_setOversample(PyObject* self, PyObject* args); + +static PyMethodDef DefaultSamplerMethods[] = { + {"setSubsample", (PyCFunction)DefaultSampler_setSubsample, METH_VARARGS, "Set subsampling mode."}, + {"setOversample", (PyCFunction)DefaultSampler_setOversample, METH_VARARGS, "Set oversampling mode."}, {NULL, NULL} }; -static PyObject* Triangle_Constructor(PyObject* self, PyObject* args, PyObject *kwd) +static PyTypeObject DefaultSamplerType = +TYPE_OBJECT( + "DefaultSampler", /* tp_name */ + sizeof(DefaultSamplerObject), /* tp_basicsize */ + 0, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "DefaultSampler type", /* tp_doc */ + DefaultSamplerMethods, /* tp_methods */ + 0, /* tp_members */ + &SamplerType, /* tp_base */ + 0 /* tp_init */ +); + +static PyObject* DefaultSampler_Constructor(PyObject* self, PyObject* args, PyObject *kwd) { - TriangleObject *v; - MaterialObject *material; - static char *kwdlist[] = {"A", "B", "C", "material", NULL}; - NormalVertexObject *A, *B, *C; + int w = 0, h = 0; + PyObject *o1, *o2; + DefaultSamplerObject *v; - if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!O!", kwdlist, - &NormalVertexType, &A, &NormalVertexType, &B, &NormalVertexType, &C, - &MaterialType, &material)) + if (!PyArg_ParseTuple(args, "O|O", &o1, &o2)) return NULL; - v = PyObject_New(TriangleObject, &TriangleType); - v->triangle = new Triangle(A->nvertex, B->nvertex, C->nvertex, material->material); - Py_INCREF(material); - Py_INCREF(A); - Py_INCREF(B); - Py_INCREF(C); + if (PyTuple_Check(o1)) + { + if (!PyArg_ParseTuple(o1, "ii", &w, &h)) + return NULL; + } + else + if (!PyArg_ParseTuple(args, "ii", &w, &h)) + return NULL; + + v = PyObject_New(DefaultSamplerObject, &DefaultSamplerType); + v->sampler.sampler = new DefaultSampler(w, h); return (PyObject*)v; } -static void Triangle_Destructor(PyObject* self) +static PyObject* DefaultSampler_setSubsample(PyObject* self, PyObject* args) +{ + int size = 0; + + if (!PyArg_ParseTuple(args, "i", &size)) + return NULL; + + ((DefaultSampler *)((DefaultSamplerObject *)self)->sampler.sampler)->setSubsample(size); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* DefaultSampler_setOversample(PyObject* self, PyObject* args) { - delete ((TriangleObject *)self)->triangle; - PyObject_Del(self); + int osa = 0; + + if (!PyArg_ParseTuple(args, "i", &osa)) + return NULL; + + ((DefaultSampler *)((DefaultSamplerObject *)self)->sampler.sampler)->setOversample(osa); + Py_INCREF(Py_None); + return Py_None; +} + +//=========================== Container Object =========================== + +typedef struct { + PyObject_HEAD + Container *container; +} ContainerObject; + +static PyObject *Container_Constructor(PyObject* self, PyObject* args); +static void Container_Destructor(PyObject* self); +static PyObject* Container_optimize(PyObject* self, PyObject* args); + +static PyMethodDef ContainerMethods[] = { + {"optimize", (PyCFunction)Container_optimize, METH_NOARGS, "Build acceleration structures."}, + {NULL, NULL} +}; + +static PyTypeObject ContainerType = +TYPE_OBJECT( + "Container", /* tp_name */ + sizeof(ContainerObject), /* tp_basicsize */ + Container_Destructor, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Container type", /* tp_doc */ + ContainerMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + +static PyObject* Container_Constructor(PyObject* self, PyObject* args) +{ + ContainerObject *v; + v = PyObject_New(ContainerObject, &ContainerType); + v->container = new Container(); + return (PyObject*)v; +} + +static void Container_Destructor(PyObject* self) +{ + delete ((ContainerObject *)self)->container; + self->ob_type->tp_free(self); } -static PyObject *Triangle_Getattr(PyObject *self, char *name) +static PyObject* Container_optimize(PyObject* self, PyObject* args) { - return Py_FindMethod(TriangleMethods, self, name); + ((ContainerObject *)self)->container->optimize(); + Py_INCREF(Py_None); + return Py_None; } -static PyObject* Triangle_getNormal(PyObject* self, PyObject* args) -{ - PyObject *obj; +//=========================== Octree Object =========================== + +typedef struct { + ContainerObject container; +} OctreeObject; + +static PyObject* Octree_Constructor(PyObject* self, PyObject* args); + +static PyMethodDef OctreeMethods[] = { + {NULL, NULL} +}; + +static PyTypeObject OctreeType = +TYPE_OBJECT( + "Octree", /* tp_name */ + sizeof(OctreeObject), /* tp_basicsize */ + 0, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Octree type", /* tp_doc */ + OctreeMethods, /* tp_methods */ + 0, /* tp_members */ + &ContainerType, /* tp_base */ + 0 /* tp_init */ +); - Vector3 N = ((TriangleObject *)self)->triangle->getNormal(); +static PyObject* Octree_Constructor(PyObject* self, PyObject* args) +{ + OctreeObject *v; + v = PyObject_New(OctreeObject, &OctreeType); + v->container.container = new Octree(); + return (PyObject*)v; +} + +//=========================== KdTree Object =========================== + +typedef struct { + ContainerObject container; +} KdTreeObject; + +static PyObject* KdTree_Constructor(PyObject* self, PyObject* args); + +static PyMethodDef KdTreeMethods[] = { + {NULL, NULL} +}; - obj = Py_BuildValue("(fff)", N.x, N.y, N.z); - return obj; +static PyTypeObject KdTreeType = +TYPE_OBJECT( + "KdTree", /* tp_name */ + sizeof(KdTreeObject), /* tp_basicsize */ + 0, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "KdTree type", /* tp_doc */ + KdTreeMethods, /* tp_methods */ + 0, /* tp_members */ + &ContainerType, /* tp_base */ + 0 /* tp_init */ +); + +static PyObject* KdTree_Constructor(PyObject* self, PyObject* args) +{ + KdTreeObject *v; + v = PyObject_New(KdTreeObject, &KdTreeType); + v->container.container = new KdTree(); + return (PyObject*)v; } //=========================== Raytracer Object =========================== @@ -711,36 +995,20 @@ 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_setSampler(PyObject* self, PyObject* args); static PyObject *Raytracer_setCamera(PyObject* self, PyObject* args); +static PyObject *Raytracer_setTop(PyObject* self, PyObject* args); static PyObject *Raytracer_setBgColour(PyObject* self, PyObject* args); static PyObject *Raytracer_addShape(PyObject* self, PyObject* args); static PyObject *Raytracer_addLight(PyObject* self, PyObject* args); static PyObject *Raytracer_ambientOcclusion(PyObject* self, PyObject* args, PyObject *kwd); -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."}, + {"render", (PyCFunction)Raytracer_render, METH_NOARGS, "Render scene."}, + {"setSampler", (PyCFunction)Raytracer_setSampler, METH_VARARGS, "Set sampler."}, {"setCamera", (PyCFunction)Raytracer_setCamera, METH_VARARGS, "Set camera for the scene."}, + {"setTop", (PyCFunction)Raytracer_setTop, METH_VARARGS, "Set top container for shapes."}, {"setBgColour", (PyCFunction)Raytracer_setBgColour, METH_VARARGS, "Set background colour."}, {"addShape", (PyCFunction)Raytracer_addShape, METH_VARARGS, "Add new shape to scene."}, {"addLight", (PyCFunction)Raytracer_addLight, METH_VARARGS, "Add new light source to scene."}, @@ -749,6 +1017,19 @@ {NULL, NULL} }; +static PyTypeObject RaytracerType = +TYPE_OBJECT( + "Raytracer", /* tp_name */ + sizeof(RaytracerObject), /* tp_basicsize */ + Raytracer_Destructor, /* tp_dealloc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Raytracer type", /* tp_doc */ + RaytracerMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_base */ + 0 /* tp_init */ +); + static PyObject* Raytracer_Constructor(PyObject* self, PyObject* args) { RaytracerObject *v; @@ -759,9 +1040,6 @@ v = PyObject_New(RaytracerObject, &RaytracerType); v->raytracer = new Raytracer(); v->children = new vector(); - v->raytracer->setCamera(new Camera()); - v->raytracer->setTop(new KdTree()); - return (PyObject*)v; } @@ -772,41 +1050,28 @@ 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); + self->ob_type->tp_free(self); } static PyObject* Raytracer_render(PyObject* self, PyObject* args) { - int w = 0, h = 0; - unsigned char *chardata; - Float *data; - PyObject *o; + ((RaytracerObject *)self)->raytracer->render(); + Py_INCREF(Py_None); + return Py_None; +} - if (!PyArg_ParseTuple(args, "(ii)", &w, &h)) +static PyObject* Raytracer_setSampler(PyObject* self, PyObject* args) +{ + SamplerObject *samp; + + if (!PyArg_ParseTuple(args, "O!", &SamplerType, &samp)) return NULL; - printf("[pyrit] Running ray tracer\n"); - ((RaytracerObject *)self)->raytracer->getTop()->optimize(); - data = (Float *) malloc(w*h*3*sizeof(Float)); - DefaultSampler sampler(data, w, h); - ((RaytracerObject *)self)->raytracer->setSampler(&sampler); - ((RaytracerObject *)self)->raytracer->render(); - if (!data) { - Py_INCREF(Py_None); - return Py_None; - } + ((RaytracerObject *)self)->raytracer->setSampler(samp->sampler); - printf("[pyrit] Converting image data (float to char)\n"); - chardata = sampler.getPixmap().getCharData(); - o = Py_BuildValue("s#", chardata, w*h*3); - delete[] chardata; - printf("[pyrit] Done.\n"); - return o; + Py_INCREF(samp); + Py_INCREF(Py_None); + return Py_None; } static PyObject* Raytracer_setCamera(PyObject* self, PyObject* args) @@ -823,6 +1088,20 @@ return Py_None; } +static PyObject* Raytracer_setTop(PyObject* self, PyObject* args) +{ + ContainerObject *cont; + + if (!PyArg_ParseTuple(args, "O!", &ContainerType, &cont)) + return NULL; + + ((RaytracerObject *)self)->raytracer->setTop(cont->container); + + Py_INCREF(cont); + Py_INCREF(Py_None); + return Py_None; +} + static PyObject* Raytracer_setBgColour(PyObject* self, PyObject* args) { Float r,g,b; @@ -838,16 +1117,14 @@ static PyObject* Raytracer_addShape(PyObject* self, PyObject* args) { - PyObject *obj; + ShapeObject *shape; - if (!PyArg_ParseTuple(args, "O", &obj)) + if (!PyArg_ParseTuple(args, "O!", &ShapeType, &shape)) return NULL; - ((RaytracerObject *)self)->raytracer->addShape( - ((BoxObject*)obj)->shape); - - ((RaytracerObject *)self)->children->push_back(obj); - Py_INCREF(obj); + ((RaytracerObject *)self)->raytracer->addShape(shape->shape); + ((RaytracerObject *)self)->children->push_back((PyObject*)shape); + Py_INCREF(shape); Py_INCREF(Py_None); return Py_None; } @@ -893,17 +1170,50 @@ METH_VARARGS | METH_KEYWORDS, "Material object constructor."}, {"NormalVertex", (PyCFunction) NormalVertex_Constructor, METH_VARARGS | METH_KEYWORDS, "NormalVertex object constructor."}, + {"Triangle", (PyCFunction) Triangle_Constructor, + METH_VARARGS | METH_KEYWORDS, "Triangle object constructor."}, {"Sphere", (PyCFunction) Sphere_Constructor, METH_VARARGS | METH_KEYWORDS, "Sphere object constructor."}, {"Box", (PyCFunction) Box_Constructor, METH_VARARGS | METH_KEYWORDS, "Box object constructor."}, - {"Triangle", (PyCFunction) Triangle_Constructor, - METH_VARARGS | METH_KEYWORDS, "Triangle object constructor."}, + {"Pixmap", (PyCFunction) Pixmap_Constructor, + METH_VARARGS | METH_KEYWORDS, "Pixmap object constructor."}, + {"DefaultSampler", (PyCFunction) DefaultSampler_Constructor, + METH_VARARGS | METH_KEYWORDS, "DefaultSampler object constructor."}, + {"Container", (PyCFunction) Container_Constructor, + METH_NOARGS, "Container object constructor."}, + {"Octree", (PyCFunction) Octree_Constructor, + METH_NOARGS, "Octree object constructor."}, + {"KdTree", (PyCFunction) KdTree_Constructor, + METH_NOARGS, "KdTree object constructor."}, {NULL, NULL} }; -extern "C" void initraytracer(void) +extern "C" void initpyrit(void) { - Py_InitModule("raytracer", ModuleMethods); + PyObject* m; + + if (PyType_Ready(&RaytracerType) < 0 + || PyType_Ready(&LightType) < 0 + || PyType_Ready(&CameraType) < 0 + || PyType_Ready(&MaterialType) < 0 + || PyType_Ready(&NormalVertexType) < 0 + || PyType_Ready(&ShapeType) < 0 + || PyType_Ready(&TriangleType) < 0 + || PyType_Ready(&SphereType) < 0 + || PyType_Ready(&BoxType) < 0 + || PyType_Ready(&PixmapType) < 0 + || PyType_Ready(&SamplerType) < 0 + || PyType_Ready(&DefaultSamplerType) < 0 + || PyType_Ready(&ContainerType) < 0 + || PyType_Ready(&OctreeType) < 0 + || PyType_Ready(&KdTreeType) < 0 + ) + return; + + m = Py_InitModule3("pyrit", ModuleMethods, "Pyrit ray tracer."); + + if (m == NULL) + return; }