Some generic modules from blender 2.4x building with py3k and mostly working.
authorCampbell Barton <ideasman42@gmail.com>
Wed, 17 Jun 2009 20:33:34 +0000 (20:33 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 17 Jun 2009 20:33:34 +0000 (20:33 +0000)
* Mathutils, Geometry, BGL, Mostly working, some //XXX comments for things to fix with py3

python import override (bpy_internal_import.c) so you can import python internal scripts from the BGE and running blender normally.

20 files changed:
source/blender/python/SConscript
source/blender/python/generic/BGL.c [new file with mode: 0644]
source/blender/python/generic/BGL.h [new file with mode: 0755]
source/blender/python/generic/Geometry.c [new file with mode: 0644]
source/blender/python/generic/Geometry.h [new file with mode: 0644]
source/blender/python/generic/Mathutils.c [new file with mode: 0644]
source/blender/python/generic/Mathutils.h [new file with mode: 0644]
source/blender/python/generic/bpy_internal_import.c [new file with mode: 0644]
source/blender/python/generic/bpy_internal_import.h [new file with mode: 0644]
source/blender/python/generic/euler.c [new file with mode: 0644]
source/blender/python/generic/euler.h [new file with mode: 0644]
source/blender/python/generic/matrix.c [new file with mode: 0644]
source/blender/python/generic/matrix.h [new file with mode: 0644]
source/blender/python/generic/quat.c [new file with mode: 0644]
source/blender/python/generic/quat.h [new file with mode: 0644]
source/blender/python/generic/vector.c [new file with mode: 0644]
source/blender/python/generic/vector.h [new file with mode: 0644]
source/blender/python/intern/bpy_interface.c
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/SConscript

index 9d7fcf6a9cf049cf6d6557c278880837ded48d7b..93b23a9c4cfa8688df3f9b2335340e85db258edd 100644 (file)
@@ -15,3 +15,7 @@ if env['OURPLATFORM'] in ('win32-mingw', 'win32-vc') and env['BF_DEBUG']:
 
 env.BlenderLib( libname = 'bf_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [140])
 
+
+# generic  XXX todo, BGE currently uses these externally
+# sources = env.Glob('generic/*.c')
+# env.BlenderLib( libname = 'bf_gen_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [140])
diff --git a/source/blender/python/generic/BGL.c b/source/blender/python/generic/BGL.c
new file mode 100644 (file)
index 0000000..f1a7227
--- /dev/null
@@ -0,0 +1,1605 @@
+/* 
+ * $Id: BGL.c 20922 2009-06-16 07:16:51Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+/* This file is the Blender.BGL part of opy_draw.c, from the old
+ * bpython/intern dir, with minor changes to adapt it to the new Python
+ * implementation.  The BGL submodule "wraps" OpenGL functions and constants,
+ * allowing script writers to make OpenGL calls in their Python scripts. */
+
+#include "BGL.h" /*This must come first */
+
+#include "MEM_guardedalloc.h"
+
+static int type_size( int type );
+static Buffer *make_buffer( int type, int ndimensions, int *dimensions );
+
+static char Method_Buffer_doc[] =
+       "(type, dimensions, [template]) - Create a new Buffer object\n\n\
+(type) - The format to store data in\n\
+(dimensions) - An int or sequence specifying the dimensions of the buffer\n\
+[template] - A sequence of matching dimensions to the buffer to be created\n\
+  which will be used to initialize the Buffer.\n\n\
+If a template is not passed in all fields will be initialized to 0.\n\n\
+The type should be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, or GL_DOUBLE.\n\
+If the dimensions are specified as an int a linear buffer will be\n\
+created. If a sequence is passed for the dimensions the buffer\n\
+will have len(sequence) dimensions, where the size for each dimension\n\
+is determined by the value in the sequence at that index.\n\n\
+For example, passing [100, 100] will create a 2 dimensional\n\
+square buffer. Passing [16, 16, 32] will create a 3 dimensional\n\
+buffer which is twice as deep as it is wide or high.";
+
+static PyObject *Method_Buffer( PyObject * self, PyObject * args );
+
+/* Buffer sequence methods */
+
+static int Buffer_len( PyObject * self );
+static PyObject *Buffer_item( PyObject * self, int i );
+static PyObject *Buffer_slice( PyObject * self, int begin, int end );
+static int Buffer_ass_item( PyObject * self, int i, PyObject * v );
+static int Buffer_ass_slice( PyObject * self, int begin, int end,
+                            PyObject * seq );
+
+static PySequenceMethods Buffer_SeqMethods = {
+       ( inquiry ) Buffer_len, /*sq_length */
+       ( binaryfunc ) 0,       /*sq_concat */
+       ( ssizeargfunc ) 0,     /*sq_repeat */
+       ( ssizeargfunc ) Buffer_item,   /*sq_item */
+       ( ssizessizeargfunc ) Buffer_slice,     /*sq_slice */
+       ( ssizeobjargproc ) Buffer_ass_item,    /*sq_ass_item */
+       ( ssizessizeobjargproc ) Buffer_ass_slice,      /*sq_ass_slice */
+};
+
+static void Buffer_dealloc( PyObject * self );
+static PyObject *Buffer_tolist( PyObject * self );
+static PyObject *Buffer_dimensions( PyObject * self );
+static PyObject *Buffer_getattr( PyObject * self, char *name );
+static PyObject *Buffer_repr( PyObject * self );
+
+PyTypeObject buffer_Type = {
+       PyObject_HEAD_INIT( NULL )      /* required python macro */
+       0,      /*ob_size */
+       "buffer",               /*tp_name */
+       sizeof( Buffer ),       /*tp_basicsize */
+       0,                      /*tp_itemsize */
+       ( destructor ) Buffer_dealloc,  /*tp_dealloc */
+       ( printfunc ) 0,        /*tp_print */
+       ( getattrfunc ) Buffer_getattr, /*tp_getattr */
+       ( setattrfunc ) 0,      /*tp_setattr */
+       0,              /*tp_compare */
+       ( reprfunc ) Buffer_repr,       /*tp_repr */
+       0,                      /*tp_as_number */
+       &Buffer_SeqMethods,     /*tp_as_sequence */
+};
+
+/* #ifndef __APPLE__ */
+
+#define BGL_Wrap(nargs, funcname, ret, arg_list) \
+static PyObject *Method_##funcname (PyObject *self, PyObject *args) {\
+       arg_def##nargs arg_list; \
+       ret_def_##ret; \
+       if(!PyArg_ParseTuple(args, arg_str##nargs arg_list, arg_ref##nargs arg_list)) return NULL;\
+       ret_set_##ret gl##funcname (arg_var##nargs arg_list);\
+       ret_ret_##ret; \
+}
+
+#define BGLU_Wrap(nargs, funcname, ret, arg_list) \
+static PyObject *Method_##funcname (PyObject *self, PyObject *args) {\
+       arg_def##nargs arg_list; \
+       ret_def_##ret; \
+       if(!PyArg_ParseTuple(args, arg_str##nargs arg_list, arg_ref##nargs arg_list)) return NULL;\
+       ret_set_##ret glu##funcname (arg_var##nargs arg_list);\
+       ret_ret_##ret; \
+}
+
+/* #endif */
+
+/********/
+static int type_size(int type)
+{
+       switch (type) {
+               case GL_BYTE: 
+                 return sizeof(char);
+               case GL_SHORT: 
+                 return sizeof(short);
+               case GL_INT: 
+                 return sizeof(int);
+               case GL_FLOAT: 
+                 return sizeof(float);
+               case GL_DOUBLE:
+                 return sizeof(double);
+       }
+       return -1;
+}
+
+static Buffer *make_buffer(int type, int ndimensions, int *dimensions)
+{
+       Buffer *buffer;
+       void *buf= NULL;
+       int i, size, length;
+       length= 1;
+       for (i=0; i<ndimensions; i++) 
+               length*= dimensions[i];
+       size= type_size(type);
+       buf= MEM_mallocN(length*size, "Buffer buffer");
+       buffer= (Buffer *) PyObject_NEW(Buffer, &buffer_Type);
+       buffer->parent= NULL;
+       buffer->ndimensions= ndimensions;
+       buffer->dimensions= dimensions;
+       buffer->type= type;
+       buffer->buf.asvoid= buf;
+       for (i= 0; i<length; i++) {
+               if (type==GL_BYTE) 
+                       buffer->buf.asbyte[i]= 0;
+               else if (type==GL_SHORT) 
+                       buffer->buf.asshort[i]= 0;
+               else if (type==GL_INT) 
+                       buffer->buf.asint[i]= 0;
+               else if (type==GL_FLOAT) 
+                   buffer->buf.asfloat[i]= 0.0f;
+               else if (type==GL_DOUBLE)
+                       buffer->buf.asdouble[i]= 0.0;
+       }
+       return buffer;
+}
+
+static PyObject *Method_Buffer (PyObject *self, PyObject *args)
+{
+       PyObject *length_ob= NULL, *template= NULL;
+       Buffer *buffer;
+       
+       int i, type;
+       int *dimensions = 0, ndimensions = 0;
+       
+       if (!PyArg_ParseTuple(args, "iO|O", &type, &length_ob, &template)) {
+               PyErr_SetString(PyExc_AttributeError, "expected an int and one or two PyObjects");
+               return NULL;
+       }
+       if (type!=GL_BYTE && type!=GL_SHORT && type!=GL_INT && type!=GL_FLOAT && type!=GL_DOUBLE) {
+               PyErr_SetString(PyExc_AttributeError, "invalid first argument type, should be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE");
+               return NULL;
+       }
+
+       if (PyNumber_Check(length_ob)) {
+               ndimensions= 1;
+               dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions");
+               dimensions[0]= PyLong_AsLong(length_ob);
+       } else if (PySequence_Check(length_ob)) {
+               ndimensions= PySequence_Length(length_ob);
+               dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions");
+               for (i=0; i<ndimensions; i++) {
+                       PyObject *ob= PySequence_GetItem(length_ob, i);
+
+                       if (!PyNumber_Check(ob)) dimensions[i]= 1;
+                       else dimensions[i]= PyLong_AsLong(ob);
+                       Py_DECREF(ob);
+               }
+       }
+       
+       buffer= make_buffer(type, ndimensions, dimensions);
+       if (template && ndimensions) {
+               if (Buffer_ass_slice((PyObject *) buffer, 0, dimensions[0], template)) {
+                       Py_DECREF(buffer);
+                       return NULL;
+               }
+       }
+       
+       return (PyObject *) buffer;
+}
+
+/*@ Buffer sequence methods */
+
+static int Buffer_len(PyObject *self)
+{
+       Buffer *buf= (Buffer *) self;
+       return buf->dimensions[0];
+}
+
+static PyObject *Buffer_item(PyObject *self, int i)
+{
+       Buffer *buf= (Buffer *) self;
+
+       if (i >= buf->dimensions[0]) {
+               PyErr_SetString(PyExc_IndexError, "array index out of range");
+               return NULL;
+       }
+
+       if (buf->ndimensions==1) {
+               switch (buf->type) {
+                       case GL_BYTE: return Py_BuildValue("b", buf->buf.asbyte[i]);
+                       case GL_SHORT: return Py_BuildValue("h", buf->buf.asshort[i]);
+                       case GL_INT: return Py_BuildValue("i", buf->buf.asint[i]);
+                       case GL_FLOAT: return PyFloat_FromDouble(buf->buf.asfloat[i]);
+                       case GL_DOUBLE: return Py_BuildValue("d", buf->buf.asdouble[i]);
+               }
+       } else {
+               Buffer *newbuf;
+               int j, length, size;
+               length= 1;
+               for (j=1; j<buf->ndimensions; j++) {
+                       length*= buf->dimensions[j];
+               }
+               size= type_size(buf->type);
+
+               newbuf= (Buffer *) PyObject_NEW(Buffer, &buffer_Type);
+    
+               Py_INCREF(self);
+               newbuf->parent= self;
+
+               newbuf->ndimensions= buf->ndimensions-1;
+               newbuf->type= buf->type;
+               newbuf->buf.asvoid= buf->buf.asbyte + i*length*size;
+               newbuf->dimensions= MEM_mallocN(newbuf->ndimensions*sizeof(int),
+                       "Buffer dimensions");
+               memcpy(newbuf->dimensions, buf->dimensions+1,
+                       newbuf->ndimensions*sizeof(int));
+
+               return (PyObject *) newbuf;
+       }
+  
+       return NULL;
+}
+
+static PyObject *Buffer_slice(PyObject *self, int begin, int end)
+{
+       Buffer *buf= (Buffer *) self;
+       PyObject *list;
+       int count;
+       
+       if (begin<0) begin= 0;
+       if (end>buf->dimensions[0]) 
+               end= buf->dimensions[0];
+       if (begin>end) begin= end;
+         
+       list= PyList_New(end-begin);
+
+       for (count= begin; count<end; count++)
+               PyList_SetItem(list, count-begin, Buffer_item(self, count));
+       
+       return list;
+}
+
+static int Buffer_ass_item(PyObject *self, int i, PyObject *v)
+{
+       Buffer *buf= (Buffer *) self;
+       
+       if (i >= buf->dimensions[0]) {
+               PyErr_SetString(PyExc_IndexError, "array assignment index out of range");
+               return -1;
+       }
+       
+       if (buf->ndimensions!=1) {
+               PyObject *row= Buffer_item(self, i);
+               int ret;
+
+               if (!row) return -1;
+               ret= Buffer_ass_slice(row, 0, buf->dimensions[1], v);
+               Py_DECREF(row);
+               return ret;
+       }
+
+       if (buf->type==GL_BYTE) {
+               if (!PyArg_Parse(v, "b;Coordinates must be ints", &buf->buf.asbyte[i]))
+               return -1;
+       } else if (buf->type==GL_SHORT) {
+               if (!PyArg_Parse(v, "h;Coordinates must be ints", &buf->buf.asshort[i]))
+                       return -1;
+         
+       } else if (buf->type==GL_INT) {
+               if (!PyArg_Parse(v, "i;Coordinates must be ints", &buf->buf.asint[i]))
+                       return -1;
+       } else if (buf->type==GL_FLOAT) {
+               if (!PyArg_Parse(v, "f;Coordinates must be floats", &buf->buf.asfloat[i]))
+                       return -1;
+       } else if (buf->type==GL_DOUBLE) {
+               if (!PyArg_Parse(v, "d;Coordinates must be floats", &buf->buf.asdouble[i]))
+                       return -1;
+       }
+       return 0;
+}
+
+static int Buffer_ass_slice(PyObject *self, int begin, int end, PyObject *seq)
+{
+       Buffer *buf= (Buffer *) self;
+       PyObject *item;
+       int count, err=0;
+       
+       if (begin<0) begin= 0;
+       if (end>buf->dimensions[0]) end= buf->dimensions[0];
+       if (begin>end) begin= end;
+       
+       if (!PySequence_Check(seq)) {
+               PyErr_SetString(PyExc_TypeError,
+                       "illegal argument type for built-in operation");
+               return -1;
+       }
+
+       if (PySequence_Length(seq)!=(end-begin)) {
+               PyErr_SetString(PyExc_TypeError, "size mismatch in assignment");
+               return -1;
+       }
+       
+       for (count= begin; count<end; count++) {
+               item= PySequence_GetItem(seq, count-begin);
+               err= Buffer_ass_item(self, count, item);
+               Py_DECREF(item);
+               if (err) break;
+       }
+       return err;
+}
+
+static void Buffer_dealloc(PyObject *self)
+{
+       Buffer *buf = (Buffer *)self;
+
+       if (buf->parent) Py_DECREF (buf->parent);
+       else MEM_freeN (buf->buf.asvoid);
+
+       MEM_freeN (buf->dimensions);
+       
+       PyObject_DEL (self);
+}
+
+static PyObject *Buffer_tolist(PyObject *self)
+{
+       int i, len= ((Buffer *)self)->dimensions[0];
+       PyObject *list= PyList_New(len);
+       
+       for (i=0; i<len; i++) {
+         PyList_SetItem(list, i, Buffer_item(self, i));
+       }
+       
+       return list;
+}
+
+static PyObject *Buffer_dimensions(PyObject *self)
+{
+       Buffer *buffer= (Buffer *) self;
+       PyObject *list= PyList_New(buffer->ndimensions);
+       int i;
+         
+       for (i= 0; i<buffer->ndimensions; i++) {
+         PyList_SetItem(list, i, PyLong_FromLong(buffer->dimensions[i]));
+       }
+       
+       return list;
+}
+
+static PyObject *Buffer_getattr(PyObject *self, char *name)
+{
+       if (strcmp(name, "list")==0) return Buffer_tolist(self);
+       else if (strcmp(name, "dimensions")==0) return Buffer_dimensions(self);
+       
+       PyErr_SetString(PyExc_AttributeError, name);
+       return NULL;
+}
+
+static PyObject *Buffer_repr(PyObject *self)
+{
+       PyObject *list= Buffer_tolist(self);
+       PyObject *repr= PyObject_Repr(list);
+       Py_DECREF(list);
+       
+       return repr;
+}
+
+
+BGL_Wrap(2, Accum,          void,     (GLenum, GLfloat))
+BGL_Wrap(2, AlphaFunc,      void,     (GLenum, GLclampf))
+BGL_Wrap(3, AreTexturesResident,  GLboolean,  (GLsizei, GLuintP, GLbooleanP))
+BGL_Wrap(1, Begin,          void,     (GLenum))
+BGL_Wrap(2, BindTexture,    void,   (GLenum, GLuint))
+BGL_Wrap(7, Bitmap,         void,     (GLsizei, GLsizei, GLfloat,
+                        GLfloat, GLfloat, GLfloat, GLubyteP))
+BGL_Wrap(2, BlendFunc,        void,     (GLenum, GLenum))
+BGL_Wrap(1, CallList,         void,     (GLuint))
+BGL_Wrap(3, CallLists,        void,     (GLsizei, GLenum, GLvoidP))
+BGL_Wrap(1, Clear,            void,     (GLbitfield))
+BGL_Wrap(4, ClearAccum,       void,     (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(4, ClearColor,       void,     (GLclampf, GLclampf, GLclampf, GLclampf))
+BGL_Wrap(1, ClearDepth,       void,     (GLclampd))
+BGL_Wrap(1, ClearIndex,       void,     (GLfloat))
+BGL_Wrap(1, ClearStencil,     void,     (GLint))
+BGL_Wrap(2, ClipPlane,        void,     (GLenum, GLdoubleP))
+BGL_Wrap(3, Color3b,          void,     (GLbyte, GLbyte, GLbyte))
+BGL_Wrap(1, Color3bv,         void,     (GLbyteP))
+BGL_Wrap(3, Color3d,          void,     (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Color3dv,         void,     (GLdoubleP))
+BGL_Wrap(3, Color3f,          void,     (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Color3fv,         void,     (GLfloatP))
+BGL_Wrap(3, Color3i,          void,     (GLint, GLint, GLint))
+BGL_Wrap(1, Color3iv,         void,     (GLintP))
+BGL_Wrap(3, Color3s,          void,     (GLshort, GLshort, GLshort))
+BGL_Wrap(1, Color3sv,         void,     (GLshortP))
+BGL_Wrap(3, Color3ub,         void,     (GLubyte, GLubyte, GLubyte))
+BGL_Wrap(1, Color3ubv,        void,     (GLubyteP))
+BGL_Wrap(3, Color3ui,         void,     (GLuint, GLuint, GLuint))
+BGL_Wrap(1, Color3uiv,        void,     (GLuintP))
+BGL_Wrap(3, Color3us,         void,     (GLushort, GLushort, GLushort))
+BGL_Wrap(1, Color3usv,        void,     (GLushortP))
+BGL_Wrap(4, Color4b,          void,     (GLbyte, GLbyte, GLbyte, GLbyte))
+BGL_Wrap(1, Color4bv,         void,     (GLbyteP))
+BGL_Wrap(4, Color4d,          void,     (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Color4dv,         void,     (GLdoubleP))
+BGL_Wrap(4, Color4f,          void,     (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Color4fv,         void,     (GLfloatP))
+BGL_Wrap(4, Color4i,          void,     (GLint, GLint, GLint, GLint))
+BGL_Wrap(1, Color4iv,         void,     (GLintP))
+BGL_Wrap(4, Color4s,          void,     (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(1, Color4sv,         void,     (GLshortP))
+BGL_Wrap(4, Color4ub,         void,     (GLubyte, GLubyte, GLubyte, GLubyte))
+BGL_Wrap(1, Color4ubv,        void,     (GLubyteP))
+BGL_Wrap(4, Color4ui,         void,     (GLuint, GLuint, GLuint, GLuint))
+BGL_Wrap(1, Color4uiv,        void,     (GLuintP))
+BGL_Wrap(4, Color4us,         void,     (GLushort, GLushort, GLushort, GLushort))
+BGL_Wrap(1, Color4usv,        void,     (GLushortP))
+BGL_Wrap(4, ColorMask,        void,     (GLboolean, GLboolean, GLboolean, GLboolean))
+BGL_Wrap(2, ColorMaterial,    void,     (GLenum, GLenum))
+BGL_Wrap(5, CopyPixels,       void,     (GLint, GLint, GLsizei, GLsizei, GLenum))
+BGL_Wrap(1, CullFace,         void,     (GLenum))
+BGL_Wrap(2, DeleteLists,      void,     (GLuint, GLsizei))
+BGL_Wrap(2, DeleteTextures,   void,   (GLsizei, GLuintP))
+BGL_Wrap(1, DepthFunc,        void,     (GLenum))
+BGL_Wrap(1, DepthMask,        void,     (GLboolean))
+BGL_Wrap(2, DepthRange,       void,     (GLclampd, GLclampd))
+BGL_Wrap(1, Disable,          void,     (GLenum))
+BGL_Wrap(1, DrawBuffer,       void,     (GLenum))
+BGL_Wrap(5, DrawPixels,       void,     (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(1, EdgeFlag,         void,     (GLboolean))
+BGL_Wrap(1, EdgeFlagv,        void,     (GLbooleanP))
+BGL_Wrap(1, Enable,           void,     (GLenum))
+BGL_Wrap(1, End,              void,     (void))
+BGL_Wrap(1, EndList,          void,     (void))
+BGL_Wrap(1, EvalCoord1d,      void,     (GLdouble))
+BGL_Wrap(1, EvalCoord1dv,     void,     (GLdoubleP))
+BGL_Wrap(1, EvalCoord1f,      void,     (GLfloat))
+BGL_Wrap(1, EvalCoord1fv,     void,     (GLfloatP))
+BGL_Wrap(2, EvalCoord2d,      void,     (GLdouble, GLdouble))
+BGL_Wrap(1, EvalCoord2dv,     void,     (GLdoubleP))
+BGL_Wrap(2, EvalCoord2f,      void,     (GLfloat, GLfloat))
+BGL_Wrap(1, EvalCoord2fv,     void,     (GLfloatP))
+BGL_Wrap(3, EvalMesh1,        void,     (GLenum, GLint, GLint))
+BGL_Wrap(5, EvalMesh2,        void,     (GLenum, GLint, GLint, GLint, GLint))
+BGL_Wrap(1, EvalPoint1,       void,     (GLint))
+BGL_Wrap(2, EvalPoint2,       void,     (GLint, GLint))
+BGL_Wrap(3, FeedbackBuffer,   void,     (GLsizei, GLenum, GLfloatP))
+BGL_Wrap(1, Finish,           void,     (void))
+BGL_Wrap(1, Flush,            void,     (void))
+BGL_Wrap(2, Fogf,             void,     (GLenum, GLfloat))
+BGL_Wrap(2, Fogfv,            void,     (GLenum, GLfloatP))
+BGL_Wrap(2, Fogi,             void,     (GLenum, GLint))
+BGL_Wrap(2, Fogiv,            void,     (GLenum, GLintP))
+BGL_Wrap(1, FrontFace,        void,     (GLenum))
+BGL_Wrap(6, Frustum,          void,     (GLdouble, GLdouble,
+                        GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, GenLists,         GLuint,   (GLsizei))
+BGL_Wrap(2, GenTextures,      void,   (GLsizei, GLuintP))
+BGL_Wrap(2, GetBooleanv,      void,     (GLenum, GLbooleanP))
+BGL_Wrap(2, GetClipPlane,     void,     (GLenum, GLdoubleP))
+BGL_Wrap(2, GetDoublev,       void,     (GLenum, GLdoubleP))
+BGL_Wrap(1, GetError,         GLenum,   (void))
+BGL_Wrap(2, GetFloatv,        void,     (GLenum, GLfloatP))
+BGL_Wrap(2, GetIntegerv,      void,     (GLenum, GLintP))
+BGL_Wrap(3, GetLightfv,       void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetLightiv,       void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(3, GetMapdv,         void,     (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(3, GetMapfv,         void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetMapiv,         void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(3, GetMaterialfv,    void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetMaterialiv,    void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(2, GetPixelMapfv,    void,     (GLenum, GLfloatP))
+BGL_Wrap(2, GetPixelMapuiv,   void,     (GLenum, GLuintP))
+BGL_Wrap(2, GetPixelMapusv,   void,     (GLenum, GLushortP))
+BGL_Wrap(1, GetPolygonStipple,void,     (GLubyteP))
+BGL_Wrap(1, GetString,        GLstring,   (GLenum))
+BGL_Wrap(3, GetTexEnvfv,      void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetTexEnviv,      void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(3, GetTexGendv,      void,     (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(3, GetTexGenfv,      void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetTexGeniv,      void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(5, GetTexImage,      void,     (GLenum, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(4, GetTexLevelParameterfv, void,     (GLenum, GLint, GLenum, GLfloatP))
+BGL_Wrap(4, GetTexLevelParameteriv, void,     (GLenum, GLint, GLenum, GLintP))
+BGL_Wrap(3, GetTexParameterfv,    void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, GetTexParameteriv,    void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(2, Hint,           void,     (GLenum, GLenum))
+BGL_Wrap(1, IndexMask,      void,     (GLuint))
+BGL_Wrap(1, Indexd,         void,     (GLdouble))
+BGL_Wrap(1, Indexdv,        void,     (GLdoubleP))
+BGL_Wrap(1, Indexf,         void,     (GLfloat))
+BGL_Wrap(1, Indexfv,        void,     (GLfloatP))
+BGL_Wrap(1, Indexi,         void,     (GLint))
+BGL_Wrap(1, Indexiv,        void,     (GLintP))
+BGL_Wrap(1, Indexs,         void,     (GLshort))
+BGL_Wrap(1, Indexsv,        void,     (GLshortP))
+BGL_Wrap(1, InitNames,      void,     (void))
+BGL_Wrap(1, IsEnabled,      GLboolean,  (GLenum))
+BGL_Wrap(1, IsList,         GLboolean,  (GLuint))
+BGL_Wrap(1, IsTexture,      GLboolean,  (GLuint))
+BGL_Wrap(2, LightModelf,    void,     (GLenum, GLfloat))
+BGL_Wrap(2, LightModelfv,   void,     (GLenum, GLfloatP))
+BGL_Wrap(2, LightModeli,    void,     (GLenum, GLint))
+BGL_Wrap(2, LightModeliv,   void,     (GLenum, GLintP))
+BGL_Wrap(3, Lightf,         void,     (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, Lightfv,        void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, Lighti,         void,     (GLenum, GLenum, GLint))
+BGL_Wrap(3, Lightiv,        void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(2, LineStipple,    void,     (GLint, GLushort))
+BGL_Wrap(1, LineWidth,      void,     (GLfloat))
+BGL_Wrap(1, ListBase,       void,     (GLuint))
+BGL_Wrap(1, LoadIdentity,   void,     (void))
+BGL_Wrap(1, LoadMatrixd,    void,     (GLdoubleP))
+BGL_Wrap(1, LoadMatrixf,    void,     (GLfloatP))
+BGL_Wrap(1, LoadName,       void,     (GLuint))
+BGL_Wrap(1, LogicOp,        void,     (GLenum))
+BGL_Wrap(6, Map1d,          void,     (GLenum, GLdouble, GLdouble,
+                        GLint, GLint, GLdoubleP))
+BGL_Wrap(6, Map1f,          void,     (GLenum, GLfloat, GLfloat,
+                        GLint, GLint, GLfloatP))
+BGL_Wrap(10, Map2d,         void,     (GLenum, GLdouble, GLdouble,
+                        GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
+BGL_Wrap(10, Map2f,         void,     (GLenum, GLfloat, GLfloat,
+                        GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP))
+BGL_Wrap(3, MapGrid1d,        void,     (GLint, GLdouble, GLdouble))
+BGL_Wrap(3, MapGrid1f,        void,     (GLint, GLfloat, GLfloat))
+BGL_Wrap(6, MapGrid2d,        void,     (GLint, GLdouble, GLdouble,
+                        GLint, GLdouble, GLdouble))
+BGL_Wrap(6, MapGrid2f,        void,     (GLint, GLfloat, GLfloat,
+                        GLint, GLfloat, GLfloat))
+BGL_Wrap(3, Materialf,        void,     (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, Materialfv,       void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, Materiali,        void,     (GLenum, GLenum, GLint))
+BGL_Wrap(3, Materialiv,       void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(1, MatrixMode,       void,     (GLenum))
+BGL_Wrap(1, MultMatrixd,      void,     (GLdoubleP))
+BGL_Wrap(1, MultMatrixf,      void,     (GLfloatP))
+BGL_Wrap(2, NewList,          void,     (GLuint, GLenum))
+BGL_Wrap(3, Normal3b,         void,     (GLbyte, GLbyte, GLbyte))
+BGL_Wrap(1, Normal3bv,        void,     (GLbyteP))
+BGL_Wrap(3, Normal3d,         void,     (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Normal3dv,        void,     (GLdoubleP))
+BGL_Wrap(3, Normal3f,         void,     (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Normal3fv,        void,     (GLfloatP))
+BGL_Wrap(3, Normal3i,         void,     (GLint, GLint, GLint))
+BGL_Wrap(1, Normal3iv,        void,     (GLintP))
+BGL_Wrap(3, Normal3s,         void,     (GLshort, GLshort, GLshort))
+BGL_Wrap(1, Normal3sv,        void,     (GLshortP))
+BGL_Wrap(6, Ortho,            void,     (GLdouble, GLdouble,
+                        GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, PassThrough,      void,     (GLfloat))
+BGL_Wrap(3, PixelMapfv,       void,     (GLenum, GLint, GLfloatP))
+BGL_Wrap(3, PixelMapuiv,      void,     (GLenum, GLint, GLuintP))
+BGL_Wrap(3, PixelMapusv,      void,     (GLenum, GLint, GLushortP))
+BGL_Wrap(2, PixelStoref,      void,     (GLenum, GLfloat))
+BGL_Wrap(2, PixelStorei,      void,     (GLenum, GLint))
+BGL_Wrap(2, PixelTransferf,   void,     (GLenum, GLfloat))
+BGL_Wrap(2, PixelTransferi,   void,     (GLenum, GLint))
+BGL_Wrap(2, PixelZoom,        void,     (GLfloat, GLfloat))
+BGL_Wrap(1, PointSize,        void,     (GLfloat))
+BGL_Wrap(2, PolygonMode,      void,     (GLenum, GLenum))
+BGL_Wrap(2, PolygonOffset,    void,     (GLfloat, GLfloat))
+BGL_Wrap(1, PolygonStipple,   void,     (GLubyteP))
+BGL_Wrap(1, PopAttrib,        void,     (void))
+BGL_Wrap(1, PopClientAttrib,  void,     (void))
+BGL_Wrap(1, PopMatrix,        void,     (void))
+BGL_Wrap(1, PopName,          void,     (void))
+BGL_Wrap(3, PrioritizeTextures,   void,   (GLsizei, GLuintP, GLclampfP))
+BGL_Wrap(1, PushAttrib,       void,     (GLbitfield))
+BGL_Wrap(1, PushClientAttrib, void,     (GLbitfield))
+BGL_Wrap(1, PushMatrix,       void,     (void))
+BGL_Wrap(1, PushName,         void,     (GLuint))
+BGL_Wrap(2, RasterPos2d,      void,     (GLdouble, GLdouble))
+BGL_Wrap(1, RasterPos2dv,     void,     (GLdoubleP))
+BGL_Wrap(2, RasterPos2f,      void,     (GLfloat, GLfloat))
+BGL_Wrap(1, RasterPos2fv,     void,     (GLfloatP))
+BGL_Wrap(2, RasterPos2i,      void,     (GLint, GLint))
+BGL_Wrap(1, RasterPos2iv,     void,     (GLintP))
+BGL_Wrap(2, RasterPos2s,      void,     (GLshort, GLshort))
+BGL_Wrap(1, RasterPos2sv,     void,     (GLshortP))
+BGL_Wrap(3, RasterPos3d,      void,     (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, RasterPos3dv,     void,     (GLdoubleP))
+BGL_Wrap(3, RasterPos3f,      void,     (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, RasterPos3fv,     void,     (GLfloatP))
+BGL_Wrap(3, RasterPos3i,      void,     (GLint, GLint, GLint))
+BGL_Wrap(1, RasterPos3iv,     void,     (GLintP))
+BGL_Wrap(3, RasterPos3s,      void,     (GLshort, GLshort, GLshort))
+BGL_Wrap(1, RasterPos3sv,     void,     (GLshortP))
+BGL_Wrap(4, RasterPos4d,      void,     (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, RasterPos4dv,     void,     (GLdoubleP))
+BGL_Wrap(4, RasterPos4f,      void,     (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, RasterPos4fv,     void,     (GLfloatP))
+BGL_Wrap(4, RasterPos4i,      void,     (GLint, GLint, GLint, GLint))
+BGL_Wrap(1, RasterPos4iv,     void,     (GLintP))
+BGL_Wrap(4, RasterPos4s,      void,     (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(1, RasterPos4sv,     void,     (GLshortP))
+BGL_Wrap(1, ReadBuffer,       void,     (GLenum))
+BGL_Wrap(7, ReadPixels,       void,     (GLint, GLint, GLsizei,
+                        GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(4, Rectd,          void,     (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(2, Rectdv,         void,     (GLdoubleP, GLdoubleP))
+BGL_Wrap(4, Rectf,          void,     (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(2, Rectfv,         void,     (GLfloatP, GLfloatP))
+BGL_Wrap(4, Recti,          void,     (GLint, GLint, GLint, GLint))
+BGL_Wrap(2, Rectiv,         void,     (GLintP, GLintP))
+BGL_Wrap(4, Rects,          void,     (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(2, Rectsv,         void,     (GLshortP, GLshortP))
+BGL_Wrap(1, RenderMode,     GLint,    (GLenum))
+BGL_Wrap(4, Rotated,        void,     (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(4, Rotatef,        void,     (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(3, Scaled,         void,     (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(3, Scalef,         void,     (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(4, Scissor,        void,     (GLint, GLint, GLsizei, GLsizei))
+BGL_Wrap(2, SelectBuffer,   void,     (GLsizei, GLuintP))
+BGL_Wrap(1, ShadeModel,       void,     (GLenum))
+BGL_Wrap(3, StencilFunc,      void,     (GLenum, GLint, GLuint))
+BGL_Wrap(1, StencilMask,      void,     (GLuint))
+BGL_Wrap(3, StencilOp,        void,     (GLenum, GLenum, GLenum))
+BGL_Wrap(1, TexCoord1d,       void,     (GLdouble))
+BGL_Wrap(1, TexCoord1dv,      void,     (GLdoubleP))
+BGL_Wrap(1, TexCoord1f,       void,     (GLfloat))
+BGL_Wrap(1, TexCoord1fv,      void,     (GLfloatP))
+BGL_Wrap(1, TexCoord1i,       void,     (GLint))
+BGL_Wrap(1, TexCoord1iv,      void,     (GLintP))
+BGL_Wrap(1, TexCoord1s,       void,     (GLshort))
+BGL_Wrap(1, TexCoord1sv,      void,     (GLshortP))
+BGL_Wrap(2, TexCoord2d,       void,     (GLdouble, GLdouble))
+BGL_Wrap(1, TexCoord2dv,      void,     (GLdoubleP))
+BGL_Wrap(2, TexCoord2f,       void,     (GLfloat, GLfloat))
+BGL_Wrap(1, TexCoord2fv,      void,     (GLfloatP))
+BGL_Wrap(2, TexCoord2i,       void,     (GLint, GLint))
+BGL_Wrap(1, TexCoord2iv,      void,     (GLintP))
+BGL_Wrap(2, TexCoord2s,       void,     (GLshort, GLshort))
+BGL_Wrap(1, TexCoord2sv,      void,     (GLshortP))
+BGL_Wrap(3, TexCoord3d,       void,     (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, TexCoord3dv,      void,     (GLdoubleP))
+BGL_Wrap(3, TexCoord3f,       void,     (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, TexCoord3fv,      void,     (GLfloatP))
+BGL_Wrap(3, TexCoord3i,       void,     (GLint, GLint, GLint))
+BGL_Wrap(1, TexCoord3iv,      void,     (GLintP))
+BGL_Wrap(3, TexCoord3s,       void,     (GLshort, GLshort, GLshort))
+BGL_Wrap(1, TexCoord3sv,      void,     (GLshortP))
+BGL_Wrap(4, TexCoord4d,       void,     (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, TexCoord4dv,      void,     (GLdoubleP))
+BGL_Wrap(4, TexCoord4f,       void,     (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, TexCoord4fv,      void,     (GLfloatP))
+BGL_Wrap(4, TexCoord4i,       void,     (GLint, GLint, GLint, GLint))
+BGL_Wrap(1, TexCoord4iv,      void,     (GLintP))
+BGL_Wrap(4, TexCoord4s,       void,     (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(1, TexCoord4sv,      void,     (GLshortP))
+BGL_Wrap(3, TexEnvf,        void,     (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, TexEnvfv,       void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, TexEnvi,        void,     (GLenum, GLenum, GLint))
+BGL_Wrap(3, TexEnviv,       void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(3, TexGend,        void,     (GLenum, GLenum, GLdouble))
+BGL_Wrap(3, TexGendv,       void,     (GLenum, GLenum, GLdoubleP))
+BGL_Wrap(3, TexGenf,        void,     (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, TexGenfv,       void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, TexGeni,        void,     (GLenum, GLenum, GLint))
+BGL_Wrap(3, TexGeniv,       void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(8, TexImage1D,     void,     (GLenum, GLint, GLint,
+                        GLsizei, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(9, TexImage2D,     void,     (GLenum, GLint, GLint,
+                        GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
+BGL_Wrap(3, TexParameterf,      void,     (GLenum, GLenum, GLfloat))
+BGL_Wrap(3, TexParameterfv,     void,     (GLenum, GLenum, GLfloatP))
+BGL_Wrap(3, TexParameteri,      void,     (GLenum, GLenum, GLint))
+BGL_Wrap(3, TexParameteriv,     void,     (GLenum, GLenum, GLintP))
+BGL_Wrap(3, Translated,         void,     (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(3, Translatef,         void,     (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(2, Vertex2d,           void,     (GLdouble, GLdouble))
+BGL_Wrap(1, Vertex2dv,          void,     (GLdoubleP))
+BGL_Wrap(2, Vertex2f,           void,     (GLfloat, GLfloat))
+BGL_Wrap(1, Vertex2fv,          void,     (GLfloatP))
+BGL_Wrap(2, Vertex2i,           void,     (GLint, GLint))
+BGL_Wrap(1, Vertex2iv,          void,     (GLintP))
+BGL_Wrap(2, Vertex2s,           void,     (GLshort, GLshort))
+BGL_Wrap(1, Vertex2sv,          void,     (GLshortP))
+BGL_Wrap(3, Vertex3d,           void,     (GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Vertex3dv,          void,     (GLdoubleP))
+BGL_Wrap(3, Vertex3f,           void,     (GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Vertex3fv,          void,     (GLfloatP))
+BGL_Wrap(3, Vertex3i,           void,     (GLint, GLint, GLint))
+BGL_Wrap(1, Vertex3iv,          void,     (GLintP))
+BGL_Wrap(3, Vertex3s,           void,     (GLshort, GLshort, GLshort))
+BGL_Wrap(1, Vertex3sv,          void,     (GLshortP))
+BGL_Wrap(4, Vertex4d,           void,     (GLdouble, GLdouble, GLdouble, GLdouble))
+BGL_Wrap(1, Vertex4dv,          void,     (GLdoubleP))
+BGL_Wrap(4, Vertex4f,           void,     (GLfloat, GLfloat, GLfloat, GLfloat))
+BGL_Wrap(1, Vertex4fv,          void,     (GLfloatP))
+BGL_Wrap(4, Vertex4i,           void,     (GLint, GLint, GLint, GLint))
+BGL_Wrap(1, Vertex4iv,          void,     (GLintP))
+BGL_Wrap(4, Vertex4s,           void,     (GLshort, GLshort, GLshort, GLshort))
+BGL_Wrap(1, Vertex4sv,          void,     (GLshortP))
+BGL_Wrap(4, Viewport,           void,     (GLint, GLint, GLsizei, GLsizei))
+BGLU_Wrap(4, Perspective,       void,          (GLdouble, GLdouble, GLdouble, GLdouble))
+BGLU_Wrap(9, LookAt,                   void,           (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
+BGLU_Wrap(4, Ortho2D,          void,           (GLdouble, GLdouble, GLdouble, GLdouble))
+BGLU_Wrap(5, PickMatrix,               void,           (GLdouble, GLdouble, GLdouble, GLdouble, GLintP))
+BGLU_Wrap(9, Project,                  GLint,          (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
+BGLU_Wrap(9, UnProject,                        GLint,          (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
+
+#undef MethodDef
+#define MethodDef(func) {"gl"#func, Method_##func, METH_VARARGS, "no string"}
+#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, "no string"}
+/* So that MethodDef(Accum) becomes:
+ * {"glAccum", Method_Accumfunc, METH_VARARGS} */
+
+static struct PyMethodDef BGL_methods[] = {
+  {"Buffer", Method_Buffer, METH_VARARGS, Method_Buffer_doc}, 
+
+/* #ifndef __APPLE__ */
+       MethodDef(Accum),
+       MethodDef(AlphaFunc),
+       MethodDef(AreTexturesResident), 
+       MethodDef(Begin),
+       MethodDef(BindTexture), 
+       MethodDef(Bitmap),
+       MethodDef(BlendFunc),
+       MethodDef(CallList),
+       MethodDef(CallLists),
+       MethodDef(Clear),
+       MethodDef(ClearAccum),
+       MethodDef(ClearColor),
+       MethodDef(ClearDepth),
+       MethodDef(ClearIndex),
+       MethodDef(ClearStencil),
+       MethodDef(ClipPlane),
+       MethodDef(Color3b),
+       MethodDef(Color3bv),
+       MethodDef(Color3d),
+       MethodDef(Color3dv),
+       MethodDef(Color3f),
+       MethodDef(Color3fv),
+       MethodDef(Color3i),
+       MethodDef(Color3iv),
+       MethodDef(Color3s),
+       MethodDef(Color3sv),
+       MethodDef(Color3ub),
+       MethodDef(Color3ubv),
+       MethodDef(Color3ui),
+       MethodDef(Color3uiv),
+       MethodDef(Color3us),
+       MethodDef(Color3usv),
+       MethodDef(Color4b),
+       MethodDef(Color4bv),
+       MethodDef(Color4d),
+       MethodDef(Color4dv),
+       MethodDef(Color4f),
+       MethodDef(Color4fv),
+       MethodDef(Color4i),
+       MethodDef(Color4iv),
+       MethodDef(Color4s),
+       MethodDef(Color4sv),
+       MethodDef(Color4ub),
+       MethodDef(Color4ubv),
+       MethodDef(Color4ui),
+       MethodDef(Color4uiv),
+       MethodDef(Color4us),
+       MethodDef(Color4usv),
+       MethodDef(ColorMask),
+       MethodDef(ColorMaterial),
+       MethodDef(CopyPixels),
+       MethodDef(CullFace),
+       MethodDef(DeleteLists),
+       MethodDef(DeleteTextures),
+       MethodDef(DepthFunc),
+       MethodDef(DepthMask),
+       MethodDef(DepthRange),
+       MethodDef(Disable),
+       MethodDef(DrawBuffer),
+       MethodDef(DrawPixels),
+       MethodDef(EdgeFlag),
+       MethodDef(EdgeFlagv),
+       MethodDef(Enable),
+       MethodDef(End),
+       MethodDef(EndList),
+       MethodDef(EvalCoord1d),
+       MethodDef(EvalCoord1dv),
+       MethodDef(EvalCoord1f),
+       MethodDef(EvalCoord1fv),
+       MethodDef(EvalCoord2d),
+       MethodDef(EvalCoord2dv),
+       MethodDef(EvalCoord2f),
+       MethodDef(EvalCoord2fv),
+       MethodDef(EvalMesh1),
+       MethodDef(EvalMesh2),
+       MethodDef(EvalPoint1),
+       MethodDef(EvalPoint2),
+       MethodDef(FeedbackBuffer),
+       MethodDef(Finish),
+       MethodDef(Flush),
+       MethodDef(Fogf),
+       MethodDef(Fogfv),
+       MethodDef(Fogi),
+       MethodDef(Fogiv),
+       MethodDef(FrontFace),
+       MethodDef(Frustum),
+       MethodDef(GenLists),
+       MethodDef(GenTextures), 
+       MethodDef(GetBooleanv),
+       MethodDef(GetClipPlane),
+       MethodDef(GetDoublev),
+       MethodDef(GetError),
+       MethodDef(GetFloatv),
+       MethodDef(GetIntegerv),
+       MethodDef(GetLightfv),
+       MethodDef(GetLightiv),
+       MethodDef(GetMapdv),
+       MethodDef(GetMapfv),
+       MethodDef(GetMapiv),
+       MethodDef(GetMaterialfv),
+       MethodDef(GetMaterialiv),
+       MethodDef(GetPixelMapfv),
+       MethodDef(GetPixelMapuiv),
+       MethodDef(GetPixelMapusv),
+       MethodDef(GetPolygonStipple),
+       MethodDef(GetString),
+       MethodDef(GetTexEnvfv),
+       MethodDef(GetTexEnviv),
+       MethodDef(GetTexGendv),
+       MethodDef(GetTexGenfv),
+       MethodDef(GetTexGeniv),
+       MethodDef(GetTexImage),
+       MethodDef(GetTexLevelParameterfv),
+       MethodDef(GetTexLevelParameteriv),
+       MethodDef(GetTexParameterfv),
+       MethodDef(GetTexParameteriv),
+       MethodDef(Hint),
+       MethodDef(IndexMask),
+       MethodDef(Indexd),
+       MethodDef(Indexdv),
+       MethodDef(Indexf),
+       MethodDef(Indexfv),
+       MethodDef(Indexi),
+       MethodDef(Indexiv),
+       MethodDef(Indexs),
+       MethodDef(Indexsv),
+       MethodDef(InitNames),
+       MethodDef(IsEnabled),
+       MethodDef(IsList),
+       MethodDef(IsTexture), 
+       MethodDef(LightModelf),
+       MethodDef(LightModelfv),
+       MethodDef(LightModeli),
+       MethodDef(LightModeliv),
+       MethodDef(Lightf),
+       MethodDef(Lightfv),
+       MethodDef(Lighti),
+       MethodDef(Lightiv),
+       MethodDef(LineStipple),
+       MethodDef(LineWidth),
+       MethodDef(ListBase),
+       MethodDef(LoadIdentity),
+       MethodDef(LoadMatrixd),
+       MethodDef(LoadMatrixf),
+       MethodDef(LoadName),
+       MethodDef(LogicOp),
+       MethodDef(Map1d),
+       MethodDef(Map1f),
+       MethodDef(Map2d),
+       MethodDef(Map2f),
+       MethodDef(MapGrid1d),
+       MethodDef(MapGrid1f),
+       MethodDef(MapGrid2d),
+       MethodDef(MapGrid2f),
+       MethodDef(Materialf),
+       MethodDef(Materialfv),
+       MethodDef(Materiali),
+       MethodDef(Materialiv),
+       MethodDef(MatrixMode),
+       MethodDef(MultMatrixd),
+       MethodDef(MultMatrixf),
+       MethodDef(NewList),
+       MethodDef(Normal3b),
+       MethodDef(Normal3bv),
+       MethodDef(Normal3d),
+       MethodDef(Normal3dv),
+       MethodDef(Normal3f),
+       MethodDef(Normal3fv),
+       MethodDef(Normal3i),
+       MethodDef(Normal3iv),
+       MethodDef(Normal3s),
+       MethodDef(Normal3sv),
+       MethodDef(Ortho),
+       MethodDef(PassThrough),
+       MethodDef(PixelMapfv),
+       MethodDef(PixelMapuiv),
+       MethodDef(PixelMapusv),
+       MethodDef(PixelStoref),
+       MethodDef(PixelStorei),
+       MethodDef(PixelTransferf),
+       MethodDef(PixelTransferi),
+       MethodDef(PixelZoom),
+       MethodDef(PointSize),
+       MethodDef(PolygonMode),
+       MethodDef(PolygonOffset),
+       MethodDef(PolygonStipple),
+       MethodDef(PopAttrib),
+       MethodDef(PopClientAttrib),
+       MethodDef(PopMatrix),
+       MethodDef(PopName),
+       MethodDef(PrioritizeTextures), 
+       MethodDef(PushAttrib),
+       MethodDef(PushClientAttrib),
+       MethodDef(PushMatrix),
+       MethodDef(PushName),
+       MethodDef(RasterPos2d),
+       MethodDef(RasterPos2dv),
+       MethodDef(RasterPos2f),
+       MethodDef(RasterPos2fv),
+       MethodDef(RasterPos2i),
+       MethodDef(RasterPos2iv),
+       MethodDef(RasterPos2s),
+       MethodDef(RasterPos2sv),
+       MethodDef(RasterPos3d),
+       MethodDef(RasterPos3dv),
+       MethodDef(RasterPos3f),
+       MethodDef(RasterPos3fv),
+       MethodDef(RasterPos3i),
+       MethodDef(RasterPos3iv),
+       MethodDef(RasterPos3s),
+       MethodDef(RasterPos3sv),
+       MethodDef(RasterPos4d),
+       MethodDef(RasterPos4dv),
+       MethodDef(RasterPos4f),
+       MethodDef(RasterPos4fv),
+       MethodDef(RasterPos4i),
+       MethodDef(RasterPos4iv),
+       MethodDef(RasterPos4s),
+       MethodDef(RasterPos4sv),
+       MethodDef(ReadBuffer),
+       MethodDef(ReadPixels),
+       MethodDef(Rectd),
+       MethodDef(Rectdv),
+       MethodDef(Rectf),
+       MethodDef(Rectfv),
+       MethodDef(Recti),
+       MethodDef(Rectiv),
+       MethodDef(Rects),
+       MethodDef(Rectsv),
+       MethodDef(RenderMode),
+       MethodDef(Rotated),
+       MethodDef(Rotatef),
+       MethodDef(Scaled),
+       MethodDef(Scalef),
+       MethodDef(Scissor),
+       MethodDef(SelectBuffer),
+       MethodDef(ShadeModel),
+       MethodDef(StencilFunc),
+       MethodDef(StencilMask),
+       MethodDef(StencilOp),
+       MethodDef(TexCoord1d),
+       MethodDef(TexCoord1dv),
+       MethodDef(TexCoord1f),
+       MethodDef(TexCoord1fv),
+       MethodDef(TexCoord1i),
+       MethodDef(TexCoord1iv),
+       MethodDef(TexCoord1s),
+       MethodDef(TexCoord1sv),
+       MethodDef(TexCoord2d),
+       MethodDef(TexCoord2dv),
+       MethodDef(TexCoord2f),
+       MethodDef(TexCoord2fv),
+       MethodDef(TexCoord2i),
+       MethodDef(TexCoord2iv),
+       MethodDef(TexCoord2s),
+       MethodDef(TexCoord2sv),
+       MethodDef(TexCoord3d),
+       MethodDef(TexCoord3dv),
+       MethodDef(TexCoord3f),
+       MethodDef(TexCoord3fv),
+       MethodDef(TexCoord3i),
+       MethodDef(TexCoord3iv),
+       MethodDef(TexCoord3s),
+       MethodDef(TexCoord3sv),
+       MethodDef(TexCoord4d),
+       MethodDef(TexCoord4dv),
+       MethodDef(TexCoord4f),
+       MethodDef(TexCoord4fv),
+       MethodDef(TexCoord4i),
+       MethodDef(TexCoord4iv),
+       MethodDef(TexCoord4s),
+       MethodDef(TexCoord4sv),
+       MethodDef(TexEnvf),
+       MethodDef(TexEnvfv),
+       MethodDef(TexEnvi),
+       MethodDef(TexEnviv),
+       MethodDef(TexGend),
+       MethodDef(TexGendv),
+       MethodDef(TexGenf),
+       MethodDef(TexGenfv),
+       MethodDef(TexGeni),
+       MethodDef(TexGeniv),
+       MethodDef(TexImage1D),
+       MethodDef(TexImage2D),
+       MethodDef(TexParameterf),
+       MethodDef(TexParameterfv),
+       MethodDef(TexParameteri),
+       MethodDef(TexParameteriv),
+       MethodDef(Translated),
+       MethodDef(Translatef),
+       MethodDef(Vertex2d),
+       MethodDef(Vertex2dv),
+       MethodDef(Vertex2f),
+       MethodDef(Vertex2fv),
+       MethodDef(Vertex2i),
+       MethodDef(Vertex2iv),
+       MethodDef(Vertex2s),
+       MethodDef(Vertex2sv),
+       MethodDef(Vertex3d),
+       MethodDef(Vertex3dv),
+       MethodDef(Vertex3f),
+       MethodDef(Vertex3fv),
+       MethodDef(Vertex3i),
+       MethodDef(Vertex3iv),
+       MethodDef(Vertex3s),
+       MethodDef(Vertex3sv),
+       MethodDef(Vertex4d),
+       MethodDef(Vertex4dv),
+       MethodDef(Vertex4f),
+       MethodDef(Vertex4fv),
+       MethodDef(Vertex4i),
+       MethodDef(Vertex4iv),
+       MethodDef(Vertex4s),
+       MethodDef(Vertex4sv),
+       MethodDef(Viewport),
+       MethodDefu(Perspective),
+       MethodDefu(LookAt),
+       MethodDefu(Ortho2D),
+       MethodDefu(PickMatrix),
+       MethodDefu(Project),
+       MethodDefu(UnProject),
+/* #endif */
+       {NULL, NULL, 0, NULL}
+};
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef BGL_module_def = {
+       {}, /* m_base */
+       "BGL",  /* m_name */
+       0,  /* m_doc */
+       0,  /* m_size */
+       BGL_methods,  /* m_methods */
+       0,  /* m_reload */
+       0,  /* m_traverse */
+       0,  /* m_clear */
+       0,  /* m_free */
+};
+#endif
+
+PyObject *BGL_Init(const char *from) 
+{
+       PyObject *mod, *dict, *item;
+#if (PY_VERSION_HEX >= 0x03000000)
+       mod = PyModule_Create(&BGL_module_def);
+       PyDict_SetItemString(PySys_GetObject("modules"), BGL_module_def.m_name, mod);
+#else
+       mod= Py_InitModule(from, BGL_methods);
+#endif
+       dict= PyModule_GetDict(mod);
+       
+       if( PyType_Ready( &buffer_Type) < 0)
+               return NULL; /* should never happen */
+
+#define EXPP_ADDCONST(x) PyDict_SetItemString(dict, #x, item=PyLong_FromLong((int)x)); Py_DECREF(item)
+
+/* So, for example:
+ * EXPP_ADDCONST(GL_CURRENT_BIT) becomes
+ * PyDict_SetItemString(dict, "GL_CURRENT_BIT", item=PyLong_FromLong(GL_CURRENT_BIT)); Py_DECREF(item) */
+
+       EXPP_ADDCONST(GL_CURRENT_BIT);
+       EXPP_ADDCONST(GL_POINT_BIT);
+       EXPP_ADDCONST(GL_LINE_BIT);
+       EXPP_ADDCONST(GL_POLYGON_BIT);
+       EXPP_ADDCONST(GL_POLYGON_STIPPLE_BIT);
+       EXPP_ADDCONST(GL_PIXEL_MODE_BIT);
+       EXPP_ADDCONST(GL_LIGHTING_BIT);
+       EXPP_ADDCONST(GL_FOG_BIT);
+       EXPP_ADDCONST(GL_DEPTH_BUFFER_BIT);
+       EXPP_ADDCONST(GL_ACCUM_BUFFER_BIT);
+       EXPP_ADDCONST(GL_STENCIL_BUFFER_BIT);
+       EXPP_ADDCONST(GL_VIEWPORT_BIT);
+       EXPP_ADDCONST(GL_TRANSFORM_BIT);
+       EXPP_ADDCONST(GL_ENABLE_BIT);
+       EXPP_ADDCONST(GL_COLOR_BUFFER_BIT);
+       EXPP_ADDCONST(GL_HINT_BIT);
+       EXPP_ADDCONST(GL_EVAL_BIT);
+       EXPP_ADDCONST(GL_LIST_BIT);
+       EXPP_ADDCONST(GL_TEXTURE_BIT);
+       EXPP_ADDCONST(GL_SCISSOR_BIT);
+       EXPP_ADDCONST(GL_ALL_ATTRIB_BITS);
+       EXPP_ADDCONST(GL_CLIENT_ALL_ATTRIB_BITS);
+       
+       EXPP_ADDCONST(GL_FALSE);
+       EXPP_ADDCONST(GL_TRUE);
+
+       EXPP_ADDCONST(GL_POINTS);
+       EXPP_ADDCONST(GL_LINES);
+       EXPP_ADDCONST(GL_LINE_LOOP);
+       EXPP_ADDCONST(GL_LINE_STRIP);
+       EXPP_ADDCONST(GL_TRIANGLES);
+       EXPP_ADDCONST(GL_TRIANGLE_STRIP);
+       EXPP_ADDCONST(GL_TRIANGLE_FAN);
+       EXPP_ADDCONST(GL_QUADS);
+       EXPP_ADDCONST(GL_QUAD_STRIP);
+       EXPP_ADDCONST(GL_POLYGON);
+
+       EXPP_ADDCONST(GL_ACCUM);
+       EXPP_ADDCONST(GL_LOAD);
+       EXPP_ADDCONST(GL_RETURN);
+       EXPP_ADDCONST(GL_MULT);
+       EXPP_ADDCONST(GL_ADD);
+
+       EXPP_ADDCONST(GL_NEVER);
+       EXPP_ADDCONST(GL_LESS);
+       EXPP_ADDCONST(GL_EQUAL);
+       EXPP_ADDCONST(GL_LEQUAL);
+       EXPP_ADDCONST(GL_GREATER);
+       EXPP_ADDCONST(GL_NOTEQUAL);
+       EXPP_ADDCONST(GL_GEQUAL);
+       EXPP_ADDCONST(GL_ALWAYS);
+
+       EXPP_ADDCONST(GL_ZERO);
+       EXPP_ADDCONST(GL_ONE);
+       EXPP_ADDCONST(GL_SRC_COLOR);
+       EXPP_ADDCONST(GL_ONE_MINUS_SRC_COLOR);
+       EXPP_ADDCONST(GL_SRC_ALPHA);
+       EXPP_ADDCONST(GL_ONE_MINUS_SRC_ALPHA);
+       EXPP_ADDCONST(GL_DST_ALPHA);
+       EXPP_ADDCONST(GL_ONE_MINUS_DST_ALPHA);
+
+       EXPP_ADDCONST(GL_DST_COLOR);
+       EXPP_ADDCONST(GL_ONE_MINUS_DST_COLOR);
+       EXPP_ADDCONST(GL_SRC_ALPHA_SATURATE);
+
+       EXPP_ADDCONST(GL_NONE);
+       EXPP_ADDCONST(GL_FRONT_LEFT);
+       EXPP_ADDCONST(GL_FRONT_RIGHT);
+       EXPP_ADDCONST(GL_BACK_LEFT);
+       EXPP_ADDCONST(GL_BACK_RIGHT);
+       EXPP_ADDCONST(GL_FRONT);
+       EXPP_ADDCONST(GL_BACK);
+       EXPP_ADDCONST(GL_LEFT);
+       EXPP_ADDCONST(GL_RIGHT);
+       EXPP_ADDCONST(GL_FRONT_AND_BACK);
+       EXPP_ADDCONST(GL_AUX0);
+       EXPP_ADDCONST(GL_AUX1);
+       EXPP_ADDCONST(GL_AUX2);
+       EXPP_ADDCONST(GL_AUX3);
+
+       EXPP_ADDCONST(GL_NO_ERROR);
+       EXPP_ADDCONST(GL_INVALID_ENUM);
+       EXPP_ADDCONST(GL_INVALID_VALUE);
+       EXPP_ADDCONST(GL_INVALID_OPERATION);
+       EXPP_ADDCONST(GL_STACK_OVERFLOW);
+       EXPP_ADDCONST(GL_STACK_UNDERFLOW);
+       EXPP_ADDCONST(GL_OUT_OF_MEMORY);
+
+       EXPP_ADDCONST(GL_2D);
+       EXPP_ADDCONST(GL_3D);
+       EXPP_ADDCONST(GL_3D_COLOR);
+       EXPP_ADDCONST(GL_3D_COLOR_TEXTURE);
+       EXPP_ADDCONST(GL_4D_COLOR_TEXTURE);
+
+       EXPP_ADDCONST(GL_PASS_THROUGH_TOKEN);
+       EXPP_ADDCONST(GL_POINT_TOKEN);
+       EXPP_ADDCONST(GL_LINE_TOKEN);
+       EXPP_ADDCONST(GL_POLYGON_TOKEN);
+       EXPP_ADDCONST(GL_BITMAP_TOKEN);
+       EXPP_ADDCONST(GL_DRAW_PIXEL_TOKEN);
+       EXPP_ADDCONST(GL_COPY_PIXEL_TOKEN);
+       EXPP_ADDCONST(GL_LINE_RESET_TOKEN);
+
+       EXPP_ADDCONST(GL_EXP);
+       EXPP_ADDCONST(GL_EXP2);
+
+       EXPP_ADDCONST(GL_CW);
+       EXPP_ADDCONST(GL_CCW);
+
+       EXPP_ADDCONST(GL_COEFF);
+       EXPP_ADDCONST(GL_ORDER);
+       EXPP_ADDCONST(GL_DOMAIN);
+
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_I);
+       EXPP_ADDCONST(GL_PIXEL_MAP_S_TO_S);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_R);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_G);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_B);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_A);
+       EXPP_ADDCONST(GL_PIXEL_MAP_R_TO_R);
+       EXPP_ADDCONST(GL_PIXEL_MAP_G_TO_G);
+       EXPP_ADDCONST(GL_PIXEL_MAP_B_TO_B);
+       EXPP_ADDCONST(GL_PIXEL_MAP_A_TO_A);
+
+       EXPP_ADDCONST(GL_CURRENT_COLOR);
+       EXPP_ADDCONST(GL_CURRENT_INDEX);
+       EXPP_ADDCONST(GL_CURRENT_NORMAL);
+       EXPP_ADDCONST(GL_CURRENT_TEXTURE_COORDS);
+       EXPP_ADDCONST(GL_CURRENT_RASTER_COLOR);
+       EXPP_ADDCONST(GL_CURRENT_RASTER_INDEX);
+       EXPP_ADDCONST(GL_CURRENT_RASTER_TEXTURE_COORDS);
+       EXPP_ADDCONST(GL_CURRENT_RASTER_POSITION);
+       EXPP_ADDCONST(GL_CURRENT_RASTER_POSITION_VALID);
+       EXPP_ADDCONST(GL_CURRENT_RASTER_DISTANCE);
+       EXPP_ADDCONST(GL_POINT_SMOOTH);
+       EXPP_ADDCONST(GL_POINT_SIZE);
+       EXPP_ADDCONST(GL_POINT_SIZE_RANGE);
+       EXPP_ADDCONST(GL_POINT_SIZE_GRANULARITY);
+       EXPP_ADDCONST(GL_LINE_SMOOTH);
+       EXPP_ADDCONST(GL_LINE_WIDTH);
+       EXPP_ADDCONST(GL_LINE_WIDTH_RANGE);
+       EXPP_ADDCONST(GL_LINE_WIDTH_GRANULARITY);
+       EXPP_ADDCONST(GL_LINE_STIPPLE);
+       EXPP_ADDCONST(GL_LINE_STIPPLE_PATTERN);
+       EXPP_ADDCONST(GL_LINE_STIPPLE_REPEAT);
+       EXPP_ADDCONST(GL_LIST_MODE);
+       EXPP_ADDCONST(GL_MAX_LIST_NESTING);
+       EXPP_ADDCONST(GL_LIST_BASE);
+       EXPP_ADDCONST(GL_LIST_INDEX);
+       EXPP_ADDCONST(GL_POLYGON_MODE);
+       EXPP_ADDCONST(GL_POLYGON_SMOOTH);
+       EXPP_ADDCONST(GL_POLYGON_STIPPLE);
+       EXPP_ADDCONST(GL_EDGE_FLAG);
+       EXPP_ADDCONST(GL_CULL_FACE);
+       EXPP_ADDCONST(GL_CULL_FACE_MODE);
+       EXPP_ADDCONST(GL_FRONT_FACE);
+       EXPP_ADDCONST(GL_LIGHTING);
+       EXPP_ADDCONST(GL_LIGHT_MODEL_LOCAL_VIEWER);
+       EXPP_ADDCONST(GL_LIGHT_MODEL_TWO_SIDE);
+       EXPP_ADDCONST(GL_LIGHT_MODEL_AMBIENT);
+       EXPP_ADDCONST(GL_SHADE_MODEL);
+       EXPP_ADDCONST(GL_COLOR_MATERIAL_FACE);
+       EXPP_ADDCONST(GL_COLOR_MATERIAL_PARAMETER);
+       EXPP_ADDCONST(GL_COLOR_MATERIAL);
+       EXPP_ADDCONST(GL_FOG);
+       EXPP_ADDCONST(GL_FOG_INDEX);
+       EXPP_ADDCONST(GL_FOG_DENSITY);
+       EXPP_ADDCONST(GL_FOG_START);
+       EXPP_ADDCONST(GL_FOG_END);
+       EXPP_ADDCONST(GL_FOG_MODE);
+       EXPP_ADDCONST(GL_FOG_COLOR);
+       EXPP_ADDCONST(GL_DEPTH_RANGE);
+       EXPP_ADDCONST(GL_DEPTH_TEST);
+       EXPP_ADDCONST(GL_DEPTH_WRITEMASK);
+       EXPP_ADDCONST(GL_DEPTH_CLEAR_VALUE);
+       EXPP_ADDCONST(GL_DEPTH_FUNC);
+       EXPP_ADDCONST(GL_ACCUM_CLEAR_VALUE);
+       EXPP_ADDCONST(GL_STENCIL_TEST);
+       EXPP_ADDCONST(GL_STENCIL_CLEAR_VALUE);
+       EXPP_ADDCONST(GL_STENCIL_FUNC);
+       EXPP_ADDCONST(GL_STENCIL_VALUE_MASK);
+       EXPP_ADDCONST(GL_STENCIL_FAIL);
+       EXPP_ADDCONST(GL_STENCIL_PASS_DEPTH_FAIL);
+       EXPP_ADDCONST(GL_STENCIL_PASS_DEPTH_PASS);
+       EXPP_ADDCONST(GL_STENCIL_REF);
+       EXPP_ADDCONST(GL_STENCIL_WRITEMASK);
+       EXPP_ADDCONST(GL_MATRIX_MODE);
+       EXPP_ADDCONST(GL_NORMALIZE);
+       EXPP_ADDCONST(GL_VIEWPORT);
+       EXPP_ADDCONST(GL_MODELVIEW_STACK_DEPTH);
+       EXPP_ADDCONST(GL_PROJECTION_STACK_DEPTH);
+       EXPP_ADDCONST(GL_TEXTURE_STACK_DEPTH);
+       EXPP_ADDCONST(GL_MODELVIEW_MATRIX);
+       EXPP_ADDCONST(GL_PROJECTION_MATRIX);
+       EXPP_ADDCONST(GL_TEXTURE_MATRIX);
+       EXPP_ADDCONST(GL_ATTRIB_STACK_DEPTH);
+       EXPP_ADDCONST(GL_ALPHA_TEST);
+       EXPP_ADDCONST(GL_ALPHA_TEST_FUNC);
+       EXPP_ADDCONST(GL_ALPHA_TEST_REF);
+       EXPP_ADDCONST(GL_DITHER);
+       EXPP_ADDCONST(GL_BLEND_DST);
+       EXPP_ADDCONST(GL_BLEND_SRC);
+       EXPP_ADDCONST(GL_BLEND);
+       EXPP_ADDCONST(GL_LOGIC_OP_MODE);
+       EXPP_ADDCONST(GL_LOGIC_OP);
+       EXPP_ADDCONST(GL_AUX_BUFFERS);
+       EXPP_ADDCONST(GL_DRAW_BUFFER);
+       EXPP_ADDCONST(GL_READ_BUFFER);
+       EXPP_ADDCONST(GL_SCISSOR_BOX);
+       EXPP_ADDCONST(GL_SCISSOR_TEST);
+       EXPP_ADDCONST(GL_INDEX_CLEAR_VALUE);
+       EXPP_ADDCONST(GL_INDEX_WRITEMASK);
+       EXPP_ADDCONST(GL_COLOR_CLEAR_VALUE);
+       EXPP_ADDCONST(GL_COLOR_WRITEMASK);
+       EXPP_ADDCONST(GL_INDEX_MODE);
+       EXPP_ADDCONST(GL_RGBA_MODE);
+       EXPP_ADDCONST(GL_DOUBLEBUFFER);
+       EXPP_ADDCONST(GL_STEREO);
+       EXPP_ADDCONST(GL_RENDER_MODE);
+       EXPP_ADDCONST(GL_PERSPECTIVE_CORRECTION_HINT);
+       EXPP_ADDCONST(GL_POINT_SMOOTH_HINT);
+       EXPP_ADDCONST(GL_LINE_SMOOTH_HINT);
+       EXPP_ADDCONST(GL_POLYGON_SMOOTH_HINT);
+       EXPP_ADDCONST(GL_FOG_HINT);
+       EXPP_ADDCONST(GL_TEXTURE_GEN_S);
+       EXPP_ADDCONST(GL_TEXTURE_GEN_T);
+       EXPP_ADDCONST(GL_TEXTURE_GEN_R);
+       EXPP_ADDCONST(GL_TEXTURE_GEN_Q);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_I_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_S_TO_S_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_R_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_G_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_B_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_A_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_R_TO_R_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_G_TO_G_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_B_TO_B_SIZE);
+       EXPP_ADDCONST(GL_PIXEL_MAP_A_TO_A_SIZE);
+       EXPP_ADDCONST(GL_UNPACK_SWAP_BYTES);
+       EXPP_ADDCONST(GL_UNPACK_LSB_FIRST);
+       EXPP_ADDCONST(GL_UNPACK_ROW_LENGTH);
+       EXPP_ADDCONST(GL_UNPACK_SKIP_ROWS);
+       EXPP_ADDCONST(GL_UNPACK_SKIP_PIXELS);
+       EXPP_ADDCONST(GL_UNPACK_ALIGNMENT);
+       EXPP_ADDCONST(GL_PACK_SWAP_BYTES);
+       EXPP_ADDCONST(GL_PACK_LSB_FIRST);
+       EXPP_ADDCONST(GL_PACK_ROW_LENGTH);
+       EXPP_ADDCONST(GL_PACK_SKIP_ROWS);
+       EXPP_ADDCONST(GL_PACK_SKIP_PIXELS);
+       EXPP_ADDCONST(GL_PACK_ALIGNMENT);
+       EXPP_ADDCONST(GL_MAP_COLOR);
+       EXPP_ADDCONST(GL_MAP_STENCIL);
+       EXPP_ADDCONST(GL_INDEX_SHIFT);
+       EXPP_ADDCONST(GL_INDEX_OFFSET);
+       EXPP_ADDCONST(GL_RED_SCALE);
+       EXPP_ADDCONST(GL_RED_BIAS);
+       EXPP_ADDCONST(GL_ZOOM_X);
+       EXPP_ADDCONST(GL_ZOOM_Y);
+       EXPP_ADDCONST(GL_GREEN_SCALE);
+       EXPP_ADDCONST(GL_GREEN_BIAS);
+       EXPP_ADDCONST(GL_BLUE_SCALE);
+       EXPP_ADDCONST(GL_BLUE_BIAS);
+       EXPP_ADDCONST(GL_ALPHA_SCALE);
+       EXPP_ADDCONST(GL_ALPHA_BIAS);
+       EXPP_ADDCONST(GL_DEPTH_SCALE);
+       EXPP_ADDCONST(GL_DEPTH_BIAS);
+       EXPP_ADDCONST(GL_MAX_EVAL_ORDER);
+       EXPP_ADDCONST(GL_MAX_LIGHTS);
+       EXPP_ADDCONST(GL_MAX_CLIP_PLANES);
+       EXPP_ADDCONST(GL_MAX_TEXTURE_SIZE);
+       EXPP_ADDCONST(GL_MAX_PIXEL_MAP_TABLE);
+       EXPP_ADDCONST(GL_MAX_ATTRIB_STACK_DEPTH);
+       EXPP_ADDCONST(GL_MAX_MODELVIEW_STACK_DEPTH);
+       EXPP_ADDCONST(GL_MAX_NAME_STACK_DEPTH);
+       EXPP_ADDCONST(GL_MAX_PROJECTION_STACK_DEPTH);
+       EXPP_ADDCONST(GL_MAX_TEXTURE_STACK_DEPTH);
+       EXPP_ADDCONST(GL_MAX_VIEWPORT_DIMS);
+       EXPP_ADDCONST(GL_SUBPIXEL_BITS);
+       EXPP_ADDCONST(GL_INDEX_BITS);
+       EXPP_ADDCONST(GL_RED_BITS);
+       EXPP_ADDCONST(GL_GREEN_BITS);
+       EXPP_ADDCONST(GL_BLUE_BITS);
+       EXPP_ADDCONST(GL_ALPHA_BITS);
+       EXPP_ADDCONST(GL_DEPTH_BITS);
+       EXPP_ADDCONST(GL_STENCIL_BITS);
+       EXPP_ADDCONST(GL_ACCUM_RED_BITS);
+       EXPP_ADDCONST(GL_ACCUM_GREEN_BITS);
+       EXPP_ADDCONST(GL_ACCUM_BLUE_BITS);
+       EXPP_ADDCONST(GL_ACCUM_ALPHA_BITS);
+       EXPP_ADDCONST(GL_NAME_STACK_DEPTH);
+       EXPP_ADDCONST(GL_AUTO_NORMAL);
+       EXPP_ADDCONST(GL_MAP1_COLOR_4);
+       EXPP_ADDCONST(GL_MAP1_INDEX);
+       EXPP_ADDCONST(GL_MAP1_NORMAL);
+       EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_1);
+       EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_2);
+       EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_3);
+       EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_4);
+       EXPP_ADDCONST(GL_MAP1_VERTEX_3);
+       EXPP_ADDCONST(GL_MAP1_VERTEX_4);
+       EXPP_ADDCONST(GL_MAP2_COLOR_4);
+       EXPP_ADDCONST(GL_MAP2_INDEX);
+       EXPP_ADDCONST(GL_MAP2_NORMAL);
+       EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_1);
+       EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_2);
+       EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_3);
+       EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_4);
+       EXPP_ADDCONST(GL_MAP2_VERTEX_3);
+       EXPP_ADDCONST(GL_MAP2_VERTEX_4);
+       EXPP_ADDCONST(GL_MAP1_GRID_DOMAIN);
+       EXPP_ADDCONST(GL_MAP1_GRID_SEGMENTS);
+       EXPP_ADDCONST(GL_MAP2_GRID_DOMAIN);
+       EXPP_ADDCONST(GL_MAP2_GRID_SEGMENTS);
+       EXPP_ADDCONST(GL_TEXTURE_1D);
+       EXPP_ADDCONST(GL_TEXTURE_2D);
+
+       EXPP_ADDCONST(GL_TEXTURE_WIDTH);
+       EXPP_ADDCONST(GL_TEXTURE_HEIGHT);
+       EXPP_ADDCONST(GL_TEXTURE_COMPONENTS);
+       EXPP_ADDCONST(GL_TEXTURE_BORDER_COLOR);
+       EXPP_ADDCONST(GL_TEXTURE_BORDER);
+
+       EXPP_ADDCONST(GL_DONT_CARE);
+       EXPP_ADDCONST(GL_FASTEST);
+       EXPP_ADDCONST(GL_NICEST);
+
+       EXPP_ADDCONST(GL_AMBIENT);
+       EXPP_ADDCONST(GL_DIFFUSE);
+       EXPP_ADDCONST(GL_SPECULAR);
+       EXPP_ADDCONST(GL_POSITION);
+       EXPP_ADDCONST(GL_SPOT_DIRECTION);
+       EXPP_ADDCONST(GL_SPOT_EXPONENT);
+       EXPP_ADDCONST(GL_SPOT_CUTOFF);
+       EXPP_ADDCONST(GL_CONSTANT_ATTENUATION);
+       EXPP_ADDCONST(GL_LINEAR_ATTENUATION);
+       EXPP_ADDCONST(GL_QUADRATIC_ATTENUATION);
+
+       EXPP_ADDCONST(GL_COMPILE);
+       EXPP_ADDCONST(GL_COMPILE_AND_EXECUTE);
+
+       EXPP_ADDCONST(GL_BYTE);
+       EXPP_ADDCONST(GL_UNSIGNED_BYTE);
+       EXPP_ADDCONST(GL_SHORT);
+       EXPP_ADDCONST(GL_UNSIGNED_SHORT);
+       EXPP_ADDCONST(GL_INT);
+       EXPP_ADDCONST(GL_UNSIGNED_INT);
+       EXPP_ADDCONST(GL_FLOAT);
+       EXPP_ADDCONST(GL_DOUBLE);
+       EXPP_ADDCONST(GL_2_BYTES);
+       EXPP_ADDCONST(GL_3_BYTES);
+       EXPP_ADDCONST(GL_4_BYTES);
+
+       EXPP_ADDCONST(GL_CLEAR);
+       EXPP_ADDCONST(GL_AND);
+       EXPP_ADDCONST(GL_AND_REVERSE);
+       EXPP_ADDCONST(GL_COPY);
+       EXPP_ADDCONST(GL_AND_INVERTED);
+       EXPP_ADDCONST(GL_NOOP);
+       EXPP_ADDCONST(GL_XOR);
+       EXPP_ADDCONST(GL_OR);
+       EXPP_ADDCONST(GL_NOR);
+       EXPP_ADDCONST(GL_EQUIV);
+       EXPP_ADDCONST(GL_INVERT);
+       EXPP_ADDCONST(GL_OR_REVERSE);
+       EXPP_ADDCONST(GL_COPY_INVERTED);
+       EXPP_ADDCONST(GL_OR_INVERTED);
+       EXPP_ADDCONST(GL_NAND);
+       EXPP_ADDCONST(GL_SET);
+
+       EXPP_ADDCONST(GL_EMISSION);
+       EXPP_ADDCONST(GL_SHININESS);
+       EXPP_ADDCONST(GL_AMBIENT_AND_DIFFUSE);
+       EXPP_ADDCONST(GL_COLOR_INDEXES);
+
+       EXPP_ADDCONST(GL_MODELVIEW);
+       EXPP_ADDCONST(GL_PROJECTION);
+       EXPP_ADDCONST(GL_TEXTURE);
+
+       EXPP_ADDCONST(GL_COLOR);
+       EXPP_ADDCONST(GL_DEPTH);
+       EXPP_ADDCONST(GL_STENCIL);
+
+       EXPP_ADDCONST(GL_COLOR_INDEX);
+       EXPP_ADDCONST(GL_STENCIL_INDEX);
+       EXPP_ADDCONST(GL_DEPTH_COMPONENT);
+       EXPP_ADDCONST(GL_RED);
+       EXPP_ADDCONST(GL_GREEN);
+       EXPP_ADDCONST(GL_BLUE);
+       EXPP_ADDCONST(GL_ALPHA);
+       EXPP_ADDCONST(GL_RGB);
+       EXPP_ADDCONST(GL_RGBA);
+       EXPP_ADDCONST(GL_LUMINANCE);
+       EXPP_ADDCONST(GL_LUMINANCE_ALPHA);
+
+       EXPP_ADDCONST(GL_BITMAP);
+
+       EXPP_ADDCONST(GL_POINT);
+       EXPP_ADDCONST(GL_LINE);
+       EXPP_ADDCONST(GL_FILL);
+
+       EXPP_ADDCONST(GL_RENDER);
+       EXPP_ADDCONST(GL_FEEDBACK);
+       EXPP_ADDCONST(GL_SELECT);
+
+       EXPP_ADDCONST(GL_FLAT);
+       EXPP_ADDCONST(GL_SMOOTH);
+
+       EXPP_ADDCONST(GL_KEEP);
+       EXPP_ADDCONST(GL_REPLACE);
+       EXPP_ADDCONST(GL_INCR);
+       EXPP_ADDCONST(GL_DECR);
+
+       EXPP_ADDCONST(GL_VENDOR);
+       EXPP_ADDCONST(GL_RENDERER);
+       EXPP_ADDCONST(GL_VERSION);
+       EXPP_ADDCONST(GL_EXTENSIONS);
+
+       EXPP_ADDCONST(GL_S);
+       EXPP_ADDCONST(GL_T);
+       EXPP_ADDCONST(GL_R);
+       EXPP_ADDCONST(GL_Q);
+
+       EXPP_ADDCONST(GL_MODULATE);
+       EXPP_ADDCONST(GL_DECAL);
+
+       EXPP_ADDCONST(GL_TEXTURE_ENV_MODE);
+       EXPP_ADDCONST(GL_TEXTURE_ENV_COLOR);
+
+       EXPP_ADDCONST(GL_TEXTURE_ENV);
+
+       EXPP_ADDCONST(GL_EYE_LINEAR);
+       EXPP_ADDCONST(GL_OBJECT_LINEAR);
+       EXPP_ADDCONST(GL_SPHERE_MAP);
+
+       EXPP_ADDCONST(GL_TEXTURE_GEN_MODE);
+       EXPP_ADDCONST(GL_OBJECT_PLANE);
+       EXPP_ADDCONST(GL_EYE_PLANE);
+
+       EXPP_ADDCONST(GL_NEAREST);
+       EXPP_ADDCONST(GL_LINEAR);
+
+       EXPP_ADDCONST(GL_NEAREST_MIPMAP_NEAREST);
+       EXPP_ADDCONST(GL_LINEAR_MIPMAP_NEAREST);
+       EXPP_ADDCONST(GL_NEAREST_MIPMAP_LINEAR);
+       EXPP_ADDCONST(GL_LINEAR_MIPMAP_LINEAR);
+
+       EXPP_ADDCONST(GL_TEXTURE_MAG_FILTER);
+       EXPP_ADDCONST(GL_TEXTURE_MIN_FILTER);
+       EXPP_ADDCONST(GL_TEXTURE_WRAP_S);
+       EXPP_ADDCONST(GL_TEXTURE_WRAP_T);
+
+       EXPP_ADDCONST(GL_CLAMP);
+       EXPP_ADDCONST(GL_REPEAT);
+
+       EXPP_ADDCONST(GL_CLIP_PLANE0);
+       EXPP_ADDCONST(GL_CLIP_PLANE1);
+       EXPP_ADDCONST(GL_CLIP_PLANE2);
+       EXPP_ADDCONST(GL_CLIP_PLANE3);
+       EXPP_ADDCONST(GL_CLIP_PLANE4);
+       EXPP_ADDCONST(GL_CLIP_PLANE5);
+
+       EXPP_ADDCONST(GL_LIGHT0);
+       EXPP_ADDCONST(GL_LIGHT1);
+       EXPP_ADDCONST(GL_LIGHT2);
+       EXPP_ADDCONST(GL_LIGHT3);
+       EXPP_ADDCONST(GL_LIGHT4);
+       EXPP_ADDCONST(GL_LIGHT5);
+       EXPP_ADDCONST(GL_LIGHT6);
+       EXPP_ADDCONST(GL_LIGHT7);
+       
+       EXPP_ADDCONST(GL_POLYGON_OFFSET_UNITS);
+       EXPP_ADDCONST(GL_POLYGON_OFFSET_POINT);
+       EXPP_ADDCONST(GL_POLYGON_OFFSET_LINE);
+       EXPP_ADDCONST(GL_POLYGON_OFFSET_FILL);
+       EXPP_ADDCONST(GL_POLYGON_OFFSET_FACTOR);
+       
+       EXPP_ADDCONST(GL_TEXTURE_PRIORITY);
+       EXPP_ADDCONST(GL_TEXTURE_RESIDENT);
+       EXPP_ADDCONST(GL_TEXTURE_BINDING_1D);
+       EXPP_ADDCONST(GL_TEXTURE_BINDING_2D);
+      
+       return mod;
+}
+
diff --git a/source/blender/python/generic/BGL.h b/source/blender/python/generic/BGL.h
new file mode 100755 (executable)
index 0000000..345536d
--- /dev/null
@@ -0,0 +1,337 @@
+/* 
+ * $Id: BGL.h 19717 2009-04-14 17:19:09Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+/* This is the Blender.BGL part of opy_draw.c, from the old bpython/intern
+ * dir, with minor changes to adapt it to the new Python implementation.
+ * The BGL submodule "wraps" OpenGL functions and constants, allowing script
+ * writers to make OpenGL calls in their Python scripts for Blender.  The
+ * more important original comments are marked with an @ symbol. */
+
+#ifndef EXPP_BGL_H
+#define EXPP_BGL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Python.h>
+#include "BIF_gl.h"
+
+PyObject *BGL_Init( const char *from );
+
+/*@ Buffer Object */
+/*@ For Python access to OpenGL functions requiring a pointer. */
+
+typedef struct _Buffer {
+       PyObject_VAR_HEAD 
+       PyObject * parent;
+
+       int type;               /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */
+       int ndimensions;
+       int *dimensions;
+
+       union {
+               char *asbyte;
+               short *asshort;
+               int *asint;
+               float *asfloat;
+               double *asdouble;
+
+               void *asvoid;
+       } buf;
+} Buffer;
+
+
+/*@ By golly George! It looks like fancy pants macro time!!! */
+
+/*
+#define int_str       "i"
+#define int_var(number)   bgl_int##number
+#define int_ref(number)   &bgl_int##number
+#define int_def(number)   int int_var(number)
+
+#define float_str     "f"
+#define float_var(number) bgl_float##number
+#define float_ref(number) &bgl_float##number
+#define float_def(number) float float_var(number)
+*/
+
+/* TYPE_str is the string to pass to Py_ArgParse (for the format) */
+/* TYPE_var is the name to pass to the GL function */
+/* TYPE_ref is the pointer to pass to Py_ArgParse (to store in) */
+/* TYPE_def is the C initialization of the variable */
+
+#define void_str      ""
+#define void_var(num)
+#define void_ref(num)   &bgl_var##num
+#define void_def(num)   char bgl_var##num
+
+#define buffer_str      "O!"
+#define buffer_var(number)  (bgl_buffer##number)->buf.asvoid
+#define buffer_ref(number)  &buffer_Type, &bgl_buffer##number
+#define buffer_def(number)  Buffer *bgl_buffer##number
+
+/* GL Pointer fields, handled by buffer type */
+/* GLdoubleP, GLfloatP, GLintP, GLuintP, GLshortP */
+
+#define GLbooleanP_str      "O!"
+#define GLbooleanP_var(number)  (bgl_buffer##number)->buf.asvoid
+#define GLbooleanP_ref(number)  &buffer_Type, &bgl_buffer##number
+#define GLbooleanP_def(number)  Buffer *bgl_buffer##number
+
+#define GLbyteP_str     "O!"
+#define GLbyteP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLbyteP_ref(number) &buffer_Type, &bgl_buffer##number
+#define GLbyteP_def(number) Buffer *bgl_buffer##number
+
+#define GLubyteP_str      "O!"
+#define GLubyteP_var(number)  (bgl_buffer##number)->buf.asvoid
+#define GLubyteP_ref(number)  &buffer_Type, &bgl_buffer##number
+#define GLubyteP_def(number)  Buffer *bgl_buffer##number
+
+#define GLintP_str      "O!"
+#define GLintP_var(number)  (bgl_buffer##number)->buf.asvoid
+#define GLintP_ref(number)  &buffer_Type, &bgl_buffer##number
+#define GLintP_def(number)  Buffer *bgl_buffer##number
+
+#define GLuintP_str     "O!"
+#define GLuintP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLuintP_ref(number) &buffer_Type, &bgl_buffer##number
+#define GLuintP_def(number) Buffer *bgl_buffer##number
+
+#define GLshortP_str      "O!"
+#define GLshortP_var(number)  (bgl_buffer##number)->buf.asvoid
+#define GLshortP_ref(number)  &buffer_Type, &bgl_buffer##number
+#define GLshortP_def(number)  Buffer *bgl_buffer##number
+
+#define GLushortP_str     "O!"
+#define GLushortP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLushortP_ref(number) &buffer_Type, &bgl_buffer##number
+#define GLushortP_def(number) Buffer *bgl_buffer##number
+
+#define GLfloatP_str      "O!"
+#define GLfloatP_var(number)  (bgl_buffer##number)->buf.asvoid
+#define GLfloatP_ref(number)  &buffer_Type, &bgl_buffer##number
+#define GLfloatP_def(number)  Buffer *bgl_buffer##number
+
+#define GLdoubleP_str     "O!"
+#define GLdoubleP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLdoubleP_ref(number) &buffer_Type, &bgl_buffer##number
+#define GLdoubleP_def(number) Buffer *bgl_buffer##number
+
+#define GLclampfP_str     "O!"
+#define GLclampfP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLclampfP_ref(number) &buffer_Type, &bgl_buffer##number
+#define GLclampfP_def(number) Buffer *bgl_buffer##number
+
+#define GLvoidP_str     "O!"
+#define GLvoidP_var(number) (bgl_buffer##number)->buf.asvoid
+#define GLvoidP_ref(number) &buffer_Type, &bgl_buffer##number
+#define GLvoidP_def(number) Buffer *bgl_buffer##number
+
+#define buffer_str      "O!"
+#define buffer_var(number)  (bgl_buffer##number)->buf.asvoid
+#define buffer_ref(number)  &buffer_Type, &bgl_buffer##number
+#define buffer_def(number)  Buffer *bgl_buffer##number
+
+/*@The standard GL typedefs are used as prototypes, we can't
+ * use the GL type directly because Py_ArgParse expects normal
+ * C types.
+ * 
+ * Py_ArgParse doesn't grok writing into unsigned variables, 
+ * so we use signed everything (even stuff that should be unsigned.
+ */
+
+/* typedef unsigned int GLenum; */
+#define GLenum_str      "i"
+#define GLenum_var(num)   bgl_var##num
+#define GLenum_ref(num)   &bgl_var##num
+#define GLenum_def(num)   /* unsigned */ int GLenum_var(num)
+
+/* typedef unsigned int GLboolean; */
+#define GLboolean_str     "b"
+#define GLboolean_var(num)    bgl_var##num
+#define GLboolean_ref(num)    &bgl_var##num
+#define GLboolean_def(num)    /* unsigned */ char GLboolean_var(num)
+
+/* typedef unsigned int GLbitfield; */
+#define GLbitfield_str      "i"
+#define GLbitfield_var(num)   bgl_var##num
+#define GLbitfield_ref(num)   &bgl_var##num
+#define GLbitfield_def(num)   /* unsigned */ int GLbitfield_var(num)
+
+/* typedef signed char GLbyte; */
+#define GLbyte_str        "b"
+#define GLbyte_var(num)     bgl_var##num
+#define GLbyte_ref(num)     &bgl_var##num
+#define GLbyte_def(num)     signed char GLbyte_var(num)
+
+/* typedef short GLshort; */
+#define GLshort_str       "h"
+#define GLshort_var(num)    bgl_var##num
+#define GLshort_ref(num)    &bgl_var##num
+#define GLshort_def(num)    short GLshort_var(num)
+
+/* typedef int GLint; */
+#define GLint_str       "i"
+#define GLint_var(num)      bgl_var##num
+#define GLint_ref(num)      &bgl_var##num
+#define GLint_def(num)      int GLint_var(num)
+
+/* typedef int GLsizei; */
+#define GLsizei_str       "i"
+#define GLsizei_var(num)    bgl_var##num
+#define GLsizei_ref(num)    &bgl_var##num
+#define GLsizei_def(num)    int GLsizei_var(num)
+
+/* typedef unsigned char GLubyte; */
+#define GLubyte_str       "b"
+#define GLubyte_var(num)    bgl_var##num
+#define GLubyte_ref(num)    &bgl_var##num
+#define GLubyte_def(num)    /* unsigned */ char GLubyte_var(num)
+
+/* typedef unsigned short GLushort; */
+#define GLushort_str      "h"
+#define GLushort_var(num)   bgl_var##num
+#define GLushort_ref(num)   &bgl_var##num
+#define GLushort_def(num)   /* unsigned */ short GLushort_var(num)
+
+/* typedef unsigned int GLuint; */
+#define GLuint_str        "i"
+#define GLuint_var(num)     bgl_var##num
+#define GLuint_ref(num)     &bgl_var##num
+#define GLuint_def(num)     /* unsigned */ int GLuint_var(num)
+
+/* typedef float GLfloat; */
+#define GLfloat_str       "f"
+#define GLfloat_var(num)    bgl_var##num
+#define GLfloat_ref(num)    &bgl_var##num
+#define GLfloat_def(num)    float GLfloat_var(num)
+
+/* typedef float GLclampf; */
+#define GLclampf_str      "f"
+#define GLclampf_var(num)   bgl_var##num
+#define GLclampf_ref(num)   &bgl_var##num
+#define GLclampf_def(num)   float GLclampf_var(num)
+
+/* typedef double GLdouble; */
+#define GLdouble_str      "d"
+#define GLdouble_var(num)   bgl_var##num
+#define GLdouble_ref(num)   &bgl_var##num
+#define GLdouble_def(num)   double GLdouble_var(num)
+
+/* typedef double GLclampd; */
+#define GLclampd_str      "d"
+#define GLclampd_var(num)   bgl_var##num
+#define GLclampd_ref(num)   &bgl_var##num
+#define GLclampd_def(num)   double GLclampd_var(num)
+
+/* typedef void GLvoid; */
+/* #define GLvoid_str       "" */
+/* #define GLvoid_var(num)      bgl_var##num */
+/* #define GLvoid_ref(num)      &bgl_var##num */
+/* #define GLvoid_def(num)      char bgl_var##num */
+
+#define arg_def1(a1)          a1##_def(1)
+#define arg_def2(a1, a2)        arg_def1(a1); a2##_def(2)
+#define arg_def3(a1, a2, a3)      arg_def2(a1, a2); a3##_def(3)
+#define arg_def4(a1, a2, a3, a4)    arg_def3(a1, a2, a3); a4##_def(4)
+#define arg_def5(a1, a2, a3, a4, a5)  arg_def4(a1, a2, a3, a4); a5##_def(5)
+#define arg_def6(a1, a2, a3, a4, a5, a6)arg_def5(a1, a2, a3, a4, a5); a6##_def(6)
+#define arg_def7(a1, a2, a3, a4, a5, a6, a7)arg_def6(a1, a2, a3, a4, a5, a6); a7##_def(7)
+#define arg_def8(a1, a2, a3, a4, a5, a6, a7, a8)arg_def7(a1, a2, a3, a4, a5, a6, a7); a8##_def(8)
+#define arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_def8(a1, a2, a3, a4, a5, a6, a7, a8); a9##_def(9)
+#define arg_def10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9); a10##_def(10)
+
+#define arg_var1(a1)          a1##_var(1)
+#define arg_var2(a1, a2)        arg_var1(a1), a2##_var(2)
+#define arg_var3(a1, a2, a3)      arg_var2(a1, a2), a3##_var(3)
+#define arg_var4(a1, a2, a3, a4)    arg_var3(a1, a2, a3), a4##_var(4)
+#define arg_var5(a1, a2, a3, a4, a5)  arg_var4(a1, a2, a3, a4), a5##_var(5)
+#define arg_var6(a1, a2, a3, a4, a5, a6)arg_var5(a1, a2, a3, a4, a5), a6##_var(6)
+#define arg_var7(a1, a2, a3, a4, a5, a6, a7)arg_var6(a1, a2, a3, a4, a5, a6), a7##_var(7)
+#define arg_var8(a1, a2, a3, a4, a5, a6, a7, a8)arg_var7(a1, a2, a3, a4, a5, a6, a7), a8##_var(8)
+#define arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_var8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_var(9)
+#define arg_var10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_var(10)
+
+#define arg_ref1(a1)          a1##_ref(1)
+#define arg_ref2(a1, a2)        arg_ref1(a1), a2##_ref(2)
+#define arg_ref3(a1, a2, a3)      arg_ref2(a1, a2), a3##_ref(3)
+#define arg_ref4(a1, a2, a3, a4)    arg_ref3(a1, a2, a3), a4##_ref(4)
+#define arg_ref5(a1, a2, a3, a4, a5)  arg_ref4(a1, a2, a3, a4), a5##_ref(5)
+#define arg_ref6(a1, a2, a3, a4, a5, a6)arg_ref5(a1, a2, a3, a4, a5), a6##_ref(6)
+#define arg_ref7(a1, a2, a3, a4, a5, a6, a7)arg_ref6(a1, a2, a3, a4, a5, a6), a7##_ref(7)
+#define arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8)arg_ref7(a1, a2, a3, a4, a5, a6, a7), a8##_ref(8)
+#define arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_ref(9)
+#define arg_ref10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_ref(10)
+
+#define arg_str1(a1)          a1##_str
+#define arg_str2(a1, a2)        arg_str1(a1) a2##_str
+#define arg_str3(a1, a2, a3)      arg_str2(a1, a2) a3##_str
+#define arg_str4(a1, a2, a3, a4)    arg_str3(a1, a2, a3) a4##_str
+#define arg_str5(a1, a2, a3, a4, a5)  arg_str4(a1, a2, a3, a4) a5##_str
+#define arg_str6(a1, a2, a3, a4, a5, a6)arg_str5(a1, a2, a3, a4, a5) a6##_str
+#define arg_str7(a1, a2, a3, a4, a5, a6, a7)arg_str6(a1, a2, a3, a4, a5, a6) a7##_str
+#define arg_str8(a1, a2, a3, a4, a5, a6, a7, a8)arg_str7(a1, a2, a3, a4, a5, a6, a7) a8##_str
+#define arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_str8(a1, a2, a3, a4, a5, a6, a7, a8) a9##_str
+#define arg_str10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a10##_str
+
+#define ret_def_void
+#define ret_set_void
+/* would use Py_RETURN_NONE - except for py 2.3 doesnt have it */
+#define ret_ret_void    { Py_INCREF(Py_None); return Py_None; }
+
+#define ret_def_GLint   int ret_int
+#define ret_set_GLint   ret_int=
+#define ret_ret_GLint   return PyLong_FromLong(ret_int);
+
+#define ret_def_GLuint    unsigned int ret_uint
+#define ret_set_GLuint    ret_uint=
+#define ret_ret_GLuint    return PyLong_FromLong((long) ret_uint);
+
+#define ret_def_GLenum    unsigned int ret_uint
+#define ret_set_GLenum    ret_uint=
+#define ret_ret_GLenum    return PyLong_FromLong((long) ret_uint);
+
+#define ret_def_GLboolean unsigned char ret_bool
+#define ret_set_GLboolean ret_bool=
+#define ret_ret_GLboolean return PyLong_FromLong((long) ret_bool);
+
+#define ret_def_GLstring  const unsigned char *ret_str;
+#define ret_set_GLstring  ret_str=
+
+#define ret_ret_GLstring \
+       if (ret_str) {\
+               return PyUnicode_FromString(ret_str);\
+       } else {\
+               PyErr_SetString(PyExc_AttributeError, "could not get opengl string");\
+               return NULL;\
+       }
+
+#endif  /*  EXPP_BGL_H */
diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c
new file mode 100644 (file)
index 0000000..d1e8b47
--- /dev/null
@@ -0,0 +1,522 @@
+/* 
+ * $Id: Geometry.c 20922 2009-06-16 07:16:51Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA       02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Joseph Gilbert, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "Geometry.h"
+
+/*  - Not needed for now though other geometry functions will probably need them
+#include "BLI_arithb.h"
+#include "BKE_utildefines.h"
+*/
+
+/* Used for PolyFill */
+#include "BKE_displist.h"
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BKE_utildefines.h"
+#include "BKE_curve.h"
+#include "BLI_boxpack2d.h"
+#include "BLI_arithb.h"
+
+#define SWAP_FLOAT(a,b,tmp) tmp=a; a=b; b=tmp
+#define eul 0.000001
+
+/*-- forward declarations -- */
+static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq );
+static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args );
+static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args );
+static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args );
+static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args );
+static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * args );
+static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args );
+
+
+/*-------------------------DOC STRINGS ---------------------------*/
+static char M_Geometry_doc[] = "The Blender Geometry module\n\n";
+static char M_Geometry_PolyFill_doc[] = "(veclist_list) - takes a list of polylines (each point a vector) and returns the point indicies for a polyline filled with triangles";
+static char M_Geometry_LineIntersect2D_doc[] = "(lineA_p1, lineA_p2, lineB_p1, lineB_p2) - takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None";
+static char M_Geometry_ClosestPointOnLine_doc[] = "(pt, line_p1, line_p2) - takes a point and a line and returns a (Vector, float) for the point on the line, and the bool so you can know if the point was between the 2 points";
+static char M_Geometry_PointInTriangle2D_doc[] = "(pt, tri_p1, tri_p2, tri_p3) - takes 4 vectors, one is the point and the next 3 define the triangle, only the x and y are used from the vectors";
+static char M_Geometry_PointInQuad2D_doc[] = "(pt, quad_p1, quad_p2, quad_p3, quad_p4) - takes 5 vectors, one is the point and the next 4 define the quad, only the x and y are used from the vectors";
+static char M_Geometry_BoxPack2D_doc[] = "";
+static char M_Geometry_BezierInterp_doc[] = "";
+/*-----------------------METHOD DEFINITIONS ----------------------*/
+struct PyMethodDef M_Geometry_methods[] = {
+       {"PolyFill", ( PyCFunction ) M_Geometry_PolyFill, METH_O, M_Geometry_PolyFill_doc},
+       {"LineIntersect2D", ( PyCFunction ) M_Geometry_LineIntersect2D, METH_VARARGS, M_Geometry_LineIntersect2D_doc},
+       {"ClosestPointOnLine", ( PyCFunction ) M_Geometry_ClosestPointOnLine, METH_VARARGS, M_Geometry_ClosestPointOnLine_doc},
+       {"PointInTriangle2D", ( PyCFunction ) M_Geometry_PointInTriangle2D, METH_VARARGS, M_Geometry_PointInTriangle2D_doc},
+       {"PointInQuad2D", ( PyCFunction ) M_Geometry_PointInQuad2D, METH_VARARGS, M_Geometry_PointInQuad2D_doc},
+       {"BoxPack2D", ( PyCFunction ) M_Geometry_BoxPack2D, METH_O, M_Geometry_BoxPack2D_doc},
+       {"BezierInterp", ( PyCFunction ) M_Geometry_BezierInterp, METH_VARARGS, M_Geometry_BezierInterp_doc},
+       {NULL, NULL, 0, NULL}
+};
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef M_Geometry_module_def = {
+       {}, /* m_base */
+       "Geometry",  /* m_name */
+       M_Geometry_doc,  /* m_doc */
+       0,  /* m_size */
+       M_Geometry_methods,  /* m_methods */
+       0,  /* m_reload */
+       0,  /* m_traverse */
+       0,  /* m_clear */
+       0,  /* m_free */
+};
+#endif
+
+/*----------------------------MODULE INIT-------------------------*/
+PyObject *Geometry_Init(const char *from)
+{
+       PyObject *submodule;
+       
+#if (PY_VERSION_HEX >= 0x03000000)
+       submodule = PyModule_Create(&M_Geometry_module_def);
+       PyDict_SetItemString(PySys_GetObject("modules"), M_Geometry_module_def.m_name, submodule);
+#else
+       submodule = Py_InitModule3(from, M_Geometry_methods, M_Geometry_doc);
+#endif
+       
+       return (submodule);
+}
+
+/*----------------------------------Geometry.PolyFill() -------------------*/
+/* PolyFill function, uses Blenders scanfill to fill multiple poly lines */
+static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
+{
+       PyObject *tri_list; /*return this list of tri's */
+       PyObject *polyLine, *polyVec;
+       int i, len_polylines, len_polypoints, ls_error = 0;
+       
+       /* display listbase */
+       ListBase dispbase={NULL, NULL};
+       DispList *dl;
+       float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */
+       int index, *dl_face, totpoints=0;
+       
+       
+       dispbase.first= dispbase.last= NULL;
+       
+       
+       if(!PySequence_Check(polyLineSeq)) {
+               PyErr_SetString( PyExc_TypeError, "expected a sequence of poly lines" );
+               return NULL;
+       }
+       
+       len_polylines = PySequence_Size( polyLineSeq );
+       
+       for( i = 0; i < len_polylines; ++i ) {
+               polyLine= PySequence_GetItem( polyLineSeq, i );
+               if (!PySequence_Check(polyLine)) {
+                       freedisplist(&dispbase);
+                       Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/
+                       PyErr_SetString( PyExc_TypeError, "One or more of the polylines is not a sequence of Mathutils.Vector's" );
+                       return NULL;
+               }
+               
+               len_polypoints= PySequence_Size( polyLine );
+               if (len_polypoints>0) { /* dont bother adding edges as polylines */
+#if 0
+                       if (EXPP_check_sequence_consistency( polyLine, &vector_Type ) != 1) {
+                               freedisplist(&dispbase);
+                               Py_DECREF(polyLine);
+                               PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" );
+                               return NULL;
+                       }
+#endif
+                       dl= MEM_callocN(sizeof(DispList), "poly disp");
+                       BLI_addtail(&dispbase, dl);
+                       dl->type= DL_INDEX3;
+                       dl->nr= len_polypoints;
+                       dl->type= DL_POLY;
+                       dl->parts= 1; /* no faces, 1 edge loop */
+                       dl->col= 0; /* no material */
+                       dl->verts= fp= MEM_callocN( sizeof(float)*3*len_polypoints, "dl verts");
+                       dl->index= MEM_callocN(sizeof(int)*3*len_polypoints, "dl index");
+                       
+                       for( index = 0; index<len_polypoints; ++index, fp+=3) {
+                               polyVec= PySequence_GetItem( polyLine, index );
+                               if(VectorObject_Check(polyVec)) {
+                                       fp[0] = ((VectorObject *)polyVec)->vec[0];
+                                       fp[1] = ((VectorObject *)polyVec)->vec[1];
+                                       if( ((VectorObject *)polyVec)->size > 2 )
+                                               fp[2] = ((VectorObject *)polyVec)->vec[2];
+                                       else
+                                               fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */
+                               }
+                               else {
+                                       ls_error= 1;
+                               }
+                               
+                               totpoints++;
+                               Py_DECREF(polyVec);
+                       }
+               }
+               Py_DECREF(polyLine);
+       }
+       
+       if(ls_error) {
+               freedisplist(&dispbase); /* possible some dl was allocated */
+               PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" );
+               return NULL;
+       }
+       else if (totpoints) {
+               /* now make the list to return */
+               filldisplist(&dispbase, &dispbase);
+               
+               /* The faces are stored in a new DisplayList
+               thats added to the head of the listbase */
+               dl= dispbase.first; 
+               
+               tri_list= PyList_New(dl->parts);
+               if( !tri_list ) {
+                       freedisplist(&dispbase);
+                       PyErr_SetString( PyExc_RuntimeError, "Geometry.PolyFill failed to make a new list" );
+                       return NULL;
+               }
+               
+               index= 0;
+               dl_face= dl->index;
+               while(index < dl->parts) {
+                       PyList_SetItem(tri_list, index, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2]) );
+                       dl_face+= 3;
+                       index++;
+               }
+               freedisplist(&dispbase);
+       } else {
+               /* no points, do this so scripts dont barf */
+               freedisplist(&dispbase); /* possible some dl was allocated */
+               tri_list= PyList_New(0);
+       }
+       
+       return tri_list;
+}
+
+
+static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
+{
+       VectorObject *line_a1, *line_a2, *line_b1, *line_b2;
+       float a1x, a1y, a2x, a2y,  b1x, b1y, b2x, b2y, xi, yi, a1,a2,b1,b2, newvec[2];
+       if( !PyArg_ParseTuple ( args, "O!O!O!O!",
+         &vector_Type, &line_a1,
+         &vector_Type, &line_a2,
+         &vector_Type, &line_b1,
+         &vector_Type, &line_b2)
+       ) {
+               PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+               return NULL;
+       }
+       
+       a1x= line_a1->vec[0];
+       a1y= line_a1->vec[1];
+       a2x= line_a2->vec[0];
+       a2y= line_a2->vec[1];
+
+       b1x= line_b1->vec[0];
+       b1y= line_b1->vec[1];
+       b2x= line_b2->vec[0];
+       b2y= line_b2->vec[1];
+       
+       if((MIN2(a1x, a2x) > MAX2(b1x, b2x)) ||
+          (MAX2(a1x, a2x) < MIN2(b1x, b2x)) ||
+          (MIN2(a1y, a2y) > MAX2(b1y, b2y)) ||
+          (MAX2(a1y, a2y) < MIN2(b1y, b2y))  ) {
+               Py_RETURN_NONE;
+       }
+       /* Make sure the hoz/vert line comes first. */
+       if (fabs(b1x - b2x) < eul || fabs(b1y - b2y) < eul) {
+               SWAP_FLOAT(a1x, b1x, xi); /*abuse xi*/
+               SWAP_FLOAT(a1y, b1y, xi);
+               SWAP_FLOAT(a2x, b2x, xi);
+               SWAP_FLOAT(a2y, b2y, xi);
+       }
+       
+       if (fabs(a1x-a2x) < eul) { /* verticle line */
+               if (fabs(b1x-b2x) < eul){ /*verticle second line */
+                       Py_RETURN_NONE; /* 2 verticle lines dont intersect. */
+               }
+               else if (fabs(b1y-b2y) < eul) {
+                       /*X of vert, Y of hoz. no calculation needed */
+                       newvec[0]= a1x;
+                       newvec[1]= b1y;
+                       return newVectorObject(newvec, 2, Py_NEW);
+               }
+               
+               yi = (float)(((b1y / fabs(b1x - b2x)) * fabs(b2x - a1x)) + ((b2y / fabs(b1x - b2x)) * fabs(b1x - a1x)));
+               
+               if (yi > MAX2(a1y, a2y)) {/* New point above seg1's vert line */
+                       Py_RETURN_NONE;
+               } else if (yi < MIN2(a1y, a2y)) { /* New point below seg1's vert line */
+                       Py_RETURN_NONE;
+               }
+               newvec[0]= a1x;
+               newvec[1]= yi;
+               return newVectorObject(newvec, 2, Py_NEW);
+       } else if (fabs(a2y-a1y) < eul) {  /* hoz line1 */
+               if (fabs(b2y-b1y) < eul) { /*hoz line2*/
+                       Py_RETURN_NONE; /*2 hoz lines dont intersect*/
+               }
+               
+               /* Can skip vert line check for seg 2 since its covered above. */
+               xi = (float)(((b1x / fabs(b1y - b2y)) * fabs(b2y - a1y)) + ((b2x / fabs(b1y - b2y)) * fabs(b1y - a1y)));
+               if (xi > MAX2(a1x, a2x)) { /* New point right of hoz line1's */
+                       Py_RETURN_NONE;
+               } else if (xi < MIN2(a1x, a2x)) { /*New point left of seg1's hoz line */
+                       Py_RETURN_NONE;
+               }
+               newvec[0]= xi;
+               newvec[1]= a1y;
+               return newVectorObject(newvec, 2, Py_NEW);
+       }
+       
+       b1 = (a2y-a1y)/(a2x-a1x);
+       b2 = (b2y-b1y)/(b2x-b1x);
+       a1 = a1y-b1*a1x;
+       a2 = b1y-b2*b1x;
+       
+       if (b1 - b2 == 0.0) {
+               Py_RETURN_NONE;
+       }
+       
+       xi = - (a1-a2)/(b1-b2);
+       yi = a1+b1*xi;
+       if ((a1x-xi)*(xi-a2x) >= 0 && (b1x-xi)*(xi-b2x) >= 0 && (a1y-yi)*(yi-a2y) >= 0 && (b1y-yi)*(yi-b2y)>=0) {
+               newvec[0]= xi;
+               newvec[1]= yi;
+               return newVectorObject(newvec, 2, Py_NEW);
+       }
+       Py_RETURN_NONE;
+}
+
+static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args )
+{
+       VectorObject *pt, *line_1, *line_2;
+       float pt_in[3], pt_out[3], l1[3], l2[3];
+       float lambda;
+       PyObject *ret;
+       
+       if( !PyArg_ParseTuple ( args, "O!O!O!",
+       &vector_Type, &pt,
+       &vector_Type, &line_1,
+       &vector_Type, &line_2)
+         ) {
+               PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
+               return NULL;
+       }
+       /* accept 2d verts */
+       if (pt->size==3) { VECCOPY(pt_in, pt->vec);}
+       else { pt_in[2]=0.0;    VECCOPY2D(pt_in, pt->vec) }
+       
+       if (line_1->size==3) { VECCOPY(l1, line_1->vec);}
+       else { l1[2]=0.0;       VECCOPY2D(l1, line_1->vec) }
+       
+       if (line_2->size==3) { VECCOPY(l2, line_2->vec);}
+       else { l2[2]=0.0;       VECCOPY2D(l2, line_2->vec) }
+       
+       /* do the calculation */
+       lambda = lambda_cp_line_ex(pt_in, l1, l2, pt_out);
+       
+       ret = PyTuple_New(2);
+       PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW) );
+       PyTuple_SET_ITEM( ret, 1, PyFloat_FromDouble(lambda) );
+       return ret;
+}
+
+static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args )
+{
+       VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
+       
+       if( !PyArg_ParseTuple ( args, "O!O!O!O!",
+         &vector_Type, &pt_vec,
+         &vector_Type, &tri_p1,
+         &vector_Type, &tri_p2,
+         &vector_Type, &tri_p3)
+       ) {
+               PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+               return NULL;
+       }
+       
+       return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
+}
+
+static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args )
+{
+       VectorObject *pt_vec, *quad_p1, *quad_p2, *quad_p3, *quad_p4;
+       
+       if( !PyArg_ParseTuple ( args, "O!O!O!O!O!",
+         &vector_Type, &pt_vec,
+         &vector_Type, &quad_p1,
+         &vector_Type, &quad_p2,
+         &vector_Type, &quad_p3,
+         &vector_Type, &quad_p4)
+       ) {
+               PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
+               return NULL;
+       }
+       
+       return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
+}
+
+static int boxPack_FromPyObject(PyObject * value, boxPack **boxarray )
+{
+       int len, i;
+       PyObject *list_item, *item_1, *item_2;
+       boxPack *box;
+       
+       
+       /* Error checking must alredy be done */
+       if( !PyList_Check( value ) ) {
+               PyErr_SetString( PyExc_TypeError, "can only back a list of [x,y,x,w]" );
+               return -1;
+       }
+       
+       len = PyList_Size( value );
+       
+       (*boxarray) = MEM_mallocN( len*sizeof(boxPack), "boxPack box");
+       
+       
+       for( i = 0; i < len; i++ ) {
+               list_item = PyList_GET_ITEM( value, i );
+               if( !PyList_Check( list_item ) || PyList_Size( list_item ) < 4 ) {
+                       MEM_freeN(*boxarray);
+                       PyErr_SetString( PyExc_TypeError, "can only back a list of [x,y,x,w]" );
+                       return -1;
+               }
+               
+               box = (*boxarray)+i;
+               
+               item_1 = PyList_GET_ITEM(list_item, 2);
+               item_2 = PyList_GET_ITEM(list_item, 3);
+               
+               if (!PyNumber_Check(item_1) || !PyNumber_Check(item_2)) {
+                       MEM_freeN(*boxarray);
+                       PyErr_SetString( PyExc_TypeError, "can only back a list of 2d boxes [x,y,x,w]" );
+                       return -1;
+               }
+               
+               box->w =  (float)PyFloat_AsDouble( item_1 );
+               box->h =  (float)PyFloat_AsDouble( item_2 );
+               box->index = i;
+               /* verts will be added later */
+       }
+       return 0;
+}
+
+static void boxPack_ToPyObject(PyObject * value, boxPack **boxarray)
+{
+       int len, i;
+       PyObject *list_item;
+       boxPack *box;
+       
+       len = PyList_Size( value );
+       
+       for( i = 0; i < len; i++ ) {
+               box = (*boxarray)+i;
+               list_item = PyList_GET_ITEM( value, box->index );
+               PyList_SET_ITEM( list_item, 0, PyFloat_FromDouble( box->x ));
+               PyList_SET_ITEM( list_item, 1, PyFloat_FromDouble( box->y ));
+       }
+       MEM_freeN(*boxarray);
+}
+
+
+static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * boxlist )
+{
+       boxPack *boxarray = NULL;
+       float tot_width, tot_height;
+       int len;
+       int error;
+       
+       if(!PyList_Check(boxlist)) {
+               PyErr_SetString( PyExc_TypeError, "expected a sequence of boxes [[x,y,w,h], ... ]" );
+               return NULL;
+       }
+       
+       len = PyList_Size( boxlist );
+       
+       if (!len)
+               return Py_BuildValue( "ff", 0.0, 0.0);
+       
+       error = boxPack_FromPyObject(boxlist, &boxarray);
+       if (error!=0)   return NULL;
+       
+       /* Non Python function */
+       boxPack2D(boxarray, len, &tot_width, &tot_height);
+       
+       boxPack_ToPyObject(boxlist, &boxarray);
+       
+       return Py_BuildValue( "ff", tot_width, tot_height);
+}
+
+static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args )
+{
+       VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
+       int resolu;
+       int dims;
+       int i;
+       float *coord_array, *fp;
+       PyObject *list;
+       
+       float k1[4] = {0.0, 0.0, 0.0, 0.0};
+       float h1[4] = {0.0, 0.0, 0.0, 0.0};
+       float k2[4] = {0.0, 0.0, 0.0, 0.0};
+       float h2[4] = {0.0, 0.0, 0.0, 0.0};
+       
+       
+       if( !PyArg_ParseTuple ( args, "O!O!O!O!i",
+         &vector_Type, &vec_k1,
+         &vector_Type, &vec_h1,
+         &vector_Type, &vec_h2,
+         &vector_Type, &vec_k2, &resolu) || (resolu<=1)
+       ) {
+               PyErr_SetString( PyExc_TypeError, "expected 4 vector types and an int greater then 1\n" );
+               return NULL;
+       }
+       
+       dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
+       
+       for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i];
+       for(i=0; i < vec_h1->size; i++) h1[i]= vec_h1->vec[i];
+       for(i=0; i < vec_k2->size; i++) k2[i]= vec_k2->vec[i];
+       for(i=0; i < vec_h2->size; i++) h2[i]= vec_h2->vec[i];
+       
+       coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "BezierInterp");
+       for(i=0; i<dims; i++) {
+               forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array+i, resolu-1, dims);
+       }
+       
+       list= PyList_New(resolu);
+       fp= coord_array;
+       for(i=0; i<resolu; i++, fp= fp+dims) {
+               PyList_SET_ITEM(list, i, newVectorObject(fp, dims, Py_NEW));
+       }
+       MEM_freeN(coord_array);
+       return list;
+}
diff --git a/source/blender/python/generic/Geometry.h b/source/blender/python/generic/Geometry.h
new file mode 100644 (file)
index 0000000..d7292e3
--- /dev/null
@@ -0,0 +1,39 @@
+/* 
+ * $Id: Geometry.h 20007 2009-04-30 12:45:13Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA       02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+/*Include this file for access to vector, quat, matrix, euler, etc...*/
+
+#ifndef EXPP_Geometry_H
+#define EXPP_Geometry_H
+
+#include <Python.h>
+#include "Mathutils.h"
+
+PyObject *Geometry_Init( const char *from );
+
+#endif                         /* EXPP_Geometry_H */
diff --git a/source/blender/python/generic/Mathutils.c b/source/blender/python/generic/Mathutils.c
new file mode 100644 (file)
index 0000000..1e2e59e
--- /dev/null
@@ -0,0 +1,1712 @@
+/* 
+ * $Id: Mathutils.c 20922 2009-06-16 07:16:51Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA       02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Joseph Gilbert, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "Mathutils.h"
+
+#include "BLI_arithb.h"
+#include "PIL_time.h"
+#include "BLI_rand.h"
+#include "BKE_utildefines.h"
+
+//-------------------------DOC STRINGS ---------------------------
+static char M_Mathutils_doc[] = "The Blender Mathutils module\n\n";
+static char M_Mathutils_Vector_doc[] = "() - create a new vector object from a list of floats";
+static char M_Mathutils_Matrix_doc[] = "() - create a new matrix object from a list of floats";
+static char M_Mathutils_Quaternion_doc[] = "() - create a quaternion from a list or an axis of rotation and an angle";
+static char M_Mathutils_Euler_doc[] = "() - create and return a new euler object";
+static char M_Mathutils_Rand_doc[] = "() - return a random number";
+static char M_Mathutils_CrossVecs_doc[] = "() - returns a vector perpedicular to the 2 vectors crossed";
+static char M_Mathutils_CopyVec_doc[] = "() - create a copy of vector";
+static char M_Mathutils_DotVecs_doc[] = "() - return the dot product of two vectors";
+static char M_Mathutils_AngleBetweenVecs_doc[] = "() - returns the angle between two vectors in degrees";
+static char M_Mathutils_MidpointVecs_doc[] = "() - return the vector to the midpoint between two vectors";
+static char M_Mathutils_MatMultVec_doc[] = "() - multiplies a matrix by a column vector";
+static char M_Mathutils_VecMultMat_doc[] = "() - multiplies a row vector by a matrix";
+static char M_Mathutils_ProjectVecs_doc[] =    "() - returns the projection vector from the projection of vecA onto vecB";
+static char M_Mathutils_RotationMatrix_doc[] = "() - construct a rotation matrix from an angle and axis of rotation";
+static char M_Mathutils_ScaleMatrix_doc[] =    "() - construct a scaling matrix from a scaling factor";
+static char M_Mathutils_OrthoProjectionMatrix_doc[] = "() - construct a orthographic projection matrix from a selected plane";
+static char M_Mathutils_ShearMatrix_doc[] = "() - construct a shearing matrix from a plane of shear and a shear factor";
+static char M_Mathutils_CopyMat_doc[] = "() - create a copy of a matrix";
+static char M_Mathutils_TranslationMatrix_doc[] = "(vec) - create a translation matrix from a vector";
+static char M_Mathutils_CopyQuat_doc[] = "() - copy quatB to quatA";
+static char M_Mathutils_CopyEuler_doc[] = "() - copy eulB to eultA";
+static char M_Mathutils_CrossQuats_doc[] = "() - return the mutliplication of two quaternions";
+static char M_Mathutils_DotQuats_doc[] = "() - return the dot product of two quaternions";
+static char M_Mathutils_Slerp_doc[] = "() - returns the interpolation between two quaternions";
+static char M_Mathutils_DifferenceQuats_doc[] = "() - return the angular displacment difference between two quats";
+static char M_Mathutils_RotateEuler_doc[] = "() - rotate euler by an axis and angle";
+static char M_Mathutils_Intersect_doc[] = "(v1, v2, v3, ray, orig, clip=1) - returns the intersection between a ray and a triangle, if possible, returns None otherwise";
+static char M_Mathutils_TriangleArea_doc[] = "(v1, v2, v3) - returns the area size of the 2D or 3D triangle defined";
+static char M_Mathutils_TriangleNormal_doc[] = "(v1, v2, v3) - returns the normal of the 3D triangle defined";
+static char M_Mathutils_QuadNormal_doc[] = "(v1, v2, v3, v4) - returns the normal of the 3D quad defined";
+static char M_Mathutils_LineIntersect_doc[] = "(v1, v2, v3, v4) - returns a tuple with the points on each line respectively closest to the other";
+//-----------------------METHOD DEFINITIONS ----------------------
+struct PyMethodDef M_Mathutils_methods[] = {
+       {"Rand", (PyCFunction) M_Mathutils_Rand, METH_VARARGS, M_Mathutils_Rand_doc},
+       {"Vector", (PyCFunction) M_Mathutils_Vector, METH_VARARGS, M_Mathutils_Vector_doc},
+       {"CrossVecs", (PyCFunction) M_Mathutils_CrossVecs, METH_VARARGS, M_Mathutils_CrossVecs_doc},
+       {"DotVecs", (PyCFunction) M_Mathutils_DotVecs, METH_VARARGS, M_Mathutils_DotVecs_doc},
+       {"AngleBetweenVecs", (PyCFunction) M_Mathutils_AngleBetweenVecs, METH_VARARGS, M_Mathutils_AngleBetweenVecs_doc},
+       {"MidpointVecs", (PyCFunction) M_Mathutils_MidpointVecs, METH_VARARGS, M_Mathutils_MidpointVecs_doc},
+       {"VecMultMat", (PyCFunction) M_Mathutils_VecMultMat, METH_VARARGS, M_Mathutils_VecMultMat_doc},
+       {"ProjectVecs", (PyCFunction) M_Mathutils_ProjectVecs, METH_VARARGS, M_Mathutils_ProjectVecs_doc},
+       {"CopyVec", (PyCFunction) M_Mathutils_CopyVec, METH_VARARGS, M_Mathutils_CopyVec_doc},
+       {"Matrix", (PyCFunction) M_Mathutils_Matrix, METH_VARARGS, M_Mathutils_Matrix_doc},
+       {"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc},
+       {"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc},
+       {"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc},
+       {"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc},
+       {"CopyMat", (PyCFunction) M_Mathutils_CopyMat, METH_VARARGS, M_Mathutils_CopyMat_doc},
+       {"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix,  METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc},
+       {"MatMultVec", (PyCFunction) M_Mathutils_MatMultVec, METH_VARARGS, M_Mathutils_MatMultVec_doc},
+       {"Quaternion", (PyCFunction) M_Mathutils_Quaternion, METH_VARARGS, M_Mathutils_Quaternion_doc},
+       {"CopyQuat", (PyCFunction) M_Mathutils_CopyQuat, METH_VARARGS, M_Mathutils_CopyQuat_doc},
+       {"CrossQuats", (PyCFunction) M_Mathutils_CrossQuats, METH_VARARGS, M_Mathutils_CrossQuats_doc},
+       {"DotQuats", (PyCFunction) M_Mathutils_DotQuats, METH_VARARGS, M_Mathutils_DotQuats_doc},
+       {"DifferenceQuats", (PyCFunction) M_Mathutils_DifferenceQuats, METH_VARARGS,M_Mathutils_DifferenceQuats_doc},
+       {"Slerp", (PyCFunction) M_Mathutils_Slerp, METH_VARARGS, M_Mathutils_Slerp_doc},
+       {"Euler", (PyCFunction) M_Mathutils_Euler, METH_VARARGS, M_Mathutils_Euler_doc},
+       {"CopyEuler", (PyCFunction) M_Mathutils_CopyEuler, METH_VARARGS, M_Mathutils_CopyEuler_doc},
+       {"RotateEuler", (PyCFunction) M_Mathutils_RotateEuler, METH_VARARGS, M_Mathutils_RotateEuler_doc},
+       {"Intersect", ( PyCFunction ) M_Mathutils_Intersect, METH_VARARGS, M_Mathutils_Intersect_doc},
+       {"TriangleArea", ( PyCFunction ) M_Mathutils_TriangleArea, METH_VARARGS, M_Mathutils_TriangleArea_doc},
+       {"TriangleNormal", ( PyCFunction ) M_Mathutils_TriangleNormal, METH_VARARGS, M_Mathutils_TriangleNormal_doc},
+       {"QuadNormal", ( PyCFunction ) M_Mathutils_QuadNormal, METH_VARARGS, M_Mathutils_QuadNormal_doc},
+       {"LineIntersect", ( PyCFunction ) M_Mathutils_LineIntersect, METH_VARARGS, M_Mathutils_LineIntersect_doc},
+       {NULL, NULL, 0, NULL}
+};
+/*----------------------------MODULE INIT-------------------------*/
+/* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef M_Mathutils_module_def = {
+       {}, /* m_base */
+       "Mathutils",  /* m_name */
+       M_Mathutils_doc,  /* m_doc */
+       0,  /* m_size */
+       M_Mathutils_methods,  /* m_methods */
+       0,  /* m_reload */
+       0,  /* m_traverse */
+       0,  /* m_clear */
+       0,  /* m_free */
+};
+#endif
+
+PyObject *Mathutils_Init(const char *from)
+{
+       PyObject *submodule;
+
+       //seed the generator for the rand function
+       BLI_srand((unsigned int) (PIL_check_seconds_timer() * 0x7FFFFFFF));
+       
+       if( PyType_Ready( &vector_Type ) < 0 )
+               return NULL;
+       if( PyType_Ready( &matrix_Type ) < 0 )
+               return NULL;    
+       if( PyType_Ready( &euler_Type ) < 0 )
+               return NULL;
+       if( PyType_Ready( &quaternion_Type ) < 0 )
+               return NULL;
+       
+#if (PY_VERSION_HEX >= 0x03000000)
+       submodule = PyModule_Create(&M_Mathutils_module_def);
+       PyDict_SetItemString(PySys_GetObject("modules"), M_Mathutils_module_def.m_name, submodule);
+#else
+       submodule = Py_InitModule3(from, M_Mathutils_methods, M_Mathutils_doc);
+#endif
+       
+       return (submodule);
+}
+
+//-----------------------------METHODS----------------------------
+//----------------column_vector_multiplication (internal)---------
+//COLUMN VECTOR Multiplication (Matrix X Vector)
+// [1][2][3]   [a]
+// [4][5][6] * [b]
+// [7][8][9]   [c]
+//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
+PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
+{
+       float vecNew[4], vecCopy[4];
+       double dot = 0.0f;
+       int x, y, z = 0;
+
+       if(mat->rowSize != vec->size){
+               if(mat->rowSize == 4 && vec->size != 3){
+                       PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
+                       return NULL;
+               }else{
+                       vecCopy[3] = 1.0f;
+               }
+       }
+
+       for(x = 0; x < vec->size; x++){
+               vecCopy[x] = vec->vec[x];
+               }
+
+       for(x = 0; x < mat->rowSize; x++) {
+               for(y = 0; y < mat->colSize; y++) {
+                       dot += mat->matrix[x][y] * vecCopy[y];
+               }
+               vecNew[z++] = (float)dot;
+               dot = 0.0f;
+       }
+       return newVectorObject(vecNew, vec->size, Py_NEW);
+}
+
+//-----------------row_vector_multiplication (internal)-----------
+//ROW VECTOR Multiplication - Vector X Matrix
+//[x][y][z] *  [1][2][3]
+//             [4][5][6]
+//             [7][8][9]
+//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
+PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
+{
+       float vecNew[4], vecCopy[4];
+       double dot = 0.0f;
+       int x, y, z = 0, vec_size = vec->size;
+
+       if(mat->colSize != vec_size){
+               if(mat->rowSize == 4 && vec_size != 3){
+                       PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
+                       return NULL;
+               }else{
+                       vecCopy[3] = 1.0f;
+               }
+       }
+       
+       for(x = 0; x < vec_size; x++){
+               vecCopy[x] = vec->vec[x];
+       }
+
+       //muliplication
+       for(x = 0; x < mat->colSize; x++) {
+               for(y = 0; y < mat->rowSize; y++) {
+                       dot += mat->matrix[y][x] * vecCopy[y];
+               }
+               vecNew[z++] = (float)dot;
+               dot = 0.0f;
+       }
+       return newVectorObject(vecNew, vec_size, Py_NEW);
+}
+
+//-----------------quat_rotation (internal)-----------
+//This function multiplies a vector/point * quat or vice versa
+//to rotate the point/vector by the quaternion
+//arguments should all be 3D
+PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
+{
+       float rot[3];
+       QuaternionObject *quat = NULL;
+       VectorObject *vec = NULL;
+
+       if(QuaternionObject_Check(arg1)){
+               quat = (QuaternionObject*)arg1;
+               if(VectorObject_Check(arg2)){
+                       vec = (VectorObject*)arg2;
+                       rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - 
+                               2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] + 
+                               2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] - 
+                               quat->quat[3]*quat->quat[3]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[0];
+                       rot[1] = 2*quat->quat[1]*quat->quat[2]*vec->vec[0] + quat->quat[2]*quat->quat[2]*vec->vec[1] + 
+                               2*quat->quat[3]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[3]*vec->vec[0] - 
+                               quat->quat[3]*quat->quat[3]*vec->vec[1] + quat->quat[0]*quat->quat[0]*vec->vec[1] - 
+                               2*quat->quat[1]*quat->quat[0]*vec->vec[2] - quat->quat[1]*quat->quat[1]*vec->vec[1];
+                       rot[2] = 2*quat->quat[1]*quat->quat[3]*vec->vec[0] + 2*quat->quat[2]*quat->quat[3]*vec->vec[1] + 
+                               quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] - 
+                               quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] - 
+                               quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
+                       return newVectorObject(rot, 3, Py_NEW);
+               }
+       }else if(VectorObject_Check(arg1)){
+               vec = (VectorObject*)arg1;
+               if(QuaternionObject_Check(arg2)){
+                       quat = (QuaternionObject*)arg2;
+                       rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - 
+                               2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] + 
+                               2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] - 
+                               quat->quat[3]*quat->quat[3]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[0];
+                       rot[1] = 2*quat->quat[1]*quat->quat[2]*vec->vec[0] + quat->quat[2]*quat->quat[2]*vec->vec[1] + 
+                               2*quat->quat[3]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[3]*vec->vec[0] - 
+                               quat->quat[3]*quat->quat[3]*vec->vec[1] + quat->quat[0]*quat->quat[0]*vec->vec[1] - 
+                               2*quat->quat[1]*quat->quat[0]*vec->vec[2] - quat->quat[1]*quat->quat[1]*vec->vec[1];
+                       rot[2] = 2*quat->quat[1]*quat->quat[3]*vec->vec[0] + 2*quat->quat[2]*quat->quat[3]*vec->vec[1] + 
+                               quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] - 
+                               quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] - 
+                               quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
+                       return newVectorObject(rot, 3, Py_NEW);
+               }
+       }
+
+       PyErr_SetString(PyExc_RuntimeError, "quat_rotation(internal): internal problem rotating vector/point\n");
+       return NULL;
+       
+}
+
+//----------------------------------Mathutils.Rand() --------------------
+//returns a random number between a high and low value
+PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args)
+{
+       float high, low, range;
+       double drand;
+       //initializers
+       high = 1.0;
+       low = 0.0;
+
+       if(!PyArg_ParseTuple(args, "|ff", &low, &high)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.Rand(): expected nothing or optional (float, float)\n");
+               return NULL;
+       }
+
+       if((high < low) || (high < 0 && low > 0)) {
+               PyErr_SetString(PyExc_ValueError, "Mathutils.Rand(): high value should be larger than low value\n");
+               return NULL;
+       }
+       //get the random number 0 - 1
+       drand = BLI_drand();
+
+       //set it to range
+       range = high - low;
+       drand = drand * range;
+       drand = drand + low;
+
+       return PyFloat_FromDouble(drand);
+}
+//----------------------------------VECTOR FUNCTIONS---------------------
+//----------------------------------Mathutils.Vector() ------------------
+// Supports 2D, 3D, and 4D vector objects both int and float values
+// accepted. Mixed float and int values accepted. Ints are parsed to float 
+PyObject *M_Mathutils_Vector(PyObject * self, PyObject * args)
+{
+       PyObject *listObject = NULL;
+       int size, i;
+       float vec[4], f;
+       PyObject *v;
+
+       size = PySequence_Length(args);
+       if (size == 1) {
+               listObject = PySequence_GetItem(args, 0);
+               if (PySequence_Check(listObject)) {
+                       size = PySequence_Length(listObject);
+               } else { // Single argument was not a sequence
+                       Py_XDECREF(listObject);
+                       PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+                       return NULL;
+               }
+       } else if (size == 0) {
+               //returns a new empty 3d vector
+               return newVectorObject(NULL, 3, Py_NEW); 
+       } else {
+               Py_INCREF(args);
+               listObject = args;
+       }
+
+       if (size<2 || size>4) { // Invalid vector size
+               Py_XDECREF(listObject);
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+               return NULL;
+       }
+
+       for (i=0; i<size; i++) {
+               v=PySequence_GetItem(listObject, i);
+               if (v==NULL) { // Failed to read sequence
+                       Py_XDECREF(listObject);
+                       PyErr_SetString(PyExc_RuntimeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+                       return NULL;
+               }
+
+               f= PyFloat_AsDouble(v);
+               if(f==-1 && PyErr_Occurred()) { // parsed item not a number
+                       Py_DECREF(v);
+                       Py_XDECREF(listObject);
+                       PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
+                       return NULL;
+               }
+
+               vec[i]= f;
+               Py_DECREF(v);
+       }
+       Py_DECREF(listObject);
+       return newVectorObject(vec, size, Py_NEW);
+}
+//----------------------------------Mathutils.CrossVecs() ---------------
+//finds perpendicular vector - only 3D is supported
+PyObject *M_Mathutils_CrossVecs(PyObject * self, PyObject * args)
+{
+       PyObject *vecCross = NULL;
+       VectorObject *vec1 = NULL, *vec2 = NULL;
+
+       if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.CrossVecs(): expects (2) 3D vector objects\n");
+               return NULL;
+       }
+       
+       if(vec1->size != 3 || vec2->size != 3) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.CrossVecs(): expects (2) 3D vector objects\n");
+               return NULL;
+       }
+       vecCross = newVectorObject(NULL, 3, Py_NEW);
+       Crossf(((VectorObject*)vecCross)->vec, vec1->vec, vec2->vec);
+       return vecCross;
+}
+//----------------------------------Mathutils.DotVec() -------------------
+//calculates the dot product of two vectors
+PyObject *M_Mathutils_DotVecs(PyObject * self, PyObject * args)
+{
+       VectorObject *vec1 = NULL, *vec2 = NULL;
+       double dot = 0.0f;
+       int x;
+
+       if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.DotVecs(): expects (2) vector objects of the same size\n");
+               return NULL;
+       }
+       
+       if(vec1->size != vec2->size) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.DotVecs(): expects (2) vector objects of the same size\n");
+               return NULL;
+       }
+
+       for(x = 0; x < vec1->size; x++) {
+               dot += vec1->vec[x] * vec2->vec[x];
+       }
+       return PyFloat_FromDouble(dot);
+}
+//----------------------------------Mathutils.AngleBetweenVecs() ---------
+//calculates the angle between 2 vectors
+PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
+{
+       VectorObject *vec1 = NULL, *vec2 = NULL;
+       double dot = 0.0f, angleRads, test_v1 = 0.0f, test_v2 = 0.0f;
+       int x, size;
+
+       if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
+               goto AttributeError1; //not vectors
+       if(vec1->size != vec2->size)
+               goto AttributeError1; //bad sizes
+
+       //since size is the same....
+       size = vec1->size;
+
+       for(x = 0; x < size; x++) {
+               test_v1 += vec1->vec[x] * vec1->vec[x];
+               test_v2 += vec2->vec[x] * vec2->vec[x];
+       }
+       if (!test_v1 || !test_v2){
+               goto AttributeError2; //zero-length vector
+       }
+
+       //dot product
+       for(x = 0; x < size; x++) {
+               dot += vec1->vec[x] * vec2->vec[x];
+       }
+       dot /= (sqrt(test_v1) * sqrt(test_v2));
+
+       angleRads = (double)saacos(dot);
+
+       return PyFloat_FromDouble(angleRads * (180/ Py_PI));
+
+AttributeError1:
+       PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n");
+       return NULL;
+
+AttributeError2:
+       PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): zero length vectors are not acceptable arguments\n");
+       return NULL;
+}
+//----------------------------------Mathutils.MidpointVecs() -------------
+//calculates the midpoint between 2 vectors
+PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
+{
+       VectorObject *vec1 = NULL, *vec2 = NULL;
+       float vec[4];
+       int x;
+       
+       if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
+               return NULL;
+       }
+       if(vec1->size != vec2->size) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
+               return NULL;
+       }
+
+       for(x = 0; x < vec1->size; x++) {
+               vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]);
+       }
+       return newVectorObject(vec, vec1->size, Py_NEW);
+}
+//----------------------------------Mathutils.ProjectVecs() -------------
+//projects vector 1 onto vector 2
+PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
+{
+       VectorObject *vec1 = NULL, *vec2 = NULL;
+       float vec[4]; 
+       double dot = 0.0f, dot2 = 0.0f;
+       int x, size;
+
+       if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
+               return NULL;
+       }
+       if(vec1->size != vec2->size) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
+               return NULL;
+       }
+
+       //since they are the same size...
+       size = vec1->size;
+
+       //get dot products
+       for(x = 0; x < size; x++) {
+               dot += vec1->vec[x] * vec2->vec[x];
+               dot2 += vec2->vec[x] * vec2->vec[x];
+       }
+       //projection
+       dot /= dot2;
+       for(x = 0; x < size; x++) {
+               vec[x] = (float)(dot * vec2->vec[x]);
+       }
+       return newVectorObject(vec, size, Py_NEW);
+}
+//----------------------------------MATRIX FUNCTIONS--------------------
+//----------------------------------Mathutils.Matrix() -----------------
+//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
+//create a new matrix type
+PyObject *M_Mathutils_Matrix(PyObject * self, PyObject * args)
+{
+       PyObject *listObject = NULL;
+       PyObject *argObject, *m, *s, *f;
+       MatrixObject *mat;
+       int argSize, seqSize = 0, i, j;
+       float matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+
+       argSize = PySequence_Length(args);
+       if(argSize > 4){        //bad arg nums
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+               return NULL;
+       } else if (argSize == 0) { //return empty 4D matrix
+               return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW);
+       }else if (argSize == 1){
+               //copy constructor for matrix objects
+               argObject = PySequence_GetItem(args, 0);
+               if(MatrixObject_Check(argObject)){
+                       mat = (MatrixObject*)argObject;
+
+                       argSize = mat->rowSize; //rows
+                       seqSize = mat->colSize; //col
+                       for(i = 0; i < (seqSize * argSize); i++){
+                               matrix[i] = mat->contigPtr[i];
+                       }
+               }
+               Py_DECREF(argObject);
+       }else{ //2-4 arguments (all seqs? all same size?)
+               for(i =0; i < argSize; i++){
+                       argObject = PySequence_GetItem(args, i);
+                       if (PySequence_Check(argObject)) { //seq?
+                               if(seqSize){ //0 at first
+                                       if(PySequence_Length(argObject) != seqSize){ //seq size not same
+                                               Py_DECREF(argObject);
+                                               PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+                                               return NULL;
+                                       }
+                               }
+                               seqSize = PySequence_Length(argObject);
+                       }else{ //arg not a sequence
+                               Py_XDECREF(argObject);
+                               PyErr_SetString(PyExc_TypeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+                               return NULL;
+                       }
+                       Py_DECREF(argObject);
+               }
+               //all is well... let's continue parsing
+               listObject = args;
+               for (i = 0; i < argSize; i++){
+                       m = PySequence_GetItem(listObject, i);
+                       if (m == NULL) { // Failed to read sequence
+                               PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
+                               return NULL;
+                       }
+
+                       for (j = 0; j < seqSize; j++) {
+                               s = PySequence_GetItem(m, j);
+                               if (s == NULL) { // Failed to read sequence
+                                       Py_DECREF(m);
+                                       PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
+                                       return NULL;
+                               }
+
+                               f = PyNumber_Float(s);
+                               if(f == NULL) { // parsed item is not a number
+                                       Py_DECREF(m);
+                                       Py_DECREF(s);
+                                       PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
+                                       return NULL;
+                               }
+
+                               matrix[(seqSize*i)+j]=(float)PyFloat_AS_DOUBLE(f);
+                               Py_DECREF(f);
+                               Py_DECREF(s);
+                       }
+                       Py_DECREF(m);
+               }
+       }
+       return newMatrixObject(matrix, argSize, seqSize, Py_NEW);
+}
+//----------------------------------Mathutils.RotationMatrix() ----------
+//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
+//creates a rotation matrix
+PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
+{
+       VectorObject *vec = NULL;
+       char *axis = NULL;
+       int matSize;
+       float angle = 0.0f, norm = 0.0f, cosAngle = 0.0f, sinAngle = 0.0f;
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+
+       if(!PyArg_ParseTuple(args, "fi|sO!", &angle, &matSize, &axis, &vector_Type, &vec)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): expected float int and optional string and vector\n");
+               return NULL;
+       }
+       
+       /* Clamp to -360:360 */
+       while (angle<-360.0f)
+               angle+=360.0;
+       while (angle>360.0f)
+               angle-=360.0;
+       
+       if(matSize != 2 && matSize != 3 && matSize != 4) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+               return NULL;
+       }
+       if(matSize == 2 && (axis != NULL || vec != NULL)) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n");
+               return NULL;
+       }
+       if((matSize == 3 || matSize == 4) && axis == NULL) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n");
+               return NULL;
+       }
+       if(axis) {
+               if(((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) && vec == NULL) {
+                       PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please define the arbitrary axis of rotation\n");
+                       return NULL;
+               }
+       }
+       if(vec) {
+               if(vec->size != 3) {
+                       PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
+                       return NULL;
+               }
+       }
+       //convert to radians
+       angle = angle * (float) (Py_PI / 180);
+       if(axis == NULL && matSize == 2) {
+               //2D rotation matrix
+               mat[0] = (float) cos (angle);
+               mat[1] = (float) sin (angle);
+               mat[2] = -((float) sin(angle));
+               mat[3] = (float) cos(angle);
+       } else if((strcmp(axis, "x") == 0) || (strcmp(axis, "X") == 0)) {
+               //rotation around X
+               mat[0] = 1.0f;
+               mat[4] = (float) cos(angle);
+               mat[5] = (float) sin(angle);
+               mat[7] = -((float) sin(angle));
+               mat[8] = (float) cos(angle);
+       } else if((strcmp(axis, "y") == 0) || (strcmp(axis, "Y") == 0)) {
+               //rotation around Y
+               mat[0] = (float) cos(angle);
+               mat[2] = -((float) sin(angle));
+               mat[4] = 1.0f;
+               mat[6] = (float) sin(angle);
+               mat[8] = (float) cos(angle);
+       } else if((strcmp(axis, "z") == 0) || (strcmp(axis, "Z") == 0)) {
+               //rotation around Z
+               mat[0] = (float) cos(angle);
+               mat[1] = (float) sin(angle);
+               mat[3] = -((float) sin(angle));
+               mat[4] = (float) cos(angle);
+               mat[8] = 1.0f;
+       } else if((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) {
+               //arbitrary rotation
+               //normalize arbitrary axis
+               norm = (float) sqrt(vec->vec[0] * vec->vec[0] +
+                                      vec->vec[1] * vec->vec[1] +
+                                      vec->vec[2] * vec->vec[2]);
+               vec->vec[0] /= norm;
+               vec->vec[1] /= norm;
+               vec->vec[2] /= norm;
+               
+               if (isnan(vec->vec[0]) || isnan(vec->vec[1]) || isnan(vec->vec[2])) {
+                       /* zero length vector, return an identity matrix, could also return an error */
+                       mat[0]= mat[4] = mat[8] = 1.0f;
+               } else {        
+                       /* create matrix */
+                       cosAngle = (float) cos(angle);
+                       sinAngle = (float) sin(angle);
+                       mat[0] = ((vec->vec[0] * vec->vec[0]) * (1 - cosAngle)) +
+                               cosAngle;
+                       mat[1] = ((vec->vec[0] * vec->vec[1]) * (1 - cosAngle)) +
+                               (vec->vec[2] * sinAngle);
+                       mat[2] = ((vec->vec[0] * vec->vec[2]) * (1 - cosAngle)) -
+                               (vec->vec[1] * sinAngle);
+                       mat[3] = ((vec->vec[0] * vec->vec[1]) * (1 - cosAngle)) -
+                               (vec->vec[2] * sinAngle);
+                       mat[4] = ((vec->vec[1] * vec->vec[1]) * (1 - cosAngle)) +
+                               cosAngle;
+                       mat[5] = ((vec->vec[1] * vec->vec[2]) * (1 - cosAngle)) +
+                               (vec->vec[0] * sinAngle);
+                       mat[6] = ((vec->vec[0] * vec->vec[2]) * (1 - cosAngle)) +
+                               (vec->vec[1] * sinAngle);
+                       mat[7] = ((vec->vec[1] * vec->vec[2]) * (1 - cosAngle)) -
+                               (vec->vec[0] * sinAngle);
+                       mat[8] = ((vec->vec[2] * vec->vec[2]) * (1 - cosAngle)) +
+                               cosAngle;
+               }
+       } else {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): unrecognizable axis of rotation type - expected x,y,z or r\n");
+               return NULL;
+       }
+       if(matSize == 4) {
+               //resize matrix
+               mat[10] = mat[8];
+               mat[9] = mat[7];
+               mat[8] = mat[6];
+               mat[7] = 0.0f;
+               mat[6] = mat[5];
+               mat[5] = mat[4];
+               mat[4] = mat[3];
+               mat[3] = 0.0f;
+       }
+       //pass to matrix creation
+       return newMatrixObject(mat, matSize, matSize, Py_NEW);
+}
+//----------------------------------Mathutils.TranslationMatrix() -------
+//creates a translation matrix
+PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec)
+{
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+       
+       if(!VectorObject_Check(vec)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): expected vector\n");
+               return NULL;
+       }
+       if(vec->size != 3 && vec->size != 4) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): vector must be 3D or 4D\n");
+               return NULL;
+       }
+       //create a identity matrix and add translation
+       Mat4One((float(*)[4]) mat);
+       mat[12] = vec->vec[0];
+       mat[13] = vec->vec[1];
+       mat[14] = vec->vec[2];
+
+       return newMatrixObject(mat, 4, 4, Py_NEW);
+}
+//----------------------------------Mathutils.ScaleMatrix() -------------
+//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
+//creates a scaling matrix
+PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
+{
+       VectorObject *vec = NULL;
+       float norm = 0.0f, factor;
+       int matSize, x;
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+
+       if(!PyArg_ParseTuple(args, "fi|O!", &factor, &matSize, &vector_Type, &vec)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.ScaleMatrix(): expected float int and optional vector\n");
+               return NULL;
+       }
+       if(matSize != 2 && matSize != 3 && matSize != 4) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+               return NULL;
+       }
+       if(vec) {
+               if(vec->size > 2 && matSize == 2) {
+                       PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n");
+                       return NULL;
+               }
+       }
+       if(vec == NULL) {       //scaling along axis
+               if(matSize == 2) {
+                       mat[0] = factor;
+                       mat[3] = factor;
+               } else {
+                       mat[0] = factor;
+                       mat[4] = factor;
+                       mat[8] = factor;
+               }
+       } else { //scaling in arbitrary direction
+               //normalize arbitrary axis
+               for(x = 0; x < vec->size; x++) {
+                       norm += vec->vec[x] * vec->vec[x];
+               }
+               norm = (float) sqrt(norm);
+               for(x = 0; x < vec->size; x++) {
+                       vec->vec[x] /= norm;
+               }
+               if(matSize == 2) {
+                       mat[0] = 1 +((factor - 1) *(vec->vec[0] * vec->vec[0]));
+                       mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1]));
+                       mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[1]));
+                       mat[3] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1]));
+               } else {
+                       mat[0] = 1 + ((factor - 1) *(vec->vec[0] * vec->vec[0]));
+                       mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1]));
+                       mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[2]));
+                       mat[3] =((factor - 1) *(vec->vec[0] * vec->vec[1]));
+                       mat[4] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1]));
+                       mat[5] =((factor - 1) *(vec->vec[1] * vec->vec[2]));
+                       mat[6] =((factor - 1) *(vec->vec[0] * vec->vec[2]));
+                       mat[7] =((factor - 1) *(vec->vec[1] * vec->vec[2]));
+                       mat[8] = 1 + ((factor - 1) *(vec->vec[2] * vec->vec[2]));
+               }
+       }
+       if(matSize == 4) {
+               //resize matrix
+               mat[10] = mat[8];
+               mat[9] = mat[7];
+               mat[8] = mat[6];
+               mat[7] = 0.0f;
+               mat[6] = mat[5];
+               mat[5] = mat[4];
+               mat[4] = mat[3];
+               mat[3] = 0.0f;
+       }
+       //pass to matrix creation
+       return newMatrixObject(mat, matSize, matSize, Py_NEW);
+}
+//----------------------------------Mathutils.OrthoProjectionMatrix() ---
+//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
+//creates an ortho projection matrix
+PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
+{
+       VectorObject *vec = NULL;
+       char *plane;
+       int matSize, x;
+       float norm = 0.0f;
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+       
+       if(!PyArg_ParseTuple(args, "si|O!", &plane, &matSize, &vector_Type, &vec)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.OrthoProjectionMatrix(): expected string and int and optional vector\n");
+               return NULL;
+       }
+       if(matSize != 2 && matSize != 3 && matSize != 4) {
+               PyErr_SetString(PyExc_AttributeError,"Mathutils.OrthoProjectionMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+               return NULL;
+       }
+       if(vec) {
+               if(vec->size > 2 && matSize == 2) {
+                       PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n");
+                       return NULL;
+               }
+       }
+       if(vec == NULL) {       //ortho projection onto cardinal plane
+               if(((strcmp(plane, "x") == 0)
+                     || (strcmp(plane, "X") == 0)) && matSize == 2) {
+                       mat[0] = 1.0f;
+               } else if(((strcmp(plane, "y") == 0) 
+                       || (strcmp(plane, "Y") == 0))
+                          && matSize == 2) {
+                       mat[3] = 1.0f;
+               } else if(((strcmp(plane, "xy") == 0)
+                            || (strcmp(plane, "XY") == 0))
+                          && matSize > 2) {
+                       mat[0] = 1.0f;
+                       mat[4] = 1.0f;
+               } else if(((strcmp(plane, "xz") == 0)
+                            || (strcmp(plane, "XZ") == 0))
+                          && matSize > 2) {
+                       mat[0] = 1.0f;
+                       mat[8] = 1.0f;
+               } else if(((strcmp(plane, "yz") == 0)
+                            || (strcmp(plane, "YZ") == 0))
+                          && matSize > 2) {
+                       mat[4] = 1.0f;
+                       mat[8] = 1.0f;
+               } else {
+                       PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: x, y, xy, xz, yz\n");
+                       return NULL;
+               }
+       } else { //arbitrary plane
+               //normalize arbitrary axis
+               for(x = 0; x < vec->size; x++) {
+                       norm += vec->vec[x] * vec->vec[x];
+               }
+               norm = (float) sqrt(norm);
+               for(x = 0; x < vec->size; x++) {
+                       vec->vec[x] /= norm;
+               }
+               if(((strcmp(plane, "r") == 0)
+                     || (strcmp(plane, "R") == 0)) && matSize == 2) {
+                       mat[0] = 1 - (vec->vec[0] * vec->vec[0]);
+                       mat[1] = -(vec->vec[0] * vec->vec[1]);
+                       mat[2] = -(vec->vec[0] * vec->vec[1]);
+                       mat[3] = 1 - (vec->vec[1] * vec->vec[1]);
+               } else if(((strcmp(plane, "r") == 0)
+                            || (strcmp(plane, "R") == 0))
+                          && matSize > 2) {
+                       mat[0] = 1 - (vec->vec[0] * vec->vec[0]);
+                       mat[1] = -(vec->vec[0] * vec->vec[1]);
+                       mat[2] = -(vec->vec[0] * vec->vec[2]);
+                       mat[3] = -(vec->vec[0] * vec->vec[1]);
+                       mat[4] = 1 - (vec->vec[1] * vec->vec[1]);
+                       mat[5] = -(vec->vec[1] * vec->vec[2]);
+                       mat[6] = -(vec->vec[0] * vec->vec[2]);
+                       mat[7] = -(vec->vec[1] * vec->vec[2]);
+                       mat[8] = 1 - (vec->vec[2] * vec->vec[2]);
+               } else {
+                       PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: 'r' expected for axis designation\n");
+                       return NULL;
+               }
+       }
+       if(matSize == 4) {
+               //resize matrix
+               mat[10] = mat[8];
+               mat[9] = mat[7];
+               mat[8] = mat[6];
+               mat[7] = 0.0f;
+               mat[6] = mat[5];
+               mat[5] = mat[4];
+               mat[4] = mat[3];
+               mat[3] = 0.0f;
+       }
+       //pass to matrix creation
+       return newMatrixObject(mat, matSize, matSize, Py_NEW);
+}
+//----------------------------------Mathutils.ShearMatrix() -------------
+//creates a shear matrix
+PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
+{
+       int matSize;
+       char *plane;
+       float factor;
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+
+       if(!PyArg_ParseTuple(args, "sfi", &plane, &factor, &matSize)) {
+               PyErr_SetString(PyExc_TypeError,"Mathutils.ShearMatrix(): expected string float and int\n");
+               return NULL;
+       }
+       if(matSize != 2 && matSize != 3 && matSize != 4) {
+               PyErr_SetString(PyExc_AttributeError,"Mathutils.ShearMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
+               return NULL;
+       }
+
+       if(((strcmp(plane, "x") == 0) || (strcmp(plane, "X") == 0))
+           && matSize == 2) {
+               mat[0] = 1.0f;
+               mat[2] = factor;
+               mat[3] = 1.0f;
+       } else if(((strcmp(plane, "y") == 0)
+                    || (strcmp(plane, "Y") == 0)) && matSize == 2) {
+               mat[0] = 1.0f;
+               mat[1] = factor;
+               mat[3] = 1.0f;
+       } else if(((strcmp(plane, "xy") == 0)
+                    || (strcmp(plane, "XY") == 0)) && matSize > 2) {
+               mat[0] = 1.0f;
+               mat[4] = 1.0f;
+               mat[6] = factor;
+               mat[7] = factor;
+       } else if(((strcmp(plane, "xz") == 0)
+                    || (strcmp(plane, "XZ") == 0)) && matSize > 2) {
+               mat[0] = 1.0f;
+               mat[3] = factor;
+               mat[4] = 1.0f;
+               mat[5] = factor;
+               mat[8] = 1.0f;
+       } else if(((strcmp(plane, "yz") == 0)
+                    || (strcmp(plane, "YZ") == 0)) && matSize > 2) {
+               mat[0] = 1.0f;
+               mat[1] = factor;
+               mat[2] = factor;
+               mat[4] = 1.0f;
+               mat[8] = 1.0f;
+       } else {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.ShearMatrix(): expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n");
+               return NULL;
+       }
+       if(matSize == 4) {
+               //resize matrix
+               mat[10] = mat[8];
+               mat[9] = mat[7];
+               mat[8] = mat[6];
+               mat[7] = 0.0f;
+               mat[6] = mat[5];
+               mat[5] = mat[4];
+               mat[4] = mat[3];
+               mat[3] = 0.0f;
+       }
+       //pass to matrix creation
+       return newMatrixObject(mat, matSize, matSize, Py_NEW);
+}
+//----------------------------------QUATERNION FUNCTIONS-----------------
+//----------------------------------Mathutils.Quaternion() --------------
+PyObject *M_Mathutils_Quaternion(PyObject * self, PyObject * args)
+{
+       PyObject *listObject = NULL, *n, *q, *f;
+       int size, i;
+       float quat[4];
+       double norm = 0.0f, angle = 0.0f;
+
+       size = PySequence_Length(args);
+       if (size == 1 || size == 2) { //seq?
+               listObject = PySequence_GetItem(args, 0);
+               if (PySequence_Check(listObject)) {
+                       size = PySequence_Length(listObject);
+                       if ((size == 4 && PySequence_Length(args) !=1) || 
+                               (size == 3 && PySequence_Length(args) !=2) || (size >4 || size < 3)) { 
+                               // invalid args/size
+                               Py_DECREF(listObject);
+                               PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                               return NULL;
+                       }
+                       if(size == 3){ //get angle in axis/angle
+                               n = PySequence_GetItem(args, 1);
+                               if(n == NULL) { // parsed item not a number or getItem fail
+                                       Py_DECREF(listObject);
+                                       PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                                       return NULL;
+                               }
+                               
+                               angle = PyFloat_AsDouble(n);
+                               Py_DECREF(n);
+                               
+                               if (angle==-1 && PyErr_Occurred()) {
+                                       Py_DECREF(listObject);
+                                       PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                                       return NULL;
+                               }
+                       }
+               }else{
+                       Py_DECREF(listObject); /* assume the list is teh second arg */
+                       listObject = PySequence_GetItem(args, 1);
+                       if (size>1 && PySequence_Check(listObject)) {
+                               size = PySequence_Length(listObject);
+                               if (size != 3) { 
+                                       // invalid args/size
+                                       Py_DECREF(listObject);
+                                       PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                                       return NULL;
+                               }
+                               n = PySequence_GetItem(args, 0);
+                               if(n == NULL) { // parsed item not a number or getItem fail
+                                       Py_DECREF(listObject);
+                                       PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                                       return NULL;
+                               }
+                               angle = PyFloat_AsDouble(n);
+                               Py_DECREF(n);
+                               
+                               if (angle==-1 && PyErr_Occurred()) {
+                                       Py_DECREF(listObject);
+                                       PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                                       return NULL;
+                               }
+                       } else { // argument was not a sequence
+                               Py_XDECREF(listObject);
+                               PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                               return NULL;
+                       }
+               }
+       } else if (size == 0) { //returns a new empty quat
+               return newQuaternionObject(NULL, Py_NEW); 
+       } else {
+               Py_INCREF(args);
+               listObject = args;
+       }
+
+       if (size == 3) { // invalid quat size
+               if(PySequence_Length(args) != 2){
+                       Py_DECREF(listObject);
+                       PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                       return NULL;
+               }
+       }else{
+               if(size != 4){
+                       Py_DECREF(listObject);
+                       PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                       return NULL;
+               }
+       }
+
+       for (i=0; i<size; i++) { //parse
+               q = PySequence_GetItem(listObject, i);
+               if (q == NULL) { // Failed to read sequence
+                       Py_DECREF(listObject);
+                       PyErr_SetString(PyExc_RuntimeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                       return NULL;
+               }
+
+               f = PyNumber_Float(q);
+               if(f == NULL) { // parsed item not a number
+                       Py_DECREF(q);
+                       Py_DECREF(listObject);
+                       PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+                       return NULL;
+               }
+
+               quat[i] = (float)PyFloat_AS_DOUBLE(f);
+               Py_DECREF(f);
+               Py_DECREF(q);
+       }
+       if(size == 3){ //calculate the quat based on axis/angle
+               norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2]);
+               quat[0] /= (float)norm;
+               quat[1] /= (float)norm;
+               quat[2] /= (float)norm;
+
+               angle = angle * (Py_PI / 180);
+               quat[3] =(float) (sin(angle/ 2.0f)) * quat[2];
+               quat[2] =(float) (sin(angle/ 2.0f)) * quat[1];
+               quat[1] =(float) (sin(angle/ 2.0f)) * quat[0];
+               quat[0] =(float) (cos(angle/ 2.0f));
+       }
+
+       Py_DECREF(listObject);
+       return newQuaternionObject(quat, Py_NEW);
+}
+//----------------------------------Mathutils.CrossQuats() ----------------
+//quaternion multiplication - associate not commutative
+PyObject *M_Mathutils_CrossQuats(PyObject * self, PyObject * args)
+{
+       QuaternionObject *quatU = NULL, *quatV = NULL;
+       float quat[4];
+
+       if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
+               PyErr_SetString(PyExc_TypeError,"Mathutils.CrossQuats(): expected Quaternion types");
+               return NULL;
+       }
+       QuatMul(quat, quatU->quat, quatV->quat);
+
+       return newQuaternionObject(quat, Py_NEW);
+}
+//----------------------------------Mathutils.DotQuats() ----------------
+//returns the dot product of 2 quaternions
+PyObject *M_Mathutils_DotQuats(PyObject * self, PyObject * args)
+{
+       QuaternionObject *quatU = NULL, *quatV = NULL;
+       double dot = 0.0f;
+       int x;
+
+       if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.DotQuats(): expected Quaternion types");
+               return NULL;
+       }
+
+       for(x = 0; x < 4; x++) {
+               dot += quatU->quat[x] * quatV->quat[x];
+       }
+       return PyFloat_FromDouble(dot);
+}
+//----------------------------------Mathutils.DifferenceQuats() ---------
+//returns the difference between 2 quaternions
+PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
+{
+       QuaternionObject *quatU = NULL, *quatV = NULL;
+       float quat[4], tempQuat[4];
+       double dot = 0.0f;
+       int x;
+
+       if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
+               return NULL;
+       }
+       tempQuat[0] = quatU->quat[0];
+       tempQuat[1] = -quatU->quat[1];
+       tempQuat[2] = -quatU->quat[2];
+       tempQuat[3] = -quatU->quat[3];
+
+       dot = sqrt(tempQuat[0] * tempQuat[0] + tempQuat[1] *  tempQuat[1] +
+                              tempQuat[2] * tempQuat[2] + tempQuat[3] * tempQuat[3]);
+
+       for(x = 0; x < 4; x++) {
+               tempQuat[x] /= (float)(dot * dot);
+       }
+       QuatMul(quat, tempQuat, quatV->quat);
+       return newQuaternionObject(quat, Py_NEW);
+}
+//----------------------------------Mathutils.Slerp() ------------------
+//attemps to interpolate 2 quaternions and return the result
+PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
+{
+       QuaternionObject *quatU = NULL, *quatV = NULL;
+       float quat[4], quat_u[4], quat_v[4], param;
+       double x, y, dot, sinT, angle, IsinT;
+       int z;
+
+       if(!PyArg_ParseTuple(args, "O!O!f", &quaternion_Type, &quatU, &quaternion_Type, &quatV, &param)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
+               return NULL;
+       }
+       if(param > 1.0f || param < 0.0f) {
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
+               return NULL;
+       }
+
+       //copy quats
+       for(z = 0; z < 4; z++){
+               quat_u[z] = quatU->quat[z];
+               quat_v[z] = quatV->quat[z];
+       }
+
+       //dot product
+       dot = quat_u[0] * quat_v[0] + quat_u[1] * quat_v[1] +
+               quat_u[2] * quat_v[2] + quat_u[3] * quat_v[3];
+
+       //if negative negate a quat (shortest arc)
+       if(dot < 0.0f) {
+               quat_v[0] = -quat_v[0];
+               quat_v[1] = -quat_v[1];
+               quat_v[2] = -quat_v[2];
+               quat_v[3] = -quat_v[3];
+               dot = -dot;
+       }
+       if(dot > .99999f) { //very close
+               x = 1.0f - param;
+               y = param;
+       } else {
+               //calculate sin of angle
+               sinT = sqrt(1.0f - (dot * dot));
+               //calculate angle
+               angle = atan2(sinT, dot);
+               //caluculate inverse of sin(theta)
+               IsinT = 1.0f / sinT;
+               x = sin((1.0f - param) * angle) * IsinT;
+               y = sin(param * angle) * IsinT;
+       }
+       //interpolate
+       quat[0] = (float)(quat_u[0] * x + quat_v[0] * y);
+       quat[1] = (float)(quat_u[1] * x + quat_v[1] * y);
+       quat[2] = (float)(quat_u[2] * x + quat_v[2] * y);
+       quat[3] = (float)(quat_u[3] * x + quat_v[3] * y);
+
+       return newQuaternionObject(quat, Py_NEW);
+}
+//----------------------------------EULER FUNCTIONS----------------------
+//----------------------------------Mathutils.Euler() -------------------
+//makes a new euler for you to play with
+PyObject *M_Mathutils_Euler(PyObject * self, PyObject * args)
+{
+
+       PyObject *listObject = NULL;
+       int size, i;
+       float eul[3];
+       PyObject *e, *f;
+
+       size = PySequence_Length(args);
+       if (size == 1) {
+               listObject = PySequence_GetItem(args, 0);
+               if (PySequence_Check(listObject)) {
+                       size = PySequence_Length(listObject);
+               } else { // Single argument was not a sequence
+                       Py_DECREF(listObject);
+                       PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
+                       return NULL;
+               }
+       } else if (size == 0) {
+               //returns a new empty 3d euler
+               return newEulerObject(NULL, Py_NEW); 
+       } else {
+               Py_INCREF(args);
+               listObject = args;
+       }
+
+       if (size != 3) { // Invalid euler size
+               Py_DECREF(listObject);
+               PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
+               return NULL;
+       }
+
+       for (i=0; i<size; i++) {
+               e = PySequence_GetItem(listObject, i);
+               if (e == NULL) { // Failed to read sequence
+                       Py_DECREF(listObject);
+                       PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
+                       return NULL;
+               }
+
+               f = PyNumber_Float(e);
+               if(f == NULL) { // parsed item not a number
+                       Py_DECREF(e);
+                       Py_DECREF(listObject);
+                       PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
+                       return NULL;
+               }
+
+               eul[i]=(float)PyFloat_AS_DOUBLE(f);
+               Py_DECREF(f);
+               Py_DECREF(e);
+       }
+       Py_DECREF(listObject);
+       return newEulerObject(eul, Py_NEW);
+}
+
+//---------------------------------INTERSECTION FUNCTIONS--------------------
+//----------------------------------Mathutils.Intersect() -------------------
+PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
+{
+       VectorObject *ray, *ray_off, *vec1, *vec2, *vec3;
+       float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
+       float det, inv_det, u, v, t;
+       int clip = 1;
+
+       if(!PyArg_ParseTuple(args, "O!O!O!O!O!|i", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off , &clip)) {
+               PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
+               return NULL;
+       }
+       if(vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
+               PyErr_SetString( PyExc_TypeError, "only 3D vectors for all parameters\n");
+               return NULL;
+       }
+
+       VECCOPY(v1, vec1->vec);
+       VECCOPY(v2, vec2->vec);
+       VECCOPY(v3, vec3->vec);
+
+       VECCOPY(dir, ray->vec);
+       Normalize(dir);
+
+       VECCOPY(orig, ray_off->vec);
+
+       /* find vectors for two edges sharing v1 */
+       VecSubf(e1, v2, v1);
+       VecSubf(e2, v3, v1);
+
+       /* begin calculating determinant - also used to calculated U parameter */
+       Crossf(pvec, dir, e2);  
+
+       /* if determinant is near zero, ray lies in plane of triangle */
+       det = Inpf(e1, pvec);
+
+       if (det > -0.000001 && det < 0.000001) {
+               Py_RETURN_NONE;
+       }
+
+       inv_det = 1.0f / det;
+
+       /* calculate distance from v1 to ray origin */
+       VecSubf(tvec, orig, v1);
+
+       /* calculate U parameter and test bounds */
+       u = Inpf(tvec, pvec) * inv_det;
+       if (clip && (u < 0.0f || u > 1.0f)) {
+               Py_RETURN_NONE;
+       }
+
+       /* prepare to test the V parameter */
+       Crossf(qvec, tvec, e1);
+
+       /* calculate V parameter and test bounds */
+       v = Inpf(dir, qvec) * inv_det;
+
+       if (clip && (v < 0.0f || u + v > 1.0f)) {
+               Py_RETURN_NONE;
+       }
+
+       /* calculate t, ray intersects triangle */
+       t = Inpf(e2, qvec) * inv_det;
+
+       VecMulf(dir, t);
+       VecAddf(pvec, orig, dir);
+
+       return newVectorObject(pvec, 3, Py_NEW);
+}
+//----------------------------------Mathutils.LineIntersect() -------------------
+/* Line-Line intersection using algorithm from mathworld.wolfram.com */
+PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
+{
+       PyObject * tuple;
+       VectorObject *vec1, *vec2, *vec3, *vec4;
+       float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3];
+
+       if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
+               PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+               return NULL;
+       }
+       if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec2->size) {
+               PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
+               return NULL;
+       }
+       if( vec1->size == 3 || vec1->size == 2) {
+               int result;
+               
+               if (vec1->size == 3) {
+                       VECCOPY(v1, vec1->vec);
+                       VECCOPY(v2, vec2->vec);
+                       VECCOPY(v3, vec3->vec);
+                       VECCOPY(v4, vec4->vec);
+               }
+               else {
+                       v1[0] = vec1->vec[0];
+                       v1[1] = vec1->vec[1];
+                       v1[2] = 0.0f;
+
+                       v2[0] = vec2->vec[0];
+                       v2[1] = vec2->vec[1];
+                       v2[2] = 0.0f;
+
+                       v3[0] = vec3->vec[0];
+                       v3[1] = vec3->vec[1];
+                       v3[2] = 0.0f;
+
+                       v4[0] = vec4->vec[0];
+                       v4[1] = vec4->vec[1];
+                       v4[2] = 0.0f;
+               }
+               
+               result = LineIntersectLine(v1, v2, v3, v4, i1, i2);
+
+               if (result == 0) {
+                       /* colinear */
+                       Py_RETURN_NONE;
+               }
+               else {
+                       tuple = PyTuple_New( 2 );
+                       PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW) );
+                       PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW) );
+                       return tuple;
+               }
+       }
+       else {
+               PyErr_SetString( PyExc_TypeError, "2D/3D vectors only\n" );
+               return NULL;
+       }
+}
+
+
+
+//---------------------------------NORMALS FUNCTIONS--------------------
+//----------------------------------Mathutils.QuadNormal() -------------------
+PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
+{
+       VectorObject *vec1;
+       VectorObject *vec2;
+       VectorObject *vec3;
+       VectorObject *vec4;
+       float v1[3], v2[3], v3[3], v4[3], e1[3], e2[3], n1[3], n2[3];
+
+       if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
+               PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+               return NULL;
+       }
+       if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
+               PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
+               return NULL;
+       }
+       if( vec1->size != 3 ) {
+               PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
+               return NULL;
+       }
+       VECCOPY(v1, vec1->vec);
+       VECCOPY(v2, vec2->vec);
+       VECCOPY(v3, vec3->vec);
+       VECCOPY(v4, vec4->vec);
+
+       /* find vectors for two edges sharing v2 */
+       VecSubf(e1, v1, v2);
+       VecSubf(e2, v3, v2);
+
+       Crossf(n1, e2, e1);
+       Normalize(n1);
+
+       /* find vectors for two edges sharing v4 */
+       VecSubf(e1, v3, v4);
+       VecSubf(e2, v1, v4);
+
+       Crossf(n2, e2, e1);
+       Normalize(n2);
+
+       /* adding and averaging the normals of both triangles */
+       VecAddf(n1, n2, n1);
+       Normalize(n1);
+
+       return newVectorObject(n1, 3, Py_NEW);
+}
+
+//----------------------------Mathutils.TriangleNormal() -------------------
+PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
+{
+       VectorObject *vec1, *vec2, *vec3;
+       float v1[3], v2[3], v3[3], e1[3], e2[3], n[3];
+
+       if( !PyArg_ParseTuple( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3 ) ) {
+               PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
+               return NULL;
+       }
+       if( vec1->size != vec2->size || vec1->size != vec3->size ) {
+               PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
+               return NULL;
+       }
+       if( vec1->size != 3 ) {
+               PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
+               return NULL;
+       }
+
+       VECCOPY(v1, vec1->vec);
+       VECCOPY(v2, vec2->vec);
+       VECCOPY(v3, vec3->vec);
+
+       /* find vectors for two edges sharing v2 */
+       VecSubf(e1, v1, v2);
+       VecSubf(e2, v3, v2);
+
+       Crossf(n, e2, e1);
+       Normalize(n);
+
+       return newVectorObject(n, 3, Py_NEW);
+}
+
+//--------------------------------- AREA FUNCTIONS--------------------
+//----------------------------------Mathutils.TriangleArea() -------------------
+PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
+{
+       VectorObject *vec1, *vec2, *vec3;
+       float v1[3], v2[3], v3[3];
+
+       if( !PyArg_ParseTuple
+           ( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
+               , &vector_Type, &vec3 ) ) {
+               PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n");
+               return NULL;
+       }
+       if( vec1->size != vec2->size || vec1->size != vec3->size ) {
+               PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
+               return NULL;
+       }
+
+       if (vec1->size == 3) {
+               VECCOPY(v1, vec1->vec);
+               VECCOPY(v2, vec2->vec);
+               VECCOPY(v3, vec3->vec);
+
+               return PyFloat_FromDouble( AreaT3Dfl(v1, v2, v3) );
+       }
+       else if (vec1->size == 2) {
+               v1[0] = vec1->vec[0];
+               v1[1] = vec1->vec[1];
+
+               v2[0] = vec2->vec[0];
+               v2[1] = vec2->vec[1];
+
+               v3[0] = vec3->vec[0];
+               v3[1] = vec3->vec[1];
+
+               return PyFloat_FromDouble( AreaF2Dfl(v1, v2, v3) );
+       }
+       else {
+               PyErr_SetString( PyExc_TypeError, "only 2D,3D vectors are supported\n" );
+               return NULL;
+       }
+}
+//#############################DEPRECATED################################
+//#######################################################################
+//----------------------------------Mathutils.CopyMat() -----------------
+//copies a matrix into a new matrix
+PyObject *M_Mathutils_CopyMat(PyObject * self, PyObject * args)
+{
+       PyObject *matrix = NULL;
+       static char warning = 1;
+
+       if( warning ) {
+               printf("Mathutils.CopyMat(): deprecated :use Mathutils.Matrix() to copy matrices\n");
+               --warning;
+       }
+
+       matrix = M_Mathutils_Matrix(self, args);
+       if(matrix == NULL)
+               return NULL; //error string already set if we get here
+       else
+               return matrix;
+}
+//----------------------------------Mathutils.CopyVec() -----------------
+//makes a new vector that is a copy of the input
+PyObject *M_Mathutils_CopyVec(PyObject * self, PyObject * args)
+{
+       PyObject *vec = NULL;
+       static char warning = 1;
+
+       if( warning ) {
+               printf("Mathutils.CopyVec(): Deprecated: use Mathutils.Vector() to copy vectors\n");
+               --warning;
+       }
+
+       vec = M_Mathutils_Vector(self, args);
+       if(vec == NULL)
+               return NULL; //error string already set if we get here
+       else
+               return vec;
+}
+//----------------------------------Mathutils.CopyQuat() --------------
+//Copies a quaternion to a new quat
+PyObject *M_Mathutils_CopyQuat(PyObject * self, PyObject * args)
+{
+       PyObject *quat = NULL;
+       static char warning = 1;
+
+       if( warning ) {
+               printf("Mathutils.CopyQuat(): Deprecated: use Mathutils.Quaternion() to copy vectors\n");
+               --warning;
+       }
+
+       quat = M_Mathutils_Quaternion(self, args);
+       if(quat == NULL)
+               return NULL; //error string already set if we get here
+       else
+               return quat;
+}
+//----------------------------------Mathutils.CopyEuler() ---------------
+//copies a euler to a new euler
+PyObject *M_Mathutils_CopyEuler(PyObject * self, PyObject * args)
+{
+       PyObject *eul = NULL;
+       static char warning = 1;
+
+       if( warning ) {
+               printf("Mathutils.CopyEuler(): deprecated:use Mathutils.Euler() to copy vectors\n");
+               --warning;
+       }
+
+       eul = M_Mathutils_Euler(self, args);
+       if(eul == NULL)
+               return NULL; //error string already set if we get here
+       else
+               return eul;
+}
+//----------------------------------Mathutils.RotateEuler() ------------
+//rotates a euler a certain amount and returns the result
+//should return a unique euler rotation (i.e. no 720 degree pitches :)
+PyObject *M_Mathutils_RotateEuler(PyObject * self, PyObject * args)
+{
+       EulerObject *Eul = NULL;
+       float angle;
+       char *axis;
+       static char warning = 1;
+
+       if( warning ) {
+               printf("Mathutils.RotateEuler(): Deprecated:use Euler.rotate() to rotate a euler\n");
+               --warning;
+       }
+
+       if(!PyArg_ParseTuple(args, "O!fs", &euler_Type, &Eul, &angle, &axis)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.RotateEuler(): expected euler type & float & string");
+               return NULL;
+       }
+
+       Euler_Rotate(Eul, Py_BuildValue("fs", angle, axis));
+       Py_RETURN_NONE;
+}
+//----------------------------------Mathutils.MatMultVec() --------------
+//COLUMN VECTOR Multiplication (Matrix X Vector)
+PyObject *M_Mathutils_MatMultVec(PyObject * self, PyObject * args)
+{
+       MatrixObject *mat = NULL;
+       VectorObject *vec = NULL;
+       static char warning = 1;
+
+       if( warning ) {
+               printf("Mathutils.MatMultVec(): Deprecated: use matrix * vec to perform column vector multiplication\n");
+               --warning;
+       }
+
+       //get pyObjects
+       if(!PyArg_ParseTuple(args, "O!O!", &matrix_Type, &mat, &vector_Type, &vec)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.MatMultVec(): MatMultVec() expects a matrix and a vector object - in that order\n");
+               return NULL;
+       }
+
+       return column_vector_multiplication(mat, vec);
+}
+//----------------------------------Mathutils.VecMultMat() ---------------
+//ROW VECTOR Multiplication - Vector X Matrix
+PyObject *M_Mathutils_VecMultMat(PyObject * self, PyObject * args)
+{
+       MatrixObject *mat = NULL;
+       VectorObject *vec = NULL;
+       static char warning = 1;
+
+       if( warning ) {
+               printf("Mathutils.VecMultMat(): Deprecated: use vec * matrix to perform row vector multiplication\n");
+               --warning;
+       }
+
+       //get pyObjects
+       if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec, &matrix_Type, &mat)) {
+               PyErr_SetString(PyExc_TypeError, "Mathutils.VecMultMat(): VecMultMat() expects a vector and matrix object - in that order\n");
+               return NULL;
+       }
+
+       return row_vector_multiplication(vec, mat);
+}
+
+/* Utility functions */
+
+/*---------------------- EXPP_FloatsAreEqual -------------------------
+  Floating point comparisons 
+  floatStep = number of representable floats allowable in between
+   float A and float B to be considered equal. */
+int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
+{
+       int a, b, delta;
+    assert(floatSteps > 0 && floatSteps < (4 * 1024 * 1024));
+    a = *(int*)&A;
+    if (a < 0) 
+               a = 0x80000000 - a;
+    b = *(int*)&B;
+    if (b < 0) 
+               b = 0x80000000 - b;
+    delta = abs(a - b);
+    if (delta <= floatSteps)   
+               return 1;
+    return 0;
+}
+/*---------------------- EXPP_VectorsAreEqual -------------------------
+  Builds on EXPP_FloatsAreEqual to test vectors */
+int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
+
+       int x;
+       for (x=0; x< size; x++){
+               if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
+                       return 0;
+       }
+       return 1;
+}
+
+
+
+//#######################################################################
+//#############################DEPRECATED################################
diff --git a/source/blender/python/generic/Mathutils.h b/source/blender/python/generic/Mathutils.h
new file mode 100644 (file)
index 0000000..4c8153e
--- /dev/null
@@ -0,0 +1,100 @@
+/* 
+ * $Id: Mathutils.h 20332 2009-05-22 03:22:56Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA       02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+//Include this file for access to vector, quat, matrix, euler, etc...
+
+#ifndef EXPP_Mathutils_H
+#define EXPP_Mathutils_H
+
+#include <Python.h>
+#include "vector.h"
+#include "matrix.h"
+#include "quat.h"
+#include "euler.h"
+
+PyObject *Mathutils_Init( const char * from );
+
+PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat);
+PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec);
+PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
+
+PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_Vector(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_Matrix(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * value);
+PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_Quaternion(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_Euler(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args );
+PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args );
+PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args );
+PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args );
+PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args );
+//DEPRECATED   
+PyObject *M_Mathutils_CopyMat(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_CopyVec(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_CopyQuat(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_CopyEuler(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_RotateEuler(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_MatMultVec(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_VecMultMat(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_CrossVecs(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_DotVecs(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_CrossQuats(PyObject * self, PyObject * args);
+PyObject *M_Mathutils_DotQuats(PyObject * self, PyObject * args);
+
+int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
+int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
+
+
+#define Py_PI  3.14159265358979323846
+#define Py_WRAP 1024
+#define Py_NEW  2048
+
+
+/* Mathutils is used by the BGE and Blender so have to define 
+ * some things here for luddite mac users of py2.3 */
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE  return Py_INCREF(Py_None), Py_None
+#endif
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE  return Py_INCREF(Py_False), Py_False
+#endif
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE  return Py_INCREF(Py_True), Py_True
+#endif
+
+#endif                         /* EXPP_Mathutils_H */
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
new file mode 100644 (file)
index 0000000..6789aea
--- /dev/null
@@ -0,0 +1,341 @@
+/* 
+ * $Id: bpy_internal_import.c 20434 2009-05-26 18:06:09Z campbellbarton $
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+#include "bpy_internal_import.h"
+#include "DNA_text_types.h"
+#include "DNA_ID.h"
+
+#include "MEM_guardedalloc.h"
+#include "BKE_text.h" /* txt_to_buf */ 
+#include "BKE_main.h"
+
+static Main *bpy_import_main= NULL;
+
+static void free_compiled_text(Text *text)
+{
+       if(text->compiled) {
+               Py_DECREF(( PyObject * )text->compiled);
+       }
+       text->compiled= NULL;
+}
+
+struct Main *bpy_import_main_get(void)
+{
+       return bpy_import_main;
+}
+
+void bpy_import_main_set(struct Main *maggie)
+{
+       bpy_import_main= maggie;
+}
+
+
+PyObject *bpy_text_import( char *name, int *found )
+{
+       Text *text;
+       char txtname[22]; /* 21+NULL */
+       char *buf = NULL;
+       int namelen = strlen( name );
+//XXX  Main *maggie= bpy_import_main ? bpy_import_main:G.main;
+       Main *maggie= bpy_import_main;
+       
+       *found= 0;
+       
+       if (namelen>21-3) return NULL; /* we know this cant be importable, the name is too long for blender! */
+       
+       memcpy( txtname, name, namelen );
+       memcpy( &txtname[namelen], ".py", 4 );
+
+       for(text = maggie->text.first; text; text = text->id.next) {
+               if( !strcmp( txtname, text->id.name+2 ) )
+                       break;
+       }
+
+       if( !text )
+               return NULL;
+       else
+               *found = 1;
+       
+       if( !text->compiled ) {
+               buf = txt_to_buf( text );
+               text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
+               MEM_freeN( buf );
+
+               if( PyErr_Occurred(  ) ) {
+                       PyErr_Print(  );
+                       PyErr_Clear(  );
+                       PySys_SetObject("last_traceback", NULL);
+                       free_compiled_text( text );
+                       return NULL;
+               }
+       }
+
+       return PyImport_ExecCodeModule( name, text->compiled );
+}
+
+
+/*
+ * find in-memory module and recompile
+ */
+
+PyObject *bpy_text_reimport( PyObject *module, int *found )
+{
+       Text *text;
+       char *txtname;
+       char *name;
+       char *buf = NULL;
+//XXX  Main *maggie= bpy_import_main ? bpy_import_main:G.main;
+       Main *maggie= bpy_import_main;
+       
+       *found= 0;
+       
+       /* get name, filename from the module itself */
+
+       txtname = PyModule_GetFilename( module );
+       name = PyModule_GetName( module );
+       if( !txtname || !name)
+               return NULL;
+
+       /* look up the text object */
+       text = ( Text * ) & ( maggie->text.first );
+       while( text ) {
+               if( !strcmp( txtname, text->id.name+2 ) )
+                       break;
+               text = text->id.next;
+       }
+
+       /* uh-oh.... didn't find it */
+       if( !text )
+               return NULL;
+       else
+               *found = 1;
+
+       /* if previously compiled, free the object */
+       /* (can't see how could be NULL, but check just in case) */ 
+       if( text->compiled ){
+               Py_DECREF( (PyObject *)text->compiled );
+       }
+
+       /* compile the buffer */
+       buf = txt_to_buf( text );
+       text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
+       MEM_freeN( buf );
+
+       /* if compile failed.... return this error */
+       if( PyErr_Occurred(  ) ) {
+               PyErr_Print(  );
+               PyErr_Clear(  );
+               PySys_SetObject("last_traceback", NULL);
+               free_compiled_text( text );
+               return NULL;
+       }
+
+       /* make into a module */
+       return PyImport_ExecCodeModule( name, text->compiled );
+}
+
+
+static PyObject *blender_import( PyObject * self, PyObject * args,  PyObject * kw)
+{
+       PyObject *exception, *err, *tb;
+       char *name;
+       int found= 0;
+       PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
+       PyObject *newmodule;
+       
+       //PyObject_Print(args, stderr, 0);
+#if (PY_VERSION_HEX >= 0x02060000)
+       int dummy_val; /* what does this do?*/
+       static char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", 0};
+       
+       if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOOi:bpy_import_meth", kwlist,
+                              &name, &globals, &locals, &fromlist, &dummy_val) )
+               return NULL;
+#else
+       static char *kwlist[] = {"name", "globals", "locals", "fromlist", 0};
+       
+       if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOO:bpy_import_meth", kwlist,
+                              &name, &globals, &locals, &fromlist ) )
+               return NULL;
+#endif
+
+       /* import existing builtin modules or modules that have been imported alredy */
+       newmodule = PyImport_ImportModuleEx( name, globals, locals, fromlist );
+       
+       if(newmodule)
+               return newmodule;
+       
+       PyErr_Fetch( &exception, &err, &tb );   /* get the python error incase we cant import as blender text either */
+       
+       /* importing from existing modules failed, see if we have this module as blender text */
+       newmodule = bpy_text_import( name, &found );
+       
+       if( newmodule ) {/* found module as blender text, ignore above exception */
+               PyErr_Clear(  );
+               Py_XDECREF( exception );
+               Py_XDECREF( err );
+               Py_XDECREF( tb );
+               /* printf( "imported from text buffer...\n" ); */
+       }
+       else if (found==1) { /* blender text module failed to execute but was found, use its error message */
+               Py_XDECREF( exception );
+               Py_XDECREF( err );
+               Py_XDECREF( tb );
+               return NULL;
+       }
+       else {
+               /* no blender text was found that could import the module
+                * rause the original error from PyImport_ImportModuleEx */
+               PyErr_Restore( exception, err, tb );
+       }
+       return newmodule;
+}
+
+
+/*
+ * our reload() module, to handle reloading in-memory scripts
+ */
+
+static PyObject *blender_reload( PyObject * self, PyObject * args )
+{
+       PyObject *exception, *err, *tb;
+       PyObject *module = NULL;
+       PyObject *newmodule = NULL;
+       int found= 0;
+       
+       /* check for a module arg */
+       if( !PyArg_ParseTuple( args, "O:bpy_reload_meth", &module ) )
+               return NULL;
+
+       /* try reimporting from file */
+       newmodule = PyImport_ReloadModule( module );
+       if( newmodule )
+               return newmodule;
+
+       /* no file, try importing from memory */
+       PyErr_Fetch( &exception, &err, &tb );   /*restore for probable later use */
+
+       newmodule = bpy_text_reimport( module, &found );
+       if( newmodule ) {/* found module as blender text, ignore above exception */
+               PyErr_Clear(  );
+               Py_XDECREF( exception );
+               Py_XDECREF( err );
+               Py_XDECREF( tb );
+               /* printf( "imported from text buffer...\n" ); */
+       }
+       else if (found==1) { /* blender text module failed to execute but was found, use its error message */
+               Py_XDECREF( exception );
+               Py_XDECREF( err );
+               Py_XDECREF( tb );
+               return NULL;
+       }
+       else {
+               /* no blender text was found that could import the module
+                * rause the original error from PyImport_ImportModuleEx */
+               PyErr_Restore( exception, err, tb );
+       }
+
+       return newmodule;
+}
+
+PyMethodDef bpy_import_meth[] = { {"bpy_import_meth", blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"} };
+PyMethodDef bpy_reload_meth[] = { {"bpy_reload_meth", blender_reload, METH_VARARGS, "blenders reload"} };
+
+
+/* Clear user modules.
+ * This is to clear any modules that could be defined from running scripts in blender.
+ * 
+ * Its also needed for the BGE Python api so imported scripts are not used between levels
+ * 
+ * This clears every modules that has a __file__ attribute (is not a builtin)
+ *
+ * Note that clearing external python modules is important for the BGE otherwise
+ * it wont reload scripts between loading different blend files or while making the game.
+ * - use 'clear_all' arg in this case.
+ *
+ * Since pythons bultins include a full path even for win32.
+ * even if we remove a python module a reimport will bring it back again.
+ */
+
+#if 0 // not used anymore but may still come in handy later
+
+#if defined(WIN32) || defined(WIN64)
+#define SEPSTR "\\"
+#else
+#define SEPSTR "/"
+#endif
+
+
+void bpy_text_clear_modules(int clear_all)
+{
+       PyObject *modules= PySys_GetObject("modules");
+       
+       char *fname;
+       char *file_extension;
+       
+       /* looping over the dict */
+       PyObject *key, *value;
+       int pos = 0;
+       
+       /* new list */
+       PyObject *list;
+
+       if (modules==NULL)
+               return; /* should never happen but just incase */
+
+       list= PyList_New(0);
+
+       /* go over sys.modules and remove anything with a 
+        * sys.modukes[x].__file__ thats ends with a .py and has no path
+        */
+       while (PyDict_Next(modules, &pos, &key, &value)) {
+               fname= PyModule_GetFilename(value);
+               if(fname) {
+                       if (clear_all || ((strstr(fname, SEPSTR))==0)) { /* no path ? */
+                               file_extension = strstr(fname, ".py");
+                               if(file_extension && (*(file_extension + 3) == '\0' || *(file_extension + 4) == '\0')) { /* .py or pyc extension? */
+                                       /* now we can be fairly sure its a python import from the blendfile */
+                                       PyList_Append(list, key); /* free'd with the list */
+                               }
+                       }
+               }
+               else {
+                       PyErr_Clear();
+               }
+       }
+       
+       /* remove all our modules */
+       for(pos=0; pos < PyList_Size(list); pos++) {
+               /* PyObject_Print(key, stderr, 0); */
+               key= PyList_GET_ITEM(list, pos);
+               PyDict_DelItem(modules, key);
+       }
+       
+       Py_DECREF(list); /* removes all references from append */
+}
+#endif
diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h
new file mode 100644 (file)
index 0000000..9c3ce57
--- /dev/null
@@ -0,0 +1,49 @@
+/* 
+ * $Id: bpy_internal_import.h 20434 2009-05-26 18:06:09Z campbellbarton $
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+/* Note, the BGE needs to use this too, keep it minimal */
+
+#ifndef EXPP_bpy_import_h
+#define EXPP_bpy_import_h
+
+#include <Python.h>
+#include "compile.h"           /* for the PyCodeObject */
+#include "eval.h"              /* for PyEval_EvalCode */
+
+PyObject*      bpy_text_import( char *name, int *found );
+PyObject*      bpy_text_reimport( PyObject *module, int *found );
+/* void                bpy_text_clear_modules( int clear_all );*/ /* Clear user modules */ 
+extern PyMethodDef bpy_import_meth[];
+extern PyMethodDef bpy_reload_meth[];
+
+/* The game engine has its own Main struct, if this is set search this rather then G.main */
+struct Main *bpy_import_main_get(void);
+void bpy_import_main_set(struct Main *maggie);
+
+
+#endif                         /* EXPP_bpy_import_h */
diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c
new file mode 100644 (file)
index 0000000..82131b1
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * $Id: euler.c 20248 2009-05-18 04:11:54Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "Mathutils.h"
+
+#include "BLI_arithb.h"
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+
+
+//-------------------------DOC STRINGS ---------------------------
+char Euler_Zero_doc[] = "() - set all values in the euler to 0";
+char Euler_Unique_doc[] ="() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock";
+char Euler_ToMatrix_doc[] =    "() - returns a rotation matrix representing the euler rotation";
+char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation";
+char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation";
+char Euler_copy_doc[] = "() - returns a copy of the euler.";
+char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping).";
+//-----------------------METHOD DEFINITIONS ----------------------
+struct PyMethodDef Euler_methods[] = {
+       {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
+       {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
+       {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
+       {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
+       {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, Euler_Rotate_doc},
+       {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
+       {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
+       {"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
+       {NULL, NULL, 0, NULL}
+};
+//-----------------------------METHODS----------------------------
+//----------------------------Euler.toQuat()----------------------
+//return a quaternion representation of the euler
+PyObject *Euler_ToQuat(EulerObject * self)
+{
+       float eul[3], quat[4];
+       int x;
+
+       for(x = 0; x < 3; x++) {
+               eul[x] = self->eul[x] * ((float)Py_PI / 180);
+       }
+       EulToQuat(eul, quat);
+       return newQuaternionObject(quat, Py_NEW);
+}
+//----------------------------Euler.toMatrix()---------------------
+//return a matrix representation of the euler
+PyObject *Euler_ToMatrix(EulerObject * self)
+{
+       float eul[3];
+       float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+       int x;
+
+       for(x = 0; x < 3; x++) {
+               eul[x] = self->eul[x] * ((float)Py_PI / 180);
+       }
+       EulToMat3(eul, (float (*)[3]) mat);
+       return newMatrixObject(mat, 3, 3 , Py_NEW);
+}
+//----------------------------Euler.unique()-----------------------
+//sets the x,y,z values to a unique euler rotation
+PyObject *Euler_Unique(EulerObject * self)
+{
+       double heading, pitch, bank;
+       double pi2 =  Py_PI * 2.0f;
+       double piO2 = Py_PI / 2.0f;
+       double Opi2 = 1.0f / pi2;
+
+       //radians
+       heading = self->eul[0] * (float)Py_PI / 180;
+       pitch = self->eul[1] * (float)Py_PI / 180;
+       bank = self->eul[2] * (float)Py_PI / 180;
+
+       //wrap heading in +180 / -180
+       pitch += Py_PI;
+       pitch -= floor(pitch * Opi2) * pi2;
+       pitch -= Py_PI;
+
+
+       if(pitch < -piO2) {
+               pitch = -Py_PI - pitch;
+               heading += Py_PI;
+               bank += Py_PI;
+       } else if(pitch > piO2) {
+               pitch = Py_PI - pitch;
+               heading += Py_PI;
+               bank += Py_PI;
+       }
+       //gimbal lock test
+       if(fabs(pitch) > piO2 - 1e-4) {
+               heading += bank;
+               bank = 0.0f;
+       } else {
+               bank += Py_PI;
+               bank -= (floor(bank * Opi2)) * pi2;
+               bank -= Py_PI;
+       }
+
+       heading += Py_PI;
+       heading -= (floor(heading * Opi2)) * pi2;
+       heading -= Py_PI;
+
+       //back to degrees
+       self->eul[0] = (float)(heading * 180 / (float)Py_PI);
+       self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
+       self->eul[2] = (float)(bank * 180 / (float)Py_PI);
+
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+//----------------------------Euler.zero()-------------------------
+//sets the euler to 0,0,0
+PyObject *Euler_Zero(EulerObject * self)
+{
+       self->eul[0] = 0.0;
+       self->eul[1] = 0.0;
+       self->eul[2] = 0.0;
+
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+//----------------------------Euler.rotate()-----------------------
+//rotates a euler a certain amount and returns the result
+//should return a unique euler rotation (i.e. no 720 degree pitches :)
+PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
+{
+       float angle = 0.0f;
+       char *axis;
+       int x;
+
+       if(!PyArg_ParseTuple(args, "fs", &angle, &axis)){
+               PyErr_SetString(PyExc_TypeError, "euler.rotate():expected angle (float) and axis (x,y,z)");
+               return NULL;
+       }
+       if(!STREQ3(axis,"x","y","z")){
+               PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'x', 'y' or 'z'");
+               return NULL;
+       }
+
+       //covert to radians
+       angle *= ((float)Py_PI / 180);
+       for(x = 0; x < 3; x++) {
+               self->eul[x] *= ((float)Py_PI / 180);
+       }
+       euler_rot(self->eul, angle, *axis);
+       //convert back from radians
+       for(x = 0; x < 3; x++) {
+               self->eul[x] *= (180 / (float)Py_PI);
+       }
+
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+
+PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
+{
+       float eul_from_rad[3];
+       int x;
+       
+       if(!EulerObject_Check(value)) {
+               PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
+               return NULL;
+       }
+       
+       //covert to radians
+       for(x = 0; x < 3; x++) {
+               self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
+               eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
+       }
+       compatible_eul(self->eul, eul_from_rad);
+       //convert back from radians
+       for(x = 0; x < 3; x++) {
+               self->eul[x] *= (180 / (float)Py_PI);
+       }
+       
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+
+//----------------------------Euler.rotate()-----------------------
+// return a copy of the euler
+PyObject *Euler_copy(EulerObject * self, PyObject *args)
+{
+       return newEulerObject(self->eul, Py_NEW);
+}
+
+
+//----------------------------dealloc()(internal) ------------------
+//free the py_object
+static void Euler_dealloc(EulerObject * self)
+{
+       //only free py_data
+       if(self->data.py_data){
+               PyMem_Free(self->data.py_data);
+       }
+       PyObject_DEL(self);
+}
+
+//----------------------------print object (internal)--------------
+//print the object to screen
+static PyObject *Euler_repr(EulerObject * self)
+{
+       char str[64];
+       sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
+       return PyUnicode_FromString(str);
+}
+//------------------------tp_richcmpr
+//returns -1 execption, 0 false, 1 true
+static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
+{
+       EulerObject *eulA = NULL, *eulB = NULL;
+       int result = 0;
+
+       if (!EulerObject_Check(objectA) || !EulerObject_Check(objectB)){
+               if (comparison_type == Py_NE){
+                       Py_RETURN_TRUE;
+               }else{
+                       Py_RETURN_FALSE;
+               }
+       }
+       eulA = (EulerObject*)objectA;
+       eulB = (EulerObject*)objectB;
+
+       switch (comparison_type){
+               case Py_EQ:
+                       result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
+                       break;
+               case Py_NE:
+                       result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
+                       if (result == 0){
+                               result = 1;
+                       }else{
+                               result = 0;
+                       }
+                       break;
+               default:
+                       printf("The result of the comparison could not be evaluated");
+                       break;
+       }
+       if (result == 1){
+               Py_RETURN_TRUE;
+       }else{
+               Py_RETURN_FALSE;
+       }
+}
+//------------------------tp_doc
+static char EulerObject_doc[] = "This is a wrapper for euler objects.";
+//---------------------SEQUENCE PROTOCOLS------------------------
+//----------------------------len(object)------------------------
+//sequence length
+static int Euler_len(EulerObject * self)
+{
+       return 3;
+}
+//----------------------------object[]---------------------------
+//sequence accessor (get)
+static PyObject *Euler_item(EulerObject * self, int i)
+{
+       if(i<0)
+               i= 3-i;
+       
+       if(i < 0 || i >= 3) {
+               PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
+               return NULL;
+       }
+       return PyFloat_FromDouble(self->eul[i]);
+
+}
+//----------------------------object[]-------------------------
+//sequence accessor (set)
+static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
+{
+       float f = PyFloat_AsDouble(value);
+
+       if(f == -1 && PyErr_Occurred()) { // parsed item not a number
+               PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
+               return -1;
+       }
+
+       if(i<0)
+               i= 3-i;
+       
+       if(i < 0 || i >= 3){
+               PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
+               return -1;
+       }
+       
+       self->eul[i] = f;
+       return 0;
+}
+//----------------------------object[z:y]------------------------
+//sequence slice (get)
+static PyObject *Euler_slice(EulerObject * self, int begin, int end)
+{
+       PyObject *list = NULL;
+       int count;
+
+       CLAMP(begin, 0, 3);
+       if (end<0) end= 4+end;
+       CLAMP(end, 0, 3);
+       begin = MIN2(begin,end);
+
+       list = PyList_New(end - begin);
+       for(count = begin; count < end; count++) {
+               PyList_SetItem(list, count - begin,
+                               PyFloat_FromDouble(self->eul[count]));
+       }
+
+       return list;
+}
+//----------------------------object[z:y]------------------------
+//sequence slice (set)
+static int Euler_ass_slice(EulerObject * self, int begin, int end,
+                            PyObject * seq)
+{
+       int i, y, size = 0;
+       float eul[3];
+       PyObject *e, *f;
+
+       CLAMP(begin, 0, 3);
+       if (end<0) end= 4+end;
+       CLAMP(end, 0, 3);
+       begin = MIN2(begin,end);
+
+       size = PySequence_Length(seq);
+       if(size != (end - begin)){
+               PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
+               return -1;
+       }
+
+       for (i = 0; i < size; i++) {
+               e = PySequence_GetItem(seq, i);
+               if (e == NULL) { // Failed to read sequence
+                       PyErr_SetString(PyExc_RuntimeError, "euler[begin:end] = []: unable to read sequence");
+                       return -1;
+               }
+
+               f = PyNumber_Float(e);
+               if(f == NULL) { // parsed item not a number
+                       Py_DECREF(e);
+                       PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
+                       return -1;
+               }
+
+               eul[i] = (float)PyFloat_AS_DOUBLE(f);
+               Py_DECREF(f);
+               Py_DECREF(e);
+       }
+       //parsed well - now set in vector
+       for(y = 0; y < 3; y++){
+               self->eul[begin + y] = eul[y];
+       }
+       return 0;
+}
+//-----------------PROTCOL DECLARATIONS--------------------------
+static PySequenceMethods Euler_SeqMethods = {
+       (inquiry) Euler_len,                                            /* sq_length */
+       (binaryfunc) 0,                                                         /* sq_concat */
+       (ssizeargfunc) 0,                                                               /* sq_repeat */
+       (ssizeargfunc) Euler_item,                                      /* sq_item */
+       (ssizessizeargfunc) Euler_slice,                                /* sq_slice */
+       (ssizeobjargproc) Euler_ass_item,                               /* sq_ass_item */
+       (ssizessizeobjargproc) Euler_ass_slice,                 /* sq_ass_slice */
+};
+
+
+
+/*
+ * vector axis, vector.x/y/z/w
+ */
+       
+static PyObject *Euler_getAxis( EulerObject * self, void *type )
+{
+       switch( (long)type ) {
+    case 'X':  /* these are backwards, but that how it works */
+               return PyFloat_FromDouble(self->eul[0]);
+    case 'Y':
+               return PyFloat_FromDouble(self->eul[1]);
+    case 'Z':
+               return PyFloat_FromDouble(self->eul[2]);
+       }
+       
+       PyErr_SetString(PyExc_SystemError, "corrupt euler, cannot get axis");
+       return NULL;
+}
+
+static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
+{
+       float param= (float)PyFloat_AsDouble( value );
+       
+       if (param==-1 && PyErr_Occurred()) {
+               PyErr_SetString(PyExc_TypeError, "expected a number for the vector axis");
+               return -1;
+       }
+       
+       switch( (long)type ) {
+    case 'X':  /* these are backwards, but that how it works */
+               self->eul[0]= param;
+               break;
+    case 'Y':
+               self->eul[1]= param;
+               break;
+    case 'Z':
+               self->eul[2]= param;
+               break;
+       }
+
+       return 0;
+}
+
+static PyObject *Euler_getWrapped( VectorObject * self, void *type )
+{
+       if (self->wrapped == Py_WRAP)
+               Py_RETURN_TRUE;
+       else
+               Py_RETURN_FALSE;
+}
+
+
+/*****************************************************************************/
+/* Python attributes get/set structure:                                      */
+/*****************************************************************************/
+static PyGetSetDef Euler_getseters[] = {
+       {"x",
+        (getter)Euler_getAxis, (setter)Euler_setAxis,
+        "Euler X axis",
+        (void *)'X'},
+       {"y",
+        (getter)Euler_getAxis, (setter)Euler_setAxis,
+        "Euler Y axis",
+        (void *)'Y'},
+       {"z",
+        (getter)Euler_getAxis, (setter)Euler_setAxis,
+        "Euler Z axis",
+        (void *)'Z'},
+       {"wrapped",
+        (getter)Euler_getWrapped, (setter)NULL,
+        "True when this wraps blenders internal data",
+        NULL},
+       {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
+};
+
+//------------------PY_OBECT DEFINITION--------------------------
+PyTypeObject euler_Type = {
+#if (PY_VERSION_HEX >= 0x02060000)
+       PyVarObject_HEAD_INIT(NULL, 0)
+#else
+       /* python 2.5 and below */
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+#endif
+       "euler",                                                //tp_name
+       sizeof(EulerObject),                    //tp_basicsize
+       0,                                                              //tp_itemsize
+       (destructor)Euler_dealloc,              //tp_dealloc
+       0,                                                              //tp_print
+       0,                                                              //tp_getattr
+       0,                                                              //tp_setattr
+       0,                                                              //tp_compare
+       (reprfunc) Euler_repr,                  //tp_repr
+       0,                              //tp_as_number
+       &Euler_SeqMethods,                              //tp_as_sequence
+       0,                                                              //tp_as_mapping
+       0,                                                              //tp_hash
+       0,                                                              //tp_call
+       0,                                                              //tp_str
+       0,                                                              //tp_getattro
+       0,                                                              //tp_setattro
+       0,                                                              //tp_as_buffer
+       Py_TPFLAGS_DEFAULT,                             //tp_flags
+       EulerObject_doc,                                //tp_doc
+       0,                                                              //tp_traverse
+       0,                                                              //tp_clear
+       (richcmpfunc)Euler_richcmpr,    //tp_richcompare
+       0,                                                              //tp_weaklistoffset
+       0,                                                              //tp_iter
+       0,                                                              //tp_iternext
+       Euler_methods,                                  //tp_methods
+       0,                                                              //tp_members
+       Euler_getseters,                                //tp_getset
+       0,                                                              //tp_base
+       0,                                                              //tp_dict
+       0,                                                              //tp_descr_get
+       0,                                                              //tp_descr_set
+       0,                                                              //tp_dictoffset
+       0,                                                              //tp_init
+       0,                                                              //tp_alloc
+       0,                                                              //tp_new
+       0,                                                              //tp_free
+       0,                                                              //tp_is_gc
+       0,                                                              //tp_bases
+       0,                                                              //tp_mro
+       0,                                                              //tp_cache
+       0,                                                              //tp_subclasses
+       0,                                                              //tp_weaklist
+       0                                                               //tp_del
+};
+//------------------------newEulerObject (internal)-------------
+//creates a new euler object
+/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
+ (i.e. it was allocated elsewhere by MEM_mallocN())
+  pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
+ (i.e. it must be created here with PyMEM_malloc())*/
+PyObject *newEulerObject(float *eul, int type)
+{
+       EulerObject *self;
+       int x;
+
+       self = PyObject_NEW(EulerObject, &euler_Type);
+       self->data.blend_data = NULL;
+       self->data.py_data = NULL;
+
+       if(type == Py_WRAP){
+               self->data.blend_data = eul;
+               self->eul = self->data.blend_data;
+               self->wrapped = Py_WRAP;
+       }else if (type == Py_NEW){
+               self->data.py_data = PyMem_Malloc(3 * sizeof(float));
+               self->eul = self->data.py_data;
+               if(!eul) { //new empty
+                       for(x = 0; x < 3; x++) {
+                               self->eul[x] = 0.0f;
+                       }
+               }else{
+                       for(x = 0; x < 3; x++){
+                               self->eul[x] = eul[x];
+                       }
+               }
+               self->wrapped = Py_NEW;
+       }else{ //bad type
+               return NULL;
+       }
+       return (PyObject *)self;
+}
diff --git a/source/blender/python/generic/euler.h b/source/blender/python/generic/euler.h
new file mode 100644 (file)
index 0000000..f94f060
--- /dev/null
@@ -0,0 +1,65 @@
+/* 
+ * $Id: euler.h 20248 2009-05-18 04:11:54Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef EXPP_euler_h
+#define EXPP_euler_h
+
+#include <Python.h>
+
+extern PyTypeObject euler_Type;
+
+#define EulerObject_Check(v) (Py_TYPE(v) == &euler_Type)
+
+typedef struct {
+       PyObject_VAR_HEAD 
+       struct{
+               float *py_data;         //python managed
+               float *blend_data;      //blender managed
+       }data;
+       float *eul;                             //1D array of data (alias)
+       int wrapped;                    //is wrapped data?
+} EulerObject;
+
+/*struct data contains a pointer to the actual data that the
+object uses. It can use either PyMem allocated data (which will
+be stored in py_data) or be a wrapper for data allocated through
+blender (stored in blend_data). This is an either/or struct not both*/
+
+//prototypes
+PyObject *Euler_Zero( EulerObject * self );
+PyObject *Euler_Unique( EulerObject * self );
+PyObject *Euler_ToMatrix( EulerObject * self );
+PyObject *Euler_ToQuat( EulerObject * self );
+PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
+PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
+PyObject *Euler_copy( EulerObject * self, PyObject *args );
+PyObject *newEulerObject( float *eul, int type );
+
+#endif                         /* EXPP_euler_h */
diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c
new file mode 100644 (file)
index 0000000..16c72d6
--- /dev/null
@@ -0,0 +1,1002 @@
+/*
+ * $Id: matrix.c 20249 2009-05-18 04:27:48Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Michel Selten & Joseph Gilbert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "Mathutils.h"
+
+#include "BKE_utildefines.h"
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+/*-------------------------DOC STRINGS ---------------------------*/
+char Matrix_Zero_doc[] = "() - set all values in the matrix to 0";
+char Matrix_Identity_doc[] = "() - set the square matrix to it's identity matrix";
+char Matrix_Transpose_doc[] = "() - set the matrix to it's transpose";
+char Matrix_Determinant_doc[] = "() - return the determinant of the matrix";
+char Matrix_Invert_doc[] =  "() - set the matrix to it's inverse if an inverse is possible";
+char Matrix_TranslationPart_doc[] = "() - return a vector encompassing the translation of the matrix";
+char Matrix_RotationPart_doc[] = "() - return a vector encompassing the rotation of the matrix";
+char Matrix_scalePart_doc[] = "() - convert matrix to a 3D vector";
+char Matrix_Resize4x4_doc[] = "() - resize the matrix to a 4x4 square matrix";
+char Matrix_toEuler_doc[] = "(eul_compat) - convert matrix to a euler angle rotation, optional euler argument that the new euler will be made compatible with.";
+char Matrix_toQuat_doc[] = "() - convert matrix to a quaternion rotation";
+char Matrix_copy_doc[] = "() - return a copy of the matrix";
+/*-----------------------METHOD DEFINITIONS ----------------------*/
+struct PyMethodDef Matrix_methods[] = {
+       {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, Matrix_Zero_doc},
+       {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, Matrix_Identity_doc},
+       {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, Matrix_Transpose_doc},
+       {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, Matrix_Determinant_doc},
+       {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, Matrix_Invert_doc},
+       {"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, Matrix_TranslationPart_doc},
+       {"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc},
+       {"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, Matrix_scalePart_doc},
+       {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc},
+       {"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, Matrix_toEuler_doc},
+       {"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc},
+       {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
+       {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
+       {NULL, NULL, 0, NULL}
+};
+/*-----------------------------METHODS----------------------------*/
+/*---------------------------Matrix.toQuat() ---------------------*/
+PyObject *Matrix_toQuat(MatrixObject * self)
+{
+       float quat[4];
+
+       /*must be 3-4 cols, 3-4 rows, square matrix*/
+       if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) {
+               PyErr_SetString(PyExc_AttributeError, "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
+               return NULL;
+       } 
+       if(self->colSize == 3){
+        Mat3ToQuat((float (*)[3])*self->matrix, quat);
+       }else{
+               Mat4ToQuat((float (*)[4])*self->matrix, quat);
+       }
+       
+       return newQuaternionObject(quat, Py_NEW);
+}
+/*---------------------------Matrix.toEuler() --------------------*/
+PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
+{
+       float eul[3], eul_compatf[3];
+       EulerObject *eul_compat = NULL;
+       int x;
+       
+       if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
+               return NULL;
+       
+       if(eul_compat) {
+               for(x = 0; x < 3; x++) {
+                       eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
+               }
+       }
+       
+       /*must be 3-4 cols, 3-4 rows, square matrix*/
+       if(self->colSize ==3 && self->rowSize ==3) {
+               if(eul_compat)  Mat3ToCompatibleEul((float (*)[3])*self->matrix, eul, eul_compatf);
+               else                    Mat3ToEul((float (*)[3])*self->matrix, eul);
+       }else if (self->colSize ==4 && self->rowSize ==4) {
+               float tempmat3[3][3];
+               Mat3CpyMat4(tempmat3, (float (*)[4])*self->matrix);
+               Mat3ToEul(tempmat3, eul);
+               if(eul_compat)  Mat3ToCompatibleEul(tempmat3, eul, eul_compatf);
+               else                    Mat3ToEul(tempmat3, eul);
+               
+       }else {
+               PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
+               return NULL;
+       }
+       /*have to convert to degrees*/
+       for(x = 0; x < 3; x++) {
+               eul[x] *= (float) (180 / Py_PI);
+       }
+       return newEulerObject(eul, Py_NEW);
+}
+/*---------------------------Matrix.resize4x4() ------------------*/
+PyObject *Matrix_Resize4x4(MatrixObject * self)
+{
+       int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
+
+       if(self->data.blend_data){
+               PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - only python matrices");
+               return NULL;
+       }
+
+       self->data.py_data = PyMem_Realloc(self->data.py_data, (sizeof(float) * 16));
+       if(self->data.py_data == NULL) {
+               PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
+               return NULL;
+       }
+       self->contigPtr = self->data.py_data;  /*force*/
+       self->matrix = PyMem_Realloc(self->matrix, (sizeof(float *) * 4));
+       if(self->matrix == NULL) {
+               PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
+               return NULL;
+       }
+       /*set row pointers*/
+       for(x = 0; x < 4; x++) {
+               self->matrix[x] = self->contigPtr + (x * 4);
+       }
+       /*move data to new spot in array + clean*/
+       for(blank_rows = (4 - self->rowSize); blank_rows > 0; blank_rows--){
+               for(x = 0; x < 4; x++){
+                       index = (4 * (self->rowSize + (blank_rows - 1))) + x;
+                       if (index == 10 || index == 15){
+                               self->contigPtr[index] = 1.0f;
+                       }else{
+                               self->contigPtr[index] = 0.0f;
+                       }
+               }
+       }
+       for(x = 1; x <= self->rowSize; x++){
+               first_row_elem = (self->colSize * (self->rowSize - x));
+               curr_pos = (first_row_elem + (self->colSize -1));
+               new_pos = (4 * (self->rowSize - x )) + (curr_pos - first_row_elem);
+               for(blank_columns = (4 - self->colSize); blank_columns > 0; blank_columns--){
+                       self->contigPtr[new_pos + blank_columns] = 0.0f;
+               }
+               for(curr_pos = curr_pos; curr_pos >= first_row_elem; curr_pos--){
+                       self->contigPtr[new_pos] = self->contigPtr[curr_pos];
+                       new_pos--;
+               }
+       }
+       self->rowSize = 4;
+       self->colSize = 4;
+       
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+/*---------------------------Matrix.translationPart() ------------*/
+PyObject *Matrix_TranslationPart(MatrixObject * self)
+{
+       float vec[4];
+
+       if(self->colSize < 3 || self->rowSize < 4){
+               PyErr_SetString(PyExc_AttributeError, "Matrix.translationPart: inappropriate matrix size");
+               return NULL;
+       }
+
+       vec[0] = self->matrix[3][0];
+       vec[1] = self->matrix[3][1];
+       vec[2] = self->matrix[3][2];
+
+       return newVectorObject(vec, 3, Py_NEW);
+}
+/*---------------------------Matrix.rotationPart() ---------------*/
+PyObject *Matrix_RotationPart(MatrixObject * self)
+{
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+
+       if(self->colSize < 3 || self->rowSize < 3){
+               PyErr_SetString(PyExc_AttributeError, "Matrix.rotationPart: inappropriate matrix size\n");
+               return NULL;
+       }
+
+       mat[0] = self->matrix[0][0];
+       mat[1] = self->matrix[0][1];
+       mat[2] = self->matrix[0][2];
+       mat[3] = self->matrix[1][0];
+       mat[4] = self->matrix[1][1];
+       mat[5] = self->matrix[1][2];
+       mat[6] = self->matrix[2][0];
+       mat[7] = self->matrix[2][1];
+       mat[8] = self->matrix[2][2];
+
+       return newMatrixObject(mat, 3, 3, Py_NEW);
+}
+/*---------------------------Matrix.scalePart() --------------------*/
+PyObject *Matrix_scalePart(MatrixObject * self)
+{
+       float scale[3], rot[3];
+       float mat[3][3], imat[3][3], tmat[3][3];
+
+       /*must be 3-4 cols, 3-4 rows, square matrix*/
+       if(self->colSize == 4 && self->rowSize == 4)
+               Mat3CpyMat4(mat, (float (*)[4])*self->matrix);
+       else if(self->colSize == 3 && self->rowSize == 3)
+               Mat3CpyMat3(mat, (float (*)[3])*self->matrix);
+       else {
+               PyErr_SetString(PyExc_AttributeError, "Matrix.scalePart(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
+               return NULL;
+       }
+       /* functionality copied from editobject.c apply_obmat */
+       Mat3ToEul(mat, rot);
+       EulToMat3(rot, tmat);
+       Mat3Inv(imat, tmat);
+       Mat3MulMat3(tmat, imat, mat);
+       
+       scale[0]= tmat[0][0];
+       scale[1]= tmat[1][1];
+       scale[2]= tmat[2][2];
+       return newVectorObject(scale, 3, Py_NEW);
+}
+/*---------------------------Matrix.invert() ---------------------*/
+PyObject *Matrix_Invert(MatrixObject * self)
+{
+       
+       int x, y, z = 0;
+       float det = 0.0f;
+       PyObject *f = NULL;
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+
+       if(self->rowSize != self->colSize){
+               PyErr_SetString(PyExc_AttributeError, "Matrix.invert(ed): only square matrices are supported");
+               return NULL;
+       }
+
+       /*calculate the determinant*/
+       f = Matrix_Determinant(self);
+       det = (float)PyFloat_AS_DOUBLE(f); /*Increfs, so we need to decref*/
+       Py_DECREF(f);
+
+       if(det != 0) {
+               /*calculate the classical adjoint*/
+               if(self->rowSize == 2) {
+                       mat[0] = self->matrix[1][1];
+                       mat[1] = -self->matrix[0][1];
+                       mat[2] = -self->matrix[1][0];
+                       mat[3] = self->matrix[0][0];
+               } else if(self->rowSize == 3) {
+                       Mat3Adj((float (*)[3]) mat,(float (*)[3]) *self->matrix);
+               } else if(self->rowSize == 4) {
+                       Mat4Adj((float (*)[4]) mat, (float (*)[4]) *self->matrix);
+               }
+               /*divide by determinate*/
+               for(x = 0; x < (self->rowSize * self->colSize); x++) {
+                       mat[x] /= det;
+               }
+               /*set values*/
+               for(x = 0; x < self->rowSize; x++) {
+                       for(y = 0; y < self->colSize; y++) {
+                               self->matrix[x][y] = mat[z];
+                               z++;
+                       }
+               }
+               /*transpose
+               Matrix_Transpose(self);*/
+       } else {
+               PyErr_SetString(PyExc_ValueError, "matrix does not have an inverse");
+               return NULL;
+       }
+       
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+
+
+/*---------------------------Matrix.determinant() ----------------*/
+PyObject *Matrix_Determinant(MatrixObject * self)
+{
+       float det = 0.0f;
+
+       if(self->rowSize != self->colSize){
+               PyErr_SetString(PyExc_AttributeError, "Matrix.determinant: only square matrices are supported");
+               return NULL;
+       }
+
+       if(self->rowSize == 2) {
+               det = Det2x2(self->matrix[0][0], self->matrix[0][1],
+                                        self->matrix[1][0], self->matrix[1][1]);
+       } else if(self->rowSize == 3) {
+               det = Det3x3(self->matrix[0][0], self->matrix[0][1],
+                                        self->matrix[0][2], self->matrix[1][0],
+                                        self->matrix[1][1], self->matrix[1][2],
+                                        self->matrix[2][0], self->matrix[2][1],
+                                        self->matrix[2][2]);
+       } else {
+               det = Det4x4((float (*)[4]) *self->matrix);
+       }
+
+       return PyFloat_FromDouble( (double) det );
+}
+/*---------------------------Matrix.transpose() ------------------*/
+PyObject *Matrix_Transpose(MatrixObject * self)
+{
+       float t = 0.0f;
+
+       if(self->rowSize != self->colSize){
+               PyErr_SetString(PyExc_AttributeError, "Matrix.transpose(d): only square matrices are supported");
+               return NULL;
+       }
+
+       if(self->rowSize == 2) {
+               t = self->matrix[1][0];
+               self->matrix[1][0] = self->matrix[0][1];
+               self->matrix[0][1] = t;
+       } else if(self->rowSize == 3) {
+               Mat3Transp((float (*)[3])*self->matrix);
+       } else {
+               Mat4Transp((float (*)[4])*self->matrix);
+       }
+
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+
+
+/*---------------------------Matrix.zero() -----------------------*/
+PyObject *Matrix_Zero(MatrixObject * self)
+{
+       int row, col;
+
+       for(row = 0; row < self->rowSize; row++) {
+               for(col = 0; col < self->colSize; col++) {
+                       self->matrix[row][col] = 0.0f;
+               }
+       }
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+/*---------------------------Matrix.identity(() ------------------*/
+PyObject *Matrix_Identity(MatrixObject * self)
+{
+       if(self->rowSize != self->colSize){
+               PyErr_SetString(PyExc_AttributeError, "Matrix.identity: only square matrices are supported\n");
+               return NULL;
+       }
+
+       if(self->rowSize == 2) {
+               self->matrix[0][0] = 1.0f;
+               self->matrix[0][1] = 0.0f;
+               self->matrix[1][0] = 0.0f;
+               self->matrix[1][1] = 1.0f;
+       } else if(self->rowSize == 3) {
+               Mat3One((float (*)[3]) *self->matrix);
+       } else {
+               Mat4One((float (*)[4]) *self->matrix);
+       }
+
+       Py_INCREF(self);
+       return (PyObject *)self;
+}
+
+/*---------------------------Matrix.inverted() ------------------*/
+PyObject *Matrix_copy(MatrixObject * self)
+{
+       return (PyObject*)(MatrixObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW);
+}
+
+/*----------------------------dealloc()(internal) ----------------*/
+/*free the py_object*/
+static void Matrix_dealloc(MatrixObject * self)
+{
+       Py_XDECREF(self->coerced_object);
+       PyMem_Free(self->matrix);
+       /*only free py_data*/
+       if(self->data.py_data){
+               PyMem_Free(self->data.py_data);
+       }
+       PyObject_DEL(self);
+}
+/*----------------------------getattr()(internal) ----------------*/
+/*object.attribute access (get)*/
+static PyObject *Matrix_getattr(MatrixObject * self, char *name)
+{
+       if(STREQ(name, "rowSize")) {
+               return PyLong_FromLong((long) self->rowSize);
+       } else if(STREQ(name, "colSize")) {
+               return PyLong_FromLong((long) self->colSize);
+       }
+       if(STREQ(name, "wrapped")){
+               if(self->wrapped == Py_WRAP)
+                       Py_RETURN_TRUE;
+               else 
+                       Py_RETURN_FALSE;
+       }
+#if 0 //XXX
+       return Py_FindMethod(Matrix_methods, (PyObject *) self, name);
+#else
+       PyErr_SetString(PyExc_AttributeError, "blender 2.5 is not finished yet");
+       return NULL;
+#endif
+}
+/*----------------------------setattr()(internal) ----------------*/
+/*object.attribute access (set)*/
+static int Matrix_setattr(MatrixObject * self, char *name, PyObject * v)
+{
+       /* This is not supported. */
+       return (-1);
+}
+/*----------------------------print object (internal)-------------*/
+/*print the object to screen*/
+static PyObject *Matrix_repr(MatrixObject * self)
+{
+       int x, y;
+       char buffer[48], str[1024];
+
+       BLI_strncpy(str,"",1024);
+       for(x = 0; x < self->rowSize; x++){
+               sprintf(buffer, "[");
+               strcat(str,buffer);
+               for(y = 0; y < (self->colSize - 1); y++) {
+                       sprintf(buffer, "%.6f, ", self->matrix[x][y]);
+                       strcat(str,buffer);
+               }
+               if(x < (self->rowSize-1)){
+                       sprintf(buffer, "%.6f](matrix [row %d])\n", self->matrix[x][y], x);
+                       strcat(str,buffer);
+               }else{
+                       sprintf(buffer, "%.6f](matrix [row %d])", self->matrix[x][y], x);
+                       strcat(str,buffer);
+               }
+       }
+
+       return PyUnicode_FromString(str);
+}
+/*------------------------tp_richcmpr*/
+/*returns -1 execption, 0 false, 1 true*/
+static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
+{
+       MatrixObject *matA = NULL, *matB = NULL;
+       int result = 0;
+
+       if (!MatrixObject_Check(objectA) || !MatrixObject_Check(objectB)){
+               if (comparison_type == Py_NE){
+                       Py_RETURN_TRUE;
+               }else{
+                       Py_RETURN_FALSE;
+               }
+       }
+       matA = (MatrixObject*)objectA;
+       matB = (MatrixObject*)objectB;
+
+       if (matA->colSize != matB->colSize || matA->rowSize != matB->rowSize){
+               if (comparison_type == Py_NE){
+                       Py_RETURN_TRUE;
+               }else{
+                       Py_RETURN_FALSE;
+               }
+       }
+
+       switch (comparison_type){
+               case Py_EQ:
+                       /*contigPtr is basically a really long vector*/
+                       result = EXPP_VectorsAreEqual(matA->contigPtr, matB->contigPtr,
+                               (matA->rowSize * matA->colSize), 1);
+                       break;
+               case Py_NE:
+                       result = EXPP_VectorsAreEqual(matA->contigPtr, matB->contigPtr,
+                               (matA->rowSize * matA->colSize), 1);
+                       if (result == 0){
+                               result = 1;
+                       }else{
+                               result = 0;
+                       }
+                       break;
+               default:
+                       printf("The result of the comparison could not be evaluated");
+                       break;
+       }
+       if (result == 1){
+               Py_RETURN_TRUE;
+       }else{
+               Py_RETURN_FALSE;
+       }
+}
+/*------------------------tp_doc*/
+static char MatrixObject_doc[] = "This is a wrapper for matrix objects.";
+/*---------------------SEQUENCE PROTOCOLS------------------------
+  ----------------------------len(object)------------------------
+  sequence length*/
+static int Matrix_len(MatrixObject * self)
+{
+       return (self->rowSize);
+}
+/*----------------------------object[]---------------------------
+  sequence accessor (get)
+  the wrapped vector gives direct access to the matrix data*/
+static PyObject *Matrix_item(MatrixObject * self, int i)
+{
+       if(i < 0 || i >= self->rowSize) {
+               PyErr_SetString(PyExc_IndexError, "matrix[attribute]: array index out of range");
+               return NULL;
+       }
+       return newVectorObject(self->matrix[i], self->colSize, Py_WRAP);
+}
+/*----------------------------object[]-------------------------
+  sequence accessor (set)*/
+static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
+{
+       int y, x, size = 0;
+       float vec[4];
+       PyObject *m, *f;
+
+       if(i >= self->rowSize || i < 0){
+               PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad row\n");
+               return -1;
+       }
+
+       if(PySequence_Check(ob)){
+               size = PySequence_Length(ob);
+               if(size != self->colSize){
+                       PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad sequence size\n");
+                       return -1;
+               }
+               for (x = 0; x < size; x++) {
+                       m = PySequence_GetItem(ob, x);
+                       if (m == NULL) { /*Failed to read sequence*/
+                               PyErr_SetString(PyExc_RuntimeError, "matrix[attribute] = x: unable to read sequence\n");
+                               return -1;
+                       }
+
+                       f = PyNumber_Float(m);
+                       if(f == NULL) { /*parsed item not a number*/
+                               Py_DECREF(m);
+                               PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: sequence argument not a number\n");
+                               return -1;
+                       }
+
+                       vec[x] = (float)PyFloat_AS_DOUBLE(f);
+                       Py_DECREF(m);
+                       Py_DECREF(f);
+               }
+               /*parsed well - now set in matrix*/
+               for(y = 0; y < size; y++){
+                       self->matrix[i][y] = vec[y];
+               }
+               return 0;
+       }else{
+               PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: expects a sequence of column size\n");
+               return -1;
+       }
+}
+/*----------------------------object[z:y]------------------------
+  sequence slice (get)*/
+static PyObject *Matrix_slice(MatrixObject * self, int begin, int end)
+{
+
+       PyObject *list = NULL;
+       int count;
+
+       CLAMP(begin, 0, self->rowSize);
+       CLAMP(end, 0, self->rowSize);
+       begin = MIN2(begin,end);
+
+       list = PyList_New(end - begin);
+       for(count = begin; count < end; count++) {
+               PyList_SetItem(list, count - begin,
+                               newVectorObject(self->matrix[count], self->colSize, Py_WRAP));
+       }
+
+       return list;
+}
+/*----------------------------object[z:y]------------------------
+  sequence slice (set)*/
+static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
+                            PyObject * seq)
+{
+       int i, x, y, size, sub_size = 0;
+       float mat[16], f;
+       PyObject *subseq;
+       PyObject *m;
+
+       CLAMP(begin, 0, self->rowSize);
+       CLAMP(end, 0, self->rowSize);
+       begin = MIN2(begin,end);
+
+       if(PySequence_Check(seq)){
+               size = PySequence_Length(seq);
+               if(size != (end - begin)){
+                       PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: size mismatch in slice assignment\n");
+                       return -1;
+               }
+               /*parse sub items*/
+               for (i = 0; i < size; i++) {
+                       /*parse each sub sequence*/
+                       subseq = PySequence_GetItem(seq, i);
+                       if (subseq == NULL) { /*Failed to read sequence*/
+                               PyErr_SetString(PyExc_RuntimeError, "matrix[begin:end] = []: unable to read sequence");
+                               return -1;
+                       }
+
+                       if(PySequence_Check(subseq)){
+                               /*subsequence is also a sequence*/
+                               sub_size = PySequence_Length(subseq);
+                               if(sub_size != self->colSize){
+                                       Py_DECREF(subseq);
+                                       PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: size mismatch in slice assignment\n");
+                                       return -1;
+                               }
+                               for (y = 0; y < sub_size; y++) {
+                                       m = PySequence_GetItem(subseq, y);
+                                       if (m == NULL) { /*Failed to read sequence*/
+                                               Py_DECREF(subseq);
+                                               PyErr_SetString(PyExc_RuntimeError, "matrix[begin:end] = []: unable to read sequence\n");
+                                               return -1;
+                                       }
+                                       
+                                       f = PyFloat_AsDouble(m); /* faster to assume a float and raise an error after */
+                                       if(f == -1 && PyErr_Occurred()) { /*parsed item not a number*/
+                                               Py_DECREF(m);
+                                               Py_DECREF(subseq);
+                                               PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: sequence argument not a number\n");
+                                               return -1;
+                                       }
+
+                                       mat[(i * self->colSize) + y] = f;
+                                       Py_DECREF(m);
+                               }
+                       }else{
+                               Py_DECREF(subseq);
+                               PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n");
+                               return -1;
+                       }
+                       Py_DECREF(subseq);
+               }
+               /*parsed well - now set in matrix*/
+               for(x = 0; x < (size * sub_size); x++){
+                       self->matrix[begin + (int)floor(x / self->colSize)][x % self->colSize] = mat[x];
+               }
+               return 0;
+       }else{
+               PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n");
+               return -1;
+       }
+}
+/*------------------------NUMERIC PROTOCOLS----------------------
+  ------------------------obj + obj------------------------------*/
+static PyObject *Matrix_add(PyObject * m1, PyObject * m2)
+{
+       int x, y;
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+       MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+       mat1 = (MatrixObject*)m1;
+       mat2 = (MatrixObject*)m2;
+
+       if(mat1->coerced_object || mat2->coerced_object){
+               PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
+               return NULL;
+       }
+       if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
+               PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
+               return NULL;
+       }
+
+       for(x = 0; x < mat1->rowSize; x++) {
+               for(y = 0; y < mat1->colSize; y++) {
+                       mat[((x * mat1->colSize) + y)] = mat1->matrix[x][y] + mat2->matrix[x][y];
+               }
+       }
+
+       return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
+}
+/*------------------------obj - obj------------------------------
+  subtraction*/
+static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
+{
+       int x, y;
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+       MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+       mat1 = (MatrixObject*)m1;
+       mat2 = (MatrixObject*)m2;
+
+       if(mat1->coerced_object || mat2->coerced_object){
+               PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
+               return NULL;
+       }
+       if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
+               PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
+               return NULL;
+       }
+
+       for(x = 0; x < mat1->rowSize; x++) {
+               for(y = 0; y < mat1->colSize; y++) {
+                       mat[((x * mat1->colSize) + y)] = mat1->matrix[x][y] - mat2->matrix[x][y];
+               }
+       }
+
+       return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
+}
+/*------------------------obj * obj------------------------------
+  mulplication*/
+static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
+{
+       int x, y, z;
+       float scalar;
+       float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+       double dot = 0.0f;
+       MatrixObject *mat1 = NULL, *mat2 = NULL;
+       PyObject *f = NULL;
+
+       mat1 = (MatrixObject*)m1;
+       mat2 = (MatrixObject*)m2;
+
+       if(mat1->coerced_object){
+               if (PyFloat_Check(mat1->coerced_object) || 
+                       PyLong_Check(mat1->coerced_object)){    /*FLOAT/INT * MATRIX*/
+                       f = PyNumber_Float(mat1->coerced_object);
+                       if(f == NULL) { /*parsed item not a number*/
+                               PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
+                               return NULL;
+                       }
+
+                       scalar = (float)PyFloat_AS_DOUBLE(f);
+                       Py_DECREF(f);
+                       for(x = 0; x < mat2->rowSize; x++) {
+                               for(y = 0; y < mat2->colSize; y++) {
+                                       mat[((x * mat2->colSize) + y)] = scalar * mat2->matrix[x][y];
+                               }
+                       }
+                       return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW);
+               }
+       }else{
+               if(mat2->coerced_object){
+                       /* MATRIX * VECTOR   operation is now being done by vector */
+                       /*if(VectorObject_Check(mat2->coerced_object)){ 
+                               vec = (VectorObject*)mat2->coerced_object;
+                               return column_vector_multiplication(mat1, vec);
+                       }else */
+                       if (PyFloat_Check(mat2->coerced_object) || PyLong_Check(mat2->coerced_object)){ /*MATRIX * FLOAT/INT*/
+                               f = PyNumber_Float(mat2->coerced_object);
+                               if(f == NULL) { /*parsed item not a number*/
+                                       PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation\n");
+                                       return NULL;
+                               }
+
+                               scalar = (float)PyFloat_AS_DOUBLE(f);
+                               Py_DECREF(f);
+                               for(x = 0; x < mat1->rowSize; x++) {
+                                       for(y = 0; y < mat1->colSize; y++) {
+                                               mat[((x * mat1->colSize) + y)] = scalar * mat1->matrix[x][y];
+                                       }
+                               }
+                               return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
+                       }
+               }else{  /*MATRIX * MATRIX*/
+                       if(mat1->colSize != mat2->rowSize){
+                               PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize");
+                               return NULL;
+                       }
+                       for(x = 0; x < mat1->rowSize; x++) {
+                               for(y = 0; y < mat2->colSize; y++) {
+                                       for(z = 0; z < mat1->colSize; z++) {
+                                               dot += (mat1->matrix[x][z] * mat2->matrix[z][y]);
+                                       }
+                                       mat[((x * mat1->rowSize) + y)] = (float)dot;
+                                       dot = 0.0f;
+                               }
+                       }
+                       return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW);
+               }
+       }
+
+       PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation\n");
+       return NULL;
+}
+static PyObject* Matrix_inv(MatrixObject *self)
+{
+       return Matrix_Invert(self);
+}
+/*------------------------coerce(obj, obj)-----------------------
+  coercion of unknown types to type MatrixObject for numeric protocols.
+
+  Coercion() is called whenever a math operation has 2 operands that
+ it doesn't understand how to evaluate. 2+Matrix for example. We want to 
+ evaluate some of these operations like: (vector * 2), however, for math
+ to proceed, the unknown operand must be cast to a type that python math will
+ understand. (e.g. in the case above case, 2 must be cast to a vector and 
+ then call vector.multiply(vector, scalar_cast_as_vector)*/
+static int Matrix_coerce(PyObject ** m1, PyObject ** m2)
+{
+       if(VectorObject_Check(*m2) || PyFloat_Check(*m2) || PyLong_Check(*m2)) {
+               PyObject *coerced = (PyObject *)(*m2);
+               Py_INCREF(coerced);
+               *m2 = newMatrixObject(NULL,3,3,Py_NEW);
+               ((MatrixObject*)*m2)->coerced_object = coerced;
+               Py_INCREF (*m1);
+               return 0;
+       }
+
+       PyErr_SetString(PyExc_TypeError, "matrix.coerce(): unknown operand - can't coerce for numeric protocols");
+       return -1;
+}
+/*-----------------PROTOCOL DECLARATIONS--------------------------*/
+static PySequenceMethods Matrix_SeqMethods = {
+       (inquiry) Matrix_len,                                   /* sq_length */
+       (binaryfunc) 0,                                                 /* sq_concat */
+       (ssizeargfunc) 0,                                                       /* sq_repeat */
+       (ssizeargfunc) Matrix_item,                             /* sq_item */
+       (ssizessizeargfunc) Matrix_slice,                       /* sq_slice */
+       (ssizeobjargproc) Matrix_ass_item,              /* sq_ass_item */
+       (ssizessizeobjargproc) Matrix_ass_slice,        /* sq_ass_slice */
+};
+static PyNumberMethods Matrix_NumMethods = {
+       (binaryfunc) Matrix_add,                                /* __add__ */
+       (binaryfunc) Matrix_sub,                                /* __sub__ */
+       (binaryfunc) Matrix_mul,                                /* __mul__ */
+       (binaryfunc) 0,                                                 /* __div__ */
+       (binaryfunc) 0,                                                 /* __mod__ */
+       (binaryfunc) 0,                                                 /* __divmod__ */
+       (ternaryfunc) 0,                                                /* __pow__ */
+       (unaryfunc) 0,                                                  /* __neg__ */
+       (unaryfunc) 0,                                                  /* __pos__ */
+       (unaryfunc) 0,                                                  /* __abs__ */
+       (inquiry) 0,                                                    /* __nonzero__ */
+       (unaryfunc) Matrix_inv,                                 /* __invert__ */
+       (binaryfunc) 0,                                                 /* __lshift__ */
+       (binaryfunc) 0,                                                 /* __rshift__ */
+       (binaryfunc) 0,                                                 /* __and__ */
+       (binaryfunc) 0,                                                 /* __xor__ */
+       (binaryfunc) 0,                                                 /* __or__ */
+#if 0 // XXX 2.5
+       (coercion) Matrix_coerce,                               /* __coerce__ */
+#else
+       0,
+#endif
+       (unaryfunc) 0,                                                  /* __int__ */
+       (unaryfunc) 0,                                                  /* __long__ */
+       (unaryfunc) 0,                                                  /* __float__ */
+       (unaryfunc) 0,                                                  /* __oct__ */
+       (unaryfunc) 0,                                                  /* __hex__ */
+};
+/*------------------PY_OBECT DEFINITION--------------------------*/
+PyTypeObject matrix_Type = {
+#if (PY_VERSION_HEX >= 0x02060000)
+       PyVarObject_HEAD_INIT(NULL, 0)
+#else
+       /* python 2.5 and below */
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+#endif
+       "matrix",                                               /*tp_name*/
+       sizeof(MatrixObject),                   /*tp_basicsize*/
+       0,                                                              /*tp_itemsize*/
+       (destructor)Matrix_dealloc,             /*tp_dealloc*/
+       0,                                                              /*tp_print*/
+       (getattrfunc)Matrix_getattr,    /*tp_getattr*/
+       (setattrfunc) Matrix_setattr,   /*tp_setattr*/
+       0,                                                              /*tp_compare*/
+       (reprfunc) Matrix_repr,                 /*tp_repr*/
+       &Matrix_NumMethods,                             /*tp_as_number*/
+       &Matrix_SeqMethods,                             /*tp_as_sequence*/
+       0,                                                              /*tp_as_mapping*/
+       0,                                                              /*tp_hash*/
+       0,                                                              /*tp_call*/
+       0,                                                              /*tp_str*/
+       0,                                                              /*tp_getattro*/
+       0,                                                              /*tp_setattro*/
+       0,                                                              /*tp_as_buffer*/
+       Py_TPFLAGS_DEFAULT,                             /*tp_flags*/
+       MatrixObject_doc,                               /*tp_doc*/
+       0,                                                              /*tp_traverse*/
+       0,                                                              /*tp_clear*/
+       (richcmpfunc)Matrix_richcmpr,   /*tp_richcompare*/
+       0,                                                              /*tp_weaklistoffset*/
+       0,                                                              /*tp_iter*/
+       0,                                                              /*tp_iternext*/
+       0,                                                              /*tp_methods*/
+       0,                                                              /*tp_members*/
+       0,                                                              /*tp_getset*/
+       0,                                                              /*tp_base*/
+       0,                                                              /*tp_dict*/
+       0,                                                              /*tp_descr_get*/
+       0,                                                              /*tp_descr_set*/
+       0,                                                              /*tp_dictoffset*/
+       0,                                                              /*tp_init*/
+       0,                                                              /*tp_alloc*/
+       0,                                                              /*tp_new*/
+       0,                                                              /*tp_free*/
+       0,                                                              /*tp_is_gc*/
+       0,                                                              /*tp_bases*/
+       0,                                                              /*tp_mro*/
+       0,                                                              /*tp_cache*/
+       0,                                                              /*tp_subclasses*/
+       0,                                                              /*tp_weaklist*/
+       0                                                               /*tp_del*/
+};
+
+/*------------------------newMatrixObject (internal)-------------
+creates a new matrix object
+self->matrix     self->contiguous_ptr (reference to data.xxx)
+       [0]------------->[0]
+                        [1]
+                        [2]
+       [1]------------->[3]
+                        [4]
+                        [5]
+                    ....
+self->matrix[1][1] = self->contiguous_ptr[4] = self->data.xxx_data[4]*/
+
+/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
+ (i.e. it was allocated elsewhere by MEM_mallocN())
+  pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
+ (i.e. it must be created here with PyMEM_malloc())*/
+PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
+{
+       MatrixObject *self;
+       int x, row, col;
+
+       /*matrix objects can be any 2-4row x 2-4col matrix*/
+       if(rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4){
+               PyErr_SetString(PyExc_RuntimeError, "matrix(): row and column sizes must be between 2 and 4");
+               return NULL;
+       }
+
+       self = PyObject_NEW(MatrixObject, &matrix_Type);
+       self->data.blend_data = NULL;
+       self->data.py_data = NULL;
+       self->rowSize = rowSize;
+       self->colSize = colSize;
+       self->coerced_object = NULL;
+
+       if(type == Py_WRAP){
+               self->data.blend_data = mat;
+               self->contigPtr = self->data.blend_data;
+               /*create pointer array*/
+               self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
+               if(self->matrix == NULL) { /*allocation failure*/
+                       PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space");
+                       return NULL;
+               }
+               /*pointer array points to contigous memory*/
+               for(x = 0; x < rowSize; x++) {
+                       self->matrix[x] = self->contigPtr + (x * colSize);
+               }
+               self->wrapped = Py_WRAP;
+       }else if (type == Py_NEW){
+               self->data.py_data = PyMem_Malloc(rowSize * colSize * sizeof(float));
+               if(self->data.py_data == NULL) { /*allocation failure*/
+                       PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space\n");
+                       return NULL;
+               }
+               self->contigPtr = self->data.py_data;
+               /*create pointer array*/
+               self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
+               if(self->matrix == NULL) { /*allocation failure*/
+                       PyMem_Free(self->data.py_data);
+                       PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space");
+                       return NULL;
+               }
+               /*pointer array points to contigous memory*/
+               for(x = 0; x < rowSize; x++) {
+                       self->matrix[x] = self->contigPtr + (x * colSize);
+               }
+               /*parse*/
+               if(mat) {       /*if a float array passed*/
+                       for(row = 0; row < rowSize; row++) {
+                               for(col = 0; col < colSize; col++) {
+                                       self->matrix[row][col] = mat[(row * colSize) + col];
+                               }
+                       }
+               } else if (rowSize == colSize ) { /*or if no arguments are passed return identity matrix for square matrices */
+                       Matrix_Identity(self);
+                       Py_DECREF(self);
+               }
+               self->wrapped = Py_NEW;
+       }else{ /*bad type*/
+               return NULL;
+       }
+       return (PyObject *) self;
+}
diff --git a/source/blender/python/generic/matrix.h b/source/blender/python/generic/matrix.h
new file mode 100644 (file)
index 0000000..fd51d99
--- /dev/null
@@ -0,0 +1,77 @@
+/* 
+ * $Id: matrix.h 20248 2009-05-18 04:11:54Z campbellbarton $
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef EXPP_matrix_h
+#define EXPP_matrix_h
+
+#include <Python.h>
+
+extern PyTypeObject matrix_Type;
+
+#define MatrixObject_Check(v) ((v)->ob_type == &matrix_Type)
+
+typedef float **ptRow;
+typedef struct _Matrix {
+       PyObject_VAR_HEAD 
+       struct{
+               float *py_data;         /*python managed*/
+               float *blend_data;      /*blender managed*/
+       }data;
+       ptRow matrix;                   /*ptr to the contigPtr (accessor)*/
+       float *contigPtr;               /*1D array of data (alias)*/
+       int rowSize;
+       int colSize;
+       int wrapped;                    /*is wrapped data?*/
+       PyObject *coerced_object;
+} MatrixObject;
+/*coerced_object is a pointer to the object that it was
+coerced from when a dummy vector needs to be created from
+the coerce() function for numeric protocol operations*/
+
+/*struct data contains a pointer to the actual data that the
+object uses. It can use either PyMem allocated data (which will
+be stored in py_data) or be a wrapper for data allocated through
+blender (stored in blend_data). This is an either/or struct not both*/
+
+/*prototypes*/
+PyObject *Matrix_Zero( MatrixObject * self );
+PyObject *Matrix_Identity( MatrixObject * self );
+PyObject *Matrix_Transpose( MatrixObject * self );
+PyObject *Matrix_Determinant( MatrixObject * self );
+PyObject *Matrix_Invert( MatrixObject * self );
+PyObject *Matrix_TranslationPart( MatrixObject * self );
+PyObject *Matrix_RotationPart( MatrixObject * self );
+PyObject *Matrix_scalePart( MatrixObject * self );
+PyObject *Matrix_Resize4x4( MatrixObject * self );
+PyObject *Matrix_toEuler( MatrixObject * self, PyObject *args );
+PyObject *Matrix_toQuat( MatrixObject * self );
+PyObject *Matrix_copy( MatrixObject * self );
+PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type);
+
+#endif                         /* EXPP_matrix_H */
diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c
new file mode 100644 (file)
index 0000000..ca703f1
--- /dev/null
@@ -0,0 +1,765 @@
+/*
+ * $Id: quat.c 20332 2009-05-22 03:22:56Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "Mathutils.h"
+
+#include "BLI_arithb.h"
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+
+
+//-------------------------DOC STRINGS ---------------------------
+char Quaternion_Identity_doc[] = "() - set the quaternion to it's identity (1, vector)";
+char Quaternion_Negate_doc[] = "() - set all values in the quaternion to their negative";
+char Quaternion_Conjugate_doc[] = "() - set the quaternion to it's conjugate";
+char Quaternion_Inverse_doc[] = "() - set the quaternion to it's inverse";
+char Quaternion_Normalize_doc[] = "() - normalize the vector portion of the quaternion";
+char Quaternion_ToEuler_doc[] = "(eul_compat) - return a euler rotation representing the quaternion, optional euler argument that the new euler will be made compatible with.";
+char Quaternion_ToMatrix_doc[] = "() - return a rotation matrix representing the quaternion";
+char Quaternion_Cross_doc[] = "(other) - return the cross product between this quaternion and another";
+char Quaternion_Dot_doc[] = "(other) - return the dot product between this quaternion and another";
+char Quaternion_copy_doc[] = "() - return a copy of the quat";
+//-----------------------METHOD DEFINITIONS ----------------------
+struct PyMethodDef Quaternion_methods[] = {
+       {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc},
+       {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc},
+       {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc},
+       {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc},
+       {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc},
+       {"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc},
+       {"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc},
+       {"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc},
+       {"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc},
+       {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
+       {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
+       {NULL, NULL, 0, NULL}
+};
+//-----------------------------METHODS------------------------------
+//----------------------------Quaternion.toEuler()------------------
+//return the quat as a euler
+PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
+{
+       float eul[3];
+       EulerObject *eul_compat = NULL;
+       int x;
+       
+       if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
+               return NULL;
+       
+       if(eul_compat) {
+               float mat[3][3], eul_compatf[3];
+               
+               for(x = 0; x < 3; x++) {
+                       eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
+               }
+               
+               QuatToMat3(self->quat, mat);
+               Mat3ToCompatibleEul(mat, eul, eul_compatf);
+       }
+       else {
+               QuatToEul(self->quat, eul);
+       }
+       
+       
+       for(x = 0; x < 3; x++) {
+               eul[x] *= (180 / (float)Py_PI);
+       }
+       return newEulerObject(eul, Py_NEW);
+}
+//----------------------------Quaternion.toMatrix()------------------
+//return the quat as a matrix
+PyObject *Quaternion_ToMatrix(QuaternionObject * self)
+{
+       float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+       QuatToMat3(self->quat, (float (*)[3]) mat);
+
+       return newMatrixObject(mat, 3, 3, Py_NEW);
+}
+
+//----------------------------Quaternion.cross(other)------------------
+//return the cross quat
+PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
+{
+       float quat[4];
+       
+       if (!QuaternionObject_Check(value)) {
+               PyErr_SetString( PyExc_TypeError, "quat.cross(value): expected a quaternion argument" );
+               return NULL;
+       }
+       
+       QuatMul(quat, self->quat, value->quat);
+       return newQuaternionObject(quat, Py_NEW);
+}
+
+//----------------------------Quaternion.dot(other)------------------
+//return the dot quat
+PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
+{
+       int x;
+       double dot = 0.0;
+       
+       if (!QuaternionObject_Check(value)) {
+               PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" );
+               return NULL;
+       }
+       
+       for(x = 0; x < 4; x++) {
+               dot += self->quat[x] * value->quat[x];
+       }
+       return PyFloat_FromDouble(dot);
+}
+
+//----------------------------Quaternion.normalize()----------------
+//normalize the axis of rotation of [theta,vector]
+PyObject *Quaternion_Normalize(QuaternionObject * self)
+{
+       NormalQuat(self->quat);
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+//----------------------------Quaternion.inverse()------------------
+//invert the quat
+PyObject *Quaternion_Inverse(QuaternionObject * self)
+{
+       double mag = 0.0f;
+       int x;
+
+       for(x = 1; x < 4; x++) {
+               self->quat[x] = -self->quat[x];
+       }
+       for(x = 0; x < 4; x++) {
+               mag += (self->quat[x] * self->quat[x]);
+       }
+       mag = sqrt(mag);
+       for(x = 0; x < 4; x++) {
+               self->quat[x] /= (float)(mag * mag);
+       }
+
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+//----------------------------Quaternion.identity()-----------------
+//generate the identity quaternion
+PyObject *Quaternion_Identity(QuaternionObject * self)
+{
+       self->quat[0] = 1.0;
+       self->quat[1] = 0.0;
+       self->quat[2] = 0.0;
+       self->quat[3] = 0.0;
+
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+//----------------------------Quaternion.negate()-------------------
+//negate the quat
+PyObject *Quaternion_Negate(QuaternionObject * self)
+{
+       int x;
+       for(x = 0; x < 4; x++) {
+               self->quat[x] = -self->quat[x];
+       }
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+//----------------------------Quaternion.conjugate()----------------
+//negate the vector part
+PyObject *Quaternion_Conjugate(QuaternionObject * self)
+{
+       int x;
+       for(x = 1; x < 4; x++) {
+               self->quat[x] = -self->quat[x];
+       }
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+//----------------------------Quaternion.copy()----------------
+//return a copy of the quat
+PyObject *Quaternion_copy(QuaternionObject * self)
+{
+       return newQuaternionObject(self->quat, Py_NEW); 
+}
+
+//----------------------------dealloc()(internal) ------------------
+//free the py_object
+static void Quaternion_dealloc(QuaternionObject * self)
+{
+       Py_XDECREF(self->coerced_object);
+       //only free py_data
+       if(self->data.py_data){
+               PyMem_Free(self->data.py_data);
+       }
+       PyObject_DEL(self);
+}
+
+//----------------------------print object (internal)--------------
+//print the object to screen
+static PyObject *Quaternion_repr(QuaternionObject * self)
+{
+       char str[64];
+       sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]);
+       return PyUnicode_FromString(str);
+}
+//------------------------tp_richcmpr
+//returns -1 execption, 0 false, 1 true
+static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
+{
+       QuaternionObject *quatA = NULL, *quatB = NULL;
+       int result = 0;
+
+       if (!QuaternionObject_Check(objectA) || !QuaternionObject_Check(objectB)){
+               if (comparison_type == Py_NE){
+                       Py_RETURN_TRUE;
+               }else{
+                       Py_RETURN_FALSE;
+               }
+       }
+       quatA = (QuaternionObject*)objectA;
+       quatB = (QuaternionObject*)objectB;
+
+       switch (comparison_type){
+               case Py_EQ:
+                       result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
+                       break;
+               case Py_NE:
+                       result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
+                       if (result == 0){
+                               result = 1;
+                       }else{
+                               result = 0;
+                       }
+                       break;
+               default:
+                       printf("The result of the comparison could not be evaluated");
+                       break;
+       }
+       if (result == 1){
+               Py_RETURN_TRUE;
+       }else{
+               Py_RETURN_FALSE;
+       }
+}
+//------------------------tp_doc
+static char QuaternionObject_doc[] = "This is a wrapper for quaternion objects.";
+//---------------------SEQUENCE PROTOCOLS------------------------
+//----------------------------len(object)------------------------
+//sequence length
+static int Quaternion_len(QuaternionObject * self)
+{
+       return 4;
+}
+//----------------------------object[]---------------------------
+//sequence accessor (get)
+static PyObject *Quaternion_item(QuaternionObject * self, int i)
+{
+       if(i < 0 || i >= 4) {
+               PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n");
+               return NULL;
+       }
+       return PyFloat_FromDouble(self->quat[i]);
+
+}
+//----------------------------object[]-------------------------
+//sequence accessor (set)
+static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
+{
+       PyObject *f = NULL;
+
+       f = PyNumber_Float(ob);
+       if(f == NULL) { // parsed item not a number
+               PyErr_SetString(PyExc_TypeError, "quaternion[attribute] = x: argument not a number\n");
+               return -1;
+       }
+
+       if(i < 0 || i >= 4){
+               Py_DECREF(f);
+               PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n");
+               return -1;
+       }
+       self->quat[i] = (float)PyFloat_AS_DOUBLE(f);
+       Py_DECREF(f);
+       return 0;
+}
+//----------------------------object[z:y]------------------------
+//sequence slice (get)
+static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
+{
+       PyObject *list = NULL;
+       int count;
+
+       CLAMP(begin, 0, 4);
+       if (end<0) end= 5+end;
+       CLAMP(end, 0, 4);
+       begin = MIN2(begin,end);
+
+       list = PyList_New(end - begin);
+       for(count = begin; count < end; count++) {
+               PyList_SetItem(list, count - begin,
+                               PyFloat_FromDouble(self->quat[count]));
+       }
+
+       return list;
+}
+//----------------------------object[z:y]------------------------
+//sequence slice (set)
+static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end,
+                            PyObject * seq)
+{
+       int i, y, size = 0;
+       float quat[4];
+       PyObject *q, *f;
+
+       CLAMP(begin, 0, 4);
+       if (end<0) end= 5+end;
+       CLAMP(end, 0, 4);
+       begin = MIN2(begin,end);
+
+       size = PySequence_Length(seq);
+       if(size != (end - begin)){
+               PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: size mismatch in slice assignment\n");
+               return -1;
+       }
+
+       for (i = 0; i < size; i++) {
+               q = PySequence_GetItem(seq, i);
+               if (q == NULL) { // Failed to read sequence
+                       PyErr_SetString(PyExc_RuntimeError, "quaternion[begin:end] = []: unable to read sequence\n");
+                       return -1;
+               }
+
+               f = PyNumber_Float(q);
+               if(f == NULL) { // parsed item not a number
+                       Py_DECREF(q);
+                       PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n");
+                       return -1;
+               }
+
+               quat[i] = (float)PyFloat_AS_DOUBLE(f);
+               Py_DECREF(f);
+               Py_DECREF(q);
+       }
+       //parsed well - now set in vector
+       for(y = 0; y < size; y++){
+               self->quat[begin + y] = quat[y];
+       }
+       return 0;
+}
+//------------------------NUMERIC PROTOCOLS----------------------
+//------------------------obj + obj------------------------------
+//addition
+static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
+{
+       int x;
+       float quat[4];
+       QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+       quat1 = (QuaternionObject*)q1;
+       quat2 = (QuaternionObject*)q2;
+
+       if(quat1->coerced_object || quat2->coerced_object){
+               PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
+               return NULL;
+       }
+       for(x = 0; x < 4; x++) {
+               quat[x] = quat1->quat[x] + quat2->quat[x];
+       }
+
+       return newQuaternionObject(quat, Py_NEW);
+}
+//------------------------obj - obj------------------------------
+//subtraction
+static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
+{
+       int x;
+       float quat[4];
+       QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+       quat1 = (QuaternionObject*)q1;
+       quat2 = (QuaternionObject*)q2;
+
+       if(quat1->coerced_object || quat2->coerced_object){
+               PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
+               return NULL;
+       }
+       for(x = 0; x < 4; x++) {
+               quat[x] = quat1->quat[x] - quat2->quat[x];
+       }
+
+       return newQuaternionObject(quat, Py_NEW);
+}
+//------------------------obj * obj------------------------------
+//mulplication
+static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
+{
+       int x;
+       float quat[4], scalar;
+       double dot = 0.0f;
+       QuaternionObject *quat1 = NULL, *quat2 = NULL;
+       PyObject *f = NULL;
+       VectorObject *vec = NULL;
+
+       quat1 = (QuaternionObject*)q1;
+       quat2 = (QuaternionObject*)q2;
+
+       if(quat1->coerced_object){
+               if (PyFloat_Check(quat1->coerced_object) || 
+                       PyLong_Check(quat1->coerced_object)){   // FLOAT/INT * QUAT
+                       f = PyNumber_Float(quat1->coerced_object);
+                       if(f == NULL) { // parsed item not a number
+                               PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
+                               return NULL;
+                       }
+
+                       scalar = (float)PyFloat_AS_DOUBLE(f);
+                       Py_DECREF(f);
+                       for(x = 0; x < 4; x++) {
+                               quat[x] = quat2->quat[x] * scalar;
+                       }
+                       return newQuaternionObject(quat, Py_NEW);
+               }
+       }else{
+               if(quat2->coerced_object){
+                       if (PyFloat_Check(quat2->coerced_object) || 
+                               PyLong_Check(quat2->coerced_object)){   // QUAT * FLOAT/INT
+                               f = PyNumber_Float(quat2->coerced_object);
+                               if(f == NULL) { // parsed item not a number
+                                       PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
+                                       return NULL;
+                               }
+
+                               scalar = (float)PyFloat_AS_DOUBLE(f);
+                               Py_DECREF(f);
+                               for(x = 0; x < 4; x++) {
+                                       quat[x] = quat1->quat[x] * scalar;
+                               }
+                               return newQuaternionObject(quat, Py_NEW);
+                       }else if(VectorObject_Check(quat2->coerced_object)){  //QUAT * VEC
+                               vec = (VectorObject*)quat2->coerced_object;
+                               if(vec->size != 3){
+                                       PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
+                                       return NULL;
+                               }
+                               return quat_rotation((PyObject*)quat1, (PyObject*)vec);
+                       }
+               }else{  //QUAT * QUAT (dot product)
+                       for(x = 0; x < 4; x++) {
+                               dot += quat1->quat[x] * quat1->quat[x];
+                       }
+                       return PyFloat_FromDouble(dot);
+               }
+       }
+
+       PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
+       return NULL;
+}
+//------------------------coerce(obj, obj)-----------------------
+//coercion of unknown types to type QuaternionObject for numeric protocols
+/*Coercion() is called whenever a math operation has 2 operands that
+ it doesn't understand how to evaluate. 2+Matrix for example. We want to 
+ evaluate some of these operations like: (vector * 2), however, for math
+ to proceed, the unknown operand must be cast to a type that python math will
+ understand. (e.g. in the case above case, 2 must be cast to a vector and 
+ then call vector.multiply(vector, scalar_cast_as_vector)*/
+static int Quaternion_coerce(PyObject ** q1, PyObject ** q2)
+{
+       if(VectorObject_Check(*q2) || PyFloat_Check(*q2) || PyLong_Check(*q2)) {
+               PyObject *coerced = (PyObject *)(*q2);
+               Py_INCREF(coerced);
+               
+               *q2 = newQuaternionObject(NULL,Py_NEW);
+               ((QuaternionObject*)*q2)->coerced_object = coerced;
+               Py_INCREF (*q1);
+               return 0;
+       }
+
+       PyErr_SetString(PyExc_TypeError, "quaternion.coerce(): unknown operand - can't coerce for numeric protocols");
+       return -1;
+}
+//-----------------PROTOCOL DECLARATIONS--------------------------
+static PySequenceMethods Quaternion_SeqMethods = {
+       (inquiry) Quaternion_len,                                       /* sq_length */
+       (binaryfunc) 0,                                                         /* sq_concat */
+       (ssizeargfunc) 0,                                                               /* sq_repeat */
+       (ssizeargfunc) Quaternion_item,                         /* sq_item */
+       (ssizessizeargfunc) Quaternion_slice,                   /* sq_slice */
+       (ssizeobjargproc) Quaternion_ass_item,          /* sq_ass_item */
+       (ssizessizeobjargproc) Quaternion_ass_slice,    /* sq_ass_slice */
+};
+static PyNumberMethods Quaternion_NumMethods = {
+       (binaryfunc) Quaternion_add,                            /* __add__ */
+       (binaryfunc) Quaternion_sub,                            /* __sub__ */
+       (binaryfunc) Quaternion_mul,                            /* __mul__ */
+       (binaryfunc) 0,                                                         /* __div__ */
+       (binaryfunc) 0,                                                         /* __mod__ */
+       (binaryfunc) 0,                                                         /* __divmod__ */
+       (ternaryfunc) 0,                                                        /* __pow__ */
+       (unaryfunc) 0,                                                          /* __neg__ */
+       (unaryfunc) 0,                                                          /* __pos__ */
+       (unaryfunc) 0,                                                          /* __abs__ */
+       (inquiry) 0,                                                            /* __nonzero__ */
+       (unaryfunc) 0,                                                          /* __invert__ */
+       (binaryfunc) 0,                                                         /* __lshift__ */
+       (binaryfunc) 0,                                                         /* __rshift__ */
+       (binaryfunc) 0,                                                         /* __and__ */
+       (binaryfunc) 0,                                                         /* __xor__ */
+       (binaryfunc) 0,                                                         /* __or__ */
+#if 0 //XXX 2.5
+       (coercion)  Quaternion_coerce,                          /* __coerce__ */
+#else
+       0,
+#endif
+       (unaryfunc) 0,                                                          /* __int__ */
+       (unaryfunc) 0,                                                          /* __long__ */
+       (unaryfunc) 0,                                                          /* __float__ */
+       (unaryfunc) 0,                                                          /* __oct__ */
+       (unaryfunc) 0,                                                          /* __hex__ */
+
+};
+
+
+static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
+{
+       switch( (long)type ) {
+    case 'W':
+               return PyFloat_FromDouble(self->quat[0]);
+    case 'X':
+               return PyFloat_FromDouble(self->quat[1]);
+    case 'Y':
+               return PyFloat_FromDouble(self->quat[2]);
+    case 'Z':
+               return PyFloat_FromDouble(self->quat[3]);
+       }
+       
+       PyErr_SetString(PyExc_SystemError, "corrupt quaternion, cannot get axis");
+       return NULL;
+}
+
+static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
+{
+       float param= (float)PyFloat_AsDouble( value );
+       
+       if (param==-1 && PyErr_Occurred()) {
+               PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
+               return -1;
+       }
+       switch( (long)type ) {
+    case 'W':
+               self->quat[0]= param;
+               break;
+    case 'X':
+               self->quat[1]= param;
+               break;
+    case 'Y':
+               self->quat[2]= param;
+               break;
+    case 'Z':
+               self->quat[3]= param;
+               break;
+       }
+
+       return 0;
+}
+
+static PyObject *Quaternion_getWrapped( QuaternionObject * self, void *type )
+{
+       if (self->wrapped == Py_WRAP)
+               Py_RETURN_TRUE;
+       else
+               Py_RETURN_FALSE;
+}
+
+static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
+{
+       double mag = 0.0;
+       int i;
+       for(i = 0; i < 4; i++) {
+               mag += self->quat[i] * self->quat[i];
+       }
+       return PyFloat_FromDouble(sqrt(mag));
+}
+
+static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
+{
+       double ang = self->quat[0];
+       ang = 2 * (saacos(ang));
+       ang *= (180 / Py_PI);
+       return PyFloat_FromDouble(ang);
+}
+
+static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
+{
+       int i;
+       float vec[3];
+       double mag = self->quat[0] * (Py_PI / 180);
+       mag = 2 * (saacos(mag));
+       mag = sin(mag / 2);
+       for(i = 0; i < 3; i++)
+               vec[i] = (float)(self->quat[i + 1] / mag);
+       
+       Normalize(vec);
+       //If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations
+       if( EXPP_FloatsAreEqual(vec[0], 0.0f, 10) &&
+               EXPP_FloatsAreEqual(vec[1], 0.0f, 10) &&
+               EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
+               vec[0] = 1.0f;
+       }
+       return (PyObject *) newVectorObject(vec, 3, Py_NEW);
+}
+
+
+/*****************************************************************************/
+/* Python attributes get/set structure:                                      */
+/*****************************************************************************/
+static PyGetSetDef Quaternion_getseters[] = {
+       {"w",
+        (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
+        "Quaternion W value",
+        (void *)'W'},
+       {"x",
+        (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
+        "Quaternion X axis",
+        (void *)'X'},
+       {"y",
+        (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
+        "Quaternion Y axis",
+        (void *)'Y'},
+       {"z",
+        (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
+        "Quaternion Z axis",
+        (void *)'Z'},
+       {"magnitude",
+        (getter)Quaternion_getMagnitude, (setter)NULL,
+        "Size of the quaternion",
+        NULL},
+       {"angle",
+        (getter)Quaternion_getAngle, (setter)NULL,
+        "angle of the quaternion",
+        NULL},
+       {"axis",
+        (getter)Quaternion_getAxisVec, (setter)NULL,
+        "quaternion axis as a vector",
+        NULL},
+       {"wrapped",
+        (getter)Quaternion_getWrapped, (setter)NULL,
+        "True when this wraps blenders internal data",
+        NULL},
+       {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
+};
+
+
+//------------------PY_OBECT DEFINITION--------------------------
+PyTypeObject quaternion_Type = {
+#if (PY_VERSION_HEX >= 0x02060000)
+       PyVarObject_HEAD_INIT(NULL, 0)
+#else
+       /* python 2.5 and below */
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+#endif
+       "quaternion",                                           //tp_name
+       sizeof(QuaternionObject),                       //tp_basicsize
+       0,                                                              //tp_itemsize
+       (destructor)Quaternion_dealloc,         //tp_dealloc
+       0,                                                              //tp_print
+       0,                                                              //tp_getattr
+       0,                                                              //tp_setattr
+       0,                                                              //tp_compare
+       (reprfunc) Quaternion_repr,                     //tp_repr
+       &Quaternion_NumMethods,                         //tp_as_number
+       &Quaternion_SeqMethods,                         //tp_as_sequence
+       0,                                                              //tp_as_mapping
+       0,                                                              //tp_hash
+       0,                                                              //tp_call
+       0,                                                              //tp_str
+       0,                                                              //tp_getattro
+       0,                                                              //tp_setattro
+       0,                                                              //tp_as_buffer
+       Py_TPFLAGS_DEFAULT,                             //tp_flags
+       QuaternionObject_doc,                           //tp_doc
+       0,                                                              //tp_traverse
+       0,                                                              //tp_clear
+       (richcmpfunc)Quaternion_richcmpr,       //tp_richcompare
+       0,                                                              //tp_weaklistoffset
+       0,                                                              //tp_iter
+       0,                                                              //tp_iternext
+       Quaternion_methods,                             //tp_methods
+       0,                                                              //tp_members
+       Quaternion_getseters,                   //tp_getset
+       0,                                                              //tp_base
+       0,                                                              //tp_dict
+       0,                                                              //tp_descr_get
+       0,                                                              //tp_descr_set
+       0,                                                              //tp_dictoffset
+       0,                                                              //tp_init
+       0,                                                              //tp_alloc
+       0,                                                              //tp_new
+       0,                                                              //tp_free
+       0,                                                              //tp_is_gc
+       0,                                                              //tp_bases
+       0,                                                              //tp_mro
+       0,                                                              //tp_cache
+       0,                                                              //tp_subclasses
+       0,                                                              //tp_weaklist
+       0                                                               //tp_del
+};
+//------------------------newQuaternionObject (internal)-------------
+//creates a new quaternion object
+/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
+ (i.e. it was allocated elsewhere by MEM_mallocN())
+  pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
+ (i.e. it must be created here with PyMEM_malloc())*/
+PyObject *newQuaternionObject(float *quat, int type)
+{
+       QuaternionObject *self;
+       int x;
+       
+       self = PyObject_NEW(QuaternionObject, &quaternion_Type);
+       self->data.blend_data = NULL;
+       self->data.py_data = NULL;
+       self->coerced_object = NULL;
+
+       if(type == Py_WRAP){
+               self->data.blend_data = quat;
+               self->quat = self->data.blend_data;
+               self->wrapped = Py_WRAP;
+       }else if (type == Py_NEW){
+               self->data.py_data = PyMem_Malloc(4 * sizeof(float));
+               self->quat = self->data.py_data;
+               if(!quat) { //new empty
+                       Quaternion_Identity(self);
+                       Py_DECREF(self);
+               }else{
+                       for(x = 0; x < 4; x++){
+                               self->quat[x] = quat[x];
+                       }
+               }
+               self->wrapped = Py_NEW;
+       }else{ //bad type
+               return NULL;
+       }
+       return (PyObject *) self;
+}
diff --git a/source/blender/python/generic/quat.h b/source/blender/python/generic/quat.h
new file mode 100644 (file)
index 0000000..f98665d
--- /dev/null
@@ -0,0 +1,72 @@
+/* 
+ * $Id: quat.h 20332 2009-05-22 03:22:56Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef EXPP_quat_h
+#define EXPP_quat_h
+
+#include <Python.h>
+
+extern PyTypeObject quaternion_Type;
+
+#define QuaternionObject_Check(v) (Py_TYPE(v) == &quaternion_Type)
+
+typedef struct {
+       PyObject_VAR_HEAD 
+       struct{
+               float *py_data;         //python managed
+               float *blend_data;      //blender managed
+       }data;
+       float *quat;                            //1D array of data (alias)
+       int wrapped;                    //is wrapped data?
+       PyObject *coerced_object;
+} QuaternionObject;
+/*coerced_object is a pointer to the object that it was
+coerced from when a dummy vector needs to be created from
+the coerce() function for numeric protocol operations*/
+
+/*struct data contains a pointer to the actual data that the
+object uses. It can use either PyMem allocated data (which will
+be stored in py_data) or be a wrapper for data allocated through
+blender (stored in blend_data). This is an either/or struct not both*/
+
+//prototypes
+PyObject *Quaternion_Identity( QuaternionObject * self );
+PyObject *Quaternion_Negate( QuaternionObject * self );
+PyObject *Quaternion_Conjugate( QuaternionObject * self );
+PyObject *Quaternion_Inverse( QuaternionObject * self );
+PyObject *Quaternion_Normalize( QuaternionObject * self );
+PyObject *Quaternion_ToEuler( QuaternionObject * self, PyObject *args );
+PyObject *Quaternion_ToMatrix( QuaternionObject * self );
+PyObject *Quaternion_Cross( QuaternionObject * self, QuaternionObject * value );
+PyObject *Quaternion_Dot( QuaternionObject * self, QuaternionObject * value );
+PyObject *Quaternion_copy( QuaternionObject * self );
+PyObject *newQuaternionObject( float *quat, int type );
+
+#endif                         /* EXPP_quat_h */
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c
new file mode 100644 (file)
index 0000000..86ce5c2
--- /dev/null
@@ -0,0 +1,1838 @@
+/*
+ * $Id: vector.c 20332 2009-05-22 03:22:56Z campbellbarton $
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Willian P. Germano, Joseph Gilbert, Ken Hughes, Alex Fraser, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "Mathutils.h"
+
+#include "BLI_blenlib.h"
+#include "BKE_utildefines.h"
+#include "BLI_arithb.h"
+
+#define MAX_DIMENSIONS 4
+/* Swizzle axes get packed into a single value that is used as a closure. Each
+   axis uses SWIZZLE_BITS_PER_AXIS bits. The first bit (SWIZZLE_VALID_AXIS) is
+   used as a sentinel: if it is unset, the axis is not valid. */
+#define SWIZZLE_BITS_PER_AXIS 3
+#define SWIZZLE_VALID_AXIS 0x4
+#define SWIZZLE_AXIS       0x3
+
+/*-------------------------DOC STRINGS ---------------------------*/
+char Vector_Zero_doc[] = "() - set all values in the vector to 0";
+char Vector_Normalize_doc[] = "() - normalize the vector";
+char Vector_Negate_doc[] = "() - changes vector to it's additive inverse";
+char Vector_Resize2D_doc[] = "() - resize a vector to [x,y]";
+char Vector_Resize3D_doc[] = "() - resize a vector to [x,y,z]";
+char Vector_Resize4D_doc[] = "() - resize a vector to [x,y,z,w]";
+char Vector_ToTrackQuat_doc[] = "(track, up) - extract a quaternion from the vector and the track and up axis";
+char Vector_Reflect_doc[] = "(mirror) - return a vector reflected on the mirror normal";
+char Vector_Cross_doc[] = "(other) - return the cross product between this vector and another";
+char Vector_Dot_doc[] = "(other) - return the dot product between this vector and another";
+char Vector_copy_doc[] = "() - return a copy of the vector";
+char Vector_swizzle_doc[] = "Swizzle: Get or set axes in specified order";
+/*-----------------------METHOD DEFINITIONS ----------------------*/
+struct PyMethodDef Vector_methods[] = {
+       {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc},
+       {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc},
+       {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc},
+       {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc},
+       {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize2D_doc},
+       {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize2D_doc},
+       {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc},
+       {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, Vector_Reflect_doc},
+       {"cross", ( PyCFunction ) Vector_Cross, METH_O, Vector_Dot_doc},
+       {"dot", ( PyCFunction ) Vector_Dot, METH_O, Vector_Cross_doc},
+       {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
+       {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
+       {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------------METHODS---------------------------- */
+/*----------------------------Vector.zero() ----------------------
+  set the vector data to 0,0,0 */
+PyObject *Vector_Zero(VectorObject * self)
+{
+       int i;
+       for(i = 0; i < self->size; i++) {
+               self->vec[i] = 0.0f;
+       }
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+/*----------------------------Vector.normalize() -----------------
+  normalize the vector data to a unit vector */
+PyObject *Vector_Normalize(VectorObject * self)
+{
+       int i;
+       float norm = 0.0f;
+
+       for(i = 0; i < self->size; i++) {
+               norm += self->vec[i] * self->vec[i];
+       }
+       norm = (float) sqrt(norm);
+       for(i = 0; i < self->size; i++) {
+               self->vec[i] /= norm;
+       }
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+
+
+/*----------------------------Vector.resize2D() ------------------
+  resize the vector to x,y */
+PyObject *Vector_Resize2D(VectorObject * self)
+{
+       if(self->wrapped==Py_WRAP) {
+               PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize wrapped data - only python vectors\n");
+               return NULL;
+       }
+       self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2));
+       if(self->vec == NULL) {
+               PyErr_SetString(PyExc_MemoryError, "vector.resize2d(): problem allocating pointer space\n\n");
+               return NULL;
+       }
+       
+       self->size = 2;
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+/*----------------------------Vector.resize3D() ------------------
+  resize the vector to x,y,z */
+PyObject *Vector_Resize3D(VectorObject * self)
+{
+       if (self->wrapped==Py_WRAP) {
+               PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize wrapped data - only python vectors\n");
+               return NULL;
+       }
+       self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3));
+       if(self->vec == NULL) {
+               PyErr_SetString(PyExc_MemoryError, "vector.resize3d(): problem allocating pointer space\n\n");
+               return NULL;
+       }
+       
+       if(self->size == 2)
+               self->vec[2] = 0.0f;
+       
+       self->size = 3;
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+/*----------------------------Vector.resize4D() ------------------
+  resize the vector to x,y,z,w */
+PyObject *Vector_Resize4D(VectorObject * self)
+{
+       if(self->wrapped==Py_WRAP) {
+               PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize wrapped data - only python vectors");
+               return NULL;
+       }
+       self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4));
+       if(self->vec == NULL) {
+               PyErr_SetString(PyExc_MemoryError, "vector.resize4d(): problem allocating pointer space\n\n");
+               return NULL;
+       }
+       if(self->size == 2){
+               self->vec[2] = 0.0f;
+               self->vec[3] = 1.0f;
+       }else if(self->size == 3){
+               self->vec[3] = 1.0f;
+       }
+       self->size = 4;
+       Py_INCREF(self);
+       return (PyObject*)self;
+}
+/*----------------------------Vector.toTrackQuat(track, up) ----------------------
+  extract a quaternion from the vector and the track and up axis */
+PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
+{
+       float vec[3], quat[4];
+       char *strack, *sup;
+       short track = 2, up = 1;
+
+       if( !PyArg_ParseTuple ( args, "|ss", &strack, &sup ) ) {
+               PyErr_SetString( PyExc_TypeError, "expected optional two strings\n" );
+               return NULL;
+       }
+       if (self->size != 3) {
+               PyErr_SetString( PyExc_TypeError, "only for 3D vectors\n" );
+               return NULL;
+       }
+
+       if (strack) {
+               if (strlen(strack) == 2) {
+                       if (strack[0] == '-') {
+                               switch(strack[1]) {
+                                       case 'X':
+                                       case 'x':
+                                               track = 3;
+                                               break;
+                                       case 'Y':
+                                       case 'y':
+                                               track = 4;
+                                               break;
+                                       case 'z':
+                                       case 'Z':
+                                               track = 5;
+                                               break;
+                                       default:
+                                               PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+                                               return NULL;
+                               }
+                       }
+                       else {
+                               PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+                               return NULL;
+                       }
+               }
+               else if (strlen(strack) == 1) {
+                       switch(strack[0]) {
+                       case '-':
+                       case 'X':
+                       case 'x':
+                               track = 0;
+                               break;
+                       case 'Y':
+                       case 'y':
+                               track = 1;
+                               break;
+                       case 'z':
+                       case 'Z':
+                               track = 2;
+                               break;
+                       default:
+                               PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+                               return NULL;
+                       }
+               }
+               else {
+                       PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
+                       return NULL;
+               }
+       }
+
+       if (sup) {
+               if (strlen(sup) == 1) {
+                       switch(*sup) {
+                       case 'X':
+                       case 'x':
+                               up = 0;
+                               break;
+                       case 'Y':
+                       case 'y':
+                               up = 1;
+                               break;
+                       case 'z':
+                       case 'Z':
+                               up = 2;
+                               break;
+                       default:
+                               PyErr_SetString( PyExc_ValueError, "only X, Y or Z for up axis\n" );
+                               return NULL;
+                       }
+               }
+               else {
+                       PyErr_SetString( PyExc_ValueError, "only X, Y or Z for up axis\n" );
+                       return NULL;
+               }
+       }
+
+       if (track == up) {
+               PyErr_SetString( PyExc_ValueError, "Can't have the same axis for track and up\n" );
+               return NULL;
+       }
+
+       /*
+               flip vector around, since vectoquat expect a vector from target to tracking object 
+               and the python function expects the inverse (a vector to the target).
+       */
+       vec[0] = -self->vec[0];
+       vec[1] = -self->vec[1];
+       vec[2] = -self->vec[2];
+
+       vectoquat(vec, track, up, quat);
+
+       return newQuaternionObject(quat, Py_NEW);
+}
+
+/*----------------------------Vector.reflect(mirror) ----------------------
+  return a reflected vector on the mirror normal
+  ((2 * DotVecs(vec, mirror)) * mirror) - vec
+  using arithb.c would be nice here */
+PyObject *Vector_Reflect( VectorObject * self, PyObject * value )
+{
+       VectorObject *mirrvec;
+       float mirror[3];
+       float vec[3];
+       float reflect[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+       float dot2;
+       
+       /* for normalizing */
+       int i;
+       float norm = 0.0f;
+       
+       if (!VectorObject_Check(value)) {
+               PyErr_SetString( PyExc_TypeError, "vec.reflect(value): expected a vector argument" );
+               return NULL;
+       }
+       mirrvec = (VectorObject *)value;
+       
+       mirror[0] = mirrvec->vec[0];
+       mirror[1] = mirrvec->vec[1];
+       if (mirrvec->size > 2)  mirror[2] = mirrvec->vec[2];
+       else                                    mirror[2] = 0.0;
+       
+       /* normalize, whos idea was it not to use arithb.c? :-/ */
+       for(i = 0; i < 3; i++) {
+               norm += mirror[i] * mirror[i];
+       }
+       norm = (float) sqrt(norm);
+       for(i = 0; i < 3; i++) {
+               mirror[i] /= norm;
+       }
+       /* done */
+       
+       vec[0] = self->vec[0];
+       vec[1] = self->vec[1];
+       if (self->size > 2)             vec[2] = self->vec[2];
+       else                                    vec[2] = 0.0;
+       
+       dot2 = 2 * vec[0]*mirror[0]+vec[1]*mirror[1]+vec[2]*mirror[2];
+       
+       reflect[0] = (dot2 * mirror[0]) - vec[0];
+       reflect[1] = (dot2 * mirror[1]) - vec[1];
+       reflect[2] = (dot2 * mirror[2]) - vec[2];
+       
+       return newVectorObject(reflect, self->size, Py_NEW);
+}
+
+PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
+{
+       VectorObject *vecCross = NULL;
+
+       if (!VectorObject_Check(value)) {
+               PyErr_SetString( PyExc_TypeError, "vec.cross(value): expected a vector argument" );
+               return NULL;
+       }
+       
+       if(self->size != 3 || value->size != 3) {
+               PyErr_SetString(PyExc_AttributeError, "vec.cross(value): expects both vectors to be 3D\n");
+               return NULL;
+       }
+       
+       vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW);
+       Crossf(vecCross->vec, self->vec, value->vec);
+       return (PyObject *)vecCross;
+}
+
+PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
+{
+       double dot = 0.0;
+       int x;
+       
+       if (!VectorObject_Check(value)) {
+               PyErr_SetString( PyExc_TypeError, "vec.cross(value): expected a vector argument" );
+               return NULL;
+       }
+       
+       if(self->size != value->size) {
+               PyErr_SetString(PyExc_AttributeError, "vec.dot(value): expects both vectors to have the same size\n");
+               return NULL;
+       }
+       
+       for(x = 0; x < self->size; x++) {
+               dot += self->vec[x] * value->vec[x];
+       }
+       return PyFloat_FromDouble(dot);
+}
+
+/*----------------------------Vector.copy() --------------------------------------
+  return a copy of the vector */
+PyObject *Vector_copy(VectorObject * self)
+{
+       return newVectorObject(self->vec, self->size, Py_NEW);
+}
+