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