Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Gilbert <ascotan@gmail.com>2004-02-29 16:20:34 +0300
committerJoseph Gilbert <ascotan@gmail.com>2004-02-29 16:20:34 +0300
commit8f3a9815baafb6f8fe00659cf6390a8c4092ef8b (patch)
tree9a69af7bffd6fd0d7da8e998d74a37dc273628a2
parent2255ac3b19ec3b2aa0e884ad5960f34c9c0efa23 (diff)
Mathutils library for the python API
- support for quaternions, euler, vector, matrix operations. - euler supports unique rotation calculation - new matrix memory construction and internal functions - quaternion slerp and diff calculation - 2d, 3d, 4d vector construction and handling - full conversion support between types - update to object/window to reflect to matrix type - update to types/blender/module to reflect new module
-rw-r--r--source/blender/python/api2_2x/Blender.c5
-rw-r--r--source/blender/python/api2_2x/Mathutils.c1186
-rw-r--r--source/blender/python/api2_2x/Mathutils.h205
-rw-r--r--source/blender/python/api2_2x/Object.c6
-rw-r--r--source/blender/python/api2_2x/Object.h1
-rw-r--r--source/blender/python/api2_2x/Types.c12
-rw-r--r--source/blender/python/api2_2x/Types.h6
-rw-r--r--source/blender/python/api2_2x/Window.c2
-rw-r--r--source/blender/python/api2_2x/Window.h1
-rw-r--r--source/blender/python/api2_2x/euler.c331
-rw-r--r--source/blender/python/api2_2x/euler.h65
-rw-r--r--source/blender/python/api2_2x/gen_utils.h4
-rw-r--r--source/blender/python/api2_2x/matrix.c885
-rw-r--r--source/blender/python/api2_2x/matrix.h77
-rw-r--r--source/blender/python/api2_2x/modules.h2
-rw-r--r--source/blender/python/api2_2x/quat.c504
-rw-r--r--source/blender/python/api2_2x/quat.h74
-rw-r--r--source/blender/python/api2_2x/vector.c583
-rw-r--r--source/blender/python/api2_2x/vector.h45
19 files changed, 3775 insertions, 219 deletions
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index a2de9891f1d..3f83185fc79 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -24,7 +24,7 @@
*
* This is a new part of Blender.
*
- * Contributor(s): Michel Selten, Willian P. Germano
+ * Contributor(s): Michel Selten, Willian P. Germano, Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -220,7 +220,8 @@ void M_Blender_Init (void)
PyDict_SetItemString (dict, "Curve", Curve_Init());
PyDict_SetItemString (dict, "Armature", Armature_Init());
PyDict_SetItemString (dict, "Ipo", Ipo_Init());
- PyDict_SetItemString (dict, "IpoCurve", IpoCurve_Init());
+ PyDict_SetItemString (dict, "IpoCurve", IpoCurve_Init());
+ PyDict_SetItemString (dict, "Mathutils",Mathutils_Init());
PyDict_SetItemString (dict, "Metaball", Metaball_Init());
PyDict_SetItemString (dict, "Image", Image_Init());
PyDict_SetItemString (dict, "Window", Window_Init());
diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c
new file mode 100644
index 00000000000..6f3863cec22
--- /dev/null
+++ b/source/blender/python/api2_2x/Mathutils.c
@@ -0,0 +1,1186 @@
+/*
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "Mathutils.h"
+
+//***************************************************************************
+// Function: M_Mathutils_Rand
+//***************************************************************************
+static PyObject *M_Mathutils_Rand(PyObject *self, PyObject *args)
+{
+
+ float high, low, range;
+ double rand;
+ high = 1.0;
+ low = 0.0;
+
+ if (!PyArg_ParseTuple(args, "|ff", &low, &high))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected optional float & float\n"));
+
+ if ( (high < low) ||(high < 0 && low > 0))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "high value should be larger than low value\n"));
+
+ //seed the generator
+ BLI_srand((unsigned int) (PIL_check_seconds_timer()*0x7FFFFFFF));
+
+ //get the random number 0 - 1
+ rand = BLI_drand();
+
+ //set it to range
+ range = high - low;
+ rand = rand * range;
+ rand = rand + low;
+
+ return PyFloat_FromDouble((double)rand);
+}
+
+//***************************************************************************
+// Function: M_Mathutils_Vector
+// Python equivalent: Blender.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
+//***************************************************************************
+static PyObject *M_Mathutils_Vector(PyObject *self, PyObject *args)
+{
+ PyObject *listObject = NULL;
+ PyObject *checkOb = NULL;
+ int x;
+ float *vec;
+
+ if (!PyArg_ParseTuple(args, "|O!", &PyList_Type, &listObject))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "0 or 1 list expected"));
+
+ if(!listObject) return (PyObject *)newVectorObject(NULL, 3);
+
+ //2D 3D 4D supported
+ if(PyList_Size(listObject) != 2 && PyList_Size(listObject) != 3
+ && PyList_Size(listObject) != 4)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "2D, 3D and 4D vectors supported\n"));
+
+ for (x = 0; x < PyList_Size(listObject); x++) {
+ checkOb = PyList_GetItem(listObject, x);
+ if(!PyInt_Check(checkOb) && !PyFloat_Check(checkOb))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected list of numbers\n"));
+ }
+
+ //allocate memory
+ vec = PyMem_Malloc (PyList_Size(listObject)*sizeof (float));
+
+ //parse it all as floats
+ for (x = 0; x < PyList_Size(listObject); x++) {
+ if (!PyArg_Parse(PyList_GetItem(listObject, x), "f", &vec[x])){
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "python list not parseable\n");
+ }
+ }
+ return (PyObject *)newVectorObject(vec, PyList_Size(listObject));
+}
+
+//***************************************************************************
+//Begin Vector Utils
+
+static PyObject *M_Mathutils_CopyVec(PyObject *self, PyObject *args)
+{
+ VectorObject * vector;
+ float *vec;
+ int x;
+
+ if (!PyArg_ParseTuple(args, "O!", &vector_Type, &vector))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected vector type\n"));
+
+ vec = PyMem_Malloc(vector->size * sizeof(float));
+ for(x = 0; x < vector->size; x++){
+ vec[x] = vector->vec[x];
+ }
+
+ return (PyObject *)newVectorObject(vec, vector->size);
+}
+
+//finds perpendicular vector - only 3D is supported
+static PyObject *M_Mathutils_CrossVecs(PyObject *self, PyObject *args)
+{
+ PyObject * vecCross;
+ VectorObject * vec1;
+ VectorObject * vec2;
+
+ if (!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected 2 vector types\n"));
+ if(vec1->size != 3 || vec2->size != 3)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "only 3D vectors are supported\n"));
+
+ vecCross = newVectorObject(PyMem_Malloc (3*sizeof (float)), 3);
+ Crossf(((VectorObject*)vecCross)->vec, vec1->vec, vec2->vec);
+
+ return vecCross;
+}
+
+static PyObject *M_Mathutils_DotVecs(PyObject *self, PyObject *args)
+{
+ VectorObject * vec1;
+ VectorObject * vec2;
+ float dot;
+ int x;
+
+ dot = 0;
+ if (!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected vector types\n"));
+ if(vec1->size != vec2->size)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "vectors must be of the same size\n"));
+
+ for(x = 0; x < vec1->size; x++){
+ dot += vec1->vec[x] * vec2->vec[x];
+ }
+
+ return PyFloat_FromDouble((double)dot);
+}
+
+static PyObject *M_Mathutils_AngleBetweenVecs(PyObject *self, PyObject *args)
+{
+ VectorObject * vec1;
+ VectorObject * vec2;
+ float dot, angleRads, norm;
+ int x;
+
+ dot = 0;
+ if (!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected 2 vector types\n"));
+ if(vec1->size != vec2->size)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "vectors must be of the same size\n"));
+ if(vec1->size > 3 || vec2->size > 3)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "only 2D,3D vectors are supported\n"));
+
+ //normalize vec1
+ norm = 0.0f;
+ for(x = 0; x < vec1->size; x++){
+ norm += vec1->vec[x] * vec1->vec[x];
+ }
+ norm = (float)sqrt(norm);
+ for(x = 0; x < vec1->size; x++){
+ vec1->vec[x] /= norm;
+ }
+
+ //normalize vec2
+ norm = 0.0f;
+ for(x = 0; x < vec2->size; x++){
+ norm += vec2->vec[x] * vec2->vec[x];
+ }
+ norm = (float)sqrt(norm);
+ for(x = 0; x < vec2->size; x++){
+ vec2->vec[x] /= norm;
+ }
+
+ //dot product
+ for(x = 0; x < vec1->size; x++){
+ dot += vec1->vec[x] * vec2->vec[x];
+ }
+
+ //I believe saacos checks to see if the vectors are normalized
+ angleRads = saacos(dot);
+
+ return PyFloat_FromDouble((double)(angleRads*(180/Py_PI)));
+}
+
+static PyObject *M_Mathutils_MidpointVecs(PyObject *self, PyObject *args)
+{
+
+ VectorObject * vec1;
+ VectorObject * vec2;
+ float * vec;
+ int x;
+
+ if (!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected vector types\n"));
+ if(vec1->size != vec2->size)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "vectors must be of the same size\n"));
+
+ vec = PyMem_Malloc (vec1->size*sizeof (float));
+
+ for(x = 0; x < vec1->size; x++){
+ vec[x]= 0.5f*(vec1->vec[x] + vec2->vec[x]);
+ }
+ return (PyObject *)newVectorObject(vec, vec1->size);
+}
+
+//row vector multiplication
+static PyObject *M_Mathutils_VecMultMat(PyObject *self, PyObject *args)
+{
+ PyObject * ob1 = NULL;
+ PyObject * ob2 = NULL;
+ MatrixObject * mat;
+ VectorObject * vec;
+ float * vecNew;
+ int x, y;
+ int z = 0;
+ float dot = 0.0f;
+
+ //get pyObjects
+ if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &ob1, &matrix_Type, &ob2))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "vector and matrix object expected - in that order\n"));
+
+ mat = (MatrixObject*)ob2;
+ vec = (VectorObject*)ob1;
+ if(mat->colSize != vec->size)
+ return (EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "matrix col size and vector size must be the same\n"));
+
+ vecNew = PyMem_Malloc (vec->size*sizeof (float));
+
+ for(x = 0; x < mat->colSize; x++){
+ for(y = 0; y < mat->rowSize; y++){
+ dot += mat->matrix[y][x] * vec->vec[y];
+ }
+ vecNew[z] = dot;
+ z++; dot = 0;
+ }
+
+ return (PyObject *)newVectorObject(vecNew, vec->size);
+}
+
+static PyObject *M_Mathutils_ProjectVecs(PyObject *self, PyObject *args)
+{
+ VectorObject * vec1;
+ VectorObject * vec2;
+ float *vec;
+ float dot = 0.0f;
+ float dot2 = 0.0f;
+ int x;
+
+ if (!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected vector types\n"));
+ if(vec1->size != vec2->size)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "vectors must be of the same size\n"));
+
+ vec = PyMem_Malloc (vec1->size * sizeof (float));
+
+ //dot of vec1 & vec2
+ for(x = 0; x < vec1->size; x++){
+ dot += vec1->vec[x] * vec2->vec[x];
+ }
+ //dot of vec2 & vec2
+ for(x = 0; x < vec2->size; x++){
+ dot2 += vec2->vec[x] * vec2->vec[x];
+ }
+ dot /= dot2;
+ for(x = 0; x < vec1->size; x++){
+ vec[x] = dot * vec2->vec[x];
+ }
+ return (PyObject *)newVectorObject(vec, vec1->size);
+}
+
+//End Vector Utils
+
+//***************************************************************************
+// Function: M_Mathutils_Matrix
+// Python equivalent: Blender.Mathutils.Matrix
+//***************************************************************************
+//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
+static PyObject *M_Mathutils_Matrix(PyObject *self, PyObject *args)
+{
+
+ PyObject *rowA = NULL;
+ PyObject *rowB = NULL;
+ PyObject *rowC = NULL;
+ PyObject *rowD = NULL;
+ PyObject *checkOb = NULL;
+ int x, rowSize, colSize;
+ float * mat;
+ int OK;
+
+ if (!PyArg_ParseTuple(args, "|O!O!O!O!", &PyList_Type, &rowA,
+ &PyList_Type, &rowB,
+ &PyList_Type, &rowC,
+ &PyList_Type, &rowD)){
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected 0, 2,3 or 4 lists\n"));
+ }
+
+ if(!rowA)
+ return newMatrixObject (NULL, 4, 4);
+
+ if(!rowB)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected 0, 2,3 or 4 lists\n"));
+
+ //get rowSize
+ if(rowC){
+ if(rowD){
+ rowSize = 4;
+ }else{
+ rowSize = 3;
+ }
+ }else{
+ rowSize = 2;
+ }
+
+ //check size and get colSize
+ OK = 0;
+ if((PyList_Size(rowA) == PyList_Size(rowB))){
+ if(rowC){
+ if((PyList_Size(rowA) == PyList_Size(rowC))){
+ if(rowD){
+ if((PyList_Size(rowA) == PyList_Size(rowD))){
+ OK = 1;
+ }
+ } OK = 1;
+ }
+ }else OK = 1;
+ }
+
+ if(!OK) return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "each row of vector must contain the same number of parameters\n");
+ colSize = PyList_Size(rowA);
+
+ //check for numeric types
+ for (x = 0; x < colSize; x++) {
+ checkOb = PyList_GetItem(rowA, x);
+ if(!PyInt_Check(checkOb) && !PyFloat_Check(checkOb))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "1st list - expected list of numbers\n"));
+ checkOb = PyList_GetItem(rowB, x);
+ if(!PyInt_Check(checkOb) && !PyFloat_Check(checkOb))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "2nd list - expected list of numbers\n"));
+ if(rowC){
+ checkOb = PyList_GetItem(rowC, x);
+ if(!PyInt_Check(checkOb) && !PyFloat_Check(checkOb))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "3rd list - expected list of numbers\n"));
+ }
+ if(rowD){
+ checkOb = PyList_GetItem(rowD, x);
+ if(!PyInt_Check(checkOb) && !PyFloat_Check(checkOb))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "4th list - expected list of numbers\n"));
+ }
+ }
+
+ //allocate space for 1D array
+ mat = PyMem_Malloc (rowSize * colSize * sizeof (float));
+
+ //parse rows
+ for (x = 0; x < colSize; x++) {
+ if (!PyArg_Parse(PyList_GetItem(rowA, x), "f", &mat[x]))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "rowA - python list not parseable\n");
+ }
+ for (x = 0; x < colSize; x++) {
+ if (!PyArg_Parse(PyList_GetItem(rowB, x), "f", &mat[(colSize + x)]))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "rowB - python list not parseable\n");
+ }
+ if(rowC){
+ for (x = 0; x < colSize; x++) {
+ if (!PyArg_Parse(PyList_GetItem(rowC, x), "f", &mat[((2*colSize) + x)]))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "rowC - python list not parseable\n");
+ }
+ }
+ if(rowD){
+ for (x = 0; x < colSize; x++) {
+ if (!PyArg_Parse(PyList_GetItem(rowD, x), "f", &mat[((3*colSize) + x)]))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "rowD - python list not parseable\n");
+ }
+ }
+
+ //pass to matrix creation
+ return newMatrixObject (mat, rowSize, colSize);
+}
+
+//***************************************************************************
+// Function: M_Mathutils_RotationMatrix
+// Python equivalent: Blender.Mathutils.RotationMatrix
+//***************************************************************************
+//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
+static PyObject *M_Mathutils_RotationMatrix(PyObject *self, PyObject *args)
+{
+
+ float *mat;
+ float angle = 0.0f;
+ char *axis = NULL;
+ VectorObject * vec = NULL;
+ int matSize;
+ float norm = 0.0f;
+ float cosAngle = 0.0f;
+ float sinAngle = 0.0f;
+
+ if (!PyArg_ParseTuple(args, "fi|sO!", &angle, &matSize, &axis, &vector_Type, &vec)){
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected float int and optional string and vector\n"));
+ }
+ if(angle < -360.0f || angle > 360.0f)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "angle size not appropriate\n");
+ if(matSize != 2 && matSize != 3 && matSize != 4)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "can only return a 2x2 3x3 or 4x4 matrix\n");
+ if(matSize == 2 && (axis != NULL || vec != NULL))
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "cannot create a 2x2 rotation matrix around arbitrary axis\n");
+ if((matSize == 3 || matSize == 4) && axis == NULL)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "please choose an axis of rotation\n");
+ if(axis){
+ if(((strcmp (axis, "r") == 0) ||
+ (strcmp (axis, "R") == 0)) && vec == NULL)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "please define the arbitrary axis of rotation\n");
+ }
+ if(vec){
+ if(vec->size != 3)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "the arbitrary axis must be a 3D vector\n");
+ }
+
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+
+ //convert to radians
+ angle = angle * (float)(Py_PI/180);
+
+ if(axis == NULL && matSize == 2){
+ //2D rotation matrix
+ mat[0] = ((float)cos((double)(angle)));
+ mat[1] = ((float)sin((double)(angle)));
+ mat[2] = (-((float)sin((double)(angle))));
+ mat[3] = ((float)cos((double)(angle)));
+ }else if((strcmp(axis,"x") == 0) ||
+ (strcmp(axis,"X") == 0)){
+ //rotation around X
+ mat[0] = 1.0f; mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f;
+ mat[4] = ((float)cos((double)(angle)));
+ mat[5] = ((float)sin((double)(angle)));
+ mat[6] = 0.0f;
+ mat[7] = (-((float)sin((double)(angle))));
+ mat[8] = ((float)cos((double)(angle)));
+ }else if ((strcmp(axis,"y") == 0) ||
+ (strcmp(axis,"Y") == 0)){
+ //rotation around Y
+ mat[0] = ((float)cos((double)(angle)));
+ mat[1] = 0.0f;
+ mat[2] = (-((float)sin((double)(angle))));
+ mat[3] = 0.0f; mat[4] = 1.0f; mat[5] = 0.0f;
+ mat[6] = ((float)sin((double)(angle)));
+ mat[7] = 0.0f;
+ mat[8] = ((float)cos((double)(angle)));
+ }else if ((strcmp(axis,"z") == 0) ||
+ (strcmp(axis,"Z") == 0)){
+ //rotation around Z
+ mat[0] = ((float)cos((double)(angle)));
+ mat[1] = ((float)sin((double)(angle)));
+ mat[2] = 0.0f;
+ mat[3] = (-((float)sin((double)(angle))));
+ mat[4] = ((float)cos((double)(angle)));
+ mat[5] = 0.0f; mat[6] = 0.0f; mat[7] = 0.0f; 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;
+
+ //create matrix
+ cosAngle = ((float)cos((double)(angle)));
+ sinAngle = ((float)sin((double)(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{
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "unrecognizable axis of rotation type - expected x,y,z or r\n");
+ }
+ if(matSize == 4){
+ //resize matrix
+ mat[15] = 1.0f; mat[14] = 0.0f;
+ mat[13] = 0.0f; mat[12] = 0.0f;
+ mat[11] = 0.0f; 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);
+}
+
+//***************************************************************************
+// Function: M_Mathutils_TranslationMatrix
+// Python equivalent: Blender.Mathutils.TranslationMatrix
+//***************************************************************************
+static PyObject *M_Mathutils_TranslationMatrix(PyObject *self, PyObject *args)
+{
+ VectorObject *vec;
+ float *mat;
+
+ if (!PyArg_ParseTuple(args, "O!", &vector_Type, &vec)){
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected vector\n"));
+ }
+ if(vec->size != 3 && vec->size != 4){
+ return EXPP_ReturnPyObjError(PyExc_TypeError,
+ "vector must be 3D or 4D\n");
+ }
+
+ mat = PyMem_Malloc(4*4*sizeof(float));
+ Mat4One((float(*)[4])mat);
+
+ mat[12] = vec->vec[0];
+ mat[13] = vec->vec[1];
+ mat[14] = vec->vec[2];
+
+ return newMatrixObject(mat, 4,4);
+}
+
+
+//***************************************************************************
+// Function: M_Mathutils_ScaleMatrix
+// Python equivalent: Blender.Mathutils.ScaleMatrix
+//***************************************************************************
+//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
+static PyObject *M_Mathutils_ScaleMatrix(PyObject *self, PyObject *args)
+{
+ float factor;
+ int matSize;
+ VectorObject *vec = NULL;
+ float *mat;
+ float norm = 0.0f;
+ int x;
+
+ if (!PyArg_ParseTuple(args, "fi|O!", &factor, &matSize, &vector_Type, &vec)){
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected float int and optional vector\n"));
+ }
+ if(matSize != 2 && matSize != 3 && matSize != 4)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "can only return a 2x2 3x3 or 4x4 matrix\n");
+ if(vec){
+ if(vec->size > 2 && matSize == 2)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "please use 2D vectors when scaling in 2D\n");
+ }
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+
+ if(vec == NULL){ //scaling along axis
+ if(matSize == 2){
+ mat[0] = factor;
+ mat[1] = 0.0f; mat[2] = 0.0f;
+ mat[3] = factor;
+ }else {
+ mat[0] = factor;
+ mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f;
+ mat[4] = factor;
+ mat[5] = 0.0f; mat[6] = 0.0f; mat[7] = 0.0f;
+ 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[15] = 1.0f; mat[14] = 0.0f; mat[13] = 0.0f;
+ mat[12] = 0.0f; mat[11] = 0.0f;
+ 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);
+}
+
+//***************************************************************************
+// Function: M_Mathutils_OrthoProjectionMatrix
+// Python equivalent: Blender.Mathutils.OrthoProjectionMatrix
+//***************************************************************************
+//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
+static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject *self, PyObject *args)
+{
+ char *plane;
+ int matSize;
+ float *mat;
+ VectorObject *vec = NULL;
+ float norm = 0.0f;
+ int x;
+
+ if (!PyArg_ParseTuple(args, "si|O!", &plane, &matSize, &vector_Type, &vec)){
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected string and int and optional vector\n"));
+ }
+ if(matSize != 2 && matSize != 3 && matSize != 4)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "can only return a 2x2 3x3 or 4x4 matrix\n");
+ if(vec){
+ if(vec->size > 2 && matSize == 2)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "please use 2D vectors when scaling in 2D\n");
+ }
+ if(vec == NULL){ //ortho projection onto cardinal plane
+ if (((strcmp(plane, "x") == 0) || (strcmp(plane, "X") == 0)) &&
+ matSize == 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 1.0f;
+ mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f;
+ }else if(((strcmp(plane, "y") == 0) || (strcmp(plane, "Y") == 0)) &&
+ matSize == 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 0.0f; mat[1] = 0.0f; mat[2] = 0.0f;
+ mat[3] = 1.0f;
+ }else if(((strcmp(plane, "xy") == 0) || (strcmp(plane, "XY") == 0)) &&
+ matSize > 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 1.0f;
+ mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f;
+ mat[4] = 1.0f;
+ mat[5] = 0.0f; mat[6] = 0.0f; mat[7] = 0.0f; mat[8] = 0.0f;
+ }else if(((strcmp(plane, "xz") == 0) || (strcmp(plane, "XZ") == 0)) &&
+ matSize > 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 1.0f;
+ mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f; mat[4] = 0.0f;
+ mat[5] = 0.0f; mat[6] = 0.0f; mat[7] = 0.0f;
+ mat[8] = 1.0f;
+ }else if(((strcmp(plane, "yz") == 0) || (strcmp(plane, "YZ") == 0)) &&
+ matSize > 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 0.0f; mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f;
+ mat[4] = 1.0f;
+ mat[5] = 0.0f; mat[6] = 0.0f; mat[7] = 0.0f;
+ mat[8] = 1.0f;
+ }else{
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "unknown plane - expected: x, y, xy, xz, yz\n");
+ }
+ }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 = PyMem_Malloc(matSize * matSize * sizeof(float));
+ 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 = PyMem_Malloc(matSize * matSize * sizeof(float));
+ 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{
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "unknown plane - expected: 'r' expected for axis designation\n");
+ }
+ }
+
+ if(matSize == 4){
+ //resize matrix
+ mat[15] = 1.0f; mat[14] = 0.0f;
+ mat[13] = 0.0f; mat[12] = 0.0f;
+ mat[11] = 0.0f; 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);
+}
+
+//***************************************************************************
+// Function: M_Mathutils_ShearMatrix
+// Python equivalent: Blender.Mathutils.ShearMatrix
+//***************************************************************************
+static PyObject *M_Mathutils_ShearMatrix(PyObject *self, PyObject *args)
+{
+ float factor;
+ int matSize;
+ char *plane;
+ float *mat;
+
+ if (!PyArg_ParseTuple(args, "sfi", &plane, &factor, &matSize)){
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected string float and int\n"));
+ }
+
+ if(matSize != 2 && matSize != 3 && matSize != 4)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "can only return a 2x2 3x3 or 4x4 matrix\n");
+
+ if (((strcmp(plane, "x") == 0) || (strcmp(plane, "X") == 0)) &&
+ matSize == 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 1.0f; mat[1] = 0.0f;
+ mat[2] = factor; mat[3] = 1.0f;
+ }else if(((strcmp(plane, "y") == 0) || (strcmp(plane, "Y") == 0)) &&
+ matSize == 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 1.0f; mat[1] = factor;
+ mat[2] = 0.0f; mat[3] = 1.0f;
+ }else if(((strcmp(plane, "xy") == 0) || (strcmp(plane, "XY") == 0)) &&
+ matSize > 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 1.0f; mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f;
+ mat[4] = 1.0f; mat[5] = 0.0f;
+ mat[6] = factor; mat[7] = factor; mat[8] = 0.0f;
+ }else if(((strcmp(plane, "xz") == 0) || (strcmp(plane, "XZ") == 0)) &&
+ matSize > 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 1.0f; mat[1] = 0.0f; mat[2] = 0.0f;
+ mat[3] = factor; mat[4] = 1.0f; mat[5] = factor;
+ mat[6] = 0.0f; mat[7] = 0.0f; mat[8] = 1.0f;
+ }else if(((strcmp(plane, "yz") == 0) || (strcmp(plane, "YZ") == 0)) &&
+ matSize > 2){
+ mat = PyMem_Malloc(matSize * matSize * sizeof(float));
+ mat[0] = 1.0f; mat[1] = factor; mat[2] = factor;
+ mat[3] = 0.0f; mat[4] = 1.0f;
+ mat[5] = 0.0f; mat[6] = 0.0f; mat[7] = 0.0f;
+ mat[8] = 1.0f;
+ }else{
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n");
+ }
+
+ if(matSize == 4){
+ //resize matrix
+ mat[15] = 1.0f; mat[14] = 0.0f;
+ mat[13] = 0.0f; mat[12] = 0.0f;
+ mat[11] = 0.0f; 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);
+}
+
+//***************************************************************************
+//Begin Matrix Utils
+
+static PyObject *M_Mathutils_CopyMat(PyObject *self, PyObject *args)
+{
+ MatrixObject *matrix;
+ float *mat;
+ int x,y,z;
+
+ if(!PyArg_ParseTuple(args, "O!", &matrix_Type, &matrix))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected matrix\n"));
+
+ mat = PyMem_Malloc(matrix->rowSize * matrix->colSize * sizeof(float));
+
+ z = 0;
+ for(x = 0; x < matrix->rowSize; x++){
+ for(y = 0; y < matrix->colSize; y++){
+ mat[z] = matrix->matrix[x][y];
+ z++;
+ }
+ }
+
+ return (PyObject*)newMatrixObject (mat, matrix->rowSize, matrix->colSize);
+}
+static PyObject *M_Mathutils_MatMultVec(PyObject *self, PyObject *args)
+{
+
+ PyObject * ob1 = NULL;
+ PyObject * ob2 = NULL;
+ MatrixObject * mat;
+ VectorObject * vec;
+ float * vecNew;
+ int x, y;
+ int z = 0;
+ float dot = 0.0f;
+
+ //get pyObjects
+ if(!PyArg_ParseTuple(args, "O!O!", &matrix_Type, &ob1, &vector_Type, &ob2))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "matrix and vector object expected - in that order\n"));
+
+ mat = (MatrixObject*)ob1;
+ vec = (VectorObject*)ob2;
+
+ if(mat->rowSize != vec->size)
+ return (EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "matrix row size and vector size must be the same\n"));
+
+ vecNew = PyMem_Malloc (vec->size*sizeof (float));
+
+ for(x = 0; x < mat->rowSize; x++){
+ for(y = 0; y < mat->colSize; y++){
+ dot += mat->matrix[x][y] * vec->vec[y];
+ }
+ vecNew[z] = dot;
+ z++;
+ dot = 0;
+ }
+
+ return (PyObject *)newVectorObject(vecNew, vec->size);
+}
+
+//***************************************************************************
+// Function: M_Mathutils_Quaternion
+// Python equivalent: Blender.Mathutils.Quaternion
+//***************************************************************************
+static PyObject *M_Mathutils_Quaternion(PyObject *self, PyObject *args)
+{
+ PyObject *listObject;
+ float *vec;
+ float *quat;
+ float angle = 0.0f;
+ int x;
+ float norm;
+
+ if (!PyArg_ParseTuple(args, "O!|f", &PyList_Type, &listObject, &angle))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected list and optional float\n"));
+
+ if(PyList_Size(listObject) != 4 && PyList_Size(listObject) != 3)
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "3 or 4 expected floats for the quaternion\n"));
+
+ vec = PyMem_Malloc (PyList_Size(listObject)*sizeof (float));
+ for (x = 0; x < PyList_Size(listObject); x++) {
+ if (!PyArg_Parse(PyList_GetItem(listObject, x), "f", &vec[x]))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "python list not parseable\n");
+ }
+
+ if(PyList_Size(listObject) == 3){ //an axis of rotation
+ norm = (float)sqrt(vec[0] * vec[0] + vec[1] * vec[1] +
+ vec[2] * vec[2]);
+
+ vec[0] /= norm; vec[1] /= norm; vec[2] /= norm;
+
+ angle = angle * (float)(Py_PI/180);
+ quat = PyMem_Malloc(4*sizeof(float));
+ quat[0] = (float)(cos((double)(angle)/2));
+ quat[1] = (float)(sin((double)(angle)/2)) * vec[0];
+ quat[2] = (float)(sin((double)(angle)/2)) * vec[1];
+ quat[3] = (float)(sin((double)(angle)/2)) * vec[2];
+
+ PyMem_Free(vec);
+
+ return newQuaternionObject(quat);
+ }else
+ return newQuaternionObject(vec);
+}
+
+//***************************************************************************
+//Begin Quaternion Utils
+
+static PyObject *M_Mathutils_CopyQuat(PyObject *self, PyObject *args)
+{
+ QuaternionObject * quatU;
+ float * quat;
+
+ if (!PyArg_ParseTuple(args, "O!", &quaternion_Type, &quatU))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected Quaternion type"));
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ quat[0] = quatU->quat[0];
+ quat[1] = quatU->quat[1];
+ quat[2] = quatU->quat[2];
+ quat[3] = quatU->quat[3];
+
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+static PyObject *M_Mathutils_CrossQuats(PyObject *self, PyObject *args)
+{
+ QuaternionObject * quatU;
+ QuaternionObject * quatV;
+ float * quat;
+
+ if (!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU,
+ &quaternion_Type, &quatV))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected Quaternion types"));
+ quat = PyMem_Malloc (4*sizeof(float));
+ QuatMul(quat, quatU->quat, quatV->quat);
+
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+static PyObject *M_Mathutils_DotQuats(PyObject *self, PyObject *args)
+{
+ QuaternionObject * quatU;
+ QuaternionObject * quatV;
+ float * quat;
+ int x;
+ float dot = 0.0f;
+
+ if (!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU,
+ &quaternion_Type, &quatV))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected Quaternion types"));
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ for(x = 0; x < 4; x++){
+ dot += quatU->quat[x] * quatV->quat[x];
+ }
+
+ return PyFloat_FromDouble((double)(dot));
+}
+
+static PyObject *M_Mathutils_DifferenceQuats(PyObject *self, PyObject *args)
+{
+ QuaternionObject * quatU;
+ QuaternionObject * quatV;
+ float * quat;
+ float * tempQuat;
+ int x;
+ float dot = 0.0f;
+
+ if (!PyArg_ParseTuple(args, "O!O!", &quaternion_Type,
+ &quatU, &quaternion_Type, &quatV))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected Quaternion types"));
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ tempQuat = PyMem_Malloc (4*sizeof(float));
+
+ tempQuat[0] = quatU->quat[0];
+ tempQuat[1] = -quatU->quat[1];
+ tempQuat[2] = -quatU->quat[2];
+ tempQuat[3] = -quatU->quat[3];
+
+ dot= (float)sqrt((double)tempQuat[0] * (double)tempQuat[0] +
+ (double)tempQuat[1] * (double)tempQuat[1] +
+ (double)tempQuat[2] * (double)tempQuat[2] +
+ (double)tempQuat[3] * (double)tempQuat[3]);
+
+ for(x = 0; x < 4; x++){
+ tempQuat[x] /= (dot * dot);
+ }
+ QuatMul(quat, tempQuat, quatV->quat);
+
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+static PyObject *M_Mathutils_Slerp(PyObject *self, PyObject *args)
+{
+ QuaternionObject * quatU;
+ QuaternionObject * quatV;
+ float * quat;
+ float param, x,y, cosD, sinD, deltaD, IsinD, val;
+ int flag, z;
+
+ if (!PyArg_ParseTuple(args, "O!O!f", &quaternion_Type,
+ &quatU, &quaternion_Type, &quatV, &param))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected Quaternion types and float"));
+
+ quat = PyMem_Malloc (4*sizeof(float));
+
+ cosD = quatU->quat[0] * quatV->quat[0] +
+ quatU->quat[1] * quatV->quat[1] +
+ quatU->quat[2] * quatV->quat[2] +
+ quatU->quat[3] * quatV->quat[3];
+
+ flag = 0;
+ if(cosD< 0.0f){
+ flag = 1;
+ cosD = -cosD;
+ }
+ if(cosD > .99999f){
+ x = 1.0f - param;
+ y = param;
+ }else{
+ sinD = (float)sqrt(1.0f - cosD * cosD);
+ deltaD = (float)atan2(sinD, cosD);
+ IsinD = 1.0f/sinD;
+ x = (float)sin((1.0f - param) * deltaD) * IsinD;
+ y = (float)sin(param * deltaD) * IsinD;
+ }
+ for(z = 0; z < 4; z++){
+ val = quatV->quat[z];
+ if(val) val = -val;
+ quat[z] = (quatU->quat[z] * x) + (val * y);
+ }
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+//***************************************************************************
+// Function: M_Mathutils_Euler
+// Python equivalent: Blender.Mathutils.Euler
+//***************************************************************************
+static PyObject *M_Mathutils_Euler(PyObject *self, PyObject *args)
+{
+ PyObject *listObject;
+ float *vec;
+ int x;
+
+ if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &listObject))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected list\n"));
+
+ if(PyList_Size(listObject) != 3)
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "only 3d eulers are supported\n");
+
+ vec = PyMem_Malloc (3*sizeof (float));
+ for (x = 0; x < 3; x++) {
+ if (!PyArg_Parse(PyList_GetItem(listObject, x), "f", &vec[x]))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "python list not parseable\n");
+ }
+
+ return (PyObject*)newEulerObject(vec);
+}
+
+
+//***************************************************************************
+//Begin Euler Util
+
+ static PyObject *M_Mathutils_CopyEuler(PyObject *self, PyObject *args)
+{
+ EulerObject * eulU;
+ float * eul;
+
+ if (!PyArg_ParseTuple(args, "O!", &euler_Type, &eulU))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected Euler types"));
+
+ eul = PyMem_Malloc (3*sizeof(float));
+ eul[0] = eulU->eul[0];
+ eul[1] = eulU->eul[1];
+ eul[2] = eulU->eul[2];
+
+ return (PyObject*)newEulerObject(eul);
+}
+
+static PyObject *M_Mathutils_RotateEuler(PyObject *self, PyObject *args)
+{
+ EulerObject * Eul;
+ float angle;
+ char *axis;
+ int x;
+
+ if (!PyArg_ParseTuple(args, "O!fs", &euler_Type, &Eul, &angle, &axis))
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "expected euler type & float & string"));
+
+ angle *= (float)(Py_PI/180);
+ for(x = 0; x < 3; x++){
+ Eul->eul[x] *= (float)(Py_PI/180);
+ }
+ euler_rot(Eul->eul, angle, *axis);
+ for(x = 0; x < 3; x++){
+ Eul->eul[x] *= (float)(180/Py_PI);
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+//***************************************************************************
+// Function: Mathutils_Init
+//***************************************************************************
+PyObject *Mathutils_Init (void)
+{
+ PyObject *mod= Py_InitModule3("Blender.Mathutils", M_Mathutils_methods, M_Mathutils_doc);
+ return(mod);
+}
diff --git a/source/blender/python/api2_2x/Mathutils.h b/source/blender/python/api2_2x/Mathutils.h
new file mode 100644
index 00000000000..1d4dd544dea
--- /dev/null
+++ b/source/blender/python/api2_2x/Mathutils.h
@@ -0,0 +1,205 @@
+/* * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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/BL DUAL LICENSE BLOCK *****
+*/
+
+#ifndef EXPP_Mathutils_H
+#define EXPP_Mathutils_H
+
+#include <Python.h>
+#include <BKE_main.h>
+#include <BKE_global.h>
+#include <BKE_library.h>
+#include <BKE_utildefines.h>
+#include <BLI_blenlib.h>
+#include <BLI_arithb.h>
+#include <PIL_time.h>
+#include <BLI_rand.h>
+#include <math.h>
+#include "vector.h"
+#include "euler.h"
+#include "quat.h"
+#include "matrix.h"
+#include "blendef.h"
+#include "mydevice.h"
+#include "constant.h"
+#include "gen_utils.h"
+#include "modules.h"
+#include "Types.h"
+
+
+/*****************************************************************************/
+// Python API function prototypes for the Mathutils module.
+/*****************************************************************************/
+static PyObject *M_Mathutils_Rand (PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_Vector(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_CrossVecs(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_DotVecs (PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_AngleBetweenVecs(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_MidpointVecs(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_VecMultMat(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_ProjectVecs(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_CopyVec(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_Matrix(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_RotationMatrix(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_ScaleMatrix(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_ShearMatrix(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_TranslationMatrix(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_MatMultVec(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_CopyMat(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_Quaternion(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_CrossQuats(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_DotQuats(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_CopyQuat(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_DifferenceQuats(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_Slerp(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_Euler(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_CopyEuler(PyObject *self, PyObject *args);
+static PyObject *M_Mathutils_RotateEuler(PyObject *self, PyObject *args);
+
+/*****************************************************************************/
+// The following string definitions are used for documentation strings.
+// In Python these will be written to the console when doing a
+// Blender.Mathutils.__doc__ Mathutils Module 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[] =
+"() - 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";
+
+
+/*****************************************************************************/
+// Python method structure definition for Blender.Mathutils module:
+/*****************************************************************************/
+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_VARARGS,
+ 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},
+ {NULL, NULL, 0, NULL}
+};
+
+#endif /* EXPP_Mathutils_H */
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index b2852438484..7fbcd670455 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -750,9 +750,9 @@ static PyObject *Object_getEuler (BPy_Object *self)
static PyObject *Object_getInverseMatrix (BPy_Object *self)
{
- MatrixObject *inverse = (MatrixObject *)newMatrixObject (NULL);
+ MatrixObject *inverse = (MatrixObject *)newMatrixObject(NULL, 4, 4);
- Mat4Invert (inverse->mem, self->object->obmat);
+ Mat4Invert (*inverse->matrix, self->object->obmat);
return ((PyObject *)inverse);
@@ -796,7 +796,7 @@ static PyObject *Object_getMatrix (BPy_Object *self)
ob = self->object;
- return (newMatrixObject (ob->obmat));
+ return (PyObject*)newMatrixObject((float*)ob->obmat, 4, 4);
}
static PyObject *Object_getName (BPy_Object *self)
diff --git a/source/blender/python/api2_2x/Object.h b/source/blender/python/api2_2x/Object.h
index d2954e78630..b2d5fc34c77 100644
--- a/source/blender/python/api2_2x/Object.h
+++ b/source/blender/python/api2_2x/Object.h
@@ -60,6 +60,7 @@
#include "gen_utils.h"
#include "modules.h"
#include "vector.h"
+#include "matrix.h"
/* The Object PyType Object defined in Object.c */
extern PyTypeObject Object_Type;
diff --git a/source/blender/python/api2_2x/Types.c b/source/blender/python/api2_2x/Types.c
index 0a45ceb89df..0bcf6b5afe0 100644
--- a/source/blender/python/api2_2x/Types.c
+++ b/source/blender/python/api2_2x/Types.c
@@ -24,13 +24,17 @@
*
* This is a new part of Blender.
*
- * Contributor(s): Willian P. Germano, Alex Mole
+ * Contributor(s): Willian P. Germano, Alex Mole, Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include "Types.h"
+char M_Types_doc[] =
+"The Blender Types module\n\n\
+This module is a dictionary of all Blender Python types";
+
struct PyMethodDef Null_methods[] = {{NULL, NULL}};
/*****************************************************************************/
@@ -44,7 +48,10 @@ PyObject *Types_Init (void)
* do it now, we get an easy way to crash Blender. Maybe we'd better
* have an Init function for all these internal types that more than one
* module can use. We could call it after setting the Blender dictionary */
+ matrix_Type.ob_type = &PyType_Type;
vector_Type.ob_type = &PyType_Type;
+ euler_Type.ob_type = &PyType_Type;
+ quaternion_Type.ob_type = &PyType_Type;
rgbTuple_Type.ob_type = &PyType_Type;
constant_Type.ob_type = &PyType_Type;
buffer_Type.ob_type = &PyType_Type;
@@ -100,6 +107,9 @@ PyObject *Types_Init (void)
PyDict_SetItemString(dict, "bufferType", (PyObject *)&buffer_Type);
PyDict_SetItemString(dict, "constantType", (PyObject *)&constant_Type);
PyDict_SetItemString(dict, "rgbTupleType", (PyObject *)&rgbTuple_Type);
+ PyDict_SetItemString(dict, "matrix_Type", (PyObject *)&matrix_Type);
+ PyDict_SetItemString(dict, "eulerType", (PyObject *)&euler_Type);
+ PyDict_SetItemString(dict, "quaternionType", (PyObject *)&quaternion_Type);
PyDict_SetItemString(dict, "BezTripleType", (PyObject *)&BezTriple_Type);
return submodule;
diff --git a/source/blender/python/api2_2x/Types.h b/source/blender/python/api2_2x/Types.h
index ea098cfb3eb..595f04d0383 100644
--- a/source/blender/python/api2_2x/Types.h
+++ b/source/blender/python/api2_2x/Types.h
@@ -46,11 +46,9 @@ extern PyTypeObject Armature_Type, Bone_Type;
extern PyTypeObject Curve_Type, Ipo_Type, Metaball_Type;
extern PyTypeObject Lattice_Type;
-extern PyTypeObject vector_Type, buffer_Type, rgbTuple_Type,
+extern PyTypeObject buffer_Type, rgbTuple_Type,
constant_Type, BezTriple_Type;
-static char M_Types_doc[] =
-"The Blender Types module\n\n\
-This module is a dictionary of all Blender Python types";
+extern PyTypeObject vector_Type, matrix_Type, euler_Type, quaternion_Type;
#endif /* EXPP_TYPES_H */
diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c
index a7897f56dcd..6a691515b41 100644
--- a/source/blender/python/api2_2x/Window.c
+++ b/source/blender/python/api2_2x/Window.c
@@ -327,7 +327,7 @@ static PyObject *M_Window_GetViewMatrix(PyObject *self)
return Py_None;
}
- viewmat = newMatrixObject (G.vd->viewmat);
+ viewmat = (PyObject*)newMatrixObject((float*)G.vd->viewmat, 4, 4);
if (!viewmat)
return (EXPP_ReturnPyObjError (PyExc_MemoryError,
diff --git a/source/blender/python/api2_2x/Window.h b/source/blender/python/api2_2x/Window.h
index c7b631a703a..800254b47df 100644
--- a/source/blender/python/api2_2x/Window.h
+++ b/source/blender/python/api2_2x/Window.h
@@ -52,6 +52,7 @@
#include "gen_utils.h"
#include "modules.h"
+#include "matrix.h"
/* Used in Draw.c */
extern int EXPP_disable_force_draw;
diff --git a/source/blender/python/api2_2x/euler.c b/source/blender/python/api2_2x/euler.c
new file mode 100644
index 00000000000..c6c8d61f9f3
--- /dev/null
+++ b/source/blender/python/api2_2x/euler.c
@@ -0,0 +1,331 @@
+/*
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "euler.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";
+
+//methods table
+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},
+ {NULL, NULL, 0, NULL}
+};
+
+/*****************************/
+// Euler Python Object
+/*****************************/
+
+//euler methods
+PyObject *Euler_ToQuat(EulerObject *self)
+{
+ float *quat;
+ int x;
+
+ for(x = 0; x < 3; x++){
+ self->eul[x] *= (float)(Py_PI/180);
+ }
+ quat = PyMem_Malloc(4*sizeof(float));
+ EulToQuat(self->eul, quat);
+ for(x = 0; x < 3; x++){
+ self->eul[x] *= (float)(180/Py_PI);
+ }
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+PyObject *Euler_ToMatrix(EulerObject *self)
+{
+ float *mat;
+ int x;
+
+ for(x = 0; x < 3; x++){
+ self->eul[x] *= (float)(Py_PI/180);
+ }
+ mat = PyMem_Malloc(3*3*sizeof(float));
+ EulToMat3(self->eul, (float(*)[3])mat);
+ for(x = 0; x < 3; x++){
+ self->eul[x] *= (float)(180/Py_PI);
+ }
+ return (PyObject*)newMatrixObject(mat,3,3);
+}
+
+PyObject *Euler_Unique(EulerObject *self)
+{
+ float heading, pitch, bank;
+ float pi2 = (float)Py_PI * 2.0f;
+ float piO2 = (float)Py_PI / 2.0f;
+ float 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 += (float)Py_PI;
+ pitch -= (float)floor(pitch * Opi2) * pi2;
+ pitch -= (float)Py_PI;
+
+
+ if(pitch < -piO2){
+ pitch = (float)-Py_PI - pitch;
+ heading += (float)Py_PI;
+ bank += (float)Py_PI;
+ }else if (pitch > piO2){
+ pitch = (float)Py_PI - pitch;
+ heading += (float)Py_PI;
+ bank += (float)Py_PI;
+ }
+
+ //gimbal lock test
+ if(fabs(pitch) > piO2 - 1e-4){
+ heading += bank;
+ bank = 0.0f;
+ }else{
+ bank += (float)Py_PI;
+ bank -= (float)(floor(bank * Opi2)) * pi2;
+ bank -= (float)Py_PI;
+ }
+
+ heading += (float)Py_PI;
+ heading -= (float)(floor(heading * Opi2)) * pi2;
+ heading -= (float)Py_PI;
+
+ //back to degrees
+ self->eul[0] = heading * (float)(180/Py_PI);
+ self->eul[1] = pitch * (float)(180/Py_PI);
+ self->eul[2] = bank * (float)(180/Py_PI);
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Euler_Zero(EulerObject *self)
+{
+ self->eul[0] = 0.0;
+ self->eul[1] = 0.0;
+ self->eul[2] = 0.0;
+
+ return EXPP_incr_ret(Py_None);
+}
+
+static void Euler_dealloc(EulerObject *self)
+{
+ PyObject_DEL (self);
+}
+
+static PyObject *Euler_getattr(EulerObject *self, char *name)
+{
+ if (ELEM3(name[0], 'x', 'y', 'z') && name[1]==0){
+ return PyFloat_FromDouble(self->eul[name[0]-'x']);
+ }
+ return Py_FindMethod(Euler_methods, (PyObject*)self, name);
+}
+
+static int Euler_setattr(EulerObject *self, char *name, PyObject *e)
+{
+ float val;
+
+ if (!PyArg_Parse(e, "f", &val))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "unable to parse float argument\n");
+
+ if (ELEM3(name[0], 'x', 'y', 'z') && name[1]==0){
+ self->eul[name[0]-'x']= val;
+ return 0;
+ }
+ else return -1;
+}
+
+/* Eulers Sequence methods */
+static PyObject *Euler_item(EulerObject *self, int i)
+{
+ if (i < 0 || i >= 3)
+ return EXPP_ReturnPyObjError (PyExc_IndexError, "array index out of range\n");
+
+ return Py_BuildValue("f", self->eul[i]);
+}
+
+static PyObject *Euler_slice(EulerObject *self, int begin, int end)
+{
+ PyObject *list;
+ int count;
+
+ if (begin < 0) begin= 0;
+ if (end > 3) end= 3;
+ if (begin > end) 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;
+}
+
+static int Euler_ass_item(EulerObject *self, int i, PyObject *ob)
+{
+ if (i < 0 || i >= 3)
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "array assignment index out of range\n");
+
+ if (!PyNumber_Check(ob))
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "Euler member must be a number\n");
+
+ if(!PyFloat_Check(ob) && !PyInt_Check(ob)){
+ return EXPP_ReturnIntError(PyExc_TypeError,"int or float expected\n");
+ }else{
+ self->eul[i]= (float)PyFloat_AsDouble(ob);
+ }
+ return 0;
+}
+
+static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
+{
+ int count, z;
+
+ if (begin < 0) begin= 0;
+ if (end > 3) end= 3;
+ if (begin > end) begin= end;
+
+ if (!PySequence_Check(seq))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "illegal argument type for built-in operation\n");
+ if (PySequence_Length(seq) != (end - begin))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "size mismatch in slice assignment\n");
+
+ z = 0;
+ for (count = begin; count < end; count++) {
+ PyObject *ob = PySequence_GetItem(seq, z); z++;
+
+ if(!PyFloat_Check(ob) && !PyInt_Check(ob)){
+ Py_DECREF(ob);
+ return -1;
+ }else{
+ if (!PyArg_Parse(ob, "f", &self->eul[count])) {
+ Py_DECREF(ob);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static PyObject *Euler_repr (EulerObject *self)
+{
+ int i, maxindex = 3 - 1;
+ char ftoa[24];
+ PyObject *str1, *str2;
+
+ str1 = PyString_FromString ("[");
+
+ for (i = 0; i < maxindex; i++) {
+ sprintf(ftoa, "%.4f, ", self->eul[i]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
+ }
+
+ sprintf(ftoa, "%.4f]\n", self->eul[maxindex]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
+
+ if (str1) return str1;
+
+error:
+ Py_XDECREF (str1);
+ Py_XDECREF (str2);
+ return EXPP_ReturnPyObjError (PyExc_MemoryError,
+ "couldn't create PyString!\n");
+}
+
+static PySequenceMethods Euler_SeqMethods =
+{
+ (inquiry) 0, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) Euler_item, /* sq_item */
+ (intintargfunc) Euler_slice, /* sq_slice */
+ (intobjargproc) Euler_ass_item, /* sq_ass_item */
+ (intintobjargproc) Euler_ass_slice, /* sq_ass_slice */
+};
+
+PyTypeObject euler_Type =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "euler", /*tp_name*/
+ sizeof(EulerObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) Euler_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) Euler_getattr, /*tp_getattr*/
+ (setattrfunc) Euler_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) Euler_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &Euler_SeqMethods, /*tp_as_sequence*/
+};
+
+PyObject *newEulerObject(float *eul)
+{
+ EulerObject *self;
+ int x;
+
+ euler_Type.ob_type = &PyType_Type;
+
+ self = PyObject_NEW(EulerObject, &euler_Type);
+
+ if(!eul){
+ self->eul = PyMem_Malloc (3*sizeof (float));
+ for(x = 0; x < 3; x++){
+ self->eul[x] = 0.0f;
+ }
+ }else self->eul = eul;
+
+ return (PyObject*) self;
+}
+
diff --git a/source/blender/python/api2_2x/euler.h b/source/blender/python/api2_2x/euler.h
new file mode 100644
index 00000000000..2e33c7cf350
--- /dev/null
+++ b/source/blender/python/api2_2x/euler.h
@@ -0,0 +1,65 @@
+/* * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef EXPP_euler_h
+#define EXPP_euler_h
+
+#include "Python.h"
+#include "gen_utils.h"
+#include "Types.h"
+#include <BLI_arithb.h>
+#include "quat.h"
+#include "matrix.h"
+#include "BKE_utildefines.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*****************************/
+// Euler Python Object
+/*****************************/
+
+#define EulerObject_Check(v) ((v)->ob_type == &euler_Type)
+
+typedef struct {
+ PyObject_VAR_HEAD
+ float * eul;
+} EulerObject;
+
+//prototypes
+PyObject *newEulerObject(float *eul);
+PyObject *Euler_Zero(EulerObject *self);
+PyObject *Euler_Unique(EulerObject *self);
+PyObject *Euler_ToMatrix(EulerObject *self);
+PyObject *Euler_ToQuat(EulerObject *self);
+
+#endif /* EXPP_euler_h */
+
diff --git a/source/blender/python/api2_2x/gen_utils.h b/source/blender/python/api2_2x/gen_utils.h
index 6418c9638a3..efeb0a43370 100644
--- a/source/blender/python/api2_2x/gen_utils.h
+++ b/source/blender/python/api2_2x/gen_utils.h
@@ -24,7 +24,7 @@
*
* This is a new part of Blender.
*
- * Contributor(s): Michel Selten, Willian P. Germano, Alex Mole
+ * Contributor(s): Michel Selten, Willian P. Germano, Alex Mole, Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -48,6 +48,8 @@
#include <DNA_scriptlink_types.h>
#include <DNA_listBase.h>
+#define Py_PI 3.14159265358979323846
+
int StringEqual (const char * string1, const char * string2);
char * GetIdName (ID *id);
ID *GetIdFromList(ListBase *list, char *name);
diff --git a/source/blender/python/api2_2x/matrix.c b/source/blender/python/api2_2x/matrix.c
index 76d4409dbad..fcabc1c1c48 100644
--- a/source/blender/python/api2_2x/matrix.c
+++ b/source/blender/python/api2_2x/matrix.c
@@ -22,59 +22,427 @@
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
- * Contributor(s): Michel Selten
+ * Contributor(s): Michel Selten & Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
-/* This file is the old bpython opy_matrix.c with minor modifications */
+#include "matrix.h"
-#include "vector.h"
-#include "BLI_arithb.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_Resize4x4_doc[] =
+"() - resize the matrix to a 4x4 square matrix";
+char Matrix_toEuler_doc[] =
+"() - convert matrix to a euler angle rotation";
+char Matrix_toQuat_doc[] =
+"() - convert matrix to a quaternion rotation";
-static void Matrix_dealloc (MatrixObject *self)
+//methods table
+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},
+ {"resize4x4",(PyCFunction)Matrix_Resize4x4, METH_NOARGS,
+ Matrix_Resize4x4_doc},
+ {"toEuler",(PyCFunction)Matrix_toEuler, METH_NOARGS,
+ Matrix_toEuler_doc},
+ {"toQuat",(PyCFunction)Matrix_toQuat, METH_NOARGS,
+ Matrix_toQuat_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*****************************/
+// Matrix Python Object
+/*****************************/
+
+PyObject *Matrix_toQuat(MatrixObject *self)
{
- Py_DECREF (self->rows[0]);
- Py_DECREF (self->rows[1]);
- Py_DECREF (self->rows[2]);
- Py_DECREF (self->rows[3]);
+ float *quat, *mat;
- if (self->mem)
- PyMem_Free (self->mem);
- PyMem_DEL (self);
+ if(self->colSize < 3){
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "inappropriate matrix size\n");
+ }else if (self->colSize > 2){ //3 or 4 col
+ if(self->rowSize < 3) //3 or 4 row
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "inappropriate matrix size\n");
+
+ mat = PyMem_Malloc(3*3*sizeof(float));
+ 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];
+ }
+ quat = PyMem_Malloc(4*sizeof(float));
+ Mat3ToQuat((float(*)[3])mat,quat);
+
+ return (PyObject*)newQuaternionObject(quat);
}
-static PyObject * Matrix_getattr (MatrixObject *self, char *name)
+
+PyObject *Matrix_toEuler(MatrixObject *self)
{
- PyObject * list;
- float val[3];
- float mat3[3][3];
+ float *eul, *mat;
+ int x;
- if (strcmp (name, "rot") == 0)
- {
- Mat3CpyMat4 (mat3, self->mat);
- Mat3ToEul (mat3, val);
- }
- else if (strcmp (name, "size") == 0)
- {
- Mat4ToSize (self->mat, val);
+ if(self->colSize < 3){
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "inappropriate matrix size\n");
+ }else if (self->colSize > 2){ //3 or 4 col
+ if(self->rowSize < 3) //3 or 4 row
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "inappropriate matrix size\n");
+
+ mat = PyMem_Malloc(3*3*sizeof(float));
+ 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];
+ }
+ eul = PyMem_Malloc(3*sizeof(float));
+ Mat3ToEul((float(*)[3])mat,eul);
+
+ for(x = 0; x < 3; x++){
+ eul[x] *= (float)(180/Py_PI);
+ }
+
+ return (PyObject*)newEulerObject(eul);
+}
+
+PyObject *Matrix_Resize4x4(MatrixObject *self)
+{
+ float *mat;
+ float * contigPtr;
+ int x, row, col;
+
+ if(self->colSize == 4 && self->rowSize == 4)
+ return EXPP_incr_ret(Py_None);
+
+ mat = PyMem_Malloc(4*4*sizeof(float));
+ for(x = 0; x < 16; x++){
+ mat[x] = 0.0f;
+ }
+
+ if(self->colSize == 2){ //2x2, 2x3, 2x4
+ mat[0] = self->matrix[0][0];mat[1] = self->matrix[0][1];
+ mat[4] = self->matrix[1][0];mat[5] = self->matrix[1][1];
+ if (self->rowSize > 2){
+ mat[8] = self->matrix[2][0];mat[9] = self->matrix[2][1];
+ }
+ if (self->rowSize > 3){
+ mat[12] = self->matrix[3][0];mat[13] = self->matrix[3][1];
+ }
+ mat[10] = 1.0f; mat[15] = 1.0f;
+ }else if (self->colSize == 3){ //3x2, 3x3, 3x4
+ mat[0] = self->matrix[0][0];mat[1] = self->matrix[0][1];
+ mat[2] = self->matrix[0][2];mat[4] = self->matrix[1][0];
+ mat[5] = self->matrix[1][1];mat[6] = self->matrix[1][2];
+ if (self->rowSize > 2){
+ mat[8] = self->matrix[2][0];mat[9] = self->matrix[2][1];
+ mat[10] = self->matrix[2][2];
+ }
+ if (self->rowSize > 3){
+ mat[12] = self->matrix[3][0];mat[13] = self->matrix[3][1];
+ mat[14] = self->matrix[3][2];
+ }
+ if(self->rowSize == 2) mat[10] = 1.0f;
+ mat[15] = 1.0f;
+ }else if (self->colSize == 4){ //2x4, 3x4
+ mat[0] = self->matrix[0][0];mat[1] = self->matrix[0][1];
+ mat[2] = self->matrix[0][2];mat[3] = self->matrix[0][3];
+ mat[4] = self->matrix[1][0];mat[5] = self->matrix[1][1];
+ mat[6] = self->matrix[1][2];mat[7] = self->matrix[1][3];
+ if (self->rowSize > 2
+ ){
+ mat[8] = self->matrix[2][0];mat[9] = self->matrix[2][1];
+ mat[10] = self->matrix[2][2];mat[11] = self->matrix[2][3];
+ }
+ if(self->rowSize == 2) mat[10] = 1.0f;
+ mat[15] = 1.0f;
+ }
+
+ PyMem_Free(*self->matrix);
+ contigPtr = PyMem_Malloc(4 * 4 * sizeof(float));
+ if(contigPtr == NULL){
+ return (EXPP_ReturnPyObjError (PyExc_MemoryError,
+ "problem allocating array space\n\n"));
+ }
+ self->matrix = PyMem_Malloc(4* sizeof(float*));
+ if(self->matrix == NULL){
+ return (EXPP_ReturnPyObjError (PyExc_MemoryError,
+ "problem allocating pointer space\n\n"));
+ }
+ for (x = 0; x < 4; x++){
+ self->matrix[x] = contigPtr + (x *4);
}
- else if (strcmp (name, "loc") == 0)
- {
- VECCOPY (val, (float *)(self->mat)[3]);
+
+ for (row = 0; row < 4; row++){
+ for(col = 0; col < 4; col++){
+ self->matrix[row][col] = mat[(row * 4) + col];
+ }
+ }
+ PyMem_Free(mat);
+
+ self->colSize = 4;
+ self->rowSize = 4;
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Matrix_TranslationPart(MatrixObject *self)
+{
+ float *vec;
+
+ if(self->colSize < 3){
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "inappropriate matrix size\n");
+ }else if (self->colSize > 2){ //3 or 4 columns
+ if(self->rowSize < 4) //all 4 rows
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "inappropriate matrix size\n");
+
+ vec = PyMem_Malloc(3 * sizeof(float));
+ vec[0] = self->matrix[3][0];
+ vec[1] = self->matrix[3][1];
+ vec[2] = self->matrix[3][2];
+ }
+
+ return (PyObject*)newVectorObject(vec,3);
+}
+
+PyObject *Matrix_RotationPart(MatrixObject *self)
+{
+ float *mat;
+
+ if(self->colSize < 3){
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "inappropriate matrix size\n");
+ }else if (self->colSize > 2){ //3 or 4 col
+ if(self->rowSize < 3) //3 or 4 row
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "inappropriate matrix size\n");
+
+ mat = PyMem_Malloc(3*3*sizeof(float));
+ 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 (PyObject*)newMatrixObject(mat,3,3);
+}
+
+PyObject *Matrix_Invert(MatrixObject *self)
+{
+ float det;
+ int x,y,z;
+ float *mat;
+ float t;
+
+ if(self->rowSize != self->colSize)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "only square matrices are supported\n");
+
+ //calculate the determinant
+ 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 if(self->rowSize == 4){
+ det = Det4x4(*self->matrix);
+ }else{
+ return EXPP_ReturnPyObjError(PyExc_StandardError,
+ "error calculating determinant for inverse()\n");
+ }
+
+ if(det != 0){
+
+ //calculate the classical adjoint
+ if(self->rowSize == 2){
+ mat = PyMem_Malloc(self->rowSize * self->colSize * sizeof(float));
+ mat[0] = self->matrix[1][1];
+ mat[1] = -self->matrix[1][0];
+ mat[2] = -self->matrix[0][1];
+ mat[3] = self->matrix[0][0];
+ }else if(self->rowSize == 3){
+ mat = PyMem_Malloc(self->rowSize * self->colSize * sizeof(float));
+ Mat3Adj((float(*)[3])mat, *self->matrix);
+ }else if (self->rowSize == 4){
+ mat = PyMem_Malloc(self->rowSize * self->colSize * sizeof(float));
+ Mat4Adj((float(*)[4])mat, *self->matrix);
+ }
+
+ //divide by determinate
+ for(x = 0; x < (self->rowSize * self->colSize); x++){
+ mat[x] /= det;
+ }
+
+ //set values
+ z = 0;
+ for(x = 0; x < self->rowSize; x++){
+ for(y = 0; y < self->colSize; y++){
+ self->matrix[x][y] = mat[z];
+ z++;
+ }
+ }
+
+ //transpose
+ 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])mat);
+ }
+ else if (self->rowSize == 4){
+ Mat4Transp((float(*)[4])mat);
+ }
+ }else{
+ printf("matrix does not have an inverse - none attempted\n");
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+
+PyObject *Matrix_Determinant(MatrixObject *self)
+{
+ float det;
+
+ if(self->rowSize != self->colSize)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "only square matrices are supported\n");
+
+ 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 if(self->rowSize == 4){
+ det = Det4x4(*self->matrix);
+ }else{
+ return EXPP_ReturnPyObjError(PyExc_StandardError,
+ "error in determinant()\n");
+ }
+ return PyFloat_FromDouble(det);
+}
+
+PyObject *Matrix_Transpose(MatrixObject *self)
+{
+ float t;
+
+ if(self->rowSize != self->colSize)
+ return EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "only square matrices are supported\n");
+
+ 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(*self->matrix);
+ }
+ else if (self->rowSize == 4){
+ Mat4Transp(*self->matrix);
+ }
+ else
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unable to transpose matrix\n"));
+
+ return EXPP_incr_ret(Py_None);
+}
+
+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;
+ }
+ }
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Matrix_Identity(MatrixObject *self)
+{
+ if(self->rowSize != self->colSize)
+ return (EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "only square matrices supported\n"));
+
+ 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(*self->matrix);
+ }
+ else if (self->rowSize == 4){
+ Mat4One(*self->matrix);
+ }
+ else
+ return (EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unable to create identity matrix\n"));
+
+ return EXPP_incr_ret(Py_None);
+}
+
+static void Matrix_dealloc (MatrixObject *self)
+{
+ PyMem_Free (self->matrix);
+ PyMem_DEL (self);
+}
+
+static PyObject * Matrix_getattr (MatrixObject *self, char *name)
+{
+ if (strcmp (name, "rowSize") == 0){
+ return PyInt_FromLong((long)self->rowSize);
}
- else
- {
- return (EXPP_ReturnPyObjError (PyExc_AttributeError,
- "expected 'rot', 'size' or 'loc'"));
+ else if (strcmp (name, "colSize") == 0){
+ return PyInt_FromLong((long)self->colSize);
}
- list = PyList_New (3);
- PyList_SetItem (list, 0, PyFloat_FromDouble (val[0]));
- PyList_SetItem (list, 1, PyFloat_FromDouble (val[1]));
- PyList_SetItem (list, 2, PyFloat_FromDouble (val[2]));
-
- return (list);
+ return Py_FindMethod(Matrix_methods, (PyObject*)self, name);
}
static int Matrix_setattr (MatrixObject *self, char *name, PyObject *v)
@@ -85,80 +453,435 @@ static int Matrix_setattr (MatrixObject *self, char *name, PyObject *v)
static PyObject * Matrix_repr (MatrixObject *self)
{
- return (EXPP_tuple_repr ((PyObject *) self, 4));
+ PyObject *repr, *str;
+ int x,y;
+ char ftoa[24];
+
+ repr = PyString_FromString("");
+ if (!repr)
+ return (EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "Attribute error in PyMatrix (repr)\n"));
+
+ for(x = 0; x < self->rowSize; x++){
+ str = PyString_FromString ("[");
+ PyString_ConcatAndDel(&repr,str);
+
+ for(y = 0; y < (self->colSize - 1); y++){
+ sprintf(ftoa, "%.4f, ", self->matrix[x][y]);
+ str = PyString_FromString (ftoa);
+ PyString_ConcatAndDel(&repr,str);
+ }
+ sprintf(ftoa, "%.4f]\n", self->matrix[x][y]);
+ str = PyString_FromString (ftoa);
+ PyString_ConcatAndDel(&repr,str);
+ }
+ return repr;
}
+//no support for matrix[x][y] so have to return by sequence index
static PyObject * Matrix_item (MatrixObject *self, int i)
{
- if ((i<0) || (i>=4))
- {
- return (EXPP_ReturnPyObjError (PyExc_IndexError,
- "array index out of range"));
- }
- return (EXPP_incr_ret (self->rows[i]));
+ int maxsize, x, y;
+
+ maxsize = self->colSize * self->rowSize;
+ if(i < 0 || i >= maxsize)
+ return EXPP_ReturnPyObjError(PyExc_IndexError,
+ "array index out of range\n");
+
+ x = (int)floor((double)(i / self->colSize));
+ y = i % self->colSize;
+
+ return PyFloat_FromDouble(self->matrix[x][y]);
+}
+
+static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
+{
+ PyObject *list;
+ int count, maxsize, x, y;
+
+ maxsize = self->colSize * self->rowSize;
+ if (begin < 0) begin= 0;
+ if (end > maxsize) end= maxsize;
+ if (begin > end) begin= end;
+
+ list= PyList_New(end-begin);
+
+ for (count = begin; count < end; count++){
+ x = (int)floor((double)(count / self->colSize));
+ y = count % self->colSize;
+ PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->matrix[x][y]));
+ }
+
+ return list;
+}
+
+static int Matrix_ass_item(MatrixObject *self, int i, PyObject *ob)
+{
+ int maxsize, x, y;
+
+ maxsize = self->colSize * self->rowSize;
+ if (i < 0 || i >= maxsize)
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "array assignment index out of range\n");
+ if (!PyInt_Check(ob) && !PyFloat_Check(ob))
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "matrix member must be a number\n");
+
+ x = (int)floor((double)(i / self->colSize));
+ y = i % self->colSize;
+ self->matrix[x][y] = (float)PyFloat_AsDouble(ob);
+
+ return 0;
+}
+
+static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *seq)
+{
+ int count, maxsize, x, y, z;
+
+ maxsize = self->colSize * self->rowSize;
+ if (begin < 0) begin= 0;
+ if (end > maxsize) end= maxsize;
+ if (begin > end) begin= end;
+
+ if (!PySequence_Check(seq))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "illegal argument type for built-in operation\n");
+ if (PySequence_Length(seq) != (end - begin))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "size mismatch in slice assignment\n");
+
+ z = 0;
+ for (count = begin; count < end; count++) {
+ PyObject *ob = PySequence_GetItem(seq, z); z++;
+ if (!PyInt_Check(ob) && !PyFloat_Check(ob))
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "list member must be a number\n");
+
+ x = (int)floor((double)(count / self->colSize));
+ y = count % self->colSize;
+ if (!PyArg_Parse(ob, "f", &self->matrix[x][y])){
+ Py_DECREF(ob);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int Matrix_len(MatrixObject *self)
+{
+ return (self->colSize * self->rowSize);
+}
+
+PyObject * Matrix_add(PyObject *m1, PyObject * m2)
+{
+ float * mat;
+ int matSize, rowSize, colSize, x,y;
+
+ if((!Matrix_CheckPyObject(m1)) || (!Matrix_CheckPyObject(m2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+
+ if(((MatrixObject*)m1)->flag > 0 || ((MatrixObject*)m2)->flag > 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "cannot add scalar to a matrix\n");
+
+ if(((MatrixObject*)m1)->rowSize!= ((MatrixObject*)m2)->rowSize ||
+ ((MatrixObject*)m1)->colSize != ((MatrixObject*)m2)->colSize)
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "matrices must be the same same for this operation\n");
+
+ rowSize = (((MatrixObject*)m1)->rowSize);
+ colSize = (((MatrixObject*)m1)->colSize);
+ matSize = rowSize * colSize;
+
+ mat = PyMem_Malloc (matSize * sizeof(float));
+
+ for(x = 0; x < rowSize; x++){
+ for(y = 0; y < colSize; y++){
+ mat[((x * rowSize) + y)] =
+ ((MatrixObject*)m1)->matrix[x][y] +
+ ((MatrixObject*)m2)->matrix[x][y];
+ }
+ }
+
+ return newMatrixObject(mat, rowSize, colSize);
}
+PyObject * Matrix_sub(PyObject *m1, PyObject * m2)
+{
+ float * mat;
+ int matSize, rowSize, colSize, x,y;
+
+ if((!Matrix_CheckPyObject(m1)) || (!Matrix_CheckPyObject(m2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+
+ if(((MatrixObject*)m1)->flag > 0 || ((MatrixObject*)m2)->flag > 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "cannot subtract a scalar from a matrix\n");
+
+ if(((MatrixObject*)m1)->rowSize!= ((MatrixObject*)m2)->rowSize ||
+ ((MatrixObject*)m1)->colSize != ((MatrixObject*)m2)->colSize)
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "matrices must be the same same for this operation\n");
+
+ rowSize = (((MatrixObject*)m1)->rowSize);
+ colSize = (((MatrixObject*)m1)->colSize);
+ matSize = rowSize * colSize;
+
+ mat = PyMem_Malloc (matSize * sizeof(float));
+
+ for(x = 0; x < rowSize; x++){
+ for(y = 0; y < colSize; y++){
+ mat[((x * rowSize) + y)] =
+ ((MatrixObject*)m1)->matrix[x][y] -
+ ((MatrixObject*)m2)->matrix[x][y];
+ }
+ }
+
+ return newMatrixObject(mat, rowSize, colSize);
+}
+
+PyObject * Matrix_mul(PyObject *m1, PyObject * m2)
+{
+ float * mat;
+ int matSizeV, rowSizeV, colSizeV, rowSizeW, colSizeW, matSizeW, x, y, z;
+ float dot = 0;
+ MatrixObject * matV;
+ MatrixObject * matW;
+
+ if((!Matrix_CheckPyObject(m1)) || (!Matrix_CheckPyObject(m2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+
+ //get some vars
+ rowSizeV = (((MatrixObject*)m1)->rowSize);
+ colSizeV = (((MatrixObject*)m1)->colSize);
+ matSizeV = rowSizeV * colSizeV;
+ rowSizeW = (((MatrixObject*)m2)->rowSize);
+ colSizeW = (((MatrixObject*)m2)->colSize);
+ matSizeW = rowSizeW * colSizeW;
+ matV = ((MatrixObject*)m1);
+ matW = ((MatrixObject*)m2);
+
+ //coerced int or float for scalar multiplication
+ if(matW->flag > 1 || matW->flag > 2){
+
+ if(rowSizeV != rowSizeW && colSizeV != colSizeW)
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "Matrix dimension error during scalar multiplication\n");
+
+ mat = PyMem_Malloc (matSizeV * sizeof(float));
+
+ for(x = 0; x < rowSizeV; x++){
+ for(y = 0; y < colSizeV; y++){
+ mat[((x * rowSizeV) + y)] =
+ matV->matrix[x][y] * matW->matrix[x][y];
+ }
+ }
+ return newMatrixObject(mat, rowSizeV, colSizeV);
+ }
+ else if (matW->flag == 0 && matV->flag == 0){ //true matrix multiplication
+ if(colSizeV != rowSizeW){
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "Matrix multiplication undefined...\n");
+ }
+
+ mat = PyMem_Malloc((rowSizeV * colSizeW) * sizeof(float));
+
+ for(x = 0; x < rowSizeV; x++){
+ for(y = 0; y < colSizeW; y++){
+ for(z = 0; z < colSizeV; z++){
+ dot += (matV->matrix[x][z] * matW->matrix[z][y]);
+ }
+ mat[((x * rowSizeV) + y)] = dot;
+ dot = 0;
+ }
+ }
+ return newMatrixObject(mat, rowSizeV, colSizeW);
+ }
+ else
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "Error in matrix_mul...\n");
+}
+
+//coercion of unknown types to type MatrixObject for numeric protocols
+int Matrix_coerce(PyObject **m1, PyObject **m2)
+{
+ long *tempI;
+ double *tempF;
+ float *mat;
+ int x, matSize;
+
+ matSize = (((MatrixObject*)*m1)->rowSize) * (((MatrixObject*)*m1)->rowSize);
+ if (Matrix_CheckPyObject(*m1)) {
+ if (Matrix_CheckPyObject(*m2)) { //matrix & matrix
+ Py_INCREF(*m1);
+ Py_INCREF(*m2);
+ return 0;
+ }else{
+ if(VectorObject_Check(*m2)){ //matrix & vector?
+ printf("use MatMultVec() for column vector multiplication\n");
+ Py_INCREF(*m1);
+ return 0;
+ }else if(PyNumber_Check(*m2)){ //& scalar?
+ if(PyInt_Check(*m2)){ //it's a int
+ tempI = PyMem_Malloc(1*sizeof(long));
+ *tempI = PyInt_AsLong(*m2);
+ mat = PyMem_Malloc (matSize * sizeof (float));
+ for(x = 0; x < matSize; x++){
+ mat[x] = (float)*tempI;
+ }
+ PyMem_Free(tempI);
+ *m2 = newMatrixObject(mat, (((MatrixObject*)*m1)->rowSize),
+ (((MatrixObject*)*m1)->colSize));
+ ((MatrixObject*)*m2)->flag = 1; //int coercion
+ PyMem_Free(mat);
+ Py_INCREF(*m1);
+ return 0;
+ }else if(PyFloat_Check(*m2)){ //it's a float
+ tempF = PyMem_Malloc(1*sizeof(double));
+ *tempF = PyFloat_AsDouble(*m2);
+ mat = PyMem_Malloc (matSize * sizeof (float));
+ for(x = 0; x < matSize; x++){
+ mat[x] = (float)*tempF;
+ }
+ PyMem_Free(tempF);
+ *m2 = newMatrixObject(mat, (((MatrixObject*)*m1)->rowSize),
+ (((MatrixObject*)*m1)->colSize));
+ ((MatrixObject*)*m2)->flag = 2; //float coercion
+ PyMem_Free(mat);
+ Py_INCREF(*m1);
+ return 0;
+ }
+ }
+ //unknom2n type or numeric cast failure
+ printf("attempting matrix operation m2ith unsupported type...\n");
+ Py_INCREF(*m1);
+ return 0; //operation m2ill type check
+ }
+ }else{
+ //1st not Matrix
+ printf("numeric protocol failure...\n");
+ return -1; //this should not occur - fail
+ }
+ return -1;
+}
+
+//******************************************************************
+// Matrix definition
+//******************************************************************
static PySequenceMethods Matrix_SeqMethods =
{
- (inquiry) 0, /*sq_length*/
- (binaryfunc) 0, /*sq_concat*/
- (intargfunc) 0, /*sq_repeat*/
- (intargfunc) Matrix_item, /*sq_item*/
- (intintargfunc) 0, /*sq_slice*/
- (intobjargproc) 0, /*sq_ass_item*/
- (intintobjargproc) 0, /*sq_ass_slice*/
+ (inquiry) Matrix_len, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) Matrix_item, /* sq_item */
+ (intintargfunc) Matrix_slice, /* sq_slice */
+ (intobjargproc) Matrix_ass_item, /* sq_ass_item */
+ (intintobjargproc) Matrix_ass_slice, /* sq_ass_slice */
};
-PyTypeObject Matrix_Type =
+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) 0, /* __invert__ */
+ (binaryfunc) 0, /* __lshift__ */
+ (binaryfunc) 0, /* __rshift__ */
+ (binaryfunc) 0, /* __and__ */
+ (binaryfunc) 0, /* __xor__ */
+ (binaryfunc) 0, /* __or__ */
+ (coercion) Matrix_coerce, /* __coerce__ */
+ (unaryfunc) 0, /* __int__ */
+ (unaryfunc) 0, /* __long__ */
+ (unaryfunc) 0, /* __float__ */
+ (unaryfunc) 0, /* __oct__ */
+ (unaryfunc) 0, /* __hex__ */
+};
+
+PyTypeObject matrix_Type =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Matrix", /*tp_name*/
sizeof(MatrixObject), /*tp_basicsize*/
0, /*tp_itemsize*/
- /* methods */
(destructor) Matrix_dealloc, /*tp_dealloc*/
(printfunc) 0, /*tp_print*/
(getattrfunc) Matrix_getattr, /*tp_getattr*/
(setattrfunc) Matrix_setattr, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc) Matrix_repr, /*tp_repr*/
- 0, /*tp_as_number*/
+ &Matrix_NumMethods, /*tp_as_number*/
&Matrix_SeqMethods, /*tp_as_sequence*/
};
-PyObject * newMatrixObject (float mat[][4])
+//******************************************************************
+//Function: newMatrixObject
+//******************************************************************
+PyObject * newMatrixObject (float * mat, int rowSize, int colSize)
{
MatrixObject * self;
+ float * contigPtr;
+ int row, col, x;
- self = PyObject_NEW (MatrixObject, &Matrix_Type);
- if (mat)
- {
- self->mem = NULL;
- self->mat = mat;
- }
- else
- {
- self->mem = PyMem_Malloc (4*4*sizeof (float));
- self->mat = self->mem;
- }
- self->rows[0] = newVectorObject ((float *)(self->mat[0]), 4);
- self->rows[1] = newVectorObject ((float *)(self->mat[1]), 4);
- self->rows[2] = newVectorObject ((float *)(self->mat[2]), 4);
- self->rows[3] = newVectorObject ((float *)(self->mat[3]), 4);
- if ((self->rows[0] == NULL) ||
- (self->rows[1] == NULL) ||
- (self->rows[2] == NULL) ||
- (self->rows[3] == NULL))
- {
- return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
- "Something wrong with creating a matrix object"));
+ if (rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4)
+ return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
+ "row and column sizes must be between 2 and 4\n"));
+
+ self = PyObject_NEW (MatrixObject, &matrix_Type);
+
+ //generate contigous memory space
+ contigPtr = PyMem_Malloc(rowSize * colSize* sizeof(float));
+ if(contigPtr == NULL){
+ return (EXPP_ReturnPyObjError (PyExc_MemoryError,
+ "problem allocating array space\n\n"));
+ }
+
+ //create pointer array
+ self->matrix = PyMem_Malloc(rowSize * sizeof(float*));
+ if(self->matrix == NULL){
+ return (EXPP_ReturnPyObjError (PyExc_MemoryError,
+ "problem allocating pointer space\n\n"));
+ }
+
+ //pointer array points to contigous memory
+ for (x = 0; x < rowSize; x++){
+ self->matrix[x] = contigPtr + (x * colSize);
}
+ 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{ //or if NULL passed
+ for (row = 0; row < rowSize; row++){
+ for (col = 0; col < colSize; col++){
+ self->matrix[row][col] = 0.0f;
+ }
+ }
+ }
+
+ //set size vars of matrix
+ self->rowSize = rowSize;
+ self->colSize = colSize;
+
+ //set coercion flag
+ self->flag = 0;
+
return ((PyObject *)self);
}
-void init_py_matrix (void)
-{
- Matrix_Type.ob_type = &PyType_Type;
-}
+
diff --git a/source/blender/python/api2_2x/matrix.h b/source/blender/python/api2_2x/matrix.h
new file mode 100644
index 00000000000..b7370179a74
--- /dev/null
+++ b/source/blender/python/api2_2x/matrix.h
@@ -0,0 +1,77 @@
+/*
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef EXPP_matrix_h
+#define EXPP_matrix_h
+
+#include "Python.h"
+#include "BLI_arithb.h"
+#include "vector.h"
+#include "gen_utils.h"
+#include "Types.h"
+#include "quat.h"
+#include "euler.h"
+
+#define Matrix_CheckPyObject(v) ((v)->ob_type == &matrix_Type)
+
+/*****************************/
+/* Matrix Python Object */
+/*****************************/
+typedef float **ptRow;
+
+typedef struct _Matrix {
+ PyObject_VAR_HEAD
+
+ ptRow matrix;
+ int rowSize;
+ int colSize;
+ int flag;
+ //0 - no coercion
+ //1 - coerced from int
+ //2 - coerced from float
+} MatrixObject;
+
+/*****************************************************************************/
+/* Python API function prototypes. */
+/*****************************************************************************/
+PyObject *newMatrixObject(float * mat, int rowSize, int colSize);
+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_Resize4x4(MatrixObject *self);
+PyObject *Matrix_toEuler(MatrixObject *self);
+PyObject *Matrix_toQuat(MatrixObject *self);
+
+#endif /* EXPP_matrix_H */
diff --git a/source/blender/python/api2_2x/modules.h b/source/blender/python/api2_2x/modules.h
index 899b368cdca..43a56f1379f 100644
--- a/source/blender/python/api2_2x/modules.h
+++ b/source/blender/python/api2_2x/modules.h
@@ -184,5 +184,7 @@ int Lattice_CheckPyObject (PyObject *pyobj);
PyObject * Window_Init (void);
PyObject * Draw_Init (void);
PyObject * BGL_Init (void);
+PyObject * Mathutils_Init (void);
+
#endif /* EXPP_modules_h */
diff --git a/source/blender/python/api2_2x/quat.c b/source/blender/python/api2_2x/quat.c
new file mode 100644
index 00000000000..3d785570027
--- /dev/null
+++ b/source/blender/python/api2_2x/quat.c
@@ -0,0 +1,504 @@
+/*
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "quat.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[] =
+"() - return a euler rotation representing the quaternion";
+char Quaternion_ToMatrix_doc[] =
+"() - return a rotation matrix representing the quaternion";
+
+//methods table
+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_NOARGS,
+ Quaternion_ToEuler_doc},
+ {"toMatrix",(PyCFunction)Quaternion_ToMatrix, METH_NOARGS,
+ Quaternion_ToMatrix_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*****************************/
+// Quaternion Python Object
+/*****************************/
+
+PyObject *Quaternion_ToEuler(QuaternionObject *self)
+{
+ float *eul;
+ int x;
+
+ eul = PyMem_Malloc(3*sizeof(float));
+ QuatToEul(self->quat, eul);
+
+ for(x = 0; x < 3; x++){
+ eul[x] *= (float)(180/Py_PI);
+ }
+ return (PyObject*)newEulerObject(eul);
+}
+
+PyObject *Quaternion_ToMatrix(QuaternionObject *self)
+{
+ float *mat;
+
+ mat = PyMem_Malloc(3*3*sizeof(float));
+ QuatToMat3(self->quat, (float(*)[3])mat);
+
+ return (PyObject*)newMatrixObject(mat, 3,3);
+}
+
+//normalize the axis of rotation of [theta,vector]
+PyObject *Quaternion_Normalize(QuaternionObject *self)
+{
+ NormalQuat(self->quat);
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Quaternion_Inverse(QuaternionObject *self)
+{
+ float 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 = (float)sqrt(mag);
+ for(x = 0; x < 4; x++){
+ self->quat[x] /= (mag * mag);
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+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;
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Quaternion_Negate(QuaternionObject *self)
+{
+ int x;
+
+ for(x = 0; x < 4; x++){
+ self->quat[x] = -self->quat[x];
+ }
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Quaternion_Conjugate(QuaternionObject *self)
+{
+ int x;
+
+ for(x = 1; x < 4; x++){
+ self->quat[x] = -self->quat[x];
+ }
+ return EXPP_incr_ret(Py_None);
+}
+
+static void Quaternion_dealloc(QuaternionObject *self)
+{
+ PyObject_DEL (self);
+}
+
+static PyObject *Quaternion_getattr(QuaternionObject *self, char *name)
+{
+ double mag = 0.0f;
+ float *vec;
+ int x;
+
+ if (ELEM4(name[0], 'w', 'x', 'y', 'z') && name[1]==0){
+ return PyFloat_FromDouble(self->quat[name[0]-'w']);
+ }
+ if(strcmp(name,"magnitude") == 0){
+ for(x = 0; x < 4; x++){
+ mag += self->quat[x] * self->quat[x];
+ }
+ mag = (float)sqrt(mag);
+ return PyFloat_FromDouble(mag);
+ }
+ if(strcmp(name,"angle") == 0){
+
+ mag = self->quat[0];
+ mag = 2 * (acos(mag));
+ mag *= (180/Py_PI);
+ return PyFloat_FromDouble(mag);
+ }
+ if(strcmp(name,"axis") == 0){
+
+ mag = (double)(self->quat[0] * (Py_PI/180));
+ mag = 2 * (acos(mag));
+ mag = sin(mag/2);
+ vec = PyMem_Malloc(3*sizeof(float));
+ for(x = 0; x < 3; x++){
+ vec[x] = (self->quat[x + 1]/((float)(mag)));
+ }
+ Normalise(vec);
+ return (PyObject*)newVectorObject(vec,3);
+ }
+ return Py_FindMethod(Quaternion_methods, (PyObject*)self, name);
+}
+
+static int Quaternion_setattr(QuaternionObject *self, char *name, PyObject *v)
+{
+ float val;
+
+ if(!PyFloat_Check(v) && !PyInt_Check(v)){
+ return EXPP_ReturnIntError(PyExc_TypeError,"int or float expected\n");
+ }else{
+ if (!PyArg_Parse(v, "f", &val))
+ return EXPP_ReturnIntError(PyExc_TypeError, "unable to parse float argument\n");
+ }
+ if (ELEM4(name[0], 'w', 'x', 'y', 'z') && name[1]==0){
+ self->quat[name[0]-'w']= val;
+ }else return -1;
+
+ return 0;
+}
+
+/* Quaternions Sequence methods */
+static PyObject *Quaternion_item(QuaternionObject *self, int i)
+{
+ if (i < 0 || i >= 4)
+ return EXPP_ReturnPyObjError (PyExc_IndexError, "array index out of range\n");
+
+ return Py_BuildValue("f", self->quat[i]);
+}
+
+static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end)
+{
+ PyObject *list;
+ int count;
+
+ if (begin < 0) begin= 0;
+ if (end > 4) end= 4;
+ if (begin > end) 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;
+}
+
+static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob)
+{
+ if (i < 0 || i >= 4)
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "array assignment index out of range\n");
+ if (!PyNumber_Check(ob))
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "Quaternion member must be a number\n");
+
+ if(!PyFloat_Check(ob) && !PyInt_Check(ob)){
+ return EXPP_ReturnIntError(PyExc_TypeError,"int or float expected\n");
+ }else{
+ self->quat[i]= (float)PyFloat_AsDouble(ob);
+ }
+ return 0;
+}
+
+static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq)
+{
+ int count, z;
+
+ if (begin < 0) begin= 0;
+ if (end > 4) end= 4;
+ if (begin > end) begin= end;
+
+ if (!PySequence_Check(seq))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "illegal argument type for built-in operation\n");
+ if (PySequence_Length(seq) != (end - begin))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "size mismatch in slice assignment\n");
+
+ z = 0;
+ for (count = begin; count < end; count++) {
+ PyObject *ob = PySequence_GetItem(seq, z); z++;
+
+ if(!PyFloat_Check(ob) && !PyInt_Check(ob)){
+ Py_DECREF(ob);
+ return -1;
+ }else{
+ if (!PyArg_Parse(ob, "f", &self->quat[count])) {
+ Py_DECREF(ob);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static PyObject *Quaternion_repr (QuaternionObject *self)
+{
+ int i, maxindex = 4 - 1;
+ char ftoa[24];
+ PyObject *str1, *str2;
+
+ str1 = PyString_FromString ("[");
+
+ for (i = 0; i < maxindex; i++) {
+ sprintf(ftoa, "%.4f, ", self->quat[i]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
+ }
+
+ sprintf(ftoa, "%.4f]\n", self->quat[maxindex]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
+
+ if (str1) return str1;
+
+error:
+ Py_XDECREF (str1);
+ Py_XDECREF (str2);
+ return EXPP_ReturnPyObjError (PyExc_MemoryError,
+ "couldn't create PyString!\n");
+}
+
+
+PyObject * Quaternion_add(PyObject *q1, PyObject *q2)
+{
+ float * quat;
+ int x;
+
+ if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((QuaternionObject*)q1)->flag > 0 || ((QuaternionObject*)q2)->flag > 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "cannot add a scalar and a quat\n");
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ for(x = 0; x < 4; x++){
+ quat[x] = (((QuaternionObject*)q1)->quat[x]) + (((QuaternionObject*)q2)->quat[x]);
+ }
+
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+PyObject * Quaternion_sub(PyObject *q1, PyObject *q2)
+{
+ float * quat;
+ int x;
+
+ if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((QuaternionObject*)q1)->flag > 0 || ((QuaternionObject*)q2)->flag > 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "cannot subtract a scalar and a quat\n");
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ for(x = 0; x < 4; x++){
+ quat[x] = (((QuaternionObject*)q1)->quat[x]) - (((QuaternionObject*)q2)->quat[x]);
+ }
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+PyObject * Quaternion_mul(PyObject *q1, PyObject * q2)
+{
+ float * quat;
+ int x;
+
+ if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((QuaternionObject*)q1)->flag == 0 && ((QuaternionObject*)q2)->flag == 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "please use the dot or cross product to multiply quaternions\n");
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ //scalar mult by quat
+ for(x = 0; x < 4; x++){
+ quat[x] = ((QuaternionObject*)q1)->quat[x] * ((QuaternionObject*)q2)->quat[x];
+ }
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+//coercion of unknown types to type QuaternionObject for numeric protocols
+int Quaternion_coerce(PyObject **q1, PyObject **q2)
+{
+ long *tempI;
+ double *tempF;
+ float *quat;
+ int x;
+
+ if (QuaternionObject_Check(*q1)) {
+ if (QuaternionObject_Check(*q2)) { //two Quaternions
+ Py_INCREF(*q1);
+ Py_INCREF(*q2);
+ return 0;
+ }else{
+ if(PyNumber_Check(*q2)){
+ if(PyInt_Check(*q2)){ //cast scalar to Quaternion
+ tempI = PyMem_Malloc(1*sizeof(long));
+ *tempI = PyInt_AsLong(*q2);
+ quat = PyMem_Malloc (4*sizeof (float));
+ for(x = 0; x < 4; x++){
+ quat[x] = (float)*tempI;
+ }
+ PyMem_Free(tempI);
+ *q2 = newQuaternionObject(quat);
+ ((QuaternionObject*)*q2)->flag = 1; //int coercion
+ Py_INCREF(*q1);
+ return 0;
+ }else if(PyFloat_Check(*q2)){ //cast scalar to Quaternion
+ tempF = PyMem_Malloc(1*sizeof(double));
+ *tempF = PyFloat_AsDouble(*q2);
+ quat = PyMem_Malloc (4*sizeof (float));
+ for(x = 0; x < 4; x++){
+ quat[x] = (float)*tempF;
+ }
+ PyMem_Free(tempF);
+ *q2 = newQuaternionObject(quat);
+ ((QuaternionObject*)*q2)->flag = 2; //float coercion
+ Py_INCREF(*q1);
+ return 0;
+ }
+ }
+ //unknown type or numeric cast failure
+ printf("attempting quaternion operation with unsupported type...\n");
+ Py_INCREF(*q1);
+ return 0; //operation will type check
+ }
+ }else{
+ printf("numeric protocol failure...\n");
+ return -1; //this should not occur - fail
+ }
+ return -1;
+}
+
+static PySequenceMethods Quaternion_SeqMethods =
+{
+ (inquiry) 0, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) Quaternion_item, /* sq_item */
+ (intintargfunc) Quaternion_slice, /* sq_slice */
+ (intobjargproc) Quaternion_ass_item, /* sq_ass_item */
+ (intintobjargproc) 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__ */
+ (coercion) Quaternion_coerce, /* __coerce__ */
+ (unaryfunc) 0, /* __int__ */
+ (unaryfunc) 0, /* __long__ */
+ (unaryfunc) 0, /* __float__ */
+ (unaryfunc) 0, /* __oct__ */
+ (unaryfunc) 0, /* __hex__ */
+
+};
+
+PyTypeObject quaternion_Type =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "quaternion", /*tp_name*/
+ sizeof(QuaternionObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) Quaternion_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) Quaternion_getattr, /*tp_getattr*/
+ (setattrfunc) Quaternion_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) Quaternion_repr, /*tp_repr*/
+ &Quaternion_NumMethods, /*tp_as_number*/
+ &Quaternion_SeqMethods, /*tp_as_sequence*/
+};
+
+PyObject *newQuaternionObject(float *quat)
+{
+ QuaternionObject *self;
+ int x;
+
+ quaternion_Type.ob_type = &PyType_Type;
+
+ self = PyObject_NEW(QuaternionObject, &quaternion_Type);
+
+ if(!quat){
+ self->quat = PyMem_Malloc (4 *sizeof (float));
+ for(x = 0; x < 4; x++){
+ self->quat[x] = 0.0f;
+ }
+ self->quat[3] = 1.0f;
+ }else{
+ self->quat = quat;
+ }
+ self->flag = 0;
+
+ return (PyObject*) self;
+}
+
diff --git a/source/blender/python/api2_2x/quat.h b/source/blender/python/api2_2x/quat.h
new file mode 100644
index 00000000000..586c8beba3e
--- /dev/null
+++ b/source/blender/python/api2_2x/quat.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef EXPP_quat_h
+#define EXPP_quat_h
+
+#include "Python.h"
+#include "gen_utils.h"
+#include "Types.h"
+#include <BLI_arithb.h>
+#include "euler.h"
+#include "matrix.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*****************************/
+// Quaternion Python Object
+/*****************************/
+
+#define QuaternionObject_Check(v) ((v)->ob_type == &quaternion_Type)
+
+typedef struct {
+ PyObject_VAR_HEAD
+ float * quat;
+ int flag;
+ //0 - no coercion
+ //1 - coerced from int
+ //2 - coerced from float
+} QuaternionObject;
+
+
+//prototypes
+PyObject *newQuaternionObject(float *quat);
+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 *Quaternion_ToMatrix(QuaternionObject *self);
+
+#endif /* EXPP_quat_h */
+
diff --git a/source/blender/python/api2_2x/vector.c b/source/blender/python/api2_2x/vector.c
index d08775aa6a7..efb13787204 100644
--- a/source/blender/python/api2_2x/vector.c
+++ b/source/blender/python/api2_2x/vector.c
@@ -1,5 +1,4 @@
-/*
- *
+ /*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -23,19 +22,162 @@
* All rights reserved.
*
*
- * Contributor(s): Willian P. Germano
+ * Contributor(s): Willian P. Germano & Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
-/* This file is the old bpython opy_vector.c with minor modifications */
-
#include "vector.h"
+//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]";
+
+//method table
+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},
+ {NULL, NULL, 0, NULL}
+};
+
/*****************************/
-/* Vector Python Object */
+// Vector Python Object
/*****************************/
-#define VectorObject_Check(v) ((v)->ob_type == &vector_Type)
+
+//object methods
+PyObject *Vector_Zero(VectorObject *self)
+{
+ int x;
+ for(x = 0; x < self->size; x++){
+ self->vec[x] = 0.0f;
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Vector_Normalize(VectorObject *self)
+{
+ float norm;
+ int x;
+
+ norm = 0.0f;
+ for(x = 0; x < self->size; x++){
+ norm += self->vec[x] * self->vec[x];
+ }
+ norm = (float)sqrt(norm);
+ for(x = 0; x < self->size; x++){
+ self->vec[x] /= norm;
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Vector_Negate(VectorObject *self)
+{
+ int x;
+ for(x = 0; x < self->size; x++){
+ self->vec[x] = -(self->vec[x]);
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Vector_Resize2D(VectorObject *self)
+{
+ float x, y;
+
+ if(self->size == 4 || self->size == 3){
+ x = self->vec[0];
+ y = self->vec[1];
+ PyMem_Free(self->vec);
+ self->vec = PyMem_Malloc(2*sizeof (float));
+ self->vec[0] = x;
+ self->vec[1] = y;
+ self->size = 2;
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Vector_Resize3D(VectorObject *self)
+{
+ float x, y, z;
+
+ if(self->size == 2){
+ x = self->vec[0];
+ y = self->vec[1];
+ PyMem_Free(self->vec);
+ self->vec = PyMem_Malloc(3*sizeof (float));
+ self->vec[0] = x;
+ self->vec[1] = y;
+ self->vec[2] = 0.0f;
+ self->size = 3;
+ }
+ else if (self->size == 4){
+ x = self->vec[0];
+ y = self->vec[1];
+ z = self->vec[2];
+ PyMem_Free(self->vec);
+ self->vec = PyMem_Malloc(3*sizeof (float));
+ self->vec[0] = x;
+ self->vec[1] = y;
+ self->vec[2] = z;
+ self->size = 3;
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Vector_Resize4D(VectorObject *self)
+{
+ float x, y, z;
+
+ if(self->size == 2){
+ x = self->vec[0];
+ y = self->vec[1];
+ PyMem_Free(self->vec);
+ self->vec = PyMem_Malloc(4*sizeof (float));
+ self->vec[0] = x;
+ self->vec[1] = y;
+ self->vec[2] = 0.0f;
+ self->vec[3] = 1.0f;
+ self->size = 4;
+ }
+ else if (self->size == 3){
+ x = self->vec[0];
+ y = self->vec[1];
+ z = self->vec[2];
+ PyMem_Free(self->vec);
+ self->vec = PyMem_Malloc(4*sizeof (float));
+ self->vec[0] = x;
+ self->vec[1] = y;
+ self->vec[2] = z;
+ self->vec[3] = 1.0f;
+ self->size = 4;
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
static void Vector_dealloc(VectorObject *self)
{
@@ -44,144 +186,374 @@ static void Vector_dealloc(VectorObject *self)
static PyObject *Vector_getattr(VectorObject *self, char *name)
{
- if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0)
- return PyFloat_FromDouble(self->vec[ name[0]-'x' ]);
-
- return EXPP_ReturnPyObjError(PyExc_AttributeError, "attribute not found");
+ if (self->size==4 && ELEM4(name[0], 'x', 'y', 'z', 'w') && name[1]==0){
+ if ((name[0]) == ('w')){
+ return PyFloat_FromDouble(self->vec[3]);
+ }else{
+ return PyFloat_FromDouble(self->vec[name[0]-'x']);
+ }
+ }
+ else if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0)
+ return PyFloat_FromDouble(self->vec[name[0]-'x']);
+ else if (self->size==2 && ELEM(name[0], 'x', 'y') && name[1]==0)
+ return PyFloat_FromDouble(self->vec[name[0]-'x']);
+
+ if ((strcmp(name,"length") == 0)){
+ if(self->size == 4){
+ return PyFloat_FromDouble(sqrt(self->vec[0] * self->vec[0] +
+ self->vec[1] * self->vec[1] +
+ self->vec[2] * self->vec[2] +
+ self->vec[3] * self->vec[3]));
+ }
+ else if(self->size == 3){
+ return PyFloat_FromDouble(sqrt(self->vec[0] * self->vec[0] +
+ self->vec[1] * self->vec[1] +
+ self->vec[2] * self->vec[2]));
+ }else if (self->size == 2){
+ return PyFloat_FromDouble(sqrt(self->vec[0] * self->vec[0] +
+ self->vec[1] * self->vec[1]));
+ }else EXPP_ReturnPyObjError(PyExc_AttributeError,
+ "can only return the length of a 2D ,3D or 4D vector\n");
+ }
+
+ return Py_FindMethod(Vector_methods, (PyObject*)self, name);
}
static int Vector_setattr(VectorObject *self, char *name, PyObject *v)
{
- float val;
-
- if (!PyArg_Parse(v, "f", &val))
- return EXPP_ReturnIntError(PyExc_TypeError,
- "expected float argument");
-
- if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0)
- self->vec[ name[0]-'x' ]= val;
- else
- return -1;
-
- return 0;
+ float val;
+ int valTemp;
+
+ if(!PyFloat_Check(v)){
+ if(!PyInt_Check(v)){
+ return EXPP_ReturnIntError(PyExc_TypeError,"int or float expected\n");
+ }else{
+ if (!PyArg_Parse(v, "i", &valTemp))
+ return EXPP_ReturnIntError(PyExc_TypeError, "unable to parse int argument\n");
+ val = (float)valTemp;
+ }
+ }else{
+ if (!PyArg_Parse(v, "f", &val))
+ return EXPP_ReturnIntError(PyExc_TypeError, "unable to parse float argument\n");
+ }
+ if (self->size==4 && ELEM4(name[0], 'x', 'y', 'z', 'w') && name[1]==0){
+ if ((name[0]) == ('w')){
+ self->vec[3]= val;
+ }else{
+ self->vec[name[0]-'x']= val;
+ }
+ }
+ else if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0)
+ self->vec[name[0]-'x']= val;
+ else if (self->size==2 && ELEM(name[0], 'x', 'y') && name[1]==0)
+ self->vec[name[0]-'x']= val;
+ else return -1;
+
+ return 0;
}
/* Vectors Sequence methods */
-
static int Vector_len(VectorObject *self)
{
- return self->size;
+ return self->size;
}
static PyObject *Vector_item(VectorObject *self, int i)
{
- if (i < 0 || i >= self->size)
- return EXPP_ReturnPyObjError (PyExc_IndexError,
- "array index out of range");
+ if (i < 0 || i >= self->size)
+ return EXPP_ReturnPyObjError (PyExc_IndexError, "array index out of range\n");
+
+ return Py_BuildValue("f", self->vec[i]);
- return Py_BuildValue("f", self->vec[i]);
}
static PyObject *Vector_slice(VectorObject *self, int begin, int end)
{
- PyObject *list;
- int count;
+ PyObject *list;
+ int count;
- if (begin < 0) begin= 0;
- if (end > self->size) end= self->size;
- if (begin > end) begin= end;
+ if (begin < 0) begin= 0;
+ if (end > self->size) end= self->size;
+ if (begin > end) begin= end;
- list= PyList_New(end-begin);
+ list= PyList_New(end-begin);
- for (count = begin; count < end; count++)
- PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->vec[count]));
+ for (count = begin; count < end; count++){
+ PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->vec[count]));
+ }
- return list;
+ return list;
}
static int Vector_ass_item(VectorObject *self, int i, PyObject *ob)
{
- if (i < 0 || i >= self->size)
- return EXPP_ReturnIntError(PyExc_IndexError,
- "array assignment index out of range");
+ if (i < 0 || i >= self->size)
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "array assignment index out of range\n");
+ if (!PyInt_Check(ob) && !PyFloat_Check(ob))
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "vector member must be a number\n");
- if (!PyNumber_Check(ob))
- return EXPP_ReturnIntError(PyExc_IndexError,
- "vector member must be a number");
+ self->vec[i]= (float)PyFloat_AsDouble(ob);
- self->vec[i]= PyFloat_AsDouble(ob);
-
- return 0;
+ return 0;
}
static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
{
- int count;
-
- if (begin < 0) begin= 0;
- if (end > self->size) end= self->size;
- if (begin > end) begin= end;
-
- if (!PySequence_Check(seq))
- return EXPP_ReturnIntError(PyExc_TypeError,
- "illegal argument type for built-in operation");
-
- if (PySequence_Length(seq) != (end - begin))
- return EXPP_ReturnIntError(PyExc_TypeError,
- "size mismatch in slice assignment");
-
- for (count = begin; count < end; count++) {
- PyObject *ob = PySequence_GetItem(seq, count);
-
- if (!PyArg_Parse(ob, "f", &self->vec[count])) {
- Py_DECREF(ob);
- return -1;
- }
-
- Py_DECREF(ob);
- }
+ int count, z;
+
+ if (begin < 0) begin= 0;
+ if (end > self->size) end= self->size;
+ if (begin > end) begin= end;
+
+ if (!PySequence_Check(seq))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "illegal argument type for built-in operation\n");
+ if (PySequence_Length(seq) != (end - begin))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "size mismatch in slice assignment\n");
+
+ z = 0;
+ for (count = begin; count < end; count++) {
+ PyObject *ob = PySequence_GetItem(seq, z); z++;
+ if (!PyInt_Check(ob) && !PyFloat_Check(ob))
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "list member must be a number\n");
+
+ if (!PyArg_Parse(ob, "f", &self->vec[count])){
+ Py_DECREF(ob);
+ return -1;
+ }
+ }
return 0;
}
static PyObject *Vector_repr (VectorObject *self)
{
- int i, maxindex = self->size - 1;
- char ftoa[24];
- PyObject *str1, *str2;
+ int i, maxindex = self->size - 1;
+ char ftoa[24];
+ PyObject *str1, *str2;
- str1 = PyString_FromString ("[");
+ str1 = PyString_FromString ("[");
- for (i = 0; i < maxindex; i++) {
- sprintf(ftoa, "%.3f, ", self->vec[i]);
- str2 = PyString_FromString (ftoa);
- if (!str1 || !str2) goto error; /* my first goto : ) */
- PyString_ConcatAndDel (&str1, str2);
- }
+ for (i = 0; i < maxindex; i++) {
+ sprintf(ftoa, "%.4f, ", self->vec[i]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
+ }
- sprintf(ftoa, "%.3f]\n", self->vec[maxindex]);
- str2 = PyString_FromString (ftoa);
- if (!str1 || !str2) goto error; /* uh-oh, became a habit */
- PyString_ConcatAndDel (&str1, str2);
+ sprintf(ftoa, "%.4f]\n", self->vec[maxindex]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
- if (str1) return str1;
+ if (str1) return str1;
error:
- Py_XDECREF (str1);
- Py_XDECREF (str2);
- return EXPP_ReturnPyObjError (PyExc_MemoryError,
- "couldn't create PyString!");
+ Py_XDECREF (str1);
+ Py_XDECREF (str2);
+ return EXPP_ReturnPyObjError (PyExc_MemoryError,
+ "couldn't create PyString!\n");
+}
+
+
+PyObject * Vector_add(PyObject *v1, PyObject *v2)
+{
+ float * vec;
+ int x;
+
+ if((!VectorObject_Check(v1)) || (!VectorObject_Check(v2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((VectorObject*)v1)->flag != 0 || ((VectorObject*)v2)->flag != 0)
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "cannot add a scalar to a vector\n");
+ if(((VectorObject*)v1)->size != ((VectorObject*)v2)->size)
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "vectors must have the same dimensions for this operation\n");
+
+ vec = PyMem_Malloc ((((VectorObject*)v1)->size)*sizeof (float));
+
+ for(x = 0; x < ((VectorObject*)v1)->size; x++){
+ vec[x] = ((VectorObject*)v1)->vec[x] + ((VectorObject*)v2)->vec[x];
+ }
+
+ return (PyObject*)newVectorObject(vec, (((VectorObject*)v1)->size));
+}
+
+PyObject * Vector_sub(PyObject *v1, PyObject *v2)
+{
+ float * vec;
+ int x;
+
+ if((!VectorObject_Check(v1)) || (!VectorObject_Check(v2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((VectorObject*)v1)->flag != 0 || ((VectorObject*)v2)->flag != 0)
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "cannot subtract a scalar from a vector\n");
+ if(((VectorObject*)v1)->size != ((VectorObject*)v2)->size)
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "vectors must have the same dimensions for this operation\n");
+
+ vec = PyMem_Malloc ((((VectorObject*)v1)->size)*sizeof (float));
+
+ for(x = 0; x < ((VectorObject*)v1)->size; x++){
+ vec[x] = ((VectorObject*)v1)->vec[x] - ((VectorObject*)v2)->vec[x];
+ }
+
+ return (PyObject*)newVectorObject(vec, (((VectorObject*)v1)->size));
+}
+
+PyObject * Vector_mul(PyObject *v1, PyObject * v2)
+{
+ float * vec;
+ int x;
+
+ if((!VectorObject_Check(v1)) || (!VectorObject_Check(v2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((VectorObject*)v1)->flag == 0 && ((VectorObject*)v2)->flag == 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "please use the dot product or the cross product to multiply vectors\n");
+ if(((VectorObject*)v1)->size != ((VectorObject*)v2)->size)
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "vector dimension error during Vector_mul\n");
+
+ vec = PyMem_Malloc ((((VectorObject*)v1)->size)*sizeof(float));
+
+ for(x = 0; x < ((VectorObject*)v1)->size; x++){
+ vec[x] = ((VectorObject*)v1)->vec[x] * ((VectorObject*)v2)->vec[x];
+ }
+
+ return (PyObject*)newVectorObject(vec, (((VectorObject*)v1)->size));
+}
+
+PyObject * Vector_div(PyObject *v1, PyObject * v2)
+{
+ float * vec;
+ int x;
+
+ if((!VectorObject_Check(v1)) || (!VectorObject_Check(v2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((VectorObject*)v1)->flag == 0 && ((VectorObject*)v2)->flag == 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "cannot divide two vectors\n");
+ if(((VectorObject*)v1)->flag != 0 && ((VectorObject*)v2)->flag == 0)
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "cannot divide a scalar by a vector\n");
+ if(((VectorObject*)v1)->size != ((VectorObject*)v2)->size)
+ return EXPP_ReturnPyObjError (PyExc_AttributeError,
+ "vector dimension error during Vector_mul\n");
+
+ vec = PyMem_Malloc ((((VectorObject*)v1)->size)*sizeof(float));
+
+ for(x = 0; x < ((VectorObject*)v1)->size; x++){
+ vec[x] = ((VectorObject*)v1)->vec[x] / ((VectorObject*)v2)->vec[x];
+ }
+
+ return (PyObject*)newVectorObject(vec, (((VectorObject*)v1)->size));
}
+//coercion of unknown types to type VectorObject for numeric protocols
+int Vector_coerce(PyObject **v1, PyObject **v2)
+{
+ long *tempI;
+ double *tempF;
+ float *vec;
+ int x;
+
+ if (VectorObject_Check(*v1)) {
+ if (VectorObject_Check(*v2)) { //two vectors
+ Py_INCREF(*v1);
+ Py_INCREF(*v2);
+ return 0;
+ }else{
+ if(Matrix_CheckPyObject(*v2)){
+ printf("vector/matrix numeric protocols unsupported...\n");
+ Py_INCREF(*v1);
+ return 0; //operation will type check
+ }else if(PyNumber_Check(*v2)){
+ if(PyInt_Check(*v2)){ //cast scalar to vector
+ tempI = PyMem_Malloc(1*sizeof(long));
+ *tempI = PyInt_AsLong(*v2);
+ vec = PyMem_Malloc ((((VectorObject*)*v1)->size)*sizeof (float));
+ for(x = 0; x < (((VectorObject*)*v1)->size); x++){
+ vec[x] = (float)*tempI;
+ }
+ PyMem_Free(tempI);
+ *v2 = newVectorObject(vec, (((VectorObject*)*v1)->size));
+ ((VectorObject*)*v2)->flag = 1; //int coercion
+ Py_INCREF(*v1);
+ return 0;
+ }else if(PyFloat_Check(*v2)){ //cast scalar to vector
+ tempF = PyMem_Malloc(1*sizeof(double));
+ *tempF = PyFloat_AsDouble(*v2);
+ vec = PyMem_Malloc ((((VectorObject*)*v1)->size)*sizeof (float));
+ for(x = 0; x < (((VectorObject*)*v1)->size); x++){
+ vec[x] = (float)*tempF;
+ }
+ PyMem_Free(tempF);
+ *v2 = newVectorObject(vec, (((VectorObject*)*v1)->size));
+ ((VectorObject*)*v2)->flag = 2; //float coercion
+ Py_INCREF(*v1);
+ return 0;
+ }
+ }
+ //unknown type or numeric cast failure
+ printf("attempting vector operation with unsupported type...\n");
+ Py_INCREF(*v1);
+ return 0; //operation will type check
+ }
+ }else{
+ printf("numeric protocol failure...\n");
+ return -1; //this should not occur - fail
+ }
+ return -1;
+}
+
+
static PySequenceMethods Vector_SeqMethods =
{
- (inquiry) Vector_len, /* sq_length */
- (binaryfunc) 0, /* sq_concat */
- (intargfunc) 0, /* sq_repeat */
- (intargfunc) Vector_item, /* sq_item */
- (intintargfunc) Vector_slice, /* sq_slice */
- (intobjargproc) Vector_ass_item, /* sq_ass_item */
- (intintobjargproc) Vector_ass_slice, /* sq_ass_slice */
+ (inquiry) Vector_len, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) Vector_item, /* sq_item */
+ (intintargfunc) Vector_slice, /* sq_slice */
+ (intobjargproc) Vector_ass_item, /* sq_ass_item */
+ (intintobjargproc) Vector_ass_slice, /* sq_ass_slice */
+};
+
+static PyNumberMethods Vector_NumMethods =
+{
+ (binaryfunc) Vector_add, /* __add__ */
+ (binaryfunc) Vector_sub, /* __sub__ */
+ (binaryfunc) Vector_mul, /* __mul__ */
+ (binaryfunc) Vector_div, /* __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__ */
+ (coercion) Vector_coerce, /* __coerce__ */
+ (unaryfunc) 0, /* __int__ */
+ (unaryfunc) 0, /* __long__ */
+ (unaryfunc) 0, /* __float__ */
+ (unaryfunc) 0, /* __oct__ */
+ (unaryfunc) 0, /* __hex__ */
+
};
PyTypeObject vector_Type =
@@ -191,27 +563,38 @@ PyTypeObject vector_Type =
"vector", /*tp_name*/
sizeof(VectorObject), /*tp_basicsize*/
0, /*tp_itemsize*/
- /* methods */
(destructor) Vector_dealloc, /*tp_dealloc*/
(printfunc) 0, /*tp_print*/
(getattrfunc) Vector_getattr, /*tp_getattr*/
(setattrfunc) Vector_setattr, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc) Vector_repr, /*tp_repr*/
- 0, /*tp_as_number*/
+ &Vector_NumMethods, /*tp_as_number*/
&Vector_SeqMethods, /*tp_as_sequence*/
};
PyObject *newVectorObject(float *vec, int size)
{
VectorObject *self;
+ int x;
vector_Type.ob_type = &PyType_Type;
self = PyObject_NEW(VectorObject, &vector_Type);
- self->vec = vec;
+ if(!vec){
+ self->vec = PyMem_Malloc (size *sizeof (float));
+ for(x = 0; x < size; x++){
+ self->vec[x] = 0.0f;
+ }
+ if(size == 4) self->vec[3] = 1.0f;
+ }else{
+ self->vec = vec;
+ }
+
self->size = size;
+ self->flag = 0;
return (PyObject*) self;
}
+
diff --git a/source/blender/python/api2_2x/vector.h b/source/blender/python/api2_2x/vector.h
index 2e0250c3a07..f8ad164543b 100644
--- a/source/blender/python/api2_2x/vector.h
+++ b/source/blender/python/api2_2x/vector.h
@@ -1,7 +1,3 @@
-
-
-/* Matrix and vector objects in Python */
-
/* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
@@ -28,7 +24,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Willian P. Germano
+ * Contributor(s): Willian P. Germano & Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*
@@ -38,42 +34,39 @@
#define EXPP_vector_h
#include "Python.h"
-
-#include "BKE_utildefines.h"
-
#include "gen_utils.h"
-#include "vector.h"
+#include "Types.h"
+#include "matrix.h"
+#include "BKE_utildefines.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/*****************************/
-/* Matrix Python Object */
+// Vector Python Object
/*****************************/
-/* temporar hack for typecasts */
-typedef float (*Matrix4Ptr)[4];
+#define VectorObject_Check(v) ((v)->ob_type == &vector_Type)
typedef struct {
PyObject_VAR_HEAD
- float *vec;
+ float * vec;
int size;
-
+ int flag;
+ //0 - no coercion
+ //1 - coerced from int
+ //2 - coerced from float
} VectorObject;
-typedef struct {
- PyObject_VAR_HEAD
- PyObject *rows[4];
- Matrix4Ptr mat;
- Matrix4Ptr mem;
-} MatrixObject;
-
-
-/* PROTOS */
-
+//prototypes
PyObject *newVectorObject(float *vec, int size);
-PyObject *newMatrixObject(float mat[][4]);
-void init_py_matrix(void);
+PyObject *Vector_Zero(VectorObject *self);
+PyObject *Vector_Normalize(VectorObject *self);
+PyObject *Vector_Negate(VectorObject *self);
+PyObject *Vector_Resize2D(VectorObject *self);
+PyObject *Vector_Resize3D(VectorObject *self);
+PyObject *Vector_Resize4D(VectorObject *self);
#endif /* EXPP_vector_h */
+