more build script tuning
make all float constants single precision
solve many warnings from msvc and gcc with various -W... flags
add common.cc file for dbgmsg() function witch apparently cannot be inlined
fix python module building with msvc, add manifest file handling
remove forgotten RenderrowData class
add stanford models download script for windows (.bat)
/*
* raytracermodule.cc: Python module
*
* This file is part of Pyrit Ray Tracer.
*
* Copyright 2006, 2007, 2008 Radek Brich
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <Python.h>
#include <vector>
#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 {
PyObject_HEAD
Light *light;
} LightObject;
static PyObject *Light_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
static void Light_Destructor(PyObject* self);
static PyObject *Light_castShadows(PyObject* self, PyObject* args);
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;
static char *kwdlist[] = {"position", "colour", NULL};
PyObject *TPos, *TCol = NULL;
Float px, py, pz;
Float cr = 0.9f, cg = 0.9f, cb = 0.9f;
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(Vector(px, py, pz), Colour(cr, cg, cb));
return (PyObject*)v;
}
static void Light_Destructor(PyObject* self)
{
delete ((LightObject *)self)->light;
self->ob_type->tp_free(self);
}
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;
}
//=========================== Camera Object ===========================
typedef struct {
PyObject_HEAD
Camera *camera;
} CameraObject;
static PyObject *Camera_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
static void Camera_Destructor(PyObject* self);
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 PyMethodDef CameraMethods[] = {
{"setEye", (PyCFunction)Camera_setEye, METH_VARARGS, "Set eye of the camera."},
{"setAngle", (PyCFunction)Camera_setAngle, METH_VARARGS, "Set vertical angle of view."},
{"rotate", (PyCFunction)Camera_rotate, METH_VARARGS, "Rotate camera with a quaternion."},
{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;
static char *kwdlist[] = {"eye", "lookat", "up", "p", "u", "v", NULL};
PyObject *TEye = NULL, *TLookAt = NULL, *TUp = NULL,
*Tp = NULL, *Tu = NULL, *Tv = NULL;
Float ex=0.0, ey=0.0, ez=10.0;
Float lax=0.0, lay=0.0, laz=0.0;
Float upx=0.0, upy=1.0, upz=0.0;
Float px=0.0, py=0.0, pz=-1.0;
Float ux=-1.0, uy=0.0, uz=0.0;
Float vx=0.0, vy=1.0, vz=0.0;
if (!PyArg_ParseTupleAndKeywords(args, kwd, "|O!O!O!O!O!O!", kwdlist,
&PyTuple_Type, &TEye, &PyTuple_Type, &TLookAt, &PyTuple_Type, &TUp,
&PyTuple_Type, &Tp, &PyTuple_Type, &Tu, &PyTuple_Type, &Tv))
return NULL;
if (TEye)
if (!PyArg_ParseTuple(TEye, "fff", &ex, &ey, &ez))
return NULL;
if (TLookAt)
if (!PyArg_ParseTuple(TLookAt, "fff", &lax, &lay, &laz))
return NULL;
if (TUp)
if (!PyArg_ParseTuple(TUp, "fff", &upx, &upy, &upz))
return NULL;
if (Tp)
if (!PyArg_ParseTuple(Tp, "fff", &px, &py, &pz))
return NULL;
if (Tu)
if (!PyArg_ParseTuple(Tu, "fff", &ux, &uy, &uz))
return NULL;
if (Tv)
if (!PyArg_ParseTuple(Tv, "fff", &vx, &vy, &vz))
return NULL;
v = PyObject_New(CameraObject, &CameraType);
if (TLookAt)
v->camera = new Camera(Vector(ex, ey, ez),
Vector(lax, lay, laz), Vector(upx, upy, upz));
else
v->camera = new Camera(Vector(ex, ey, ez),
Vector(px, py, pz), Vector(ux, uy, uz), Vector(vx, vy, vz));
return (PyObject*)v;
}
static void Camera_Destructor(PyObject* self)
{
delete ((CameraObject *)self)->camera;
self->ob_type->tp_free(self);
}
static PyObject *Camera_setEye(PyObject* self, PyObject* args)
{
PyObject *TEye = NULL;
Float ex=0.0, ey=0.0, ez=10.0;
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &TEye))
return NULL;
if (TEye)
if (!PyArg_ParseTuple(TEye, "fff", &ex, &ey, &ez))
return NULL;
((CameraObject *)self)->camera->setEye(Vector(ex, ey, ez));
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *Camera_setAngle(PyObject* self, PyObject* args)
{
Float angle;
if (!PyArg_ParseTuple(args, "f", &angle))
return NULL;
((CameraObject *)self)->camera->setAngle(angle);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *Camera_rotate(PyObject* self, PyObject* args)
{
PyObject *Tq = NULL;
Float qa, qb, qc, qd;
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &Tq))
return NULL;
if (!PyArg_ParseTuple(Tq, "ffff", &qa, &qb, &qc, &qd))
return NULL;
((CameraObject *)self)->camera->rotate(Quaternion(qa, qb, qc, qd).normalize());
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_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 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."},
{"setTransmissivity", (PyCFunction)Material_setTransmissivity, METH_VARARGS, "Set transmissivity and refraction index."},
{"setSmooth", (PyCFunction)Material_setSmooth, METH_VARARGS, "Set triangle smoothing."},
{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;
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 (TCol)
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;
self->ob_type->tp_free(self);
}
static PyObject *Material_setPhong(PyObject* self, PyObject* args)
{
Float amb, dif, spec, shin = 0.5;
if (!PyArg_ParseTuple(args, "fff|f", &amb, &dif, &spec, &shin))
return NULL;
((MaterialObject *)self)->material->setPhong(amb, dif, spec, shin);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *Material_setReflectivity(PyObject* self, PyObject* args)
{
Float refl;
if (!PyArg_ParseTuple(args, "f", &refl))
return NULL;
((MaterialObject *)self)->material->setReflectivity(refl);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *Material_setTransmissivity(PyObject* self, PyObject* args)
{
Float trans, rindex = 1.3f;
if (!PyArg_ParseTuple(args, "f|f", &trans, &rindex))
return NULL;
((MaterialObject *)self)->material->setTransmissivity(trans, rindex);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* Material_setSmooth(PyObject* self, PyObject* args)
{
int smooth;
if (!PyArg_ParseTuple(args, "i", &smooth))
return NULL;
((MaterialObject *)self)->material->setSmooth(smooth);
Py_INCREF(Py_None);
return Py_None;
}
//=========================== NormalVertex Object ===========================
typedef struct {
PyObject_HEAD
NormalVertex *nvertex;
} NormalVertexObject;
static PyObject *NormalVertex_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
static void NormalVertex_Destructor(PyObject* self);
static PyObject *NormalVertex_setNormal(PyObject* self, PyObject* args);
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;
static char *kwdlist[] = {"vector", "normal", NULL};
PyObject *TVer = NULL;
PyObject *TNor = NULL;
Float vx, vy, vz, nx=0, ny=0, nz=0;
if (!PyArg_ParseTupleAndKeywords(args, kwd, "O|O!", kwdlist,
&TVer, &PyTuple_Type, &TNor))
return NULL;
if (!TNor && TVer->ob_type == &NormalVertexType)
{
v = PyObject_New(NormalVertexObject, &NormalVertexType);
v->nvertex = new NormalVertex(((NormalVertexObject*)TVer)->nvertex);
}
else
{
if (!PyArg_ParseTuple(TVer, "fff", &vx, &vy, &vz))
return NULL;
if (TNor)
if (!PyArg_ParseTuple(TNor, "fff", &nx, &ny, &nz))
return NULL;
v = PyObject_New(NormalVertexObject, &NormalVertexType);
v->nvertex = new NormalVertex(Vector(vx, vy, vz), Vector(nx, ny, nz));
}
return (PyObject*)v;
}
static void NormalVertex_Destructor(PyObject* self)
{
delete ((NormalVertexObject *)self)->nvertex;
self->ob_type->tp_free(self);
}
static PyObject *NormalVertex_setNormal(PyObject* self, PyObject* args)
{
PyObject *TNor = NULL;
Float nx, ny, nz;
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &TNor))
return NULL;
if (!PyArg_ParseTuple(TNor, "fff", &nx, &ny, &nz))
return NULL;
((NormalVertexObject *)self)->nvertex->setNormal(Vector(nx,ny,nz).normalize());
Py_INCREF(Py_None);
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;
Vector N = ((Triangle*)((TriangleObject *)self)->shape.shape)->getNormal();
obj = Py_BuildValue("(fff)", N.x, N.y, N.z);
return obj;
}
//=========================== Sphere Object ===========================
typedef struct {
ShapeObject shape;
} SphereObject;
static PyObject *Sphere_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
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;
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.shape = new Sphere(Vector(cx, cy, cz), radius, material->material);
Py_INCREF(material);
return (PyObject*)v;
}
//=========================== Box Object ===========================
typedef struct {
ShapeObject shape;
} BoxObject;
static PyObject *Box_Constructor(PyObject* self, PyObject* args, PyObject *kwd);
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;
MaterialObject *material;
static char *kwdlist[] = {"L", "H", "material", NULL};
PyObject *TL = NULL;
PyObject *TH = NULL;
Float lx, ly, lz, hx, hy, hz;
if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!", kwdlist,
&PyTuple_Type, &TL, &PyTuple_Type, &TH, &MaterialType, &material))
return NULL;
if (!PyArg_ParseTuple(TL, "fff", &lx, &ly, &lz))
return NULL;
if (!PyArg_ParseTuple(TH, "fff", &hx, &hy, &hz))
return NULL;
v = PyObject_New(BoxObject, &BoxType);
v->shape.shape = new Box(Vector(lx, ly, lz), Vector(hx, hy, hz), material->material);
Py_INCREF(material);
return (PyObject*)v;
}
//=========================== 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)
{
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* Pixmap_getWidth(PyObject* self, PyObject* args)
{
return Py_BuildValue("i", ((PixmapObject *)self)->pixmap->getWidth());
}
static PyObject* Pixmap_getHeight(PyObject* self, PyObject* args)
{
return Py_BuildValue("i", ((PixmapObject *)self)->pixmap->getHeight());
}
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
Sampler *sampler;
} SamplerObject;
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 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 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)
{
int w = 0, h = 0;
PyObject *o1, *o2;
DefaultSamplerObject *v;
if (!PyArg_ParseTuple(args, "O|O", &o1, &o2))
return NULL;
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 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)
{
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* Container_optimize(PyObject* self, PyObject* args)
{
((ContainerObject *)self)->container->optimize();
Py_INCREF(Py_None);
return Py_None;
}
//=========================== 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 */
);
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}
};
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 ===========================
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_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 PyMethodDef RaytracerMethods[] = {
{"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."},
{"ambientOcclusion", (PyCFunction)Raytracer_ambientOcclusion, METH_VARARGS | METH_KEYWORDS,
"Set ambient occlusion parametrs - samples: int (0 = disable), distance: float, angle: float."},
{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;
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;
self->ob_type->tp_free(self);
}
static PyObject* Raytracer_render(PyObject* self, PyObject* args)
{
((RaytracerObject *)self)->raytracer->render();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* Raytracer_setSampler(PyObject* self, PyObject* args)
{
SamplerObject *samp;
if (!PyArg_ParseTuple(args, "O!", &SamplerType, &samp))
return NULL;
((RaytracerObject *)self)->raytracer->setSampler(samp->sampler);
Py_INCREF(samp);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* Raytracer_setCamera(PyObject* self, PyObject* args)
{
CameraObject *cam;
if (!PyArg_ParseTuple(args, "O!", &CameraType, &cam))
return NULL;
((RaytracerObject *)self)->raytracer->setCamera(cam->camera);
Py_INCREF(cam);
Py_INCREF(Py_None);
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;
if (!PyArg_ParseTuple(args, "(fff)", &r, &g, &b))
return NULL;
((RaytracerObject *)self)->raytracer->setBgColour(Colour(r,g,b));
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* Raytracer_addShape(PyObject* self, PyObject* args)
{
ShapeObject *shape;
if (!PyArg_ParseTuple(args, "O!", &ShapeType, &shape))
return NULL;
((RaytracerObject *)self)->raytracer->addShape(shape->shape);
((RaytracerObject *)self)->children->push_back((PyObject*)shape);
Py_INCREF(shape);
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."},
{"Camera", (PyCFunction) Camera_Constructor,
METH_VARARGS | METH_KEYWORDS, "Camera object constructor."},
{"Material", (PyCFunction) Material_Constructor,
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."},
{"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 initpyrit(void)
{
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;
}