--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/raytracermodule.cc Thu Oct 25 16:40:22 2007 +0200
@@ -0,0 +1,539 @@
+/*
+ * C++ RayTracer
+ * Module for Python
+ * file: raytracermodule.cc
+ *
+ * Radek Brich, 2006
+ */
+
+#include <Python.h>
+#include <vector>
+#include "scene.h"
+#include "raytracer.h"
+
+//=========================== Light Source Object ===========================
+
+typedef struct {
+ PyObject_HEAD
+ Light *light;
+} LightObject;
+
+static PyObject *Light_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Light_Destructor(PyObject* self);
+static PyObject *Light_Getattr(PyObject *self, char *name);
+static PyObject *Light_castshadows(PyObject* self, PyObject* args);
+
+static PyTypeObject LightType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Light", /*tp_name*/
+ sizeof(LightObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ Light_Destructor, /*tp_dealloc*/
+ 0, /*tp_print*/
+ Light_Getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+};
+
+static PyMethodDef LightMethods[] = {
+ {"castshadows", (PyCFunction)Light_castshadows, METH_VARARGS, "Enable or disable shadows from this light."},
+ {NULL, NULL}
+};
+
+static PyObject* Light_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+ LightObject *v;
+ static char *kwdlist[] = {"position", "colour", NULL};
+ PyObject *TPos, *TCol = NULL;
+ float px, py, pz;
+ float cr = 1.0, cg = 1.0, cb = 1.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!|O!", kwdlist,
+ &PyTuple_Type, &TPos, &PyTuple_Type, &TCol))
+ return NULL;
+
+ if (!PyArg_ParseTuple(TPos, "fff", &px, &py, &pz))
+ return NULL;
+ if (TCol && !PyArg_ParseTuple(TCol, "fff", &cr, &cg, &cb))
+ return NULL;
+
+ v = PyObject_New(LightObject, &LightType);
+ v->light = new Light(Vector3(px, py, pz), Colour(cr, cg, cb));
+ return (PyObject*)v;
+}
+
+static void Light_Destructor(PyObject* self)
+{
+ delete ((LightObject *)self)->light;
+ PyObject_Del(self);
+}
+
+static PyObject *Light_Getattr(PyObject *self, char *name)
+{
+ return Py_FindMethod(LightMethods, self, name);
+}
+
+static PyObject *Light_castshadows(PyObject* self, PyObject* args)
+{
+ int shadows = 1;
+
+ if (!PyArg_ParseTuple(args, "i", &shadows))
+ return NULL;
+
+ ((LightObject *)self)->light->castshadows(shadows);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+//=========================== Material Object ===========================
+
+typedef struct {
+ PyObject_HEAD
+ Material *material;
+} MaterialObject;
+
+static PyObject *Material_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Material_Destructor(PyObject* self);
+static PyObject *Material_Getattr(PyObject *self, char *name);
+
+static PyTypeObject MaterialType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Material", /*tp_name*/
+ sizeof(MaterialObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ Material_Destructor, /*tp_dealloc*/
+ 0, /*tp_print*/
+ Material_Getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+};
+
+static PyMethodDef MaterialMethods[] = {
+ {NULL, NULL}
+};
+
+static PyObject* Material_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+ MaterialObject *v;
+ static char *kwdlist[] = {"colour", NULL};
+ PyObject *TCol = NULL;
+ float cr=1.0, cg=1.0, cb=1.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwd, "|O!", kwdlist,
+ &PyTuple_Type, &TCol))
+ return NULL;
+
+ if (!PyArg_ParseTuple(TCol, "fff", &cr, &cg, &cb))
+ return NULL;
+
+ v = PyObject_New(MaterialObject, &MaterialType);
+ v->material = new Material(Colour(cr, cg, cb));
+ return (PyObject*)v;
+}
+
+static void Material_Destructor(PyObject* self)
+{
+ delete ((MaterialObject *)self)->material;
+ PyObject_Del(self);
+}
+
+static PyObject *Material_Getattr(PyObject *self, char *name)
+{
+ return Py_FindMethod(MaterialMethods, self, name);
+}
+
+//=========================== Sphere Object ===========================
+
+typedef struct {
+ PyObject_HEAD
+ Sphere *shape;
+} SphereObject;
+
+static PyObject *Sphere_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Sphere_Destructor(PyObject* self);
+static PyObject *Sphere_Getattr(PyObject *self, char *name);
+
+static PyTypeObject SphereType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Sphere", /*tp_name*/
+ sizeof(SphereObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ Sphere_Destructor, /*tp_dealloc*/
+ 0, /*tp_print*/
+ Sphere_Getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+};
+
+static PyMethodDef SphereMethods[] = {
+ {NULL, NULL}
+};
+
+static PyObject* Sphere_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+ SphereObject *v;
+ MaterialObject *material;
+ static char *kwdlist[] = {"centre", "radius", "material", NULL};
+ PyObject *TCentre = NULL;
+ float cx, cy, cz, radius;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!fO!", kwdlist,
+ &PyTuple_Type, &TCentre, &radius, &MaterialType, &material))
+ return NULL;
+
+ if (!PyArg_ParseTuple(TCentre, "fff", &cx, &cy, &cz))
+ return NULL;
+
+ v = PyObject_New(SphereObject, &SphereType);
+ v->shape = new Sphere(Vector3(cx, cy, cz), radius, material->material);
+ Py_INCREF(material);
+ return (PyObject*)v;
+}
+
+static void Sphere_Destructor(PyObject* self)
+{
+ delete ((SphereObject *)self)->shape;
+ PyObject_Del(self);
+}
+
+static PyObject *Sphere_Getattr(PyObject *self, char *name)
+{
+ return Py_FindMethod(SphereMethods, self, name);
+}
+
+//=========================== Plane Object ===========================
+
+typedef struct {
+ PyObject_HEAD
+ Plane *shape;
+} PlaneObject;
+
+static PyObject *Plane_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Plane_Destructor(PyObject* self);
+static PyObject *Plane_Getattr(PyObject *self, char *name);
+
+static PyTypeObject PlaneType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Plane", /*tp_name*/
+ sizeof(PlaneObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ Plane_Destructor, /*tp_dealloc*/
+ 0, /*tp_print*/
+ Plane_Getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+};
+
+static PyMethodDef PlaneMethods[] = {
+ {NULL, NULL}
+};
+
+static PyObject* Plane_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+ PlaneObject *v;
+ MaterialObject *material;
+ static char *kwdlist[] = {"normal", "d", "material", NULL};
+ PyObject *TNorm = NULL;
+ float nx, ny, nz, d;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!fO!", kwdlist,
+ &PyTuple_Type, &TNorm, &d, &MaterialType, &material))
+ return NULL;
+
+ if (!PyArg_ParseTuple(TNorm, "fff", &nx, &ny, &nz))
+ return NULL;
+
+ v = PyObject_New(PlaneObject, &PlaneType);
+ v->shape = new Plane(Vector3(nx, ny, nz), d, material->material);
+ Py_INCREF(material);
+ return (PyObject*)v;
+}
+
+static void Plane_Destructor(PyObject* self)
+{
+ delete ((PlaneObject *)self)->shape;
+ PyObject_Del(self);
+}
+
+static PyObject *Plane_Getattr(PyObject *self, char *name)
+{
+ return Py_FindMethod(PlaneMethods, self, name);
+}
+
+//=========================== Triangle Object ===========================
+
+typedef struct {
+ PyObject_HEAD
+ Triangle *shape;
+} TriangleObject;
+
+static PyObject *Triangle_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
+static void Triangle_Destructor(PyObject* self);
+static PyObject *Triangle_Getattr(PyObject *self, char *name);
+
+static PyTypeObject TriangleType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Triangle", /*tp_name*/
+ sizeof(TriangleObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ Triangle_Destructor, /*tp_dealloc*/
+ 0, /*tp_print*/
+ Triangle_Getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+};
+
+static PyMethodDef TriangleMethods[] = {
+ {NULL, NULL}
+};
+
+static PyObject* Triangle_Constructor(PyObject* self, PyObject* args, PyObject *kwd)
+{
+ TriangleObject *v;
+ MaterialObject *material;
+ static char *kwdlist[] = {"A", "B", "C", "material", NULL};
+ PyObject *A = NULL, *B = NULL, *C = NULL;
+ float ax, ay, az, bx, by, bz, cx, cy, cz;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!O!", kwdlist,
+ &PyTuple_Type, &A, &PyTuple_Type, &B, &PyTuple_Type, &C,
+ &MaterialType, &material))
+ return NULL;
+
+ if (!PyArg_ParseTuple(A, "fff", &ax, &ay, &az))
+ return NULL;
+
+ if (!PyArg_ParseTuple(B, "fff", &bx, &by, &bz))
+ return NULL;
+
+ if (!PyArg_ParseTuple(C, "fff", &cx, &cy, &cz))
+ return NULL;
+
+ v = PyObject_New(TriangleObject, &TriangleType);
+ v->shape = new Triangle(Vector3(ax, ay, az), Vector3(bx, by, bz),
+ Vector3(cx, cy, cz), material->material);
+ Py_INCREF(material);
+ return (PyObject*)v;
+}
+
+static void Triangle_Destructor(PyObject* self)
+{
+ delete ((TriangleObject *)self)->shape;
+ PyObject_Del(self);
+}
+
+static PyObject *Triangle_Getattr(PyObject *self, char *name)
+{
+ return Py_FindMethod(TriangleMethods, self, name);
+}
+
+//=========================== Raytracer Object ===========================
+
+typedef struct {
+ PyObject_HEAD
+ Raytracer *raytracer;
+ vector<PyObject*> *children;
+} RaytracerObject;
+
+static PyObject *Raytracer_Constructor(PyObject* self, PyObject* args);
+static void Raytracer_Destructor(PyObject* self);
+static PyObject *Raytracer_Getattr(PyObject *self, char *name);
+static PyObject *Raytracer_render(PyObject* self, PyObject* args);
+static PyObject *Raytracer_addshape(PyObject* self, PyObject* args);
+static PyObject *Raytracer_addlight(PyObject* self, PyObject* args);
+static PyObject *Raytracer_ambientocclusion(PyObject* self, PyObject* args, PyObject *kwd);
+
+static PyTypeObject RaytracerType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "Raytracer", /*tp_name*/
+ sizeof(RaytracerObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ Raytracer_Destructor, /*tp_dealloc*/
+ 0, /*tp_print*/
+ Raytracer_Getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+};
+
+static PyMethodDef RaytracerMethods[] = {
+ {"render", (PyCFunction)Raytracer_render, METH_VARARGS, "Render scene and return image data."},
+ {"addshape", (PyCFunction)Raytracer_addshape, METH_VARARGS, "Add new shape to scene."},
+ {"addlight", (PyCFunction)Raytracer_addlight, METH_VARARGS, "Add new light source to scene."},
+ {"ambientocclusion", (PyCFunction)Raytracer_ambientocclusion, METH_VARARGS | METH_KEYWORDS,
+ "Set ambient occlusion parametrs - samples: int (0 = disable), distance: float, angle: float."},
+ {NULL, NULL}
+};
+
+static PyObject* Raytracer_Constructor(PyObject* self, PyObject* args)
+{
+ RaytracerObject *v;
+
+ if(!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ v = PyObject_New(RaytracerObject, &RaytracerType);
+ v->raytracer = new Raytracer();
+ v->children = new vector<PyObject*>();
+
+ return (PyObject*)v;
+}
+
+static void Raytracer_Destructor(PyObject* self)
+{
+ vector<PyObject*>::iterator o;
+ for (o = ((RaytracerObject *)self)->children->begin();
+ o != ((RaytracerObject *)self)->children->end(); o++)
+ Py_DECREF(*o);
+ delete ((RaytracerObject *)self)->raytracer;
+ PyObject_Del(self);
+}
+
+static PyObject *Raytracer_Getattr(PyObject *self, char *name)
+{
+ return Py_FindMethod(RaytracerMethods, self, name);
+}
+
+static PyObject* Raytracer_render(PyObject* self, PyObject* args)
+{
+ int w = 0, h = 0;
+ char *chardata;
+ float *data;
+ PyObject *o;
+
+ if (!PyArg_ParseTuple(args, "(ii)", &w, &h))
+ return NULL;
+
+ printf("[PyRit] Raytracing...\n");
+ data = ((RaytracerObject *)self)->raytracer->render(w, h);
+ if (!data) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ // convert data to char
+ printf("[PyRit] Converting image data (float to char)...\n");
+ chardata = (char *) malloc(w*h*3);
+ float *d = data;
+ for (char *c = chardata; c != chardata + w*h*3; c++, d++) {
+ if (*d > 1.0)
+ *c = 255;
+ else
+ *c = (unsigned char)(*d * 255.0);
+ }
+ free(data);
+ o = Py_BuildValue("s#", chardata, w*h*3);
+ free(chardata);
+ printf("[PyRit] Done.\n");
+ return o;
+}
+
+static PyObject* Raytracer_addshape(PyObject* self, PyObject* args)
+{
+ PyObject *obj;
+
+ if (!PyArg_ParseTuple(args, "O", &obj))
+ return NULL;
+
+ ((RaytracerObject *)self)->raytracer->addshape(
+ ((PlaneObject*)obj)->shape);
+
+ ((RaytracerObject *)self)->children->push_back(obj);
+ Py_INCREF(obj);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject* Raytracer_addlight(PyObject* self, PyObject* args)
+{
+ LightObject *lightobj;
+
+ if (!PyArg_ParseTuple(args, "O!", &LightType, &lightobj))
+ return NULL;
+ ((RaytracerObject *)self)->raytracer->addlight(lightobj->light);
+ ((RaytracerObject *)self)->children->push_back((PyObject*)lightobj);
+ Py_INCREF(lightobj);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject* Raytracer_ambientocclusion(PyObject* self, PyObject* args, PyObject *kwd)
+{
+ int samples = 0;
+ float distance = 0.0, angle = 0.0;
+ static char *kwdlist[] = {"samples", "distance", "angle", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwd, "iff", kwdlist,
+ &samples, &distance, &angle))
+ return NULL;
+
+ ((RaytracerObject *)self)->raytracer->ambientocclusion(samples, distance, angle);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+//=========================== Module Methods ===========================
+
+static PyMethodDef ModuleMethods[] = {
+ {"Raytracer", (PyCFunction) Raytracer_Constructor,
+ METH_VARARGS, "Raytracer object constructor."},
+ {"Light", (PyCFunction) Light_Constructor,
+ METH_VARARGS | METH_KEYWORDS, "Light source object constructor."},
+ {"Material", (PyCFunction) Material_Constructor,
+ METH_VARARGS | METH_KEYWORDS, "Material object constructor."},
+ {"Sphere", (PyCFunction) Sphere_Constructor,
+ METH_VARARGS | METH_KEYWORDS, "Sphere object constructor."},
+ {"Plane", (PyCFunction) Plane_Constructor,
+ METH_VARARGS | METH_KEYWORDS, "Plane object constructor."},
+ {"Triangle", (PyCFunction) Triangle_Constructor,
+ METH_VARARGS | METH_KEYWORDS, "Triangle object constructor."},
+ {NULL, NULL}
+};
+
+
+extern "C" void initraytracer(void)
+{
+ Py_InitModule("raytracer", ModuleMethods);
+}