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
This commit is contained in:
Joseph Gilbert 2004-02-29 13:20:34 +00:00
parent 2255ac3b19
commit 8f3a9815ba
19 changed files with 3770 additions and 214 deletions

@ -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());

File diff suppressed because it is too large Load Diff

@ -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 */

@ -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)

@ -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;

@ -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;

@ -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 */

@ -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,

@ -52,6 +52,7 @@
#include "gen_utils.h"
#include "modules.h"
#include "matrix.h"
/* Used in Draw.c */
extern int EXPP_disable_force_draw;

@ -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;
}

@ -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 */

@ -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);

@ -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";
//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)
{
float *quat, *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];
}
quat = PyMem_Malloc(4*sizeof(float));
Mat3ToQuat((float(*)[3])mat,quat);
return (PyObject*)newQuaternionObject(quat);
}
PyObject *Matrix_toEuler(MatrixObject *self)
{
float *eul, *mat;
int x;
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);
}
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)
{
Py_DECREF (self->rows[0]);
Py_DECREF (self->rows[1]);
Py_DECREF (self->rows[2]);
Py_DECREF (self->rows[3]);
if (self->mem)
PyMem_Free (self->mem);
PyMem_Free (self->matrix);
PyMem_DEL (self);
}
static PyObject * Matrix_getattr (MatrixObject *self, char *name)
{
PyObject * list;
float val[3];
float mat3[3][3];
if (strcmp (name, "rot") == 0)
{
Mat3CpyMat4 (mat3, self->mat);
Mat3ToEul (mat3, val);
if (strcmp (name, "rowSize") == 0){
return PyInt_FromLong((long)self->rowSize);
}
else if (strcmp (name, "size") == 0)
{
Mat4ToSize (self->mat, val);
}
else if (strcmp (name, "loc") == 0)
{
VECCOPY (val, (float *)(self->mat)[3]);
}
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;
}

@ -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 */

@ -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 */

@ -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;
}

@ -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 */

@ -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' ]);
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']);
return EXPP_ReturnPyObjError(PyExc_AttributeError, "attribute not found");
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");
float val;
int valTemp;
if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0)
self->vec[ name[0]-'x' ]= val;
else
return -1;
return 0;
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;
int count, z;
if (!PySequence_Check(seq))
return EXPP_ReturnIntError(PyExc_TypeError,
"illegal argument type for built-in operation");
if (begin < 0) begin= 0;
if (end > self->size) end= self->size;
if (begin > end) begin= end;
if (PySequence_Length(seq) != (end - begin))
return EXPP_ReturnIntError(PyExc_TypeError,
"size mismatch in slice assignment");
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");
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);
}
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;
}

@ -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 */