src/raytracermodule.cc
branchpyrit
changeset 0 3547b885df7e
child 1 e74bf781067e
--- /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);
+}