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; }