summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2011-05-22 14:22:07 -0600
committerTavian Barnes <tavianator@gmail.com>2011-05-22 14:22:07 -0600
commit1bf306d4d93cc21c220a3f31835023e49e84dd2d (patch)
tree436959a8321100a3c36e8eef9a19279cb446e1fa
parent0f0b704144bddc045657f7ed852b49d5e349b0bd (diff)
downloaddimension-1bf306d4d93cc21c220a3f31835023e49e84dd2d.tar.xz
Add cameras, objects, and spheres to Python module.
-rw-r--r--libdimension-python/Camera.c92
-rw-r--r--libdimension-python/Camera.h28
-rw-r--r--libdimension-python/Canvas.c13
-rw-r--r--libdimension-python/Canvas.h2
-rw-r--r--libdimension-python/Color.c36
-rw-r--r--libdimension-python/Color.h3
-rw-r--r--libdimension-python/Makefile.am10
-rw-r--r--libdimension-python/Matrix.c15
-rw-r--r--libdimension-python/Matrix.h10
-rw-r--r--libdimension-python/Object.c73
-rw-r--r--libdimension-python/Object.h28
-rw-r--r--libdimension-python/PerspectiveCamera.c111
-rw-r--r--libdimension-python/PerspectiveCamera.h28
-rw-r--r--libdimension-python/Scene.c59
-rw-r--r--libdimension-python/Scene.h2
-rw-r--r--libdimension-python/Sphere.c76
-rw-r--r--libdimension-python/Sphere.h29
-rw-r--r--libdimension-python/Vector.c69
-rw-r--r--libdimension-python/Vector.h4
-rw-r--r--libdimension-python/dimension-python.h14
-rw-r--r--libdimension-python/dimension.c28
-rwxr-xr-xlibdimension-python/tests/demo.py16
-rwxr-xr-xlibdimension-python/tests/geometry.py4
23 files changed, 637 insertions, 113 deletions
diff --git a/libdimension-python/Camera.c b/libdimension-python/Camera.c
new file mode 100644
index 0000000..17347d7
--- /dev/null
+++ b/libdimension-python/Camera.c
@@ -0,0 +1,92 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+#include "dimension-python.h"
+
+static int
+dmnsn_py_Camera_init(dmnsn_py_Camera *self, PyObject *args, PyObject *kwds)
+{
+ if (kwds || (args && !PyArg_ParseTuple(args, "")))
+ return -1;
+
+ return 0;
+}
+
+static void
+dmnsn_py_Camera_dealloc(dmnsn_py_Camera *self)
+{
+ dmnsn_delete_camera(self->camera);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *
+dmnsn_py_Camera_initialize(dmnsn_py_Camera *self)
+{
+ PyErr_SetString(PyExc_TypeError, "Attempt to initialize base Camera");
+ return NULL;
+}
+
+static PyObject *
+dmnsn_py_Camera_transform(dmnsn_py_Camera *self, PyObject *args)
+{
+ dmnsn_py_Matrix *matrix;
+ if (!PyArg_ParseTuple(args, "O!", &dmnsn_py_MatrixType, &matrix))
+ return NULL;
+
+ if (!self->camera) {
+ PyErr_SetString(PyExc_TypeError, "Attempt to transform base Camera");
+ return NULL;
+ }
+
+ self->camera->trans = dmnsn_matrix_mul(matrix->m, self->camera->trans);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef dmnsn_py_Camera_methods[] = {
+ { "initialize", (PyCFunction)dmnsn_py_Camera_initialize, METH_NOARGS,
+ "Initialize a camera" },
+ { "transform", (PyCFunction)dmnsn_py_Camera_transform, METH_VARARGS,
+ "Transform a camera" },
+ { NULL }
+};
+
+static PyGetSetDef dmnsn_py_Camera_getsetters[] = {
+ { NULL }
+};
+
+PyTypeObject dmnsn_py_CameraType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "dimension.Camera",
+ .tp_basicsize = sizeof(dmnsn_py_Camera),
+ .tp_dealloc = (destructor)dmnsn_py_Camera_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = "Dimension camera",
+ .tp_methods = dmnsn_py_Camera_methods,
+ .tp_getset = dmnsn_py_Camera_getsetters,
+ .tp_init = (initproc)dmnsn_py_Camera_init,
+};
+
+bool
+dmnsn_py_init_CameraType(void)
+{
+ dmnsn_py_CameraType.tp_new = PyType_GenericNew;
+ return PyType_Ready(&dmnsn_py_CameraType) >= 0;
+}
diff --git a/libdimension-python/Camera.h b/libdimension-python/Camera.h
new file mode 100644
index 0000000..8642f2c
--- /dev/null
+++ b/libdimension-python/Camera.h
@@ -0,0 +1,28 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+typedef struct dmnsn_py_Camera {
+ PyObject_HEAD
+ dmnsn_camera *camera;
+} dmnsn_py_Camera;
+
+extern PyTypeObject dmnsn_py_CameraType;
+
+bool dmnsn_py_init_CameraType(void);
diff --git a/libdimension-python/Canvas.c b/libdimension-python/Canvas.c
index 6cce310..c5063d0 100644
--- a/libdimension-python/Canvas.c
+++ b/libdimension-python/Canvas.c
@@ -18,8 +18,7 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "Color.h"
-#include "Canvas.h"
+#include "dimension-python.h"
static int
dmnsn_py_Canvas_init(dmnsn_py_Canvas *self, PyObject *args, PyObject *kwds)
@@ -74,13 +73,13 @@ dmnsn_py_Canvas_optimizeGL(dmnsn_py_Canvas *self)
}
static PyObject *
-dmnsn_py_Canvas_clear(dmnsn_py_Canvas *self, PyObject *args, PyObject *kwds)
+dmnsn_py_Canvas_clear(dmnsn_py_Canvas *self, PyObject *args)
{
- dmnsn_color color;
- if (!dmnsn_py_Color_args(&color, args, kwds))
+ dmnsn_py_Color *color;
+ if (!PyArg_ParseTuple(args, "O!", &dmnsn_py_ColorType, &color))
return NULL;
- dmnsn_clear_canvas(self->canvas, color);
+ dmnsn_clear_canvas(self->canvas, color->c);
Py_INCREF(Py_None);
return Py_None;
@@ -124,7 +123,7 @@ static PyMethodDef dmnsn_py_Canvas_methods[] = {
"Optimize a canvas for PNG output" },
{ "optimizeGL", (PyCFunction)dmnsn_py_Canvas_optimizeGL, METH_NOARGS,
"Optimize a canvas for OpenGL output" },
- { "clear", (PyCFunction)dmnsn_py_Canvas_clear, METH_VARARGS | METH_KEYWORDS,
+ { "clear", (PyCFunction)dmnsn_py_Canvas_clear, METH_VARARGS,
"Clear a canvas with a solid color" },
{ "writePNG", (PyCFunction)dmnsn_py_Canvas_writePNG, METH_VARARGS,
"Write a canvas to a PNG file" },
diff --git a/libdimension-python/Canvas.h b/libdimension-python/Canvas.h
index 53d09c1..0714e53 100644
--- a/libdimension-python/Canvas.h
+++ b/libdimension-python/Canvas.h
@@ -18,8 +18,6 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension-python.h"
-
typedef struct dmnsn_py_Canvas {
PyObject_HEAD
dmnsn_canvas *canvas;
diff --git a/libdimension-python/Color.c b/libdimension-python/Color.c
index c147603..529aab2 100644
--- a/libdimension-python/Color.c
+++ b/libdimension-python/Color.c
@@ -18,37 +18,21 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "Color.h"
+#include "dimension-python.h"
-bool
-dmnsn_py_Color_args(dmnsn_color *c, PyObject *args, PyObject *kwds)
+static int
+dmnsn_py_Color_init(dmnsn_py_Color *self, PyObject *args, PyObject *kwds)
{
- c->trans = 0.0;
- c->filter = 0.0;
+ self->c.trans = 0.0;
+ self->c.filter = 0.0;
static char *kwlist[] = { "red", "green", "blue", "trans", "filter", NULL };
- if (PyArg_ParseTupleAndKeywords(args, kwds, "ddd|dd", kwlist,
- &c->R, &c->G, &c->B, &c->trans, &c->filter)) {
- return true;
- } else {
- if (kwds)
- return false;
-
- PyErr_Clear();
-
- dmnsn_py_Color *col;
- if (!PyArg_ParseTuple(args, "O!", &dmnsn_py_ColorType, &col))
- return false;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ddd|dd", kwlist,
+ &self->c.R, &self->c.G, &self->c.B,
+ &self->c.trans, &self->c.filter))
+ return -1;
- *c = col->c;
- return true;
- }
-}
-
-static int
-dmnsn_py_Color_init(dmnsn_py_Color *self, PyObject *args, PyObject *kwds)
-{
- return dmnsn_py_Color_args(&self->c, args, kwds) ? 0 : -1;
+ return 0;
}
static PyObject *
diff --git a/libdimension-python/Color.h b/libdimension-python/Color.h
index 1fbf5ed..2749f2f 100644
--- a/libdimension-python/Color.h
+++ b/libdimension-python/Color.h
@@ -18,8 +18,6 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension-python.h"
-
typedef struct dmnsn_py_Color {
PyObject_HEAD
dmnsn_color c;
@@ -27,7 +25,6 @@ typedef struct dmnsn_py_Color {
extern PyTypeObject dmnsn_py_ColorType;
-bool dmnsn_py_Color_args(dmnsn_color *v, PyObject *args, PyObject *kwds);
bool dmnsn_py_init_ColorType(void);
/* Color constants */
diff --git a/libdimension-python/Makefile.am b/libdimension-python/Makefile.am
index e2d2049..9919a1a 100644
--- a/libdimension-python/Makefile.am
+++ b/libdimension-python/Makefile.am
@@ -26,14 +26,22 @@ AM_CFLAGS = $(Python_CFLAGS)
AM_LDFLAGS = $(Python_LDFLAGS)
pyexec_LTLIBRARIES = dimension.la
-dimension_la_SOURCES = Canvas.c \
+dimension_la_SOURCES = Camera.c \
+ Camera.h \
+ Canvas.c \
Canvas.h \
Color.c \
Color.h \
Matrix.c \
Matrix.h \
+ Object.c \
+ Object.h \
+ PerspectiveCamera.c \
+ PerspectiveCamera.h \
Scene.c \
Scene.h \
+ Sphere.c \
+ Sphere.h \
Vector.c \
Vector.h \
dimension.c \
diff --git a/libdimension-python/Matrix.c b/libdimension-python/Matrix.c
index b18b2d7..0219965 100644
--- a/libdimension-python/Matrix.c
+++ b/libdimension-python/Matrix.c
@@ -18,8 +18,7 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "Vector.h"
-#include "Matrix.h"
+#include "dimension-python.h"
static int
dmnsn_py_Matrix_init(dmnsn_py_Matrix *self, PyObject *args, PyObject *kwds)
@@ -42,10 +41,10 @@ dmnsn_py_Matrix_init(dmnsn_py_Matrix *self, PyObject *args, PyObject *kwds)
}
PyObject *
-dmnsn_py_Matrix_scale(PyObject *self, PyObject *args, PyObject *kwds)
+dmnsn_py_Matrix_scale(PyObject *self, PyObject *args)
{
dmnsn_vector scale;
- if (!dmnsn_py_Vector_args(&scale, args, kwds))
+ if (!PyArg_ParseTuple(args, "O&", dmnsn_py_VectorParse, &scale))
return NULL;
dmnsn_py_Matrix *ret = PyObject_New(dmnsn_py_Matrix, &dmnsn_py_MatrixType);
@@ -56,10 +55,10 @@ dmnsn_py_Matrix_scale(PyObject *self, PyObject *args, PyObject *kwds)
}
PyObject *
-dmnsn_py_Matrix_translate(PyObject *self, PyObject *args, PyObject *kwds)
+dmnsn_py_Matrix_translate(PyObject *self, PyObject *args)
{
dmnsn_vector translate;
- if (!dmnsn_py_Vector_args(&translate, args, kwds))
+ if (!PyArg_ParseTuple(args, "O&", dmnsn_py_VectorParse, &translate))
return NULL;
dmnsn_py_Matrix *ret = PyObject_New(dmnsn_py_Matrix, &dmnsn_py_MatrixType);
@@ -70,10 +69,10 @@ dmnsn_py_Matrix_translate(PyObject *self, PyObject *args, PyObject *kwds)
}
PyObject *
-dmnsn_py_Matrix_rotate(PyObject *self, PyObject *args, PyObject *kwds)
+dmnsn_py_Matrix_rotate(PyObject *self, PyObject *args)
{
dmnsn_vector rotate;
- if (!dmnsn_py_Vector_args(&rotate, args, kwds))
+ if (!PyArg_ParseTuple(args, "O&", dmnsn_py_VectorParse, &rotate))
return NULL;
dmnsn_py_Matrix *ret = PyObject_New(dmnsn_py_Matrix, &dmnsn_py_MatrixType);
diff --git a/libdimension-python/Matrix.h b/libdimension-python/Matrix.h
index 6299618..fa34da6 100644
--- a/libdimension-python/Matrix.h
+++ b/libdimension-python/Matrix.h
@@ -18,8 +18,6 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension-python.h"
-
typedef struct dmnsn_py_Matrix {
PyObject_HEAD
dmnsn_matrix m;
@@ -30,8 +28,6 @@ extern PyTypeObject dmnsn_py_MatrixType;
bool dmnsn_py_init_MatrixType(void);
/* Global methods */
-PyObject *dmnsn_py_Matrix_scale(PyObject *self, PyObject *args, PyObject *kwds);
-PyObject *dmnsn_py_Matrix_translate(PyObject *self, PyObject *args,
- PyObject *kwds);
-PyObject *dmnsn_py_Matrix_rotate(PyObject *self, PyObject *args,
- PyObject *kwds);
+PyObject *dmnsn_py_Matrix_scale(PyObject *self, PyObject *args);
+PyObject *dmnsn_py_Matrix_translate(PyObject *self, PyObject *args);
+PyObject *dmnsn_py_Matrix_rotate(PyObject *self, PyObject *args);
diff --git a/libdimension-python/Object.c b/libdimension-python/Object.c
new file mode 100644
index 0000000..5942d3d
--- /dev/null
+++ b/libdimension-python/Object.c
@@ -0,0 +1,73 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+#include "dimension-python.h"
+
+static int
+dmnsn_py_Object_init(dmnsn_py_Object *self, PyObject *args, PyObject *kwds)
+{
+ if (kwds || (args && !PyArg_ParseTuple(args, "")))
+ return -1;
+
+ return 0;
+}
+
+static void
+dmnsn_py_Object_dealloc(dmnsn_py_Object *self)
+{
+ dmnsn_delete_object(self->object);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *
+dmnsn_py_Object_initialize(dmnsn_py_Object *self)
+{
+ PyErr_SetString(PyExc_TypeError, "Attempt to initialize base Object");
+ return NULL;
+}
+
+static PyMethodDef dmnsn_py_Object_methods[] = {
+ { "initialize", (PyCFunction)dmnsn_py_Object_initialize, METH_NOARGS,
+ "Initialize an object" },
+ { NULL }
+};
+
+static PyGetSetDef dmnsn_py_Object_getsetters[] = {
+ { NULL }
+};
+
+PyTypeObject dmnsn_py_ObjectType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "dimension.Object",
+ .tp_basicsize = sizeof(dmnsn_py_Object),
+ .tp_dealloc = (destructor)dmnsn_py_Object_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = "Dimension object",
+ .tp_methods = dmnsn_py_Object_methods,
+ .tp_getset = dmnsn_py_Object_getsetters,
+ .tp_init = (initproc)dmnsn_py_Object_init,
+};
+
+bool
+dmnsn_py_init_ObjectType(void)
+{
+ dmnsn_py_ObjectType.tp_new = PyType_GenericNew;
+ return PyType_Ready(&dmnsn_py_ObjectType) >= 0;
+}
diff --git a/libdimension-python/Object.h b/libdimension-python/Object.h
new file mode 100644
index 0000000..11b35f1
--- /dev/null
+++ b/libdimension-python/Object.h
@@ -0,0 +1,28 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+typedef struct dmnsn_py_Object {
+ PyObject_HEAD
+ dmnsn_object *object;
+} dmnsn_py_Object;
+
+extern PyTypeObject dmnsn_py_ObjectType;
+
+bool dmnsn_py_init_ObjectType(void);
diff --git a/libdimension-python/PerspectiveCamera.c b/libdimension-python/PerspectiveCamera.c
new file mode 100644
index 0000000..f144498
--- /dev/null
+++ b/libdimension-python/PerspectiveCamera.c
@@ -0,0 +1,111 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+#include "dimension-python.h"
+
+static int
+dmnsn_py_PerspectiveCamera_init(dmnsn_py_PerspectiveCamera *self,
+ PyObject *args, PyObject *kwds)
+{
+ if (dmnsn_py_CameraType.tp_init((PyObject *)self, NULL, NULL) < 0)
+ return -1;
+
+ static char *kwlist[] = { "location", "look_at", NULL };
+
+ dmnsn_vector location, look_at;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&", kwlist,
+ &dmnsn_py_VectorParse, &location,
+ &dmnsn_py_VectorParse, &look_at))
+ return -1;
+
+ self->location = location;
+ self->look_at = look_at;
+
+ dmnsn_delete_camera(self->base.camera);
+ self->base.camera = dmnsn_new_perspective_camera();
+ DMNSN_INCREF(self->base.camera);
+ return 0;
+}
+
+static PyObject *
+dmnsn_py_PerspectiveCamera_initialize(dmnsn_py_PerspectiveCamera *self)
+{
+ dmnsn_vector look_at = dmnsn_vector_sub(self->look_at, self->location);
+
+ /* Align the camera with the look_at point */
+
+ dmnsn_vector right = dmnsn_x;
+ dmnsn_vector up = dmnsn_y;
+ dmnsn_vector forward = dmnsn_z;
+
+ dmnsn_vector theta = dmnsn_vector_mul(
+ dmnsn_vector_axis_angle(forward, look_at, up),
+ up
+ );
+ dmnsn_matrix align = dmnsn_rotation_matrix(theta);
+
+ right = dmnsn_transform_vector(align, right);
+ forward = dmnsn_transform_vector(align, forward);
+
+ theta = dmnsn_vector_mul(
+ dmnsn_vector_axis_angle(forward, look_at, right),
+ right
+ );
+ align = dmnsn_matrix_mul(dmnsn_rotation_matrix(theta), align);
+
+ /* Translate the camera to the location */
+ dmnsn_matrix move = dmnsn_translation_matrix(self->location);
+
+ dmnsn_matrix trans = dmnsn_matrix_mul(move, align);
+ self->base.camera->trans = dmnsn_matrix_mul(self->base.camera->trans,
+ trans);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef dmnsn_py_PerspectiveCamera_methods[] = {
+ { "initialize", (PyCFunction)dmnsn_py_PerspectiveCamera_initialize,
+ METH_NOARGS, "Initialize a perspective camera" },
+ { NULL }
+};
+
+static PyGetSetDef dmnsn_py_PerspectiveCamera_getsetters[] = {
+ { NULL }
+};
+
+PyTypeObject dmnsn_py_PerspectiveCameraType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "dimension.PerspectiveCamera",
+ .tp_basicsize = sizeof(dmnsn_py_PerspectiveCamera),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = "Dimension perspective camera",
+ .tp_methods = dmnsn_py_PerspectiveCamera_methods,
+ .tp_getset = dmnsn_py_PerspectiveCamera_getsetters,
+ .tp_init = (initproc)dmnsn_py_PerspectiveCamera_init,
+ .tp_base = &dmnsn_py_CameraType,
+};
+
+bool
+dmnsn_py_init_PerspectiveCameraType(void)
+{
+ dmnsn_py_PerspectiveCameraType.tp_new = PyType_GenericNew;
+ return PyType_Ready(&dmnsn_py_PerspectiveCameraType) >= 0;
+}
diff --git a/libdimension-python/PerspectiveCamera.h b/libdimension-python/PerspectiveCamera.h
new file mode 100644
index 0000000..e6696e6
--- /dev/null
+++ b/libdimension-python/PerspectiveCamera.h
@@ -0,0 +1,28 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+typedef struct dmnsn_py_PerspectiveCamera {
+ dmnsn_py_Camera base;
+ dmnsn_vector location, look_at;
+} dmnsn_py_PerspectiveCamera;
+
+extern PyTypeObject dmnsn_py_PerspectiveCameraType;
+
+bool dmnsn_py_init_PerspectiveCameraType(void);
diff --git a/libdimension-python/Scene.c b/libdimension-python/Scene.c
index 29a623a..0e43ec9 100644
--- a/libdimension-python/Scene.c
+++ b/libdimension-python/Scene.c
@@ -18,22 +18,57 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "Canvas.h"
-#include "Scene.h"
+#include "dimension-python.h"
static int
dmnsn_py_Scene_init(dmnsn_py_Scene *self, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = { "canvas", NULL };
+ dmnsn_delete_scene(self->scene);
+ self->scene = dmnsn_new_scene();
+
+ static char *kwlist[] = { "canvas", "camera", "objects", NULL };
dmnsn_py_Canvas *canvas;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist,
- &dmnsn_py_CanvasType, &canvas))
+ dmnsn_py_Camera *camera;
+ PyObject *objects;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O!", kwlist,
+ &dmnsn_py_CanvasType, &canvas,
+ &dmnsn_py_CameraType, &camera,
+ &PyList_Type, &objects))
return -1;
- dmnsn_delete_scene(self->scene);
- self->scene = dmnsn_new_scene();
dmnsn_scene_set_canvas(self->scene, canvas->canvas);
+
+ if (!PyObject_CallMethod((PyObject *)camera, "initialize", ""))
+ return -1;
+
+ /* Account for image proportions in camera */
+ dmnsn_matrix stretch = dmnsn_scale_matrix(
+ dmnsn_new_vector(
+ (double)canvas->canvas->width/canvas->canvas->height,
+ 1.0,
+ 1.0
+ )
+ );
+ camera->camera->trans = dmnsn_matrix_mul(camera->camera->trans, stretch);
+ dmnsn_scene_set_camera(self->scene, camera->camera);
+ self->scene->background = dmnsn_white;
+
+ Py_ssize_t size = PyList_Size(objects);
+ for (Py_ssize_t i = 0; i < size; ++i) {
+ PyObject *obj = PyList_GetItem(objects, i);
+ if (!PyObject_TypeCheck(obj, &dmnsn_py_ObjectType)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a list of objects");
+ return -1;
+ }
+
+ if (!PyObject_CallMethod(obj, "initialize", ""))
+ return -1;
+
+ dmnsn_py_Object *object = (dmnsn_py_Object *)obj;
+ dmnsn_scene_add_object(self->scene, object->object);
+ }
+
return 0;
}
@@ -44,7 +79,17 @@ dmnsn_py_Scene_dealloc(dmnsn_py_Scene *self)
Py_TYPE(self)->tp_free((PyObject *)self);
}
+static PyObject *
+dmnsn_py_Scene_raytrace(dmnsn_py_Scene *self)
+{
+ dmnsn_raytrace_scene(self->scene);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
static PyMethodDef dmnsn_py_Scene_methods[] = {
+ { "raytrace", (PyCFunction)dmnsn_py_Scene_raytrace, METH_NOARGS,
+ "Raytrace a scene" },
{ NULL }
};
diff --git a/libdimension-python/Scene.h b/libdimension-python/Scene.h
index d94bd14..bf69326 100644
--- a/libdimension-python/Scene.h
+++ b/libdimension-python/Scene.h
@@ -18,8 +18,6 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension-python.h"
-
typedef struct dmnsn_py_Scene {
PyObject_HEAD
dmnsn_scene *scene;
diff --git a/libdimension-python/Sphere.c b/libdimension-python/Sphere.c
new file mode 100644
index 0000000..c2d5157
--- /dev/null
+++ b/libdimension-python/Sphere.c
@@ -0,0 +1,76 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+#include "dimension-python.h"
+
+static int
+dmnsn_py_Sphere_init(dmnsn_py_Sphere *self, PyObject *args, PyObject *kwds)
+{
+ if (dmnsn_py_ObjectType.tp_init((PyObject *)self, NULL, NULL) < 0)
+ return -1;
+
+ static char *kwlist[] = { "radius", "center", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "dO&", kwlist,
+ &self->radius,
+ &dmnsn_py_VectorParse, &self->center))
+ return -1;
+
+ dmnsn_delete_object(self->base.object);
+ self->base.object = dmnsn_new_sphere();
+ DMNSN_INCREF(self->base.object);
+ return 0;
+}
+
+static PyObject *
+dmnsn_py_Sphere_initialize(dmnsn_py_Sphere *self)
+{
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef dmnsn_py_Sphere_methods[] = {
+ { "initialize", (PyCFunction)dmnsn_py_Sphere_initialize, METH_NOARGS,
+ "Initialize an sphere" },
+ { NULL }
+};
+
+static PyGetSetDef dmnsn_py_Sphere_getsetters[] = {
+ { NULL }
+};
+
+PyTypeObject dmnsn_py_SphereType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "dimension.Sphere",
+ .tp_basicsize = sizeof(dmnsn_py_Sphere),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = "Dimension sphere",
+ .tp_methods = dmnsn_py_Sphere_methods,
+ .tp_getset = dmnsn_py_Sphere_getsetters,
+ .tp_init = (initproc)dmnsn_py_Sphere_init,
+ .tp_base = &dmnsn_py_ObjectType,
+};
+
+bool
+dmnsn_py_init_SphereType(void)
+{
+ dmnsn_py_SphereType.tp_new = PyType_GenericNew;
+ return PyType_Ready(&dmnsn_py_SphereType) >= 0;
+}
diff --git a/libdimension-python/Sphere.h b/libdimension-python/Sphere.h
new file mode 100644
index 0000000..eccd1d0
--- /dev/null
+++ b/libdimension-python/Sphere.h
@@ -0,0 +1,29 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+typedef struct dmnsn_py_Sphere {
+ dmnsn_py_Object base;
+ double radius;
+ dmnsn_vector center;
+} dmnsn_py_Sphere;
+
+extern PyTypeObject dmnsn_py_SphereType;
+
+bool dmnsn_py_init_SphereType(void);
diff --git a/libdimension-python/Vector.c b/libdimension-python/Vector.c
index 6a1928f..67f3397 100644
--- a/libdimension-python/Vector.c
+++ b/libdimension-python/Vector.c
@@ -18,34 +18,37 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "Vector.h"
+#include "dimension-python.h"
-bool
-dmnsn_py_Vector_args(dmnsn_vector *v, PyObject *args, PyObject *kwds)
+int
+dmnsn_py_VectorParse(PyObject *object, void *ptr)
{
- static char *kwlist[] = { "x", "y", "z", NULL };
- if (PyArg_ParseTupleAndKeywords(args, kwds, "ddd", kwlist,
- &v->x, &v->y, &v->z)) {
- return true;
+ dmnsn_vector *res = ptr;
+ if (PyObject_TypeCheck(object, &dmnsn_py_VectorType)) {
+ dmnsn_py_Vector *vec = (dmnsn_py_Vector *)object;
+ *res = vec->v;
+ return 1;
} else {
- if (kwds)
- return false;
-
PyErr_Clear();
-
- dmnsn_py_Vector *vec;
- if (!PyArg_ParseTuple(args, "O!", &dmnsn_py_VectorType, &vec))
- return false;
-
- *v = vec->v;
- return true;
+ if (PyArg_ParseTuple(object, "ddd", &res->x, &res->y, &res->z)) {
+ return 1;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "expected a dimension.Vector");
+ return 0;
+ }
}
}
static int
dmnsn_py_Vector_init(dmnsn_py_Vector *self, PyObject *args, PyObject *kwds)
{
- return dmnsn_py_Vector_args(&self->v, args, kwds) ? 0 : -1;
+ static char *kwlist[] = { "x", "y", "z", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ddd", kwlist,
+ &self->v.x, &self->v.y, &self->v.z))
+ return -1;
+
+ return 0;
}
static PyObject *
@@ -239,15 +242,15 @@ dmnsn_py_Vector_negative(PyObject *rhs)
PyObject *
dmnsn_py_Vector_cross(PyObject *self, PyObject *args)
{
- dmnsn_py_Vector *lhs, *rhs;
- if (!PyArg_ParseTuple(args, "O!O!",
- &dmnsn_py_VectorType, &lhs,
- &dmnsn_py_VectorType, &rhs))
+ dmnsn_vector lhs, rhs;
+ if (!PyArg_ParseTuple(args, "O&O&",
+ &dmnsn_py_VectorParse, &lhs,
+ &dmnsn_py_VectorParse, &rhs))
return NULL;
dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
if (ret) {
- ret->v = dmnsn_vector_cross(lhs->v, rhs->v);
+ ret->v = dmnsn_vector_cross(lhs, rhs);
}
return (PyObject *)ret;
}
@@ -255,27 +258,27 @@ dmnsn_py_Vector_cross(PyObject *self, PyObject *args)
PyObject *
dmnsn_py_Vector_dot(PyObject *self, PyObject *args)
{
- dmnsn_py_Vector *lhs, *rhs;
- if (!PyArg_ParseTuple(args, "O!O!",
- &dmnsn_py_VectorType, &lhs,
- &dmnsn_py_VectorType, &rhs))
+ dmnsn_vector lhs, rhs;
+ if (!PyArg_ParseTuple(args, "O&O&",
+ &dmnsn_py_VectorParse, &lhs,
+ &dmnsn_py_VectorParse, &rhs))
return NULL;
- return PyFloat_FromDouble(dmnsn_vector_dot(lhs->v, rhs->v));
+ return PyFloat_FromDouble(dmnsn_vector_dot(lhs, rhs));
}
PyObject *
dmnsn_py_Vector_proj(PyObject *self, PyObject *args)
{
- dmnsn_py_Vector *u, *d;
- if (!PyArg_ParseTuple(args, "O!O!",
- &dmnsn_py_VectorType, &u,
- &dmnsn_py_VectorType, &d))
+ dmnsn_vector u, d;
+ if (!PyArg_ParseTuple(args, "O&O&",
+ &dmnsn_py_VectorParse, &u,
+ &dmnsn_py_VectorParse, &d))
return NULL;
dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
if (ret) {
- ret->v = dmnsn_vector_proj(u->v, d->v);
+ ret->v = dmnsn_vector_proj(u, d);
}
return (PyObject *)ret;
}
diff --git a/libdimension-python/Vector.h b/libdimension-python/Vector.h
index d7e4e05..89357f2 100644
--- a/libdimension-python/Vector.h
+++ b/libdimension-python/Vector.h
@@ -18,8 +18,6 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension-python.h"
-
typedef struct dmnsn_py_Vector {
PyObject_HEAD
dmnsn_vector v;
@@ -27,7 +25,7 @@ typedef struct dmnsn_py_Vector {
extern PyTypeObject dmnsn_py_VectorType;
-bool dmnsn_py_Vector_args(dmnsn_vector *v, PyObject *args, PyObject *kwds);
+int dmnsn_py_VectorParse(PyObject *object, void *ptr);
bool dmnsn_py_init_VectorType(void);
/* Global methods */
diff --git a/libdimension-python/dimension-python.h b/libdimension-python/dimension-python.h
index f365c2c..41f08c2 100644
--- a/libdimension-python/dimension-python.h
+++ b/libdimension-python/dimension-python.h
@@ -18,6 +18,20 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+#ifndef DMNSN_PYTHON_H
+#define DMNSN_PYTHON_H
+
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "dimension.h"
+#include "Vector.h"
+#include "Matrix.h"
+#include "Color.h"
+#include "Canvas.h"
+#include "Camera.h"
+#include "PerspectiveCamera.h"
+#include "Object.h"
+#include "Sphere.h"
+#include "Scene.h"
+
+#endif /* DMNSN_PYTHON_H */
diff --git a/libdimension-python/dimension.c b/libdimension-python/dimension.c
index 03e2aaa..0ebdab3 100644
--- a/libdimension-python/dimension.c
+++ b/libdimension-python/dimension.c
@@ -19,11 +19,6 @@
*************************************************************************/
#include "dimension-python.h"
-#include "Vector.h"
-#include "Matrix.h"
-#include "Color.h"
-#include "Canvas.h"
-#include "Scene.h"
static PyObject *
dmnsn_py_dieOnWarnings(PyObject *self, PyObject *args)
@@ -50,12 +45,12 @@ static PyMethodDef DimensionMethods[] = {
{ "dot", dmnsn_py_Vector_dot, METH_VARARGS, "Dot product." },
{ "proj", dmnsn_py_Vector_proj, METH_VARARGS, "Vector projection." },
- { "scale", (PyCFunction)dmnsn_py_Matrix_scale,
- METH_VARARGS | METH_KEYWORDS, "Scaling." },
- { "translate", (PyCFunction)dmnsn_py_Matrix_translate,
- METH_VARARGS | METH_KEYWORDS, "Translation." },
- { "rotate", (PyCFunction)dmnsn_py_Matrix_rotate,
- METH_VARARGS | METH_KEYWORDS, "Rotation." },
+ { "scale", (PyCFunction)dmnsn_py_Matrix_scale, METH_VARARGS,
+ "Scaling." },
+ { "translate", (PyCFunction)dmnsn_py_Matrix_translate, METH_VARARGS,
+ "Translation." },
+ { "rotate", (PyCFunction)dmnsn_py_Matrix_rotate, METH_VARARGS,
+ "Rotation." },
{ NULL, NULL, 0, NULL }
};
@@ -75,6 +70,10 @@ PyInit_dimension(void)
|| !dmnsn_py_init_MatrixType()
|| !dmnsn_py_init_ColorType()
|| !dmnsn_py_init_CanvasType()
+ || !dmnsn_py_init_CameraType()
+ || !dmnsn_py_init_PerspectiveCameraType()
+ || !dmnsn_py_init_ObjectType()
+ || !dmnsn_py_init_SphereType()
|| !dmnsn_py_init_SceneType())
return NULL;
@@ -108,6 +107,13 @@ PyInit_dimension(void)
PyModule_AddObject(module, "Canvas", (PyObject *)&dmnsn_py_CanvasType);
+ PyModule_AddObject(module, "Camera", (PyObject *)&dmnsn_py_CanvasType);
+ PyModule_AddObject(module, "PerspectiveCamera",
+ (PyObject *)&dmnsn_py_PerspectiveCameraType);
+
+ PyModule_AddObject(module, "Object", (PyObject *)&dmnsn_py_ObjectType);
+ PyModule_AddObject(module, "Sphere", (PyObject *)&dmnsn_py_SphereType);
+
PyModule_AddObject(module, "Scene", (PyObject *)&dmnsn_py_SceneType);
return module;
diff --git a/libdimension-python/tests/demo.py b/libdimension-python/tests/demo.py
index 187f4ef..982fa60 100755
--- a/libdimension-python/tests/demo.py
+++ b/libdimension-python/tests/demo.py
@@ -35,4 +35,18 @@ except OSError as e:
else:
raise
-scene = Scene(canvas = canvas)
+camera = PerspectiveCamera(location = (0, 0.25, -4),
+ look_at = Zero)
+camera.transform(rotate(53*Y))
+
+objects = []
+
+sphere = Sphere(radius = 1, center = Zero)
+objects.append(sphere)
+
+scene = Scene(canvas = canvas,
+ camera = camera,
+ objects = objects)
+scene.raytrace()
+
+canvas.writePNG('demo.png')
diff --git a/libdimension-python/tests/geometry.py b/libdimension-python/tests/geometry.py
index 9c79ef5..0c53ad6 100755
--- a/libdimension-python/tests/geometry.py
+++ b/libdimension-python/tests/geometry.py
@@ -63,12 +63,12 @@ assert str(m) == '\n' \
'[9.0\t10.0\t11.0\t12.0]\n' \
'[0.0\t0.0\t0.0\t1.0]', str(m)
-s = scale(1, 2, 3)
+s = scale(Vector(1, 2, 3))
assert s == Matrix(1, 0, 0, 0,
0, 2, 0, 0,
0, 0, 3, 0), s
-t = translate(x = 1, y = 2, z = 3)
+t = translate((1, 2, 3))
assert t == Matrix(1, 0, 0, 1,
0, 1, 0, 2,
0, 0, 1, 3), t