svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2.5/blender
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: BPY_extern.h 12334 2007-10-21 23:00:29Z aligorith $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -50,6 +50,8 @@ struct bConstraintTarget; /* DNA_constraint_types.h*/
|
||||
struct Script; /* DNA_screen_types.h */
|
||||
struct BPyMenu;
|
||||
struct bContext;
|
||||
struct ReportList;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* $Id: BPY_menus.h 12931 2007-12-17 18:20:48Z theeth $
|
||||
*
|
||||
* ***** 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): Willian P. Germano, Matt Ebb
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef BPY_MENUS_H
|
||||
#define BPY_MENUS_H
|
||||
|
||||
/* This header exposes BPyMenu related public declarations. The implementation
|
||||
* adds 'dynamic' menus to Blender, letting scripts register themselves in any
|
||||
* of a few pre-defined (trivial to upgrade) places in menus. These places or
|
||||
* slots are called groups here (Import, Export, etc). This is how it works:
|
||||
* - scripts at dirs user pref U.pythondir and .blender/scripts/ are scanned
|
||||
* for registration info.
|
||||
* - this data is also saved to a Bpymenus file at the user's .blender/ dir and
|
||||
* only re-created when the scripts folder gets modified.
|
||||
* - on start-up Blender uses this info to fill a table, which is used to
|
||||
* create the menu entries when they are needed (see header_info.c or
|
||||
* header_script.c, under source/blender/src/, for examples).
|
||||
*/
|
||||
|
||||
/* These two structs hold py menu/submenu info.
|
||||
* BPyMenu holds a script's name (as should appear in the menu) and filename,
|
||||
* plus an optional list of submenus. Each submenu is related to a string
|
||||
* (arg) that the script can get from the __script__ pydict, to know which
|
||||
* submenu was chosen. */
|
||||
|
||||
typedef struct BPySubMenu {
|
||||
char *name;
|
||||
char *arg;
|
||||
struct BPySubMenu *next;
|
||||
} BPySubMenu;
|
||||
|
||||
typedef struct BPyMenu {
|
||||
char *name;
|
||||
char *filename;
|
||||
char *tooltip;
|
||||
short version; /* Blender version */
|
||||
int dir; /* 0: default, 1: U.pythondir */
|
||||
struct BPySubMenu *submenus;
|
||||
struct BPyMenu *next;
|
||||
} BPyMenu;
|
||||
|
||||
/* Scripts can be added to only a few pre-defined places in menus, like
|
||||
* File->Import, File->Export, etc. (for speed and better control).
|
||||
* To make a new menu 'slot' available for scripts:
|
||||
* - add an entry to the enum below, before PYMENU_TOTAL, of course;
|
||||
* - update the bpymenu_group_atoi() and BPyMenu_group_itoa() functions in
|
||||
* BPY_menus.c;
|
||||
* - add the necessary code to the header_***.c file in
|
||||
* source/blender/src/, like done in header_info.c for import/export;
|
||||
*/
|
||||
typedef enum {
|
||||
PYMENU_ADD,/* creates new objects */
|
||||
PYMENU_ANIMATION,
|
||||
PYMENU_EXPORT,
|
||||
PYMENU_IMPORT,
|
||||
PYMENU_MATERIALS,
|
||||
PYMENU_MESH,
|
||||
PYMENU_MISC,
|
||||
PYMENU_OBJECT,
|
||||
PYMENU_RENDER,/* exporters to external renderers */
|
||||
PYMENU_SYSTEM,
|
||||
PYMENU_THEMES,
|
||||
PYMENU_UV,/* UV editing tools, to go in UV/Image editor space, 'UV' menu */
|
||||
PYMENU_IMAGE,/* Image editing tools, to go in UV/Image editor space, 'Image' menu */
|
||||
PYMENU_WIZARDS,/* complex 'app' scripts */
|
||||
|
||||
/* entries put after Wizards don't appear at the Scripts win->Scripts menu;
|
||||
* see define right below */
|
||||
|
||||
PYMENU_FACESELECT,
|
||||
PYMENU_WEIGHTPAINT,
|
||||
PYMENU_VERTEXPAINT,
|
||||
PYMENU_UVCALCULATION,
|
||||
PYMENU_ARMATURE,
|
||||
PYMENU_SCRIPTTEMPLATE,
|
||||
PYMENU_HELP,/*Main Help menu items - prob best to leave for 'official' ones*/
|
||||
PYMENU_HELPSYSTEM,/* Resources, troubleshooting, system tools */
|
||||
PYMENU_HELPWEBSITES,/* Help -> Websites submenu */
|
||||
PYMENU_MESHFACEKEY, /* face key in mesh editmode */
|
||||
PYMENU_ADDMESH, /* adds mesh */
|
||||
PYMENU_TOTAL
|
||||
} PYMENUHOOKS;
|
||||
|
||||
#define PYMENU_SCRIPTS_MENU_TOTAL (PYMENU_WIZARDS + 1)
|
||||
|
||||
/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
|
||||
* where they can appear (see PYMENUHOOKS enum above).
|
||||
*/
|
||||
extern BPyMenu *BPyMenuTable[]; /* defined in BPY_menus.c */
|
||||
|
||||
/* public functions: */
|
||||
int BPyMenu_Init( int usedir );
|
||||
void BPyMenu_RemoveAllEntries( void );
|
||||
void BPyMenu_PrintAllEntries( void );
|
||||
char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short group );
|
||||
char *BPyMenu_group_itoa( short group );
|
||||
struct BPyMenu *BPyMenu_GetEntry( short group, short pos );
|
||||
|
||||
#endif /* BPY_MENUS_H */
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $
|
||||
# $Id$
|
||||
#
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: BGL.c 20922 2009-06-16 07:16:51Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -83,8 +83,13 @@ static PyObject *Buffer_getattr( PyObject * self, char *name );
|
||||
static PyObject *Buffer_repr( PyObject * self );
|
||||
|
||||
PyTypeObject buffer_Type = {
|
||||
PyObject_HEAD_INIT( NULL ) /* required python macro */
|
||||
0, /*ob_size */
|
||||
#if (PY_VERSION_HEX >= 0x02060000)
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
#else
|
||||
/* python 2.5 and below */
|
||||
PyObject_HEAD_INIT( NULL ) /* required py macro */
|
||||
0, /* ob_size */
|
||||
#endif
|
||||
"buffer", /*tp_name */
|
||||
sizeof( Buffer ), /*tp_basicsize */
|
||||
0, /*tp_itemsize */
|
||||
@@ -1087,7 +1092,7 @@ static struct PyMethodDef BGL_methods[] = {
|
||||
|
||||
#if (PY_VERSION_HEX >= 0x03000000)
|
||||
static struct PyModuleDef BGL_module_def = {
|
||||
{}, /* m_base */
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"BGL", /* m_name */
|
||||
0, /* m_doc */
|
||||
0, /* m_size */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: BGL.h 19717 2009-04-14 17:19:09Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: Geometry.c 20922 2009-06-16 07:16:51Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -80,7 +80,7 @@ struct PyMethodDef M_Geometry_methods[] = {
|
||||
|
||||
#if (PY_VERSION_HEX >= 0x03000000)
|
||||
static struct PyModuleDef M_Geometry_module_def = {
|
||||
{}, /* m_base */
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"Geometry", /* m_name */
|
||||
M_Geometry_doc, /* m_doc */
|
||||
0, /* m_size */
|
||||
@@ -164,6 +164,10 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
|
||||
for( index = 0; index<len_polypoints; ++index, fp+=3) {
|
||||
polyVec= PySequence_GetItem( polyLine, index );
|
||||
if(VectorObject_Check(polyVec)) {
|
||||
|
||||
if(!BaseMath_ReadCallback((VectorObject *)polyVec))
|
||||
ls_error= 1;
|
||||
|
||||
fp[0] = ((VectorObject *)polyVec)->vec[0];
|
||||
fp[1] = ((VectorObject *)polyVec)->vec[1];
|
||||
if( ((VectorObject *)polyVec)->size > 2 )
|
||||
@@ -234,6 +238,9 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(line_a1) || !BaseMath_ReadCallback(line_a2) || !BaseMath_ReadCallback(line_b1) || !BaseMath_ReadCallback(line_b2))
|
||||
return NULL;
|
||||
|
||||
a1x= line_a1->vec[0];
|
||||
a1y= line_a1->vec[1];
|
||||
a2x= line_a2->vec[0];
|
||||
@@ -266,7 +273,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
|
||||
/*X of vert, Y of hoz. no calculation needed */
|
||||
newvec[0]= a1x;
|
||||
newvec[1]= b1y;
|
||||
return newVectorObject(newvec, 2, Py_NEW);
|
||||
return newVectorObject(newvec, 2, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
yi = (float)(((b1y / fabs(b1x - b2x)) * fabs(b2x - a1x)) + ((b2y / fabs(b1x - b2x)) * fabs(b1x - a1x)));
|
||||
@@ -278,7 +285,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
|
||||
}
|
||||
newvec[0]= a1x;
|
||||
newvec[1]= yi;
|
||||
return newVectorObject(newvec, 2, Py_NEW);
|
||||
return newVectorObject(newvec, 2, Py_NEW, NULL);
|
||||
} else if (fabs(a2y-a1y) < eul) { /* hoz line1 */
|
||||
if (fabs(b2y-b1y) < eul) { /*hoz line2*/
|
||||
Py_RETURN_NONE; /*2 hoz lines dont intersect*/
|
||||
@@ -293,7 +300,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
|
||||
}
|
||||
newvec[0]= xi;
|
||||
newvec[1]= a1y;
|
||||
return newVectorObject(newvec, 2, Py_NEW);
|
||||
return newVectorObject(newvec, 2, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
b1 = (a2y-a1y)/(a2x-a1x);
|
||||
@@ -310,7 +317,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
|
||||
if ((a1x-xi)*(xi-a2x) >= 0 && (b1x-xi)*(xi-b2x) >= 0 && (a1y-yi)*(yi-a2y) >= 0 && (b1y-yi)*(yi-b2y)>=0) {
|
||||
newvec[0]= xi;
|
||||
newvec[1]= yi;
|
||||
return newVectorObject(newvec, 2, Py_NEW);
|
||||
return newVectorObject(newvec, 2, Py_NEW, NULL);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@@ -330,6 +337,10 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args
|
||||
PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(pt) || !BaseMath_ReadCallback(line_1) || !BaseMath_ReadCallback(line_2))
|
||||
return NULL;
|
||||
|
||||
/* accept 2d verts */
|
||||
if (pt->size==3) { VECCOPY(pt_in, pt->vec);}
|
||||
else { pt_in[2]=0.0; VECCOPY2D(pt_in, pt->vec) }
|
||||
@@ -344,7 +355,7 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args
|
||||
lambda = lambda_cp_line_ex(pt_in, l1, l2, pt_out);
|
||||
|
||||
ret = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW) );
|
||||
PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW, NULL) );
|
||||
PyTuple_SET_ITEM( ret, 1, PyFloat_FromDouble(lambda) );
|
||||
return ret;
|
||||
}
|
||||
@@ -363,6 +374,9 @@ static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(tri_p1) || !BaseMath_ReadCallback(tri_p2) || !BaseMath_ReadCallback(tri_p3))
|
||||
return NULL;
|
||||
|
||||
return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
|
||||
}
|
||||
|
||||
@@ -381,6 +395,9 @@ static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(quad_p1) || !BaseMath_ReadCallback(quad_p2) || !BaseMath_ReadCallback(quad_p3) || !BaseMath_ReadCallback(quad_p4))
|
||||
return NULL;
|
||||
|
||||
return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
|
||||
}
|
||||
|
||||
@@ -500,6 +517,9 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec_k1) || !BaseMath_ReadCallback(vec_h1) || !BaseMath_ReadCallback(vec_k2) || !BaseMath_ReadCallback(vec_h2))
|
||||
return NULL;
|
||||
|
||||
dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
|
||||
|
||||
for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i];
|
||||
@@ -515,7 +535,7 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args )
|
||||
list= PyList_New(resolu);
|
||||
fp= coord_array;
|
||||
for(i=0; i<resolu; i++, fp= fp+dims) {
|
||||
PyList_SET_ITEM(list, i, newVectorObject(fp, dims, Py_NEW));
|
||||
PyList_SET_ITEM(list, i, newVectorObject(fp, dims, Py_NEW, NULL));
|
||||
}
|
||||
MEM_freeN(coord_array);
|
||||
return list;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: Geometry.h 20007 2009-04-30 12:45:13Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $
|
||||
# $Id$
|
||||
#
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: Mathutils.c 20922 2009-06-16 07:16:51Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -96,7 +96,7 @@ struct PyMethodDef M_Mathutils_methods[] = {
|
||||
|
||||
#if (PY_VERSION_HEX >= 0x03000000)
|
||||
static struct PyModuleDef M_Mathutils_module_def = {
|
||||
{}, /* m_base */
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"Mathutils", /* m_name */
|
||||
M_Mathutils_doc, /* m_doc */
|
||||
0, /* m_size */
|
||||
@@ -137,81 +137,12 @@ PyObject *Mathutils_Init(const char *from)
|
||||
PyModule_AddObject( submodule, "Euler", (PyObject *)&euler_Type );
|
||||
PyModule_AddObject( submodule, "Quaternion", (PyObject *)&quaternion_Type );
|
||||
|
||||
mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
|
||||
|
||||
return (submodule);
|
||||
}
|
||||
|
||||
//-----------------------------METHODS----------------------------
|
||||
//----------------column_vector_multiplication (internal)---------
|
||||
//COLUMN VECTOR Multiplication (Matrix X Vector)
|
||||
// [1][2][3] [a]
|
||||
// [4][5][6] * [b]
|
||||
// [7][8][9] [c]
|
||||
//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
|
||||
PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
|
||||
{
|
||||
float vecNew[4], vecCopy[4];
|
||||
double dot = 0.0f;
|
||||
int x, y, z = 0;
|
||||
|
||||
if(mat->rowSize != vec->size){
|
||||
if(mat->rowSize == 4 && vec->size != 3){
|
||||
PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
|
||||
return NULL;
|
||||
}else{
|
||||
vecCopy[3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
for(x = 0; x < vec->size; x++){
|
||||
vecCopy[x] = vec->vec[x];
|
||||
}
|
||||
|
||||
for(x = 0; x < mat->rowSize; x++) {
|
||||
for(y = 0; y < mat->colSize; y++) {
|
||||
dot += mat->matrix[x][y] * vecCopy[y];
|
||||
}
|
||||
vecNew[z++] = (float)dot;
|
||||
dot = 0.0f;
|
||||
}
|
||||
return newVectorObject(vecNew, vec->size, Py_NEW);
|
||||
}
|
||||
|
||||
//-----------------row_vector_multiplication (internal)-----------
|
||||
//ROW VECTOR Multiplication - Vector X Matrix
|
||||
//[x][y][z] * [1][2][3]
|
||||
// [4][5][6]
|
||||
// [7][8][9]
|
||||
//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
|
||||
PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
|
||||
{
|
||||
float vecNew[4], vecCopy[4];
|
||||
double dot = 0.0f;
|
||||
int x, y, z = 0, vec_size = vec->size;
|
||||
|
||||
if(mat->colSize != vec_size){
|
||||
if(mat->rowSize == 4 && vec_size != 3){
|
||||
PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
|
||||
return NULL;
|
||||
}else{
|
||||
vecCopy[3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
for(x = 0; x < vec_size; x++){
|
||||
vecCopy[x] = vec->vec[x];
|
||||
}
|
||||
|
||||
//muliplication
|
||||
for(x = 0; x < mat->colSize; x++) {
|
||||
for(y = 0; y < mat->rowSize; y++) {
|
||||
dot += mat->matrix[y][x] * vecCopy[y];
|
||||
}
|
||||
vecNew[z++] = (float)dot;
|
||||
dot = 0.0f;
|
||||
}
|
||||
return newVectorObject(vecNew, vec_size, Py_NEW);
|
||||
}
|
||||
|
||||
//-----------------quat_rotation (internal)-----------
|
||||
//This function multiplies a vector/point * quat or vice versa
|
||||
//to rotate the point/vector by the quaternion
|
||||
@@ -224,8 +155,15 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
|
||||
|
||||
if(QuaternionObject_Check(arg1)){
|
||||
quat = (QuaternionObject*)arg1;
|
||||
if(!BaseMath_ReadCallback(quat))
|
||||
return NULL;
|
||||
|
||||
if(VectorObject_Check(arg2)){
|
||||
vec = (VectorObject*)arg2;
|
||||
|
||||
if(!BaseMath_ReadCallback(vec))
|
||||
return NULL;
|
||||
|
||||
rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] -
|
||||
2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] +
|
||||
2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] -
|
||||
@@ -238,12 +176,19 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
|
||||
quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] -
|
||||
quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] -
|
||||
quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
|
||||
return newVectorObject(rot, 3, Py_NEW);
|
||||
return newVectorObject(rot, 3, Py_NEW, NULL);
|
||||
}
|
||||
}else if(VectorObject_Check(arg1)){
|
||||
vec = (VectorObject*)arg1;
|
||||
|
||||
if(!BaseMath_ReadCallback(vec))
|
||||
return NULL;
|
||||
|
||||
if(QuaternionObject_Check(arg2)){
|
||||
quat = (QuaternionObject*)arg2;
|
||||
if(!BaseMath_ReadCallback(quat))
|
||||
return NULL;
|
||||
|
||||
rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] -
|
||||
2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] +
|
||||
2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] -
|
||||
@@ -256,7 +201,7 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
|
||||
quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] -
|
||||
quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] -
|
||||
quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
|
||||
return newVectorObject(rot, 3, Py_NEW);
|
||||
return newVectorObject(rot, 3, Py_NEW, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,6 +253,9 @@ static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
|
||||
if(vec1->size != vec2->size)
|
||||
goto AttributeError1; //bad sizes
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
|
||||
return NULL;
|
||||
|
||||
//since size is the same....
|
||||
size = vec1->size;
|
||||
|
||||
@@ -327,8 +275,11 @@ static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
|
||||
|
||||
angleRads = (double)saacos(dot);
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
return PyFloat_FromDouble(angleRads * (180/ Py_PI));
|
||||
|
||||
#else
|
||||
return PyFloat_FromDouble(angleRads);
|
||||
#endif
|
||||
AttributeError1:
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n");
|
||||
return NULL;
|
||||
@@ -353,11 +304,14 @@ static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
|
||||
return NULL;
|
||||
|
||||
for(x = 0; x < vec1->size; x++) {
|
||||
vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]);
|
||||
}
|
||||
return newVectorObject(vec, vec1->size, Py_NEW);
|
||||
return newVectorObject(vec, vec1->size, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.ProjectVecs() -------------
|
||||
//projects vector 1 onto vector 2
|
||||
@@ -377,6 +331,10 @@ static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
|
||||
return NULL;
|
||||
|
||||
|
||||
//since they are the same size...
|
||||
size = vec1->size;
|
||||
|
||||
@@ -390,7 +348,7 @@ static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
|
||||
for(x = 0; x < size; x++) {
|
||||
vec[x] = (float)(dot * vec2->vec[x]);
|
||||
}
|
||||
return newVectorObject(vec, size, Py_NEW);
|
||||
return newVectorObject(vec, size, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------MATRIX FUNCTIONS--------------------
|
||||
//----------------------------------Mathutils.RotationMatrix() ----------
|
||||
@@ -409,12 +367,19 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): expected float int and optional string and vector\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
/* Clamp to -360:360 */
|
||||
while (angle<-360.0f)
|
||||
angle+=360.0;
|
||||
while (angle>360.0f)
|
||||
angle-=360.0;
|
||||
#else
|
||||
while (angle<-(Py_PI*2))
|
||||
angle+=(Py_PI*2);
|
||||
while (angle>(Py_PI*2))
|
||||
angle-=(Py_PI*2);
|
||||
#endif
|
||||
|
||||
if(matSize != 2 && matSize != 3 && matSize != 4) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
|
||||
@@ -439,9 +404,16 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec))
|
||||
return NULL;
|
||||
|
||||
}
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
//convert to radians
|
||||
angle = angle * (float) (Py_PI / 180);
|
||||
#endif
|
||||
|
||||
if(axis == NULL && matSize == 2) {
|
||||
//2D rotation matrix
|
||||
mat[0] = (float) cos (angle);
|
||||
@@ -521,7 +493,7 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
|
||||
mat[3] = 0.0f;
|
||||
}
|
||||
//pass to matrix creation
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW);
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.TranslationMatrix() -------
|
||||
//creates a translation matrix
|
||||
@@ -538,13 +510,17 @@ static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * v
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): vector must be 3D or 4D\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec))
|
||||
return NULL;
|
||||
|
||||
//create a identity matrix and add translation
|
||||
Mat4One((float(*)[4]) mat);
|
||||
mat[12] = vec->vec[0];
|
||||
mat[13] = vec->vec[1];
|
||||
mat[14] = vec->vec[2];
|
||||
|
||||
return newMatrixObject(mat, 4, 4, Py_NEW);
|
||||
return newMatrixObject(mat, 4, 4, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.ScaleMatrix() -------------
|
||||
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
||||
@@ -570,6 +546,10 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec))
|
||||
return NULL;
|
||||
|
||||
}
|
||||
if(vec == NULL) { //scaling along axis
|
||||
if(matSize == 2) {
|
||||
@@ -618,7 +598,7 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
|
||||
mat[3] = 0.0f;
|
||||
}
|
||||
//pass to matrix creation
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW);
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.OrthoProjectionMatrix() ---
|
||||
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
||||
@@ -645,6 +625,10 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec))
|
||||
return NULL;
|
||||
|
||||
}
|
||||
if(vec == NULL) { //ortho projection onto cardinal plane
|
||||
if(((strcmp(plane, "x") == 0)
|
||||
@@ -717,7 +701,7 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
|
||||
mat[3] = 0.0f;
|
||||
}
|
||||
//pass to matrix creation
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW);
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.ShearMatrix() -------------
|
||||
//creates a shear matrix
|
||||
@@ -784,7 +768,7 @@ static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
|
||||
mat[3] = 0.0f;
|
||||
}
|
||||
//pass to matrix creation
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW);
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------QUATERNION FUNCTIONS-----------------
|
||||
|
||||
@@ -801,6 +785,10 @@ static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
|
||||
return NULL;
|
||||
|
||||
tempQuat[0] = quatU->quat[0];
|
||||
tempQuat[1] = -quatU->quat[1];
|
||||
tempQuat[2] = -quatU->quat[2];
|
||||
@@ -813,7 +801,7 @@ static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
|
||||
tempQuat[x] /= (float)(dot * dot);
|
||||
}
|
||||
QuatMul(quat, tempQuat, quatV->quat);
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.Slerp() ------------------
|
||||
//attemps to interpolate 2 quaternions and return the result
|
||||
@@ -828,6 +816,10 @@ static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
|
||||
return NULL;
|
||||
|
||||
if(param > 1.0f || param < 0.0f) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
|
||||
return NULL;
|
||||
@@ -870,7 +862,7 @@ static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
|
||||
quat[2] = (float)(quat_u[2] * x + quat_v[2] * y);
|
||||
quat[3] = (float)(quat_u[3] * x + quat_v[3] * y);
|
||||
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------EULER FUNCTIONS----------------------
|
||||
//---------------------------------INTERSECTION FUNCTIONS--------------------
|
||||
@@ -891,6 +883,9 @@ static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(ray) || !BaseMath_ReadCallback(ray_off))
|
||||
return NULL;
|
||||
|
||||
VECCOPY(v1, vec1->vec);
|
||||
VECCOPY(v2, vec2->vec);
|
||||
VECCOPY(v3, vec3->vec);
|
||||
@@ -941,7 +936,7 @@ static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
|
||||
VecMulf(dir, t);
|
||||
VecAddf(pvec, orig, dir);
|
||||
|
||||
return newVectorObject(pvec, 3, Py_NEW);
|
||||
return newVectorObject(pvec, 3, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.LineIntersect() -------------------
|
||||
/* Line-Line intersection using algorithm from mathworld.wolfram.com */
|
||||
@@ -959,6 +954,10 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
|
||||
PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
|
||||
return NULL;
|
||||
|
||||
if( vec1->size == 3 || vec1->size == 2) {
|
||||
int result;
|
||||
|
||||
@@ -994,8 +993,8 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
|
||||
}
|
||||
else {
|
||||
tuple = PyTuple_New( 2 );
|
||||
PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW) );
|
||||
PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW) );
|
||||
PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW, NULL) );
|
||||
PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW, NULL) );
|
||||
return tuple;
|
||||
}
|
||||
}
|
||||
@@ -1029,6 +1028,10 @@ static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
|
||||
PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
|
||||
return NULL;
|
||||
|
||||
VECCOPY(v1, vec1->vec);
|
||||
VECCOPY(v2, vec2->vec);
|
||||
VECCOPY(v3, vec3->vec);
|
||||
@@ -1052,7 +1055,7 @@ static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
|
||||
VecAddf(n1, n2, n1);
|
||||
Normalize(n1);
|
||||
|
||||
return newVectorObject(n1, 3, Py_NEW);
|
||||
return newVectorObject(n1, 3, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
//----------------------------Mathutils.TriangleNormal() -------------------
|
||||
@@ -1073,6 +1076,9 @@ static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
|
||||
PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
|
||||
return NULL;
|
||||
|
||||
VECCOPY(v1, vec1->vec);
|
||||
VECCOPY(v2, vec2->vec);
|
||||
@@ -1085,7 +1091,7 @@ static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
|
||||
Crossf(n, e2, e1);
|
||||
Normalize(n);
|
||||
|
||||
return newVectorObject(n, 3, Py_NEW);
|
||||
return newVectorObject(n, 3, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
//--------------------------------- AREA FUNCTIONS--------------------
|
||||
@@ -1105,6 +1111,9 @@ static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
|
||||
PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
|
||||
return NULL;
|
||||
|
||||
if (vec1->size == 3) {
|
||||
VECCOPY(v1, vec1->vec);
|
||||
@@ -1154,8 +1163,8 @@ int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
|
||||
}
|
||||
/*---------------------- EXPP_VectorsAreEqual -------------------------
|
||||
Builds on EXPP_FloatsAreEqual to test vectors */
|
||||
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
|
||||
|
||||
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps)
|
||||
{
|
||||
int x;
|
||||
for (x=0; x< size; x++){
|
||||
if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
|
||||
@@ -1165,6 +1174,86 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
|
||||
}
|
||||
|
||||
|
||||
/* Mathutils Callbacks */
|
||||
|
||||
/* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
|
||||
Mathutils_Callback *mathutils_callbacks[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
|
||||
int Mathutils_RegisterCallback(Mathutils_Callback *cb)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* find the first free slot */
|
||||
for(i= 0; mathutils_callbacks[i]; i++) {
|
||||
if(mathutils_callbacks[i]==cb) /* alredy registered? */
|
||||
return i;
|
||||
}
|
||||
|
||||
mathutils_callbacks[i] = cb;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* use macros to check for NULL */
|
||||
int _BaseMathObject_ReadCallback(BaseMathObject *self)
|
||||
{
|
||||
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
|
||||
if(cb->get(self->cb_user, self->cb_subtype, self->data))
|
||||
return 1;
|
||||
|
||||
PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _BaseMathObject_WriteCallback(BaseMathObject *self)
|
||||
{
|
||||
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
|
||||
if(cb->set(self->cb_user, self->cb_subtype, self->data))
|
||||
return 1;
|
||||
|
||||
PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
|
||||
{
|
||||
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
|
||||
if(cb->get_index(self->cb_user, self->cb_subtype, self->data, index))
|
||||
return 1;
|
||||
|
||||
PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
|
||||
{
|
||||
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
|
||||
if(cb->set_index(self->cb_user, self->cb_subtype, self->data, index))
|
||||
return 1;
|
||||
|
||||
PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BaseMathObject generic functions for all mathutils types */
|
||||
PyObject *BaseMathObject_getOwner( BaseMathObject * self, void *type )
|
||||
{
|
||||
PyObject *ret= self->cb_user ? self->cb_user : Py_None;
|
||||
Py_INCREF(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void *type )
|
||||
{
|
||||
return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0);
|
||||
}
|
||||
|
||||
void BaseMathObject_dealloc(BaseMathObject * self)
|
||||
{
|
||||
/* only free non wrapped */
|
||||
if(self->wrapped != Py_WRAP)
|
||||
PyMem_Free(self->data);
|
||||
|
||||
Py_XDECREF(self->cb_user);
|
||||
Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes
|
||||
}
|
||||
|
||||
//#######################################################################
|
||||
//#############################DEPRECATED################################
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: Mathutils.h 20332 2009-05-22 03:22:56Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -38,10 +38,28 @@
|
||||
#include "quat.h"
|
||||
#include "euler.h"
|
||||
|
||||
/* #define USE_MATHUTILS_DEG - for backwards compat */
|
||||
|
||||
/* Can cast different mathutils types to this, use for generic funcs */
|
||||
|
||||
typedef struct {
|
||||
PyObject_VAR_HEAD
|
||||
float *data; /*array of data (alias), wrapped status depends on wrapped status */
|
||||
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
|
||||
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
|
||||
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
|
||||
unsigned char wrapped; /* wrapped data type? */
|
||||
} BaseMathObject;
|
||||
|
||||
PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * );
|
||||
PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * );
|
||||
void BaseMathObject_dealloc(BaseMathObject * self);
|
||||
|
||||
|
||||
|
||||
|
||||
PyObject *Mathutils_Init( const char * from );
|
||||
|
||||
PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat);
|
||||
PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec);
|
||||
PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
|
||||
|
||||
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
|
||||
@@ -49,8 +67,9 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
|
||||
|
||||
|
||||
#define Py_PI 3.14159265358979323846
|
||||
#define Py_WRAP 1024
|
||||
#define Py_NEW 2048
|
||||
|
||||
#define Py_NEW 1
|
||||
#define Py_WRAP 2
|
||||
|
||||
|
||||
/* Mathutils is used by the BGE and Blender so have to define
|
||||
@@ -65,4 +84,26 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
|
||||
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
|
||||
#endif
|
||||
|
||||
typedef struct Mathutils_Callback Mathutils_Callback;
|
||||
struct Mathutils_Callback {
|
||||
int (*check)(PyObject *user); /* checks the user is still valid */
|
||||
int (*get)(PyObject *user, int subtype, float *from); /* gets the vector from the user */
|
||||
int (*set)(PyObject *user, int subtype, float *to); /* sets the users vector values once the vector is modified */
|
||||
int (*get_index)(PyObject *user, int subtype, float *from,int index); /* same as above but only for an index */
|
||||
int (*set_index)(PyObject *user, int subtype, float *to, int index); /* same as above but only for an index */
|
||||
};
|
||||
|
||||
int Mathutils_RegisterCallback(Mathutils_Callback *cb);
|
||||
|
||||
int _BaseMathObject_ReadCallback(BaseMathObject *self);
|
||||
int _BaseMathObject_WriteCallback(BaseMathObject *self);
|
||||
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index);
|
||||
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
|
||||
|
||||
/* since this is called so often avoid where possible */
|
||||
#define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):1))
|
||||
#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):1))
|
||||
#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):1))
|
||||
#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):1))
|
||||
|
||||
#endif /* EXPP_Mathutils_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: bpy_internal_import.c 20434 2009-05-26 18:06:09Z campbellbarton $
|
||||
* $Id$
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: bpy_internal_import.h 20434 2009-05-26 18:06:09Z campbellbarton $
|
||||
* $Id$
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: euler.c 20248 2009-05-18 04:11:54Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -34,13 +34,6 @@
|
||||
|
||||
|
||||
//-------------------------DOC STRINGS ---------------------------
|
||||
static char Euler_Zero_doc[] = "() - set all values in the euler to 0";
|
||||
static char Euler_Unique_doc[] ="() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock";
|
||||
static char Euler_ToMatrix_doc[] = "() - returns a rotation matrix representing the euler rotation";
|
||||
static char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation";
|
||||
static char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation";
|
||||
static char Euler_copy_doc[] = "() - returns a copy of the euler.";
|
||||
static char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping).";
|
||||
|
||||
static PyObject *Euler_Zero( EulerObject * self );
|
||||
static PyObject *Euler_Unique( EulerObject * self );
|
||||
@@ -52,25 +45,24 @@ static PyObject *Euler_copy( EulerObject * self, PyObject *args );
|
||||
|
||||
//-----------------------METHOD DEFINITIONS ----------------------
|
||||
static struct PyMethodDef Euler_methods[] = {
|
||||
{"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
|
||||
{"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
|
||||
{"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
|
||||
{"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
|
||||
{"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, Euler_Rotate_doc},
|
||||
{"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
|
||||
{"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
|
||||
{"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
|
||||
{"zero", (PyCFunction) Euler_Zero, METH_NOARGS, NULL},
|
||||
{"unique", (PyCFunction) Euler_Unique, METH_NOARGS, NULL},
|
||||
{"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, NULL},
|
||||
{"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, NULL},
|
||||
{"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL},
|
||||
{"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, NULL},
|
||||
{"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
|
||||
{"copy", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
//----------------------------------Mathutils.Euler() -------------------
|
||||
//makes a new euler for you to play with
|
||||
static PyObject *Euler_new(PyObject * self, PyObject * args)
|
||||
static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
|
||||
{
|
||||
|
||||
PyObject *listObject = NULL;
|
||||
int size, i;
|
||||
float eul[3], scalar;
|
||||
float eul[3];
|
||||
PyObject *e;
|
||||
|
||||
size = PyTuple_GET_SIZE(args);
|
||||
@@ -84,7 +76,7 @@ static PyObject *Euler_new(PyObject * self, PyObject * args)
|
||||
}
|
||||
} else if (size == 0) {
|
||||
//returns a new empty 3d euler
|
||||
return newEulerObject(NULL, Py_NEW);
|
||||
return newEulerObject(NULL, Py_NEW, NULL);
|
||||
} else {
|
||||
listObject = args;
|
||||
}
|
||||
@@ -102,17 +94,15 @@ static PyObject *Euler_new(PyObject * self, PyObject * args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scalar= (float)PyFloat_AsDouble(e);
|
||||
eul[i]= (float)PyFloat_AsDouble(e);
|
||||
Py_DECREF(e);
|
||||
|
||||
if(scalar==-1 && PyErr_Occurred()) { // parsed item is not a number
|
||||
if(eul[i]==-1 && PyErr_Occurred()) { // parsed item is not a number
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
eul[i]= scalar;
|
||||
}
|
||||
return newEulerObject(eul, Py_NEW);
|
||||
return newEulerObject(eul, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
//-----------------------------METHODS----------------------------
|
||||
@@ -120,14 +110,25 @@ static PyObject *Euler_new(PyObject * self, PyObject * args)
|
||||
//return a quaternion representation of the euler
|
||||
static PyObject *Euler_ToQuat(EulerObject * self)
|
||||
{
|
||||
float eul[3], quat[4];
|
||||
float quat[4];
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
float eul[3];
|
||||
int x;
|
||||
#endif
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
for(x = 0; x < 3; x++) {
|
||||
eul[x] = self->eul[x] * ((float)Py_PI / 180);
|
||||
}
|
||||
EulToQuat(eul, quat);
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
#else
|
||||
EulToQuat(self->eul, quat);
|
||||
#endif
|
||||
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------Euler.toMatrix()---------------------
|
||||
//return a matrix representation of the euler
|
||||
@@ -137,60 +138,80 @@ static PyObject *Euler_ToMatrix(EulerObject * self)
|
||||
float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
int x;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
for(x = 0; x < 3; x++) {
|
||||
eul[x] = self->eul[x] * ((float)Py_PI / 180);
|
||||
}
|
||||
EulToMat3(eul, (float (*)[3]) mat);
|
||||
return newMatrixObject(mat, 3, 3 , Py_NEW);
|
||||
#else
|
||||
EulToMat3(self->eul, (float (*)[3]) mat);
|
||||
#endif
|
||||
return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------Euler.unique()-----------------------
|
||||
//sets the x,y,z values to a unique euler rotation
|
||||
static PyObject *Euler_Unique(EulerObject * self)
|
||||
{
|
||||
double heading, pitch, bank;
|
||||
double pi2 = Py_PI * 2.0f;
|
||||
double piO2 = Py_PI / 2.0f;
|
||||
double Opi2 = 1.0f / pi2;
|
||||
#define PI_2 (Py_PI * 2.0)
|
||||
#define PI_HALF (Py_PI / 2.0)
|
||||
#define PI_INV (1.0 / Py_PI)
|
||||
|
||||
double heading, pitch, bank;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
//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;
|
||||
#else
|
||||
heading = self->eul[0];
|
||||
pitch = self->eul[1];
|
||||
bank = self->eul[2];
|
||||
#endif
|
||||
|
||||
//wrap heading in +180 / -180
|
||||
pitch += Py_PI;
|
||||
pitch -= floor(pitch * Opi2) * pi2;
|
||||
pitch -= floor(pitch * PI_INV) * PI_2;
|
||||
pitch -= Py_PI;
|
||||
|
||||
|
||||
if(pitch < -piO2) {
|
||||
if(pitch < -PI_HALF) {
|
||||
pitch = -Py_PI - pitch;
|
||||
heading += Py_PI;
|
||||
bank += Py_PI;
|
||||
} else if(pitch > piO2) {
|
||||
} else if(pitch > PI_HALF) {
|
||||
pitch = Py_PI - pitch;
|
||||
heading += Py_PI;
|
||||
bank += Py_PI;
|
||||
}
|
||||
//gimbal lock test
|
||||
if(fabs(pitch) > piO2 - 1e-4) {
|
||||
if(fabs(pitch) > PI_HALF - 1e-4) {
|
||||
heading += bank;
|
||||
bank = 0.0f;
|
||||
} else {
|
||||
bank += Py_PI;
|
||||
bank -= (floor(bank * Opi2)) * pi2;
|
||||
bank -= (floor(bank * PI_INV)) * PI_2;
|
||||
bank -= Py_PI;
|
||||
}
|
||||
|
||||
heading += Py_PI;
|
||||
heading -= (floor(heading * Opi2)) * pi2;
|
||||
heading -= (floor(heading * PI_INV)) * PI_2;
|
||||
heading -= Py_PI;
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
//back to degrees
|
||||
self->eul[0] = (float)(heading * 180 / (float)Py_PI);
|
||||
self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
|
||||
self->eul[2] = (float)(bank * 180 / (float)Py_PI);
|
||||
#endif
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -202,6 +223,7 @@ static PyObject *Euler_Zero(EulerObject * self)
|
||||
self->eul[1] = 0.0;
|
||||
self->eul[2] = 0.0;
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -223,42 +245,63 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
//covert to radians
|
||||
angle *= ((float)Py_PI / 180);
|
||||
for(x = 0; x < 3; x++) {
|
||||
self->eul[x] *= ((float)Py_PI / 180);
|
||||
}
|
||||
#endif
|
||||
euler_rot(self->eul, angle, *axis);
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
//convert back from radians
|
||||
for(x = 0; x < 3; x++) {
|
||||
self->eul[x] *= (180 / (float)Py_PI);
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
|
||||
{
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
float eul_from_rad[3];
|
||||
int x;
|
||||
#endif
|
||||
|
||||
if(!EulerObject_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
|
||||
return NULL;
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
//covert to radians
|
||||
for(x = 0; x < 3; x++) {
|
||||
self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
|
||||
eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
|
||||
}
|
||||
compatible_eul(self->eul, eul_from_rad);
|
||||
#else
|
||||
compatible_eul(self->eul, value->eul);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
//convert back from radians
|
||||
for(x = 0; x < 3; x++) {
|
||||
self->eul[x] *= (180 / (float)Py_PI);
|
||||
}
|
||||
|
||||
#endif
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -267,19 +310,10 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
|
||||
// return a copy of the euler
|
||||
static PyObject *Euler_copy(EulerObject * self, PyObject *args)
|
||||
{
|
||||
return newEulerObject(self->eul, Py_NEW);
|
||||
}
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
|
||||
//----------------------------dealloc()(internal) ------------------
|
||||
//free the py_object
|
||||
static void Euler_dealloc(EulerObject * self)
|
||||
{
|
||||
//only free py_data
|
||||
if(self->data.py_data){
|
||||
PyMem_Free(self->data.py_data);
|
||||
}
|
||||
PyObject_DEL(self);
|
||||
return newEulerObject(self->eul, Py_NEW, Py_TYPE(self));
|
||||
}
|
||||
|
||||
//----------------------------print object (internal)--------------
|
||||
@@ -287,6 +321,10 @@ static void Euler_dealloc(EulerObject * self)
|
||||
static PyObject *Euler_repr(EulerObject * self)
|
||||
{
|
||||
char str[64];
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
|
||||
return PyUnicode_FromString(str);
|
||||
}
|
||||
@@ -297,7 +335,18 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar
|
||||
EulerObject *eulA = NULL, *eulB = NULL;
|
||||
int result = 0;
|
||||
|
||||
if (!EulerObject_Check(objectA) || !EulerObject_Check(objectB)){
|
||||
if(EulerObject_Check(objectA)) {
|
||||
eulA = (EulerObject*)objectA;
|
||||
if(!BaseMath_ReadCallback(eulA))
|
||||
return NULL;
|
||||
}
|
||||
if(EulerObject_Check(objectB)) {
|
||||
eulB = (EulerObject*)objectB;
|
||||
if(!BaseMath_ReadCallback(eulB))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!eulA || !eulB){
|
||||
if (comparison_type == Py_NE){
|
||||
Py_RETURN_TRUE;
|
||||
}else{
|
||||
@@ -329,8 +378,7 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
//------------------------tp_doc
|
||||
static char EulerObject_doc[] = "This is a wrapper for euler objects.";
|
||||
|
||||
//---------------------SEQUENCE PROTOCOLS------------------------
|
||||
//----------------------------len(object)------------------------
|
||||
//sequence length
|
||||
@@ -342,13 +390,16 @@ static int Euler_len(EulerObject * self)
|
||||
//sequence accessor (get)
|
||||
static PyObject *Euler_item(EulerObject * self, int i)
|
||||
{
|
||||
if(i<0)
|
||||
i= 3-i;
|
||||
if(i<0) i= 3-i;
|
||||
|
||||
if(i < 0 || i >= 3) {
|
||||
PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadIndexCallback(self, i))
|
||||
return NULL;
|
||||
|
||||
return PyFloat_FromDouble(self->eul[i]);
|
||||
|
||||
}
|
||||
@@ -363,8 +414,7 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(i<0)
|
||||
i= 3-i;
|
||||
if(i<0) i= 3-i;
|
||||
|
||||
if(i < 0 || i >= 3){
|
||||
PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
|
||||
@@ -372,6 +422,10 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
|
||||
}
|
||||
|
||||
self->eul[i] = f;
|
||||
|
||||
if(!BaseMath_WriteIndexCallback(self, i))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
//----------------------------object[z:y]------------------------
|
||||
@@ -381,6 +435,9 @@ static PyObject *Euler_slice(EulerObject * self, int begin, int end)
|
||||
PyObject *list = NULL;
|
||||
int count;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
CLAMP(begin, 0, 3);
|
||||
if (end<0) end= 4+end;
|
||||
CLAMP(end, 0, 3);
|
||||
@@ -401,7 +458,10 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end,
|
||||
{
|
||||
int i, y, size = 0;
|
||||
float eul[3];
|
||||
PyObject *e, *f;
|
||||
PyObject *e;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return -1;
|
||||
|
||||
CLAMP(begin, 0, 3);
|
||||
if (end<0) end= 4+end;
|
||||
@@ -421,21 +481,20 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end,
|
||||
return -1;
|
||||
}
|
||||
|
||||
f = PyNumber_Float(e);
|
||||
if(f == NULL) { // parsed item not a number
|
||||
Py_DECREF(e);
|
||||
eul[i] = (float)PyFloat_AsDouble(e);
|
||||
Py_DECREF(e);
|
||||
|
||||
if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number
|
||||
PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
eul[i] = (float)PyFloat_AS_DOUBLE(f);
|
||||
Py_DECREF(f);
|
||||
Py_DECREF(e);
|
||||
}
|
||||
//parsed well - now set in vector
|
||||
for(y = 0; y < 3; y++){
|
||||
self->eul[begin + y] = eul[y];
|
||||
}
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
return 0;
|
||||
}
|
||||
//-----------------PROTCOL DECLARATIONS--------------------------
|
||||
@@ -450,79 +509,30 @@ static PySequenceMethods Euler_SeqMethods = {
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* vector axis, vector.x/y/z/w
|
||||
*/
|
||||
|
||||
static PyObject *Euler_getAxis( EulerObject * self, void *type )
|
||||
{
|
||||
switch( (long)type ) {
|
||||
case 'X': /* these are backwards, but that how it works */
|
||||
return PyFloat_FromDouble(self->eul[0]);
|
||||
case 'Y':
|
||||
return PyFloat_FromDouble(self->eul[1]);
|
||||
case 'Z':
|
||||
return PyFloat_FromDouble(self->eul[2]);
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_SystemError, "corrupt euler, cannot get axis");
|
||||
return NULL;
|
||||
return Euler_item(self, GET_INT_FROM_POINTER(type));
|
||||
}
|
||||
|
||||
static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
|
||||
{
|
||||
float param= (float)PyFloat_AsDouble( value );
|
||||
|
||||
if (param==-1 && PyErr_Occurred()) {
|
||||
PyErr_SetString(PyExc_TypeError, "expected a number for the vector axis");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch( (long)type ) {
|
||||
case 'X': /* these are backwards, but that how it works */
|
||||
self->eul[0]= param;
|
||||
break;
|
||||
case 'Y':
|
||||
self->eul[1]= param;
|
||||
break;
|
||||
case 'Z':
|
||||
self->eul[2]= param;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
|
||||
}
|
||||
|
||||
static PyObject *Euler_getWrapped( VectorObject * self, void *type )
|
||||
{
|
||||
if (self->wrapped == Py_WRAP)
|
||||
Py_RETURN_TRUE;
|
||||
else
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Python attributes get/set structure: */
|
||||
/*****************************************************************************/
|
||||
static PyGetSetDef Euler_getseters[] = {
|
||||
{"x",
|
||||
(getter)Euler_getAxis, (setter)Euler_setAxis,
|
||||
"Euler X axis",
|
||||
(void *)'X'},
|
||||
{"y",
|
||||
(getter)Euler_getAxis, (setter)Euler_setAxis,
|
||||
"Euler Y axis",
|
||||
(void *)'Y'},
|
||||
{"z",
|
||||
(getter)Euler_getAxis, (setter)Euler_setAxis,
|
||||
"Euler Z axis",
|
||||
(void *)'Z'},
|
||||
{"wrapped",
|
||||
(getter)Euler_getWrapped, (setter)NULL,
|
||||
"True when this wraps blenders internal data",
|
||||
NULL},
|
||||
{"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0},
|
||||
{"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1},
|
||||
{"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
|
||||
|
||||
{"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
|
||||
{"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
|
||||
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
@@ -538,7 +548,7 @@ PyTypeObject euler_Type = {
|
||||
"euler", //tp_name
|
||||
sizeof(EulerObject), //tp_basicsize
|
||||
0, //tp_itemsize
|
||||
(destructor)Euler_dealloc, //tp_dealloc
|
||||
(destructor)BaseMathObject_dealloc, //tp_dealloc
|
||||
0, //tp_print
|
||||
0, //tp_getattr
|
||||
0, //tp_setattr
|
||||
@@ -553,8 +563,8 @@ PyTypeObject euler_Type = {
|
||||
0, //tp_getattro
|
||||
0, //tp_setattro
|
||||
0, //tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, //tp_flags
|
||||
EulerObject_doc, //tp_doc
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
|
||||
0, //tp_doc
|
||||
0, //tp_traverse
|
||||
0, //tp_clear
|
||||
(richcmpfunc)Euler_richcmpr, //tp_richcompare
|
||||
@@ -587,30 +597,29 @@ PyTypeObject euler_Type = {
|
||||
(i.e. it was allocated elsewhere by MEM_mallocN())
|
||||
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
|
||||
(i.e. it must be created here with PyMEM_malloc())*/
|
||||
PyObject *newEulerObject(float *eul, int type)
|
||||
PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
|
||||
{
|
||||
EulerObject *self;
|
||||
int x;
|
||||
|
||||
self = PyObject_NEW(EulerObject, &euler_Type);
|
||||
self->data.blend_data = NULL;
|
||||
self->data.py_data = NULL;
|
||||
if(base_type) self = base_type->tp_alloc(base_type, 0);
|
||||
else self = PyObject_NEW(EulerObject, &euler_Type);
|
||||
|
||||
/* init callbacks as NULL */
|
||||
self->cb_user= NULL;
|
||||
self->cb_type= self->cb_subtype= 0;
|
||||
|
||||
if(type == Py_WRAP){
|
||||
self->data.blend_data = eul;
|
||||
self->eul = self->data.blend_data;
|
||||
self->eul = eul;
|
||||
self->wrapped = Py_WRAP;
|
||||
}else if (type == Py_NEW){
|
||||
self->data.py_data = PyMem_Malloc(3 * sizeof(float));
|
||||
self->eul = self->data.py_data;
|
||||
self->eul = PyMem_Malloc(3 * sizeof(float));
|
||||
if(!eul) { //new empty
|
||||
for(x = 0; x < 3; x++) {
|
||||
self->eul[x] = 0.0f;
|
||||
}
|
||||
}else{
|
||||
for(x = 0; x < 3; x++){
|
||||
self->eul[x] = eul[x];
|
||||
}
|
||||
VECCOPY(self->eul, eul);
|
||||
}
|
||||
self->wrapped = Py_NEW;
|
||||
}else{ //bad type
|
||||
@@ -618,3 +627,16 @@ PyObject *newEulerObject(float *eul, int type)
|
||||
}
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
|
||||
{
|
||||
EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL);
|
||||
if(self) {
|
||||
Py_INCREF(cb_user);
|
||||
self->cb_user= cb_user;
|
||||
self->cb_type= (unsigned char)cb_type;
|
||||
self->cb_subtype= (unsigned char)cb_subtype;
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: euler.h 20248 2009-05-18 04:11:54Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -35,17 +35,17 @@
|
||||
#include "../intern/bpy_compat.h"
|
||||
|
||||
extern PyTypeObject euler_Type;
|
||||
|
||||
#define EulerObject_Check(v) (Py_TYPE(v) == &euler_Type)
|
||||
#define EulerObject_Check(_v) PyObject_TypeCheck((_v), &euler_Type)
|
||||
|
||||
typedef struct {
|
||||
PyObject_VAR_HEAD
|
||||
struct{
|
||||
float *py_data; //python managed
|
||||
float *blend_data; //blender managed
|
||||
}data;
|
||||
float *eul; //1D array of data (alias)
|
||||
int wrapped; //is wrapped data?
|
||||
float *eul; /*1D array of data */
|
||||
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
|
||||
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
|
||||
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
|
||||
unsigned char wrapped; /* wrapped data type? */
|
||||
/* end BaseMathObject */
|
||||
|
||||
} EulerObject;
|
||||
|
||||
/*struct data contains a pointer to the actual data that the
|
||||
@@ -54,6 +54,7 @@ be stored in py_data) or be a wrapper for data allocated through
|
||||
blender (stored in blend_data). This is an either/or struct not both*/
|
||||
|
||||
//prototypes
|
||||
PyObject *newEulerObject( float *eul, int type );
|
||||
PyObject *newEulerObject( float *eul, int type, PyTypeObject *base_type);
|
||||
PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
|
||||
|
||||
#endif /* EXPP_euler_h */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: matrix.c 20249 2009-05-18 04:27:48Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -31,19 +31,72 @@
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); /* utility func */
|
||||
|
||||
|
||||
/* matrix vector callbacks */
|
||||
int mathutils_matrix_vector_cb_index= -1;
|
||||
|
||||
static int mathutils_matrix_vector_check(MatrixObject *self)
|
||||
{
|
||||
return BaseMath_ReadCallback(self);
|
||||
}
|
||||
|
||||
static int mathutils_matrix_vector_get(MatrixObject *self, int subtype, float *vec_from)
|
||||
{
|
||||
int i;
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return 0;
|
||||
|
||||
for(i=0; i<self->colSize; i++)
|
||||
vec_from[i]= self->matrix[subtype][i];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mathutils_matrix_vector_set(MatrixObject *self, int subtype, float *vec_to)
|
||||
{
|
||||
int i;
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return 0;
|
||||
|
||||
for(i=0; i<self->colSize; i++)
|
||||
self->matrix[subtype][i]= vec_to[i];
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mathutils_matrix_vector_get_index(MatrixObject *self, int subtype, float *vec_from, int index)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return 0;
|
||||
|
||||
vec_from[index]= self->matrix[subtype][index];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mathutils_matrix_vector_set_index(MatrixObject *self, int subtype, float *vec_to, int index)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return 0;
|
||||
|
||||
self->matrix[subtype][index]= vec_to[index];
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Mathutils_Callback mathutils_matrix_vector_cb = {
|
||||
mathutils_matrix_vector_check,
|
||||
mathutils_matrix_vector_get,
|
||||
mathutils_matrix_vector_set,
|
||||
mathutils_matrix_vector_get_index,
|
||||
mathutils_matrix_vector_set_index
|
||||
};
|
||||
/* matrix vector callbacks, this is so you can do matrix[i][j] = val */
|
||||
|
||||
/*-------------------------DOC STRINGS ---------------------------*/
|
||||
static char Matrix_Zero_doc[] = "() - set all values in the matrix to 0";
|
||||
static char Matrix_Identity_doc[] = "() - set the square matrix to it's identity matrix";
|
||||
static char Matrix_Transpose_doc[] = "() - set the matrix to it's transpose";
|
||||
static char Matrix_Determinant_doc[] = "() - return the determinant of the matrix";
|
||||
static char Matrix_Invert_doc[] = "() - set the matrix to it's inverse if an inverse is possible";
|
||||
static char Matrix_TranslationPart_doc[] = "() - return a vector encompassing the translation of the matrix";
|
||||
static char Matrix_RotationPart_doc[] = "() - return a vector encompassing the rotation of the matrix";
|
||||
static char Matrix_scalePart_doc[] = "() - convert matrix to a 3D vector";
|
||||
static char Matrix_Resize4x4_doc[] = "() - resize the matrix to a 4x4 square matrix";
|
||||
static char Matrix_toEuler_doc[] = "(eul_compat) - convert matrix to a euler angle rotation, optional euler argument that the new euler will be made compatible with.";
|
||||
static char Matrix_toQuat_doc[] = "() - convert matrix to a quaternion rotation";
|
||||
static char Matrix_copy_doc[] = "() - return a copy of the matrix";
|
||||
|
||||
static PyObject *Matrix_Zero( MatrixObject * self );
|
||||
static PyObject *Matrix_Identity( MatrixObject * self );
|
||||
@@ -60,19 +113,19 @@ static PyObject *Matrix_copy( MatrixObject * self );
|
||||
|
||||
/*-----------------------METHOD DEFINITIONS ----------------------*/
|
||||
static struct PyMethodDef Matrix_methods[] = {
|
||||
{"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, Matrix_Zero_doc},
|
||||
{"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, Matrix_Identity_doc},
|
||||
{"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, Matrix_Transpose_doc},
|
||||
{"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, Matrix_Determinant_doc},
|
||||
{"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, Matrix_Invert_doc},
|
||||
{"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, Matrix_TranslationPart_doc},
|
||||
{"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc},
|
||||
{"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, Matrix_scalePart_doc},
|
||||
{"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc},
|
||||
{"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, Matrix_toEuler_doc},
|
||||
{"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc},
|
||||
{"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
|
||||
{"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
|
||||
{"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, NULL},
|
||||
{"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, NULL},
|
||||
{"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, NULL},
|
||||
{"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, NULL},
|
||||
{"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, NULL},
|
||||
{"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, NULL},
|
||||
{"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, NULL},
|
||||
{"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, NULL},
|
||||
{"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, NULL},
|
||||
{"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, NULL},
|
||||
{"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, NULL},
|
||||
{"copy", (PyCFunction) Matrix_copy, METH_NOARGS, NULL},
|
||||
{"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
@@ -93,18 +146,16 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
|
||||
return NULL;
|
||||
} else if (argSize == 0) { //return empty 4D matrix
|
||||
return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW);
|
||||
return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW, NULL);
|
||||
}else if (argSize == 1){
|
||||
//copy constructor for matrix objects
|
||||
argObject = PyTuple_GET_ITEM(args, 0);
|
||||
if(MatrixObject_Check(argObject)){
|
||||
mat = (MatrixObject*)argObject;
|
||||
if(!BaseMath_ReadCallback(mat))
|
||||
return NULL;
|
||||
|
||||
argSize = mat->rowSize; //rows
|
||||
seqSize = mat->colSize; //col
|
||||
for(i = 0; i < (seqSize * argSize); i++){
|
||||
matrix[i] = mat->contigPtr[i];
|
||||
}
|
||||
memcpy(matrix, mat->contigPtr, sizeof(float) * mat->rowSize * mat->colSize);
|
||||
}
|
||||
}else{ //2-4 arguments (all seqs? all same size?)
|
||||
for(i =0; i < argSize; i++){
|
||||
@@ -149,7 +200,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
}
|
||||
}
|
||||
}
|
||||
return newMatrixObject(matrix, argSize, seqSize, Py_NEW);
|
||||
return newMatrixObject(matrix, argSize, seqSize, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
/*-----------------------------METHODS----------------------------*/
|
||||
@@ -158,6 +209,9 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
|
||||
{
|
||||
float quat[4];
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
/*must be 3-4 cols, 3-4 rows, square matrix*/
|
||||
if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
|
||||
@@ -169,22 +223,34 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
|
||||
Mat4ToQuat((float (*)[4])*self->matrix, quat);
|
||||
}
|
||||
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
/*---------------------------Matrix.toEuler() --------------------*/
|
||||
PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
|
||||
{
|
||||
float eul[3], eul_compatf[3];
|
||||
EulerObject *eul_compat = NULL;
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
int x;
|
||||
#endif
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
|
||||
return NULL;
|
||||
|
||||
if(eul_compat) {
|
||||
if(!BaseMath_ReadCallback(eul_compat))
|
||||
return NULL;
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
for(x = 0; x < 3; x++) {
|
||||
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
|
||||
}
|
||||
#else
|
||||
VECCOPY(eul_compatf, eul_compat->eul);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*must be 3-4 cols, 3-4 rows, square matrix*/
|
||||
@@ -202,28 +268,33 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
|
||||
return NULL;
|
||||
}
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
/*have to convert to degrees*/
|
||||
for(x = 0; x < 3; x++) {
|
||||
eul[x] *= (float) (180 / Py_PI);
|
||||
}
|
||||
return newEulerObject(eul, Py_NEW);
|
||||
#endif
|
||||
return newEulerObject(eul, Py_NEW, NULL);
|
||||
}
|
||||
/*---------------------------Matrix.resize4x4() ------------------*/
|
||||
PyObject *Matrix_Resize4x4(MatrixObject * self)
|
||||
{
|
||||
int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
|
||||
|
||||
if(self->data.blend_data){
|
||||
PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - only python matrices");
|
||||
if(self->wrapped==Py_WRAP){
|
||||
PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - make a copy and resize that");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->data.py_data = PyMem_Realloc(self->data.py_data, (sizeof(float) * 16));
|
||||
if(self->data.py_data == NULL) {
|
||||
if(self->cb_user){
|
||||
PyErr_SetString(PyExc_TypeError, "cannot resize owned data - make a copy and resize that");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->contigPtr = PyMem_Realloc(self->contigPtr, (sizeof(float) * 16));
|
||||
if(self->contigPtr == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
self->contigPtr = self->data.py_data; /*force*/
|
||||
self->matrix = PyMem_Realloc(self->matrix, (sizeof(float *) * 4));
|
||||
if(self->matrix == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
|
||||
@@ -266,7 +337,10 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
|
||||
PyObject *Matrix_TranslationPart(MatrixObject * self)
|
||||
{
|
||||
float vec[4];
|
||||
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(self->colSize < 3 || self->rowSize < 4){
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.translationPart: inappropriate matrix size");
|
||||
return NULL;
|
||||
@@ -276,7 +350,7 @@ PyObject *Matrix_TranslationPart(MatrixObject * self)
|
||||
vec[1] = self->matrix[3][1];
|
||||
vec[2] = self->matrix[3][2];
|
||||
|
||||
return newVectorObject(vec, 3, Py_NEW);
|
||||
return newVectorObject(vec, 3, Py_NEW, NULL);
|
||||
}
|
||||
/*---------------------------Matrix.rotationPart() ---------------*/
|
||||
PyObject *Matrix_RotationPart(MatrixObject * self)
|
||||
@@ -284,6 +358,9 @@ PyObject *Matrix_RotationPart(MatrixObject * self)
|
||||
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(self->colSize < 3 || self->rowSize < 3){
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.rotationPart: inappropriate matrix size\n");
|
||||
return NULL;
|
||||
@@ -299,7 +376,7 @@ PyObject *Matrix_RotationPart(MatrixObject * self)
|
||||
mat[7] = self->matrix[2][1];
|
||||
mat[8] = self->matrix[2][2];
|
||||
|
||||
return newMatrixObject(mat, 3, 3, Py_NEW);
|
||||
return newMatrixObject(mat, 3, 3, Py_NEW, Py_TYPE(self));
|
||||
}
|
||||
/*---------------------------Matrix.scalePart() --------------------*/
|
||||
PyObject *Matrix_scalePart(MatrixObject * self)
|
||||
@@ -307,6 +384,9 @@ PyObject *Matrix_scalePart(MatrixObject * self)
|
||||
float scale[3], rot[3];
|
||||
float mat[3][3], imat[3][3], tmat[3][3];
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
/*must be 3-4 cols, 3-4 rows, square matrix*/
|
||||
if(self->colSize == 4 && self->rowSize == 4)
|
||||
Mat3CpyMat4(mat, (float (*)[4])*self->matrix);
|
||||
@@ -325,7 +405,7 @@ PyObject *Matrix_scalePart(MatrixObject * self)
|
||||
scale[0]= tmat[0][0];
|
||||
scale[1]= tmat[1][1];
|
||||
scale[2]= tmat[2][2];
|
||||
return newVectorObject(scale, 3, Py_NEW);
|
||||
return newVectorObject(scale, 3, Py_NEW, NULL);
|
||||
}
|
||||
/*---------------------------Matrix.invert() ---------------------*/
|
||||
PyObject *Matrix_Invert(MatrixObject * self)
|
||||
@@ -337,6 +417,9 @@ PyObject *Matrix_Invert(MatrixObject * self)
|
||||
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(self->rowSize != self->colSize){
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.invert(ed): only square matrices are supported");
|
||||
return NULL;
|
||||
@@ -377,6 +460,7 @@ PyObject *Matrix_Invert(MatrixObject * self)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -387,6 +471,9 @@ PyObject *Matrix_Determinant(MatrixObject * self)
|
||||
{
|
||||
float det = 0.0f;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(self->rowSize != self->colSize){
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.determinant: only square matrices are supported");
|
||||
return NULL;
|
||||
@@ -412,6 +499,9 @@ PyObject *Matrix_Transpose(MatrixObject * self)
|
||||
{
|
||||
float t = 0.0f;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(self->rowSize != self->colSize){
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.transpose(d): only square matrices are supported");
|
||||
return NULL;
|
||||
@@ -427,6 +517,7 @@ PyObject *Matrix_Transpose(MatrixObject * self)
|
||||
Mat4Transp((float (*)[4])*self->matrix);
|
||||
}
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -436,18 +527,25 @@ PyObject *Matrix_Transpose(MatrixObject * self)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(!BaseMath_WriteCallback(self))
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
/*---------------------------Matrix.identity(() ------------------*/
|
||||
PyObject *Matrix_Identity(MatrixObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(self->rowSize != self->colSize){
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.identity: only square matrices are supported\n");
|
||||
return NULL;
|
||||
@@ -464,6 +562,9 @@ PyObject *Matrix_Identity(MatrixObject * self)
|
||||
Mat4One((float (*)[4]) *self->matrix);
|
||||
}
|
||||
|
||||
if(!BaseMath_WriteCallback(self))
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -471,19 +572,10 @@ PyObject *Matrix_Identity(MatrixObject * self)
|
||||
/*---------------------------Matrix.inverted() ------------------*/
|
||||
PyObject *Matrix_copy(MatrixObject * self)
|
||||
{
|
||||
return (PyObject*)(MatrixObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW);
|
||||
}
|
||||
|
||||
/*----------------------------dealloc()(internal) ----------------*/
|
||||
/*free the py_object*/
|
||||
static void Matrix_dealloc(MatrixObject * self)
|
||||
{
|
||||
PyMem_Free(self->matrix);
|
||||
/*only free py_data*/
|
||||
if(self->data.py_data){
|
||||
PyMem_Free(self->data.py_data);
|
||||
}
|
||||
PyObject_DEL(self);
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
return (PyObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW, Py_TYPE(self));
|
||||
}
|
||||
|
||||
/*----------------------------print object (internal)-------------*/
|
||||
@@ -493,6 +585,9 @@ static PyObject *Matrix_repr(MatrixObject * self)
|
||||
int x, y;
|
||||
char buffer[48], str[1024];
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
BLI_strncpy(str,"",1024);
|
||||
for(x = 0; x < self->rowSize; x++){
|
||||
sprintf(buffer, "[");
|
||||
@@ -529,6 +624,9 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa
|
||||
matA = (MatrixObject*)objectA;
|
||||
matB = (MatrixObject*)objectB;
|
||||
|
||||
if(!BaseMath_ReadCallback(matA) || !BaseMath_ReadCallback(matB))
|
||||
return NULL;
|
||||
|
||||
if (matA->colSize != matB->colSize || matA->rowSize != matB->rowSize){
|
||||
if (comparison_type == Py_NE){
|
||||
Py_RETURN_TRUE;
|
||||
@@ -562,8 +660,7 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
/*------------------------tp_doc*/
|
||||
static char MatrixObject_doc[] = "This is a wrapper for matrix objects.";
|
||||
|
||||
/*---------------------SEQUENCE PROTOCOLS------------------------
|
||||
----------------------------len(object)------------------------
|
||||
sequence length*/
|
||||
@@ -576,11 +673,14 @@ static int Matrix_len(MatrixObject * self)
|
||||
the wrapped vector gives direct access to the matrix data*/
|
||||
static PyObject *Matrix_item(MatrixObject * self, int i)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(i < 0 || i >= self->rowSize) {
|
||||
PyErr_SetString(PyExc_IndexError, "matrix[attribute]: array index out of range");
|
||||
return NULL;
|
||||
}
|
||||
return newVectorObject(self->matrix[i], self->colSize, Py_WRAP);
|
||||
return newVectorObject_cb((PyObject *)self, self->colSize, mathutils_matrix_vector_cb_index, i);
|
||||
}
|
||||
/*----------------------------object[]-------------------------
|
||||
sequence accessor (set)*/
|
||||
@@ -590,6 +690,9 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
|
||||
float vec[4];
|
||||
PyObject *m, *f;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return -1;
|
||||
|
||||
if(i >= self->rowSize || i < 0){
|
||||
PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad row\n");
|
||||
return -1;
|
||||
@@ -623,6 +726,8 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
|
||||
for(y = 0; y < size; y++){
|
||||
self->matrix[i][y] = vec[y];
|
||||
}
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
return 0;
|
||||
}else{
|
||||
PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: expects a sequence of column size\n");
|
||||
@@ -636,6 +741,9 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end)
|
||||
|
||||
PyObject *list = NULL;
|
||||
int count;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
CLAMP(begin, 0, self->rowSize);
|
||||
CLAMP(end, 0, self->rowSize);
|
||||
@@ -644,21 +752,24 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end)
|
||||
list = PyList_New(end - begin);
|
||||
for(count = begin; count < end; count++) {
|
||||
PyList_SetItem(list, count - begin,
|
||||
newVectorObject(self->matrix[count], self->colSize, Py_WRAP));
|
||||
newVectorObject_cb((PyObject *)self, self->colSize, mathutils_matrix_vector_cb_index, count));
|
||||
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
/*----------------------------object[z:y]------------------------
|
||||
sequence slice (set)*/
|
||||
static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
|
||||
PyObject * seq)
|
||||
static int Matrix_ass_slice(MatrixObject * self, int begin, int end, PyObject * seq)
|
||||
{
|
||||
int i, x, y, size, sub_size = 0;
|
||||
float mat[16], f;
|
||||
PyObject *subseq;
|
||||
PyObject *m;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return -1;
|
||||
|
||||
CLAMP(begin, 0, self->rowSize);
|
||||
CLAMP(end, 0, self->rowSize);
|
||||
begin = MIN2(begin,end);
|
||||
@@ -716,6 +827,8 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
|
||||
for(x = 0; x < (size * sub_size); x++){
|
||||
self->matrix[begin + (int)floor(x / self->colSize)][x % self->colSize] = mat[x];
|
||||
}
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
return 0;
|
||||
}else{
|
||||
PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n");
|
||||
@@ -738,6 +851,10 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2)
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2))
|
||||
return NULL;
|
||||
|
||||
if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
|
||||
return NULL;
|
||||
@@ -749,7 +866,7 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2)
|
||||
}
|
||||
}
|
||||
|
||||
return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
|
||||
return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL);
|
||||
}
|
||||
/*------------------------obj - obj------------------------------
|
||||
subtraction*/
|
||||
@@ -767,6 +884,10 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2))
|
||||
return NULL;
|
||||
|
||||
if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
|
||||
return NULL;
|
||||
@@ -778,7 +899,7 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
|
||||
}
|
||||
}
|
||||
|
||||
return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
|
||||
return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL);
|
||||
}
|
||||
/*------------------------obj * obj------------------------------
|
||||
mulplication*/
|
||||
@@ -791,8 +912,16 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
|
||||
double dot = 0.0f;
|
||||
MatrixObject *mat1 = NULL, *mat2 = NULL;
|
||||
|
||||
if(MatrixObject_Check(m1)) mat1 = (MatrixObject*)m1;
|
||||
if(MatrixObject_Check(m2)) mat2 = (MatrixObject*)m2;
|
||||
if(MatrixObject_Check(m1)) {
|
||||
mat1 = (MatrixObject*)m1;
|
||||
if(!BaseMath_ReadCallback(mat1))
|
||||
return NULL;
|
||||
}
|
||||
if(MatrixObject_Check(m2)) {
|
||||
mat2 = (MatrixObject*)m2;
|
||||
if(!BaseMath_ReadCallback(mat2))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mat1 && mat2) { /*MATRIX * MATRIX*/
|
||||
if(mat1->colSize != mat2->rowSize){
|
||||
@@ -809,7 +938,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
|
||||
}
|
||||
}
|
||||
|
||||
return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW);
|
||||
return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
if(mat1==NULL){
|
||||
@@ -820,7 +949,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
|
||||
mat[((x * mat2->colSize) + y)] = scalar * mat2->matrix[x][y];
|
||||
}
|
||||
}
|
||||
return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW);
|
||||
return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
|
||||
@@ -829,7 +958,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
|
||||
else /* if(mat1) { */ {
|
||||
|
||||
if(VectorObject_Check(m2)) { /* MATRIX*VECTOR */
|
||||
return column_vector_multiplication(mat1, (VectorObject *)m2);
|
||||
return column_vector_multiplication(mat1, (VectorObject *)m2); /* vector update done inside the function */
|
||||
}
|
||||
else {
|
||||
scalar= PyFloat_AsDouble(m2);
|
||||
@@ -839,7 +968,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
|
||||
mat[((x * mat1->colSize) + y)] = scalar * mat1->matrix[x][y];
|
||||
}
|
||||
}
|
||||
return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
|
||||
return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL);
|
||||
}
|
||||
}
|
||||
PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
|
||||
@@ -851,6 +980,9 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
|
||||
}
|
||||
static PyObject* Matrix_inv(MatrixObject *self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
return Matrix_Invert(self);
|
||||
}
|
||||
|
||||
@@ -864,6 +996,123 @@ static PySequenceMethods Matrix_SeqMethods = {
|
||||
(ssizeobjargproc) Matrix_ass_item, /* sq_ass_item */
|
||||
(ssizessizeobjargproc) Matrix_ass_slice, /* sq_ass_slice */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if (PY_VERSION_HEX >= 0x03000000)
|
||||
static PyObject *Matrix_subscript(MatrixObject* self, PyObject* item)
|
||||
{
|
||||
if (PyIndex_Check(item)) {
|
||||
Py_ssize_t i;
|
||||
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||
if (i == -1 && PyErr_Occurred())
|
||||
return NULL;
|
||||
if (i < 0)
|
||||
i += self->rowSize;
|
||||
return Matrix_item(self, i);
|
||||
} else if (PySlice_Check(item)) {
|
||||
Py_ssize_t start, stop, step, slicelength;
|
||||
|
||||
if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0)
|
||||
return NULL;
|
||||
|
||||
if (slicelength <= 0) {
|
||||
return PyList_New(0);
|
||||
}
|
||||
else if (step == 1) {
|
||||
return Matrix_slice(self, start, stop);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"vector indices must be integers, not %.200s",
|
||||
item->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int Matrix_ass_subscript(MatrixObject* self, PyObject* item, PyObject* value)
|
||||
{
|
||||
if (PyIndex_Check(item)) {
|
||||
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||
if (i == -1 && PyErr_Occurred())
|
||||
return -1;
|
||||
if (i < 0)
|
||||
i += self->rowSize;
|
||||
return Matrix_ass_item(self, i, value);
|
||||
}
|
||||
else if (PySlice_Check(item)) {
|
||||
Py_ssize_t start, stop, step, slicelength;
|
||||
|
||||
if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0)
|
||||
return -1;
|
||||
|
||||
if (step == 1)
|
||||
return Matrix_ass_slice(self, start, stop, value);
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"matrix indices must be integers, not %.200s",
|
||||
item->ob_type->tp_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static PyMappingMethods Matrix_AsMapping = {
|
||||
(lenfunc)Matrix_len,
|
||||
(binaryfunc)Matrix_subscript,
|
||||
(objobjargproc)Matrix_ass_subscript
|
||||
};
|
||||
#endif /* (PY_VERSION_HEX >= 0x03000000) */
|
||||
|
||||
|
||||
|
||||
#if (PY_VERSION_HEX >= 0x03000000)
|
||||
static PyNumberMethods Matrix_NumMethods = {
|
||||
(binaryfunc) Matrix_add, /*nb_add*/
|
||||
(binaryfunc) Matrix_sub, /*nb_subtract*/
|
||||
(binaryfunc) Matrix_mul, /*nb_multiply*/
|
||||
0, /*nb_remainder*/
|
||||
0, /*nb_divmod*/
|
||||
0, /*nb_power*/
|
||||
(unaryfunc) 0, /*nb_negative*/
|
||||
(unaryfunc) 0, /*tp_positive*/
|
||||
(unaryfunc) 0, /*tp_absolute*/
|
||||
(inquiry) 0, /*tp_bool*/
|
||||
(unaryfunc) Matrix_inv, /*nb_invert*/
|
||||
0, /*nb_lshift*/
|
||||
(binaryfunc)0, /*nb_rshift*/
|
||||
0, /*nb_and*/
|
||||
0, /*nb_xor*/
|
||||
0, /*nb_or*/
|
||||
0, /*nb_int*/
|
||||
0, /*nb_reserved*/
|
||||
0, /*nb_float*/
|
||||
0, /* nb_inplace_add */
|
||||
0, /* nb_inplace_subtract */
|
||||
0, /* nb_inplace_multiply */
|
||||
0, /* nb_inplace_remainder */
|
||||
0, /* nb_inplace_power */
|
||||
0, /* nb_inplace_lshift */
|
||||
0, /* nb_inplace_rshift */
|
||||
0, /* nb_inplace_and */
|
||||
0, /* nb_inplace_xor */
|
||||
0, /* nb_inplace_or */
|
||||
0, /* nb_floor_divide */
|
||||
0, /* nb_true_divide */
|
||||
0, /* nb_inplace_floor_divide */
|
||||
0, /* nb_inplace_true_divide */
|
||||
0, /* nb_index */
|
||||
};
|
||||
#else
|
||||
static PyNumberMethods Matrix_NumMethods = {
|
||||
(binaryfunc) Matrix_add, /* __add__ */
|
||||
(binaryfunc) Matrix_sub, /* __sub__ */
|
||||
@@ -889,6 +1138,7 @@ static PyNumberMethods Matrix_NumMethods = {
|
||||
(unaryfunc) 0, /* __oct__ */
|
||||
(unaryfunc) 0, /* __hex__ */
|
||||
};
|
||||
#endif
|
||||
|
||||
static PyObject *Matrix_getRowSize( MatrixObject * self, void *type )
|
||||
{
|
||||
@@ -900,21 +1150,15 @@ static PyObject *Matrix_getColSize( MatrixObject * self, void *type )
|
||||
return PyLong_FromLong((long) self->colSize);
|
||||
}
|
||||
|
||||
static PyObject *Matrix_getWrapped( MatrixObject * self, void *type )
|
||||
{
|
||||
if (self->wrapped == Py_WRAP)
|
||||
Py_RETURN_TRUE;
|
||||
else
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Python attributes get/set structure: */
|
||||
/*****************************************************************************/
|
||||
static PyGetSetDef Matrix_getseters[] = {
|
||||
{"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL},
|
||||
{"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL},
|
||||
{"wrapped", (getter)Matrix_getWrapped, (setter)NULL, "", NULL},
|
||||
{"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL},
|
||||
{"__owner__",(getter)BaseMathObject_getOwner, (setter)NULL, "",
|
||||
NULL},
|
||||
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
@@ -930,7 +1174,7 @@ PyTypeObject matrix_Type = {
|
||||
"matrix", /*tp_name*/
|
||||
sizeof(MatrixObject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
(destructor)Matrix_dealloc, /*tp_dealloc*/
|
||||
(destructor)BaseMathObject_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
@@ -938,15 +1182,19 @@ PyTypeObject matrix_Type = {
|
||||
(reprfunc) Matrix_repr, /*tp_repr*/
|
||||
&Matrix_NumMethods, /*tp_as_number*/
|
||||
&Matrix_SeqMethods, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
#if (PY_VERSION_HEX >= 0x03000000)
|
||||
&Matrix_AsMapping, /*tp_as_mapping*/
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
MatrixObject_doc, /*tp_doc*/
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
(richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/
|
||||
@@ -984,13 +1232,13 @@ self->matrix self->contiguous_ptr (reference to data.xxx)
|
||||
[4]
|
||||
[5]
|
||||
....
|
||||
self->matrix[1][1] = self->contiguous_ptr[4] = self->data.xxx_data[4]*/
|
||||
self->matrix[1][1] = self->contigPtr[4] */
|
||||
|
||||
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
|
||||
(i.e. it was allocated elsewhere by MEM_mallocN())
|
||||
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
|
||||
(i.e. it must be created here with PyMEM_malloc())*/
|
||||
PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
|
||||
PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type)
|
||||
{
|
||||
MatrixObject *self;
|
||||
int x, row, col;
|
||||
@@ -1001,15 +1249,18 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = PyObject_NEW(MatrixObject, &matrix_Type);
|
||||
self->data.blend_data = NULL;
|
||||
self->data.py_data = NULL;
|
||||
if(base_type) self = (MatrixObject *)base_type->tp_alloc(base_type, 0);
|
||||
else self = PyObject_NEW(MatrixObject, &matrix_Type);
|
||||
|
||||
self->rowSize = rowSize;
|
||||
self->colSize = colSize;
|
||||
|
||||
/* init callbacks as NULL */
|
||||
self->cb_user= NULL;
|
||||
self->cb_type= self->cb_subtype= 0;
|
||||
|
||||
if(type == Py_WRAP){
|
||||
self->data.blend_data = mat;
|
||||
self->contigPtr = self->data.blend_data;
|
||||
self->contigPtr = mat;
|
||||
/*create pointer array*/
|
||||
self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
|
||||
if(self->matrix == NULL) { /*allocation failure*/
|
||||
@@ -1022,16 +1273,15 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
|
||||
}
|
||||
self->wrapped = Py_WRAP;
|
||||
}else if (type == Py_NEW){
|
||||
self->data.py_data = PyMem_Malloc(rowSize * colSize * sizeof(float));
|
||||
if(self->data.py_data == NULL) { /*allocation failure*/
|
||||
self->contigPtr = PyMem_Malloc(rowSize * colSize * sizeof(float));
|
||||
if(self->contigPtr == NULL) { /*allocation failure*/
|
||||
PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space\n");
|
||||
return NULL;
|
||||
}
|
||||
self->contigPtr = self->data.py_data;
|
||||
/*create pointer array*/
|
||||
self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
|
||||
if(self->matrix == NULL) { /*allocation failure*/
|
||||
PyMem_Free(self->data.py_data);
|
||||
PyMem_Free(self->contigPtr);
|
||||
PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1056,3 +1306,53 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
|
||||
}
|
||||
return (PyObject *) self;
|
||||
}
|
||||
|
||||
PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb_type, int cb_subtype)
|
||||
{
|
||||
MatrixObject *self= (MatrixObject *)newMatrixObject(NULL, rowSize, colSize, Py_NEW, NULL);
|
||||
if(self) {
|
||||
Py_INCREF(cb_user);
|
||||
self->cb_user= cb_user;
|
||||
self->cb_type= (unsigned char)cb_type;
|
||||
self->cb_subtype= (unsigned char)cb_subtype;
|
||||
}
|
||||
return (PyObject *) self;
|
||||
}
|
||||
|
||||
//----------------column_vector_multiplication (internal)---------
|
||||
//COLUMN VECTOR Multiplication (Matrix X Vector)
|
||||
// [1][2][3] [a]
|
||||
// [4][5][6] * [b]
|
||||
// [7][8][9] [c]
|
||||
//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
|
||||
static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
|
||||
{
|
||||
float vecNew[4], vecCopy[4];
|
||||
double dot = 0.0f;
|
||||
int x, y, z = 0;
|
||||
|
||||
if(!BaseMath_ReadCallback(mat) || !BaseMath_ReadCallback(vec))
|
||||
return NULL;
|
||||
|
||||
if(mat->rowSize != vec->size){
|
||||
if(mat->rowSize == 4 && vec->size != 3){
|
||||
PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
|
||||
return NULL;
|
||||
}else{
|
||||
vecCopy[3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
for(x = 0; x < vec->size; x++){
|
||||
vecCopy[x] = vec->vec[x];
|
||||
}
|
||||
|
||||
for(x = 0; x < mat->rowSize; x++) {
|
||||
for(y = 0; y < mat->colSize; y++) {
|
||||
dot += mat->matrix[x][y] * vecCopy[y];
|
||||
}
|
||||
vecNew[z++] = (float)dot;
|
||||
dot = 0.0f;
|
||||
}
|
||||
return newVectorObject(vecNew, vec->size, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: matrix.h 20248 2009-05-18 04:11:54Z campbellbarton $
|
||||
* $Id$
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -33,21 +33,22 @@
|
||||
#include <Python.h>
|
||||
|
||||
extern PyTypeObject matrix_Type;
|
||||
|
||||
#define MatrixObject_Check(v) ((v)->ob_type == &matrix_Type)
|
||||
#define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type)
|
||||
|
||||
typedef float **ptRow;
|
||||
typedef struct _Matrix {
|
||||
PyObject_VAR_HEAD
|
||||
struct{
|
||||
float *py_data; /*python managed*/
|
||||
float *blend_data; /*blender managed*/
|
||||
}data;
|
||||
ptRow matrix; /*ptr to the contigPtr (accessor)*/
|
||||
float *contigPtr; /*1D array of data (alias)*/
|
||||
int rowSize;
|
||||
int colSize;
|
||||
int wrapped; /*is wrapped data?*/
|
||||
typedef struct _Matrix { /* keep aligned with BaseMathObject in Mathutils.h */
|
||||
PyObject_VAR_HEAD
|
||||
float *contigPtr; /*1D array of data (alias)*/
|
||||
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
|
||||
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
|
||||
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
|
||||
unsigned char wrapped; /*is wrapped data?*/
|
||||
/* end BaseMathObject */
|
||||
|
||||
unsigned char rowSize;
|
||||
unsigned int colSize;
|
||||
ptRow matrix; /*ptr to the contigPtr (accessor)*/
|
||||
|
||||
} MatrixObject;
|
||||
|
||||
/*struct data contains a pointer to the actual data that the
|
||||
@@ -56,6 +57,10 @@ be stored in py_data) or be a wrapper for data allocated through
|
||||
blender (stored in blend_data). This is an either/or struct not both*/
|
||||
|
||||
/*prototypes*/
|
||||
PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type);
|
||||
PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type);
|
||||
PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_type, int cb_subtype);
|
||||
|
||||
extern int mathutils_matrix_vector_cb_index;
|
||||
extern struct Mathutils_Callback mathutils_matrix_vector_cb;
|
||||
|
||||
#endif /* EXPP_matrix_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: quat.c 20332 2009-05-22 03:22:56Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -34,16 +34,6 @@
|
||||
|
||||
|
||||
//-------------------------DOC STRINGS ---------------------------
|
||||
static char Quaternion_Identity_doc[] = "() - set the quaternion to it's identity (1, vector)";
|
||||
static char Quaternion_Negate_doc[] = "() - set all values in the quaternion to their negative";
|
||||
static char Quaternion_Conjugate_doc[] = "() - set the quaternion to it's conjugate";
|
||||
static char Quaternion_Inverse_doc[] = "() - set the quaternion to it's inverse";
|
||||
static char Quaternion_Normalize_doc[] = "() - normalize the vector portion of the quaternion";
|
||||
static char Quaternion_ToEuler_doc[] = "(eul_compat) - return a euler rotation representing the quaternion, optional euler argument that the new euler will be made compatible with.";
|
||||
static char Quaternion_ToMatrix_doc[] = "() - return a rotation matrix representing the quaternion";
|
||||
static char Quaternion_Cross_doc[] = "(other) - return the cross product between this quaternion and another";
|
||||
static char Quaternion_Dot_doc[] = "(other) - return the dot product between this quaternion and another";
|
||||
static char Quaternion_copy_doc[] = "() - return a copy of the quat";
|
||||
|
||||
static PyObject *Quaternion_Identity( QuaternionObject * self );
|
||||
static PyObject *Quaternion_Negate( QuaternionObject * self );
|
||||
@@ -58,27 +48,27 @@ static PyObject *Quaternion_copy( QuaternionObject * self );
|
||||
|
||||
//-----------------------METHOD DEFINITIONS ----------------------
|
||||
static struct PyMethodDef Quaternion_methods[] = {
|
||||
{"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc},
|
||||
{"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc},
|
||||
{"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc},
|
||||
{"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc},
|
||||
{"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc},
|
||||
{"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc},
|
||||
{"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc},
|
||||
{"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc},
|
||||
{"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc},
|
||||
{"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
|
||||
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
|
||||
{"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, NULL},
|
||||
{"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, NULL},
|
||||
{"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, NULL},
|
||||
{"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, NULL},
|
||||
{"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, NULL},
|
||||
{"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, NULL},
|
||||
{"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, NULL},
|
||||
{"cross", (PyCFunction) Quaternion_Cross, METH_O, NULL},
|
||||
{"dot", (PyCFunction) Quaternion_Dot, METH_O, NULL},
|
||||
{"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL},
|
||||
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
//----------------------------------Mathutils.Quaternion() --------------
|
||||
static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *listObject = NULL, *n, *q, *f;
|
||||
PyObject *listObject = NULL, *n, *q;
|
||||
int size, i;
|
||||
float quat[4], scalar;
|
||||
double norm = 0.0f, angle = 0.0f;
|
||||
float quat[4];
|
||||
double angle = 0.0f;
|
||||
|
||||
size = PyTuple_GET_SIZE(args);
|
||||
if (size == 1 || size == 2) { //seq?
|
||||
@@ -127,7 +117,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
|
||||
}
|
||||
}
|
||||
} else if (size == 0) { //returns a new empty quat
|
||||
return newQuaternionObject(NULL, Py_NEW);
|
||||
return newQuaternionObject(NULL, Py_NEW, NULL);
|
||||
} else {
|
||||
listObject = args;
|
||||
}
|
||||
@@ -151,31 +141,23 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scalar = PyFloat_AsDouble(q);
|
||||
if (scalar==-1 && PyErr_Occurred()) {
|
||||
Py_DECREF(q);
|
||||
quat[i] = PyFloat_AsDouble(q);
|
||||
Py_DECREF(q);
|
||||
|
||||
if (quat[i]==-1 && PyErr_Occurred()) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
quat[i] = scalar;
|
||||
Py_DECREF(f);
|
||||
Py_DECREF(q);
|
||||
}
|
||||
if(size == 3){ //calculate the quat based on axis/angle
|
||||
norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2]);
|
||||
quat[0] /= (float)norm;
|
||||
quat[1] /= (float)norm;
|
||||
quat[2] /= (float)norm;
|
||||
|
||||
angle = angle * (Py_PI / 180);
|
||||
quat[3] =(float) (sin(angle/ 2.0f)) * quat[2];
|
||||
quat[2] =(float) (sin(angle/ 2.0f)) * quat[1];
|
||||
quat[1] =(float) (sin(angle/ 2.0f)) * quat[0];
|
||||
quat[0] =(float) (cos(angle/ 2.0f));
|
||||
}
|
||||
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
if(size == 3) //calculate the quat based on axis/angle
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
AxisAngleToQuat(quat, quat, angle * (Py_PI / 180));
|
||||
#else
|
||||
AxisAngleToQuat(quat, quat, angle);
|
||||
#endif
|
||||
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
//-----------------------------METHODS------------------------------
|
||||
@@ -190,34 +172,48 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
|
||||
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
|
||||
return NULL;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
if(eul_compat) {
|
||||
float mat[3][3], eul_compatf[3];
|
||||
|
||||
if(!BaseMath_ReadCallback(eul_compat))
|
||||
return NULL;
|
||||
|
||||
QuatToMat3(self->quat, mat);
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
for(x = 0; x < 3; x++) {
|
||||
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
|
||||
}
|
||||
|
||||
QuatToMat3(self->quat, mat);
|
||||
Mat3ToCompatibleEul(mat, eul, eul_compatf);
|
||||
#else
|
||||
Mat3ToCompatibleEul(mat, eul, eul_compat->eul);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
QuatToEul(self->quat, eul);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
for(x = 0; x < 3; x++) {
|
||||
eul[x] *= (180 / (float)Py_PI);
|
||||
}
|
||||
return newEulerObject(eul, Py_NEW);
|
||||
#endif
|
||||
return newEulerObject(eul, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------Quaternion.toMatrix()------------------
|
||||
//return the quat as a matrix
|
||||
static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
|
||||
{
|
||||
float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
QuatToMat3(self->quat, (float (*)[3]) mat);
|
||||
float mat[9]; /* all values are set */
|
||||
|
||||
return newMatrixObject(mat, 3, 3, Py_NEW);
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
QuatToMat3(self->quat, (float (*)[3]) mat);
|
||||
return newMatrixObject(mat, 3, 3, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
//----------------------------Quaternion.cross(other)------------------
|
||||
@@ -231,33 +227,38 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
|
||||
return NULL;
|
||||
|
||||
QuatMul(quat, self->quat, value->quat);
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
//----------------------------Quaternion.dot(other)------------------
|
||||
//return the dot quat
|
||||
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
|
||||
{
|
||||
int x;
|
||||
double dot = 0.0;
|
||||
|
||||
if (!QuaternionObject_Check(value)) {
|
||||
PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(x = 0; x < 4; x++) {
|
||||
dot += self->quat[x] * value->quat[x];
|
||||
}
|
||||
return PyFloat_FromDouble(dot);
|
||||
|
||||
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
|
||||
return NULL;
|
||||
|
||||
return PyFloat_FromDouble(QuatDot(self->quat, value->quat));
|
||||
}
|
||||
|
||||
//----------------------------Quaternion.normalize()----------------
|
||||
//normalize the axis of rotation of [theta,vector]
|
||||
static PyObject *Quaternion_Normalize(QuaternionObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
NormalQuat(self->quat);
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
@@ -265,20 +266,12 @@ static PyObject *Quaternion_Normalize(QuaternionObject * self)
|
||||
//invert the quat
|
||||
static PyObject *Quaternion_Inverse(QuaternionObject * self)
|
||||
{
|
||||
double mag = 0.0f;
|
||||
int x;
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
for(x = 1; x < 4; x++) {
|
||||
self->quat[x] = -self->quat[x];
|
||||
}
|
||||
for(x = 0; x < 4; x++) {
|
||||
mag += (self->quat[x] * self->quat[x]);
|
||||
}
|
||||
mag = sqrt(mag);
|
||||
for(x = 0; x < 4; x++) {
|
||||
self->quat[x] /= (float)(mag * mag);
|
||||
}
|
||||
QuatInv(self->quat);
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
@@ -286,11 +279,12 @@ static PyObject *Quaternion_Inverse(QuaternionObject * self)
|
||||
//generate the identity quaternion
|
||||
static 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;
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
QuatOne(self->quat);
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
@@ -298,10 +292,12 @@ static PyObject *Quaternion_Identity(QuaternionObject * self)
|
||||
//negate the quat
|
||||
static PyObject *Quaternion_Negate(QuaternionObject * self)
|
||||
{
|
||||
int x;
|
||||
for(x = 0; x < 4; x++) {
|
||||
self->quat[x] = -self->quat[x];
|
||||
}
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
QuatMulf(self->quat, -1.0f);
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
@@ -309,10 +305,12 @@ static PyObject *Quaternion_Negate(QuaternionObject * self)
|
||||
//negate the vector part
|
||||
static PyObject *Quaternion_Conjugate(QuaternionObject * self)
|
||||
{
|
||||
int x;
|
||||
for(x = 1; x < 4; x++) {
|
||||
self->quat[x] = -self->quat[x];
|
||||
}
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
QuatConj(self->quat);
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
@@ -320,18 +318,10 @@ static PyObject *Quaternion_Conjugate(QuaternionObject * self)
|
||||
//return a copy of the quat
|
||||
static PyObject *Quaternion_copy(QuaternionObject * self)
|
||||
{
|
||||
return newQuaternionObject(self->quat, Py_NEW);
|
||||
}
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
//----------------------------dealloc()(internal) ------------------
|
||||
//free the py_object
|
||||
static void Quaternion_dealloc(QuaternionObject * self)
|
||||
{
|
||||
//only free py_data
|
||||
if(self->data.py_data){
|
||||
PyMem_Free(self->data.py_data);
|
||||
}
|
||||
PyObject_DEL(self);
|
||||
return newQuaternionObject(self->quat, Py_NEW, Py_TYPE(self));
|
||||
}
|
||||
|
||||
//----------------------------print object (internal)--------------
|
||||
@@ -339,6 +329,10 @@ static void Quaternion_dealloc(QuaternionObject * self)
|
||||
static PyObject *Quaternion_repr(QuaternionObject * self)
|
||||
{
|
||||
char str[64];
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]);
|
||||
return PyUnicode_FromString(str);
|
||||
}
|
||||
@@ -349,15 +343,24 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c
|
||||
QuaternionObject *quatA = NULL, *quatB = NULL;
|
||||
int result = 0;
|
||||
|
||||
if (!QuaternionObject_Check(objectA) || !QuaternionObject_Check(objectB)){
|
||||
if(QuaternionObject_Check(objectA)) {
|
||||
quatA = (QuaternionObject*)objectA;
|
||||
if(!BaseMath_ReadCallback(quatA))
|
||||
return NULL;
|
||||
}
|
||||
if(QuaternionObject_Check(objectB)) {
|
||||
quatB = (QuaternionObject*)objectB;
|
||||
if(!BaseMath_ReadCallback(quatB))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!quatA || !quatB){
|
||||
if (comparison_type == Py_NE){
|
||||
Py_RETURN_TRUE;
|
||||
}else{
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
quatA = (QuaternionObject*)objectA;
|
||||
quatB = (QuaternionObject*)objectB;
|
||||
|
||||
switch (comparison_type){
|
||||
case Py_EQ:
|
||||
@@ -381,8 +384,7 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
//------------------------tp_doc
|
||||
static char QuaternionObject_doc[] = "This is a wrapper for quaternion objects.";
|
||||
|
||||
//---------------------SEQUENCE PROTOCOLS------------------------
|
||||
//----------------------------len(object)------------------------
|
||||
//sequence length
|
||||
@@ -394,10 +396,16 @@ static int Quaternion_len(QuaternionObject * self)
|
||||
//sequence accessor (get)
|
||||
static PyObject *Quaternion_item(QuaternionObject * self, int i)
|
||||
{
|
||||
if(i<0) i= 4-i;
|
||||
|
||||
if(i < 0 || i >= 4) {
|
||||
PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadIndexCallback(self, i))
|
||||
return NULL;
|
||||
|
||||
return PyFloat_FromDouble(self->quat[i]);
|
||||
|
||||
}
|
||||
@@ -405,21 +413,23 @@ static PyObject *Quaternion_item(QuaternionObject * self, int i)
|
||||
//sequence accessor (set)
|
||||
static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
|
||||
{
|
||||
PyObject *f = NULL;
|
||||
|
||||
f = PyNumber_Float(ob);
|
||||
if(f == NULL) { // parsed item not a number
|
||||
PyErr_SetString(PyExc_TypeError, "quaternion[attribute] = x: argument not a number\n");
|
||||
float scalar= (float)PyFloat_AsDouble(ob);
|
||||
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
|
||||
PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(i<0) i= 4-i;
|
||||
|
||||
if(i < 0 || i >= 4){
|
||||
Py_DECREF(f);
|
||||
PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n");
|
||||
return -1;
|
||||
}
|
||||
self->quat[i] = (float)PyFloat_AS_DOUBLE(f);
|
||||
Py_DECREF(f);
|
||||
self->quat[i] = scalar;
|
||||
|
||||
if(!BaseMath_WriteIndexCallback(self, i))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
//----------------------------object[z:y]------------------------
|
||||
@@ -429,6 +439,9 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
|
||||
PyObject *list = NULL;
|
||||
int count;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
CLAMP(begin, 0, 4);
|
||||
if (end<0) end= 5+end;
|
||||
CLAMP(end, 0, 4);
|
||||
@@ -444,12 +457,14 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
|
||||
}
|
||||
//----------------------------object[z:y]------------------------
|
||||
//sequence slice (set)
|
||||
static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end,
|
||||
PyObject * seq)
|
||||
static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq)
|
||||
{
|
||||
int i, y, size = 0;
|
||||
float quat[4];
|
||||
PyObject *q, *f;
|
||||
PyObject *q;
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return -1;
|
||||
|
||||
CLAMP(begin, 0, 4);
|
||||
if (end<0) end= 5+end;
|
||||
@@ -469,21 +484,19 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end,
|
||||
return -1;
|
||||
}
|
||||
|
||||
f = PyNumber_Float(q);
|
||||
if(f == NULL) { // parsed item not a number
|
||||
Py_DECREF(q);
|
||||
quat[i]= (float)PyFloat_AsDouble(q);
|
||||
Py_DECREF(q);
|
||||
|
||||
if(quat[i]==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
|
||||
PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
quat[i] = (float)PyFloat_AS_DOUBLE(f);
|
||||
Py_DECREF(f);
|
||||
Py_DECREF(q);
|
||||
}
|
||||
//parsed well - now set in vector
|
||||
for(y = 0; y < size; y++){
|
||||
for(y = 0; y < size; y++)
|
||||
self->quat[begin + y] = quat[y];
|
||||
}
|
||||
|
||||
BaseMath_WriteCallback(self);
|
||||
return 0;
|
||||
}
|
||||
//------------------------NUMERIC PROTOCOLS----------------------
|
||||
@@ -491,7 +504,6 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end,
|
||||
//addition
|
||||
static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
|
||||
{
|
||||
int x;
|
||||
float quat[4];
|
||||
QuaternionObject *quat1 = NULL, *quat2 = NULL;
|
||||
|
||||
@@ -499,15 +511,14 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
|
||||
PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
quat1 = (QuaternionObject*)q1;
|
||||
quat2 = (QuaternionObject*)q2;
|
||||
|
||||
for(x = 0; x < 4; x++) {
|
||||
quat[x] = quat1->quat[x] + quat2->quat[x];
|
||||
}
|
||||
if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
|
||||
return NULL;
|
||||
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
QuatAdd(quat, quat1->quat, quat2->quat, 1.0f);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
//------------------------obj - obj------------------------------
|
||||
//subtraction
|
||||
@@ -525,40 +536,45 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
|
||||
quat1 = (QuaternionObject*)q1;
|
||||
quat2 = (QuaternionObject*)q2;
|
||||
|
||||
if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
|
||||
return NULL;
|
||||
|
||||
for(x = 0; x < 4; x++) {
|
||||
quat[x] = quat1->quat[x] - quat2->quat[x];
|
||||
}
|
||||
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
//------------------------obj * obj------------------------------
|
||||
//mulplication
|
||||
static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
|
||||
{
|
||||
int x;
|
||||
float quat[4], scalar;
|
||||
double dot = 0.0f;
|
||||
QuaternionObject *quat1 = NULL, *quat2 = NULL;
|
||||
VectorObject *vec = NULL;
|
||||
|
||||
quat1 = (QuaternionObject*)q1;
|
||||
quat2 = (QuaternionObject*)q2;
|
||||
if(QuaternionObject_Check(q1)) {
|
||||
quat1 = (QuaternionObject*)q1;
|
||||
if(!BaseMath_ReadCallback(quat1))
|
||||
return NULL;
|
||||
}
|
||||
if(QuaternionObject_Check(q2)) {
|
||||
quat2 = (QuaternionObject*)q2;
|
||||
if(!BaseMath_ReadCallback(quat2))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(QuaternionObject_Check(q1) && QuaternionObject_Check(q2)) { /* QUAT*QUAT (dot product) */
|
||||
for(x = 0; x < 4; x++) {
|
||||
dot += quat1->quat[x] * quat1->quat[x];
|
||||
}
|
||||
return PyFloat_FromDouble(dot);
|
||||
if(quat1 && quat2) { /* QUAT*QUAT (dot product) */
|
||||
return PyFloat_FromDouble(QuatDot(quat1->quat, quat2->quat));
|
||||
}
|
||||
|
||||
/* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */
|
||||
if(!QuaternionObject_Check(q1)) {
|
||||
scalar= PyFloat_AsDouble(q1);
|
||||
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */
|
||||
for(x = 0; x < 4; x++) {
|
||||
quat[x] = quat2->quat[x] * scalar;
|
||||
}
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
QUATCOPY(quat, quat2->quat);
|
||||
QuatMulf(quat, scalar);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type");
|
||||
return NULL;
|
||||
@@ -570,15 +586,14 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
|
||||
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
|
||||
return NULL;
|
||||
}
|
||||
return quat_rotation((PyObject*)quat1, (PyObject*)vec);
|
||||
return quat_rotation((PyObject*)quat1, (PyObject*)vec); /* vector updating done inside the func */
|
||||
}
|
||||
|
||||
scalar= PyFloat_AsDouble(q2);
|
||||
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */
|
||||
for(x = 0; x < 4; x++) {
|
||||
quat[x] = quat1->quat[x] * scalar;
|
||||
}
|
||||
return newQuaternionObject(quat, Py_NEW);
|
||||
QUATCOPY(quat, quat1->quat);
|
||||
QuatMulf(quat, scalar);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,6 +611,45 @@ static PySequenceMethods Quaternion_SeqMethods = {
|
||||
(ssizeobjargproc) Quaternion_ass_item, /* sq_ass_item */
|
||||
(ssizessizeobjargproc) Quaternion_ass_slice, /* sq_ass_slice */
|
||||
};
|
||||
|
||||
#if (PY_VERSION_HEX >= 0x03000000)
|
||||
static PyNumberMethods Quaternion_NumMethods = {
|
||||
(binaryfunc) Quaternion_add, /*nb_add*/
|
||||
(binaryfunc) Quaternion_sub, /*nb_subtract*/
|
||||
(binaryfunc) Quaternion_mul, /*nb_multiply*/
|
||||
0, /*nb_remainder*/
|
||||
0, /*nb_divmod*/
|
||||
0, /*nb_power*/
|
||||
(unaryfunc) 0, /*nb_negative*/
|
||||
(unaryfunc) 0, /*tp_positive*/
|
||||
(unaryfunc) 0, /*tp_absolute*/
|
||||
(inquiry) 0, /*tp_bool*/
|
||||
(unaryfunc) 0, /*nb_invert*/
|
||||
0, /*nb_lshift*/
|
||||
(binaryfunc)0, /*nb_rshift*/
|
||||
0, /*nb_and*/
|
||||
0, /*nb_xor*/
|
||||
0, /*nb_or*/
|
||||
0, /*nb_int*/
|
||||
0, /*nb_reserved*/
|
||||
0, /*nb_float*/
|
||||
0, /* nb_inplace_add */
|
||||
0, /* nb_inplace_subtract */
|
||||
0, /* nb_inplace_multiply */
|
||||
0, /* nb_inplace_remainder */
|
||||
0, /* nb_inplace_power */
|
||||
0, /* nb_inplace_lshift */
|
||||
0, /* nb_inplace_rshift */
|
||||
0, /* nb_inplace_and */
|
||||
0, /* nb_inplace_xor */
|
||||
0, /* nb_inplace_or */
|
||||
0, /* nb_floor_divide */
|
||||
0, /* nb_true_divide */
|
||||
0, /* nb_inplace_floor_divide */
|
||||
0, /* nb_inplace_true_divide */
|
||||
0, /* nb_index */
|
||||
};
|
||||
#else
|
||||
static PyNumberMethods Quaternion_NumMethods = {
|
||||
(binaryfunc) Quaternion_add, /* __add__ */
|
||||
(binaryfunc) Quaternion_sub, /* __sub__ */
|
||||
@@ -620,76 +674,31 @@ static PyNumberMethods Quaternion_NumMethods = {
|
||||
(unaryfunc) 0, /* __float__ */
|
||||
(unaryfunc) 0, /* __oct__ */
|
||||
(unaryfunc) 0, /* __hex__ */
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
|
||||
{
|
||||
switch( (long)type ) {
|
||||
case 'W':
|
||||
return PyFloat_FromDouble(self->quat[0]);
|
||||
case 'X':
|
||||
return PyFloat_FromDouble(self->quat[1]);
|
||||
case 'Y':
|
||||
return PyFloat_FromDouble(self->quat[2]);
|
||||
case 'Z':
|
||||
return PyFloat_FromDouble(self->quat[3]);
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_SystemError, "corrupt quaternion, cannot get axis");
|
||||
return NULL;
|
||||
return Quaternion_item(self, GET_INT_FROM_POINTER(type));
|
||||
}
|
||||
|
||||
static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
|
||||
{
|
||||
float param= (float)PyFloat_AsDouble( value );
|
||||
|
||||
if (param==-1 && PyErr_Occurred()) {
|
||||
PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
|
||||
return -1;
|
||||
}
|
||||
switch( (long)type ) {
|
||||
case 'W':
|
||||
self->quat[0]= param;
|
||||
break;
|
||||
case 'X':
|
||||
self->quat[1]= param;
|
||||
break;
|
||||
case 'Y':
|
||||
self->quat[2]= param;
|
||||
break;
|
||||
case 'Z':
|
||||
self->quat[3]= param;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *Quaternion_getWrapped( QuaternionObject * self, void *type )
|
||||
{
|
||||
if (self->wrapped == Py_WRAP)
|
||||
Py_RETURN_TRUE;
|
||||
else
|
||||
Py_RETURN_FALSE;
|
||||
return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
|
||||
}
|
||||
|
||||
static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
|
||||
{
|
||||
double mag = 0.0;
|
||||
int i;
|
||||
for(i = 0; i < 4; i++) {
|
||||
mag += self->quat[i] * self->quat[i];
|
||||
}
|
||||
return PyFloat_FromDouble(sqrt(mag));
|
||||
return PyFloat_FromDouble(sqrt(QuatDot(self->quat, self->quat)));
|
||||
}
|
||||
|
||||
static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
|
||||
{
|
||||
double ang = self->quat[0];
|
||||
ang = 2 * (saacos(ang));
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
ang *= (180 / Py_PI);
|
||||
#endif
|
||||
return PyFloat_FromDouble(ang);
|
||||
}
|
||||
|
||||
@@ -710,7 +719,7 @@ static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
|
||||
EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
|
||||
vec[0] = 1.0f;
|
||||
}
|
||||
return (PyObject *) newVectorObject(vec, 3, Py_NEW);
|
||||
return (PyObject *) newVectorObject(vec, 3, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -721,19 +730,19 @@ static PyGetSetDef Quaternion_getseters[] = {
|
||||
{"w",
|
||||
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
|
||||
"Quaternion W value",
|
||||
(void *)'W'},
|
||||
(void *)0},
|
||||
{"x",
|
||||
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
|
||||
"Quaternion X axis",
|
||||
(void *)'X'},
|
||||
(void *)1},
|
||||
{"y",
|
||||
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
|
||||
"Quaternion Y axis",
|
||||
(void *)'Y'},
|
||||
(void *)2},
|
||||
{"z",
|
||||
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
|
||||
"Quaternion Z axis",
|
||||
(void *)'Z'},
|
||||
(void *)3},
|
||||
{"magnitude",
|
||||
(getter)Quaternion_getMagnitude, (setter)NULL,
|
||||
"Size of the quaternion",
|
||||
@@ -747,9 +756,14 @@ static PyGetSetDef Quaternion_getseters[] = {
|
||||
"quaternion axis as a vector",
|
||||
NULL},
|
||||
{"wrapped",
|
||||
(getter)Quaternion_getWrapped, (setter)NULL,
|
||||
(getter)BaseMathObject_getWrapped, (setter)NULL,
|
||||
"True when this wraps blenders internal data",
|
||||
NULL},
|
||||
{"__owner__",
|
||||
(getter)BaseMathObject_getOwner, (setter)NULL,
|
||||
"Read only owner for vectors that depend on another object",
|
||||
NULL},
|
||||
|
||||
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
@@ -766,7 +780,7 @@ PyTypeObject quaternion_Type = {
|
||||
"quaternion", //tp_name
|
||||
sizeof(QuaternionObject), //tp_basicsize
|
||||
0, //tp_itemsize
|
||||
(destructor)Quaternion_dealloc, //tp_dealloc
|
||||
(destructor)BaseMathObject_dealloc, //tp_dealloc
|
||||
0, //tp_print
|
||||
0, //tp_getattr
|
||||
0, //tp_setattr
|
||||
@@ -781,8 +795,8 @@ PyTypeObject quaternion_Type = {
|
||||
0, //tp_getattro
|
||||
0, //tp_setattro
|
||||
0, //tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, //tp_flags
|
||||
QuaternionObject_doc, //tp_doc
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
|
||||
0, //tp_doc
|
||||
0, //tp_traverse
|
||||
0, //tp_clear
|
||||
(richcmpfunc)Quaternion_richcmpr, //tp_richcompare
|
||||
@@ -815,29 +829,26 @@ PyTypeObject quaternion_Type = {
|
||||
(i.e. it was allocated elsewhere by MEM_mallocN())
|
||||
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
|
||||
(i.e. it must be created here with PyMEM_malloc())*/
|
||||
PyObject *newQuaternionObject(float *quat, int type)
|
||||
PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type)
|
||||
{
|
||||
QuaternionObject *self;
|
||||
int x;
|
||||
|
||||
self = PyObject_NEW(QuaternionObject, &quaternion_Type);
|
||||
self->data.blend_data = NULL;
|
||||
self->data.py_data = NULL;
|
||||
if(base_type) self = base_type->tp_alloc(base_type, 0);
|
||||
else self = PyObject_NEW(QuaternionObject, &quaternion_Type);
|
||||
|
||||
/* init callbacks as NULL */
|
||||
self->cb_user= NULL;
|
||||
self->cb_type= self->cb_subtype= 0;
|
||||
|
||||
if(type == Py_WRAP){
|
||||
self->data.blend_data = quat;
|
||||
self->quat = self->data.blend_data;
|
||||
self->quat = quat;
|
||||
self->wrapped = Py_WRAP;
|
||||
}else if (type == Py_NEW){
|
||||
self->data.py_data = PyMem_Malloc(4 * sizeof(float));
|
||||
self->quat = self->data.py_data;
|
||||
self->quat = PyMem_Malloc(4 * sizeof(float));
|
||||
if(!quat) { //new empty
|
||||
Quaternion_Identity(self);
|
||||
Py_DECREF(self);
|
||||
QuatOne(self->quat);
|
||||
}else{
|
||||
for(x = 0; x < 4; x++){
|
||||
self->quat[x] = quat[x];
|
||||
}
|
||||
QUATCOPY(self->quat, quat);
|
||||
}
|
||||
self->wrapped = Py_NEW;
|
||||
}else{ //bad type
|
||||
@@ -845,3 +856,16 @@ PyObject *newQuaternionObject(float *quat, int type)
|
||||
}
|
||||
return (PyObject *) self;
|
||||
}
|
||||
|
||||
PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
|
||||
{
|
||||
QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL);
|
||||
if(self) {
|
||||
Py_INCREF(cb_user);
|
||||
self->cb_user= cb_user;
|
||||
self->cb_type= (unsigned char)cb_type;
|
||||
self->cb_subtype= (unsigned char)cb_subtype;
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: quat.h 20332 2009-05-22 03:22:56Z campbellbarton $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -35,17 +35,17 @@
|
||||
#include "../intern/bpy_compat.h"
|
||||
|
||||
extern PyTypeObject quaternion_Type;
|
||||
#define QuaternionObject_Check(_v) PyObject_TypeCheck((_v), &quaternion_Type)
|
||||
|
||||
#define QuaternionObject_Check(v) (Py_TYPE(v) == &quaternion_Type)
|
||||
|
||||
typedef struct {
|
||||
typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */
|
||||
PyObject_VAR_HEAD
|
||||
struct{
|
||||
float *py_data; //python managed
|
||||
float *blend_data; //blender managed
|
||||
}data;
|
||||
float *quat; //1D array of data (alias)
|
||||
int wrapped; //is wrapped data?
|
||||
float *quat; /* 1D array of data (alias) */
|
||||
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
|
||||
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
|
||||
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
|
||||
unsigned char wrapped; /* wrapped data type? */
|
||||
/* end BaseMathObject */
|
||||
|
||||
} QuaternionObject;
|
||||
|
||||
/*struct data contains a pointer to the actual data that the
|
||||
@@ -54,6 +54,7 @@ be stored in py_data) or be a wrapper for data allocated through
|
||||
blender (stored in blend_data). This is an either/or struct not both*/
|
||||
|
||||
//prototypes
|
||||
PyObject *newQuaternionObject( float *quat, int type );
|
||||
PyObject *newQuaternionObject( float *quat, int type, PyTypeObject *base_type);
|
||||
PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
|
||||
|
||||
#endif /* EXPP_quat_h */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* $Id: vector.h 20332 2009-05-22 03:22:56Z campbellbarton $
|
||||
/* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -34,17 +34,22 @@
|
||||
#include "../intern/bpy_compat.h"
|
||||
|
||||
extern PyTypeObject vector_Type;
|
||||
#define VectorObject_Check(_v) PyObject_TypeCheck((_v), &vector_Type)
|
||||
|
||||
#define VectorObject_Check(v) (((PyObject *)v)->ob_type == &vector_Type)
|
||||
|
||||
typedef struct {
|
||||
typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */
|
||||
PyObject_VAR_HEAD
|
||||
float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */
|
||||
short size; /* vec size 2,3 or 4 */
|
||||
short wrapped; /* is wrapped data? */
|
||||
float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */
|
||||
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
|
||||
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
|
||||
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
|
||||
unsigned char wrapped; /* wrapped data type? */
|
||||
/* end BaseMathObject */
|
||||
|
||||
unsigned char size; /* vec size 2,3 or 4 */
|
||||
} VectorObject;
|
||||
|
||||
/*prototypes*/
|
||||
PyObject *newVectorObject(float *vec, int size, int type);
|
||||
PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type);
|
||||
PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype);
|
||||
|
||||
#endif /* EXPP_vector_h */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $
|
||||
# $Id$
|
||||
#
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: bpy_compat.h 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
#include "BPY_extern.h"
|
||||
|
||||
#include "../generic/bpy_internal_import.h" // our own imports
|
||||
/* external util modukes */
|
||||
|
||||
#include "../generic/Mathutils.h"
|
||||
#include "../generic/Geometry.h"
|
||||
#include "../generic/BGL.h"
|
||||
|
||||
|
||||
void BPY_free_compiled_text( struct Text *text )
|
||||
@@ -61,11 +66,17 @@ static void bpy_init_modules( void )
|
||||
PyModule_AddObject( mod, "types", BPY_rna_types() );
|
||||
PyModule_AddObject( mod, "props", BPY_rna_props() );
|
||||
PyModule_AddObject( mod, "ops", BPY_operator_module() );
|
||||
PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
|
||||
PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent
|
||||
|
||||
/* add the module so we can import it */
|
||||
PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
|
||||
Py_DECREF(mod);
|
||||
|
||||
|
||||
/* stand alone utility modules not related to blender directly */
|
||||
Geometry_Init("Geometry");
|
||||
Mathutils_Init("Mathutils");
|
||||
BGL_Init("BGL");
|
||||
}
|
||||
|
||||
#if (PY_VERSION_HEX < 0x02050000)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/**
|
||||
* $Id: bpy_operator.c 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/**
|
||||
* $Id: bpy_operator.h 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/**
|
||||
* $Id: bpy_operator_wrap.c 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -47,98 +47,6 @@
|
||||
#define PYOP_ATTR_IDNAME "__name__" /* use pythons class name */
|
||||
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
|
||||
|
||||
static PyObject *pyop_dict_from_event(wmEvent *event)
|
||||
{
|
||||
PyObject *dict= PyDict_New();
|
||||
PyObject *item;
|
||||
char *cstring, ascii[2];
|
||||
|
||||
/* type */
|
||||
item= PyUnicode_FromString(WM_key_event_string(event->type));
|
||||
PyDict_SetItemString(dict, "type", item); Py_DECREF(item);
|
||||
|
||||
/* val */
|
||||
switch(event->val) {
|
||||
case KM_ANY:
|
||||
cstring = "ANY";
|
||||
break;
|
||||
case KM_RELEASE:
|
||||
cstring = "RELEASE";
|
||||
break;
|
||||
case KM_PRESS:
|
||||
cstring = "PRESS";
|
||||
break;
|
||||
default:
|
||||
cstring = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
item= PyUnicode_FromString(cstring);
|
||||
PyDict_SetItemString(dict, "val", item); Py_DECREF(item);
|
||||
|
||||
/* x, y (mouse) */
|
||||
item= PyLong_FromLong(event->x);
|
||||
PyDict_SetItemString(dict, "x", item); Py_DECREF(item);
|
||||
|
||||
item= PyLong_FromLong(event->y);
|
||||
PyDict_SetItemString(dict, "y", item); Py_DECREF(item);
|
||||
|
||||
item= PyLong_FromLong(event->prevx);
|
||||
PyDict_SetItemString(dict, "prevx", item); Py_DECREF(item);
|
||||
|
||||
item= PyLong_FromLong(event->prevy);
|
||||
PyDict_SetItemString(dict, "prevy", item); Py_DECREF(item);
|
||||
|
||||
/* ascii */
|
||||
ascii[0]= event->ascii;
|
||||
ascii[1]= '\0';
|
||||
item= PyUnicode_FromString(ascii);
|
||||
PyDict_SetItemString(dict, "ascii", item); Py_DECREF(item);
|
||||
|
||||
/* modifier keys */
|
||||
item= PyLong_FromLong(event->shift);
|
||||
PyDict_SetItemString(dict, "shift", item); Py_DECREF(item);
|
||||
|
||||
item= PyLong_FromLong(event->ctrl);
|
||||
PyDict_SetItemString(dict, "ctrl", item); Py_DECREF(item);
|
||||
|
||||
item= PyLong_FromLong(event->alt);
|
||||
PyDict_SetItemString(dict, "alt", item); Py_DECREF(item);
|
||||
|
||||
item= PyLong_FromLong(event->oskey);
|
||||
PyDict_SetItemString(dict, "oskey", item); Py_DECREF(item);
|
||||
|
||||
|
||||
|
||||
/* modifier */
|
||||
#if 0
|
||||
item= PyTuple_New(0);
|
||||
if(event->keymodifier & KM_SHIFT) {
|
||||
_PyTuple_Resize(&item, size+1);
|
||||
PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("SHIFT"));
|
||||
size++;
|
||||
}
|
||||
if(event->keymodifier & KM_CTRL) {
|
||||
_PyTuple_Resize(&item, size+1);
|
||||
PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("CTRL"));
|
||||
size++;
|
||||
}
|
||||
if(event->keymodifier & KM_ALT) {
|
||||
_PyTuple_Resize(&item, size+1);
|
||||
PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("ALT"));
|
||||
size++;
|
||||
}
|
||||
if(event->keymodifier & KM_OSKEY) {
|
||||
_PyTuple_Resize(&item, size+1);
|
||||
PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("OSKEY"));
|
||||
size++;
|
||||
}
|
||||
PyDict_SetItemString(dict, "keymodifier", item); Py_DECREF(item);
|
||||
#endif
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
static struct BPY_flag_def pyop_ret_flags[] = {
|
||||
{"RUNNING_MODAL", OPERATOR_RUNNING_MODAL},
|
||||
{"CANCELLED", OPERATOR_CANCELLED},
|
||||
@@ -180,6 +88,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
|
||||
int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
|
||||
PointerRNA ptr_context;
|
||||
PointerRNA ptr_operator;
|
||||
PointerRNA ptr_event;
|
||||
PyObject *py_operator;
|
||||
|
||||
PyGILState_STATE gilstate = PyGILState_Ensure();
|
||||
@@ -198,15 +107,9 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
|
||||
|
||||
/* Assign instance attributes from operator properties */
|
||||
{
|
||||
PropertyRNA *prop, *iterprop;
|
||||
CollectionPropertyIterator iter;
|
||||
const char *arg_name;
|
||||
|
||||
iterprop= RNA_struct_iterator_property(op->ptr->type);
|
||||
RNA_property_collection_begin(op->ptr, iterprop, &iter);
|
||||
|
||||
for(; iter.valid; RNA_property_collection_next(&iter)) {
|
||||
prop= iter.ptr.data;
|
||||
RNA_STRUCT_BEGIN(op->ptr, prop) {
|
||||
arg_name= RNA_property_identifier(prop);
|
||||
|
||||
if (strcmp(arg_name, "rna_type")==0) continue;
|
||||
@@ -215,8 +118,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
|
||||
PyObject_SetAttrString(py_class_instance, arg_name, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
|
||||
RNA_property_collection_end(&iter);
|
||||
RNA_STRUCT_END;
|
||||
}
|
||||
|
||||
/* set operator pointer RNA as instance "__operator__" attribute */
|
||||
@@ -230,11 +132,13 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
|
||||
if (mode==PYOP_INVOKE) {
|
||||
item= PyObject_GetAttrString(py_class, "invoke");
|
||||
args = PyTuple_New(3);
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_Event, event, &ptr_event);
|
||||
|
||||
// PyTuple_SET_ITEM "steals" object reference, it is
|
||||
// an object passed shouldn't be DECREF'ed
|
||||
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
|
||||
PyTuple_SET_ITEM(args, 2, pyop_dict_from_event(event));
|
||||
PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_event));
|
||||
}
|
||||
else if (mode==PYOP_EXEC) {
|
||||
item= PyObject_GetAttrString(py_class, "execute");
|
||||
@@ -449,7 +353,8 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
|
||||
|
||||
/* remove if it already exists */
|
||||
if ((ot=WM_operatortype_find(idname))) {
|
||||
Py_XDECREF((PyObject*)ot->pyop_data);
|
||||
if(ot->pyop_data)
|
||||
Py_XDECREF((PyObject*)ot->pyop_data);
|
||||
WM_operatortype_remove(idname);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/**
|
||||
* $Id: bpy_operator_wrap.h 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: bpy_rna.h 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: bpy_ui.c 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: bpy_ui.h 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: bpy_util.c 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -171,7 +171,7 @@ void PyObSpit(char *name, PyObject *var) {
|
||||
else {
|
||||
PyObject_Print(var, stderr, 0);
|
||||
fprintf(stderr, " ref:%d ", var->ob_refcnt);
|
||||
fprintf(stderr, " ptr:%ld", (long)var);
|
||||
fprintf(stderr, " ptr:%p", (void *)var);
|
||||
|
||||
fprintf(stderr, " type:");
|
||||
if(Py_TYPE(var))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: bpy_util.h 21247 2009-06-29 21:50:53Z jaguarandi $
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user