- Patch #2491: Mathutils.AngleBetweenVecs BUGFIX http://projects.blender.org/tracker/?func=detail&aid=2491&group_id=9&atid=127 - #2607: Python String button can segfault if the allowable length is greater than 400 http://projects.blender.org/tracker/?func=detail&atid=125&aid=2607&group_id=9 - #2490: Vector == None gives warning http://projects.blender.org/tracker/?func=detail&aid=2490&group_id=9&atid=125 - #2476: Image.Draw() http://projects.blender.org/tracker/?func=detail&aid=2476&group_id=9&atid=125 All reported by Campbell, who also wrote the #2491 patch. Ken Hughes provided patches for #2490 and #2476. Thanks guys.
1626 lines
49 KiB
C
1626 lines
49 KiB
C
/*
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version. The Blender
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
* about this.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*
|
|
* This is a new part of Blender.
|
|
*
|
|
* Contributor(s): Joseph Gilbert, Campbell Barton
|
|
*
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
*/
|
|
|
|
#include <Python.h>
|
|
#include <BKE_main.h>
|
|
#include <BKE_global.h>
|
|
#include <BKE_library.h>
|
|
#include <BKE_utildefines.h>
|
|
#include <BLI_blenlib.h>
|
|
#include <BLI_arithb.h>
|
|
#include <PIL_time.h>
|
|
#include <BLI_rand.h>
|
|
#include <math.h>
|
|
#include "vector.h"
|
|
#include "euler.h"
|
|
#include "quat.h"
|
|
#include "matrix.h"
|
|
#include "blendef.h"
|
|
#include "mydevice.h"
|
|
#include "constant.h"
|
|
#include "gen_utils.h"
|
|
#include "Mathutils.h"
|
|
|
|
|
|
/*****************************************************************************/
|
|
// Python API function prototypes for the Mathutils module.
|
|
/*****************************************************************************/
|
|
static PyObject *M_Mathutils_Rand( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_Vector( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_CrossVecs( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_DotVecs( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_AngleBetweenVecs( PyObject * self,
|
|
PyObject * args );
|
|
static PyObject *M_Mathutils_MidpointVecs( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_VecMultMat( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_ProjectVecs( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_CopyVec( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_Matrix( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_RotationMatrix( PyObject * self,
|
|
PyObject * args );
|
|
static PyObject *M_Mathutils_ScaleMatrix( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_OrthoProjectionMatrix( PyObject * self,
|
|
PyObject * args );
|
|
static PyObject *M_Mathutils_ShearMatrix( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_TranslationMatrix( PyObject * self,
|
|
PyObject * args );
|
|
static PyObject *M_Mathutils_MatMultVec( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_CopyMat( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_Quaternion( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_CrossQuats( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_DotQuats( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_CopyQuat( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_DifferenceQuats( PyObject * self,
|
|
PyObject * args );
|
|
static PyObject *M_Mathutils_Slerp( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_Euler( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_CopyEuler( PyObject * self, PyObject * args );
|
|
static PyObject *M_Mathutils_RotateEuler( PyObject * self, PyObject * args );
|
|
|
|
/*****************************************************************************/
|
|
// The following string definitions are used for documentation strings.
|
|
// In Python these will be written to the console when doing a
|
|
// Blender.Mathutils.__doc__
|
|
/* Mathutils Module strings */
|
|
/****************************************************************************/
|
|
static char M_Mathutils_doc[] = "The Blender Mathutils module\n\n";
|
|
static char M_Mathutils_Vector_doc[] =
|
|
"() - create a new vector object from a list of floats";
|
|
static char M_Mathutils_Matrix_doc[] =
|
|
"() - create a new matrix object from a list of floats";
|
|
static char M_Mathutils_Quaternion_doc[] =
|
|
"() - create a quaternion from a list or an axis of rotation and an angle";
|
|
static char M_Mathutils_Euler_doc[] =
|
|
"() - create and return a new euler object";
|
|
static char M_Mathutils_Rand_doc[] = "() - return a random number";
|
|
static char M_Mathutils_CrossVecs_doc[] =
|
|
"() - returns a vector perpedicular to the 2 vectors crossed";
|
|
static char M_Mathutils_CopyVec_doc[] = "() - create a copy of vector";
|
|
static char M_Mathutils_DotVecs_doc[] =
|
|
"() - return the dot product of two vectors";
|
|
static char M_Mathutils_AngleBetweenVecs_doc[] =
|
|
"() - returns the angle between two vectors in degrees";
|
|
static char M_Mathutils_MidpointVecs_doc[] =
|
|
"() - return the vector to the midpoint between two vectors";
|
|
static char M_Mathutils_MatMultVec_doc[] =
|
|
"() - multiplies a matrix by a column vector";
|
|
static char M_Mathutils_VecMultMat_doc[] =
|
|
"() - multiplies a row vector by a matrix";
|
|
static char M_Mathutils_ProjectVecs_doc[] =
|
|
"() - returns the projection vector from the projection of vecA onto vecB";
|
|
static char M_Mathutils_RotationMatrix_doc[] =
|
|
"() - construct a rotation matrix from an angle and axis of rotation";
|
|
static char M_Mathutils_ScaleMatrix_doc[] =
|
|
"() - construct a scaling matrix from a scaling factor";
|
|
static char M_Mathutils_OrthoProjectionMatrix_doc[] =
|
|
"() - construct a orthographic projection matrix from a selected plane";
|
|
static char M_Mathutils_ShearMatrix_doc[] =
|
|
"() - construct a shearing matrix from a plane of shear and a shear factor";
|
|
static char M_Mathutils_CopyMat_doc[] = "() - create a copy of a matrix";
|
|
static char M_Mathutils_TranslationMatrix_doc[] =
|
|
"() - create a translation matrix from a vector";
|
|
static char M_Mathutils_CopyQuat_doc[] = "() - copy quatB to quatA";
|
|
static char M_Mathutils_CopyEuler_doc[] = "() - copy eulB to eultA";
|
|
static char M_Mathutils_CrossQuats_doc[] =
|
|
"() - return the mutliplication of two quaternions";
|
|
static char M_Mathutils_DotQuats_doc[] =
|
|
"() - return the dot product of two quaternions";
|
|
static char M_Mathutils_Slerp_doc[] =
|
|
"() - returns the interpolation between two quaternions";
|
|
static char M_Mathutils_DifferenceQuats_doc[] =
|
|
"() - return the angular displacment difference between two quats";
|
|
static char M_Mathutils_RotateEuler_doc[] =
|
|
"() - rotate euler by an axis and angle";
|
|
|
|
|
|
/****************************************************************************/
|
|
// Python method structure definition for Blender.Mathutils module:
|
|
/****************************************************************************/
|
|
struct PyMethodDef M_Mathutils_methods[] = {
|
|
{"Rand", ( PyCFunction ) M_Mathutils_Rand, METH_VARARGS,
|
|
M_Mathutils_Rand_doc},
|
|
{"Vector", ( PyCFunction ) M_Mathutils_Vector, METH_VARARGS,
|
|
M_Mathutils_Vector_doc},
|
|
{"CrossVecs", ( PyCFunction ) M_Mathutils_CrossVecs, METH_VARARGS,
|
|
M_Mathutils_CrossVecs_doc},
|
|
{"DotVecs", ( PyCFunction ) M_Mathutils_DotVecs, METH_VARARGS,
|
|
M_Mathutils_DotVecs_doc},
|
|
{"AngleBetweenVecs", ( PyCFunction ) M_Mathutils_AngleBetweenVecs,
|
|
METH_VARARGS,
|
|
M_Mathutils_AngleBetweenVecs_doc},
|
|
{"MidpointVecs", ( PyCFunction ) M_Mathutils_MidpointVecs,
|
|
METH_VARARGS,
|
|
M_Mathutils_MidpointVecs_doc},
|
|
{"VecMultMat", ( PyCFunction ) M_Mathutils_VecMultMat, METH_VARARGS,
|
|
M_Mathutils_VecMultMat_doc},
|
|
{"ProjectVecs", ( PyCFunction ) M_Mathutils_ProjectVecs, METH_VARARGS,
|
|
M_Mathutils_ProjectVecs_doc},
|
|
{"CopyVec", ( PyCFunction ) M_Mathutils_CopyVec, METH_VARARGS,
|
|
M_Mathutils_CopyVec_doc},
|
|
{"Matrix", ( PyCFunction ) M_Mathutils_Matrix, METH_VARARGS,
|
|
M_Mathutils_Matrix_doc},
|
|
{"RotationMatrix", ( PyCFunction ) M_Mathutils_RotationMatrix,
|
|
METH_VARARGS,
|
|
M_Mathutils_RotationMatrix_doc},
|
|
{"ScaleMatrix", ( PyCFunction ) M_Mathutils_ScaleMatrix, METH_VARARGS,
|
|
M_Mathutils_ScaleMatrix_doc},
|
|
{"ShearMatrix", ( PyCFunction ) M_Mathutils_ShearMatrix, METH_VARARGS,
|
|
M_Mathutils_ShearMatrix_doc},
|
|
{"TranslationMatrix", ( PyCFunction ) M_Mathutils_TranslationMatrix,
|
|
METH_VARARGS,
|
|
M_Mathutils_TranslationMatrix_doc},
|
|
{"CopyMat", ( PyCFunction ) M_Mathutils_CopyMat, METH_VARARGS,
|
|
M_Mathutils_CopyMat_doc},
|
|
{"OrthoProjectionMatrix",
|
|
( PyCFunction ) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS,
|
|
M_Mathutils_OrthoProjectionMatrix_doc},
|
|
{"MatMultVec", ( PyCFunction ) M_Mathutils_MatMultVec, METH_VARARGS,
|
|
M_Mathutils_MatMultVec_doc},
|
|
{"Quaternion", ( PyCFunction ) M_Mathutils_Quaternion, METH_VARARGS,
|
|
M_Mathutils_Quaternion_doc},
|
|
{"CopyQuat", ( PyCFunction ) M_Mathutils_CopyQuat, METH_VARARGS,
|
|
M_Mathutils_CopyQuat_doc},
|
|
{"CrossQuats", ( PyCFunction ) M_Mathutils_CrossQuats, METH_VARARGS,
|
|
M_Mathutils_CrossQuats_doc},
|
|
{"DotQuats", ( PyCFunction ) M_Mathutils_DotQuats, METH_VARARGS,
|
|
M_Mathutils_DotQuats_doc},
|
|
{"DifferenceQuats", ( PyCFunction ) M_Mathutils_DifferenceQuats,
|
|
METH_VARARGS,
|
|
M_Mathutils_DifferenceQuats_doc},
|
|
{"Slerp", ( PyCFunction ) M_Mathutils_Slerp, METH_VARARGS,
|
|
M_Mathutils_Slerp_doc},
|
|
{"Euler", ( PyCFunction ) M_Mathutils_Euler, METH_VARARGS,
|
|
M_Mathutils_Euler_doc},
|
|
{"CopyEuler", ( PyCFunction ) M_Mathutils_CopyEuler, METH_VARARGS,
|
|
M_Mathutils_CopyEuler_doc},
|
|
{"RotateEuler", ( PyCFunction ) M_Mathutils_RotateEuler, METH_VARARGS,
|
|
M_Mathutils_RotateEuler_doc},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_Rand
|
|
//***************************************************************************
|
|
static PyObject *M_Mathutils_Rand( PyObject * self, PyObject * args )
|
|
{
|
|
|
|
float high, low, range;
|
|
double rand;
|
|
high = 1.0;
|
|
low = 0.0;
|
|
|
|
if( !PyArg_ParseTuple( args, "|ff", &low, &high ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected optional float & float\n" ) );
|
|
|
|
if( ( high < low ) || ( high < 0 && low > 0 ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"high value should be larger than low value\n" ) );
|
|
|
|
//seed the generator
|
|
BLI_srand( ( unsigned int ) ( PIL_check_seconds_timer( ) *
|
|
0x7FFFFFFF ) );
|
|
|
|
//get the random number 0 - 1
|
|
rand = BLI_drand( );
|
|
|
|
//set it to range
|
|
range = high - low;
|
|
rand = rand * range;
|
|
rand = rand + low;
|
|
|
|
return PyFloat_FromDouble( ( double ) rand );
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_Vector
|
|
// Python equivalent: Blender.Mathutils.Vector
|
|
// Supports 2D, 3D, and 4D vector objects both int and float values
|
|
// accepted. Mixed float and int values accepted. Ints are parsed to float
|
|
//***************************************************************************
|
|
static PyObject *M_Mathutils_Vector( PyObject * self, PyObject * args )
|
|
{
|
|
PyObject *listObject = NULL;
|
|
int size, i;
|
|
float vec[4];
|
|
|
|
size = PySequence_Length(args);
|
|
if ( size == 1 ) {
|
|
listObject = PySequence_GetItem(args, 0);
|
|
if ( PySequence_Check(listObject) ) {
|
|
size = PySequence_Length(listObject);
|
|
} else {
|
|
goto bad_args; // Single argument was not a sequence
|
|
}
|
|
} else if ( size == 0 ) {
|
|
return ( PyObject * ) newVectorObject( NULL, 3 );
|
|
} else {
|
|
Py_INCREF(args);
|
|
listObject = args;
|
|
}
|
|
if (size<2 || size>4) {
|
|
goto bad_args; // Invalid vector size
|
|
}
|
|
for (i=0; i<size; i++) {
|
|
PyObject *v, *f;
|
|
|
|
v=PySequence_GetItem(listObject, i);
|
|
if (v==NULL) {
|
|
Py_DECREF(listObject);
|
|
return NULL; // Failed to read sequence
|
|
}
|
|
f=PyNumber_Float(v);
|
|
if(f==NULL) {
|
|
Py_DECREF(v);
|
|
goto bad_args;
|
|
}
|
|
vec[i]=PyFloat_AS_DOUBLE(f);
|
|
Py_DECREF(f);
|
|
Py_DECREF(v);
|
|
}
|
|
Py_DECREF(listObject);
|
|
return ( PyObject * ) newVectorObject( vec, size );
|
|
|
|
bad_args:
|
|
Py_XDECREF(listObject);
|
|
PyErr_SetString( PyExc_TypeError, "2-4 floats expected (optionally in a sequence)");
|
|
return NULL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//Begin Vector Utils
|
|
|
|
static PyObject *M_Mathutils_CopyVec( PyObject * self, PyObject * args )
|
|
{
|
|
VectorObject *vector;
|
|
float *vec;
|
|
int x;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!", &vector_Type, &vector ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected vector type\n" ) );
|
|
|
|
vec = PyMem_Malloc( vector->size * sizeof( float ) );
|
|
for( x = 0; x < vector->size; x++ ) {
|
|
vec[x] = vector->vec[x];
|
|
}
|
|
|
|
retval = ( PyObject * ) newVectorObject( vec, vector->size );
|
|
|
|
PyMem_Free( vec );
|
|
return retval;
|
|
}
|
|
|
|
//finds perpendicular vector - only 3D is supported
|
|
static PyObject *M_Mathutils_CrossVecs( PyObject * self, PyObject * args )
|
|
{
|
|
PyObject *vecCross;
|
|
VectorObject *vec1;
|
|
VectorObject *vec2;
|
|
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2 ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError, "expected 2 vector types\n" ) );
|
|
if( vec1->size != 3 || vec2->size != 3 )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"only 3D vectors are supported\n" ) );
|
|
|
|
vecCross = newVectorObject( NULL, 3 );
|
|
Crossf( ( ( VectorObject * ) vecCross )->vec, vec1->vec, vec2->vec );
|
|
|
|
return vecCross;
|
|
}
|
|
|
|
static PyObject *M_Mathutils_DotVecs( PyObject * self, PyObject * args )
|
|
{
|
|
VectorObject *vec1;
|
|
VectorObject *vec2;
|
|
float dot;
|
|
int x;
|
|
|
|
dot = 0;
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2 ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError, "expected vector types\n" ) );
|
|
if( vec1->size != vec2->size )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"vectors must be of the same size\n" ) );
|
|
|
|
for( x = 0; x < vec1->size; x++ ) {
|
|
dot += vec1->vec[x] * vec2->vec[x];
|
|
}
|
|
|
|
return PyFloat_FromDouble( ( double ) dot );
|
|
}
|
|
|
|
static PyObject *M_Mathutils_AngleBetweenVecs( PyObject * self,
|
|
PyObject * args )
|
|
{
|
|
// original vectors, makea copy of these
|
|
VectorObject *vec1;
|
|
VectorObject *vec2;
|
|
|
|
/* copy of the 2 input vectors, these can be normalized
|
|
without input vectors being normalized. bugfix
|
|
no need to use vector objects, just use floats
|
|
No Chance of 4D vectors getting in.
|
|
|
|
Use doubles, since floats will return nan when input vecs are large.*/
|
|
double vec1copy[3];
|
|
double vec2copy[3];
|
|
|
|
float norm;
|
|
double dot, angleRads;
|
|
int x;
|
|
|
|
dot = 0.0f;
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2 ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError, "expected 2 vector types\n" ) );
|
|
if( vec1->size != vec2->size )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"vectors must be of the same size\n" ) );
|
|
if( vec1->size > 3 || vec2->size > 3 )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"only 2D,3D vectors are supported\n" ) );
|
|
|
|
/* Check for 2 vectors being the same */
|
|
if (vec1->size == 3 &&
|
|
vec1->vec[0] == vec2->vec[0] &&
|
|
vec1->vec[1] == vec2->vec[1] &&
|
|
vec1->vec[2] == vec2->vec[2])
|
|
return PyFloat_FromDouble( dot ); /* 2 points are the same, return zero */
|
|
else if (vec1->size == 2 &&
|
|
vec1->vec[0] == vec2->vec[0] &&
|
|
vec1->vec[1] == vec2->vec[1])
|
|
return PyFloat_FromDouble( dot ); /* 2 points are the same, return zero */
|
|
|
|
//normalize vec1copy
|
|
norm = 0.0f;
|
|
for( x = 0; x < vec1->size; x++ ) {
|
|
vec1copy[x] = vec1->vec[x]; /* Assign new vector in the loop */
|
|
norm += vec1copy[x] * vec1copy[x];
|
|
}
|
|
norm = ( float ) sqrt( norm );
|
|
for( x = 0; x < vec1->size; x++ ) {
|
|
vec1copy[x] /= norm;
|
|
}
|
|
|
|
//normalize vec2copy
|
|
norm = 0.0f;
|
|
for( x = 0; x < vec2->size; x++ ) {
|
|
vec2copy[x] = vec2->vec[x]; /* Assign new vector in the loop */
|
|
norm += vec2copy[x] * vec2copy[x];
|
|
}
|
|
norm = ( float ) sqrt( norm );
|
|
for( x = 0; x < vec2->size; x++ ) {
|
|
vec2copy[x] /= norm;
|
|
}
|
|
|
|
//dot product
|
|
for( x = 0; x < vec1->size; x++ ) {
|
|
dot += vec1copy[x] * vec2copy[x];
|
|
}
|
|
|
|
//I believe saacos checks to see if the vectors are normalized
|
|
angleRads = (double)acos( dot );
|
|
|
|
return PyFloat_FromDouble( angleRads * ( 180 / Py_PI ) );
|
|
}
|
|
|
|
static PyObject *M_Mathutils_MidpointVecs( PyObject * self, PyObject * args )
|
|
{
|
|
|
|
VectorObject *vec1;
|
|
VectorObject *vec2;
|
|
float *vec;
|
|
int x;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2 ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError, "expected vector types\n" ) );
|
|
if( vec1->size != vec2->size )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"vectors must be of the same size\n" ) );
|
|
|
|
vec = PyMem_Malloc( vec1->size * sizeof( float ) );
|
|
|
|
for( x = 0; x < vec1->size; x++ ) {
|
|
vec[x] = 0.5f * ( vec1->vec[x] + vec2->vec[x] );
|
|
}
|
|
retval = ( PyObject * ) newVectorObject( vec, vec1->size );
|
|
|
|
PyMem_Free( vec );
|
|
return retval;
|
|
}
|
|
|
|
//row vector multiplication
|
|
static PyObject *M_Mathutils_VecMultMat( PyObject * self, PyObject * args )
|
|
{
|
|
PyObject *ob1 = NULL;
|
|
PyObject *ob2 = NULL;
|
|
MatrixObject *mat;
|
|
VectorObject *vec;
|
|
PyObject *retval;
|
|
float *vecNew;
|
|
int x, y;
|
|
int z = 0;
|
|
float dot = 0.0f;
|
|
|
|
//get pyObjects
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!O!", &vector_Type, &ob1, &matrix_Type, &ob2 ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"vector and matrix object expected - in that order\n" ) );
|
|
|
|
mat = ( MatrixObject * ) ob2;
|
|
vec = ( VectorObject * ) ob1;
|
|
if( mat->colSize != vec->size )
|
|
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"matrix col size and vector size must be the same\n" ) );
|
|
|
|
vecNew = PyMem_Malloc( vec->size * sizeof( float ) );
|
|
|
|
for( x = 0; x < mat->colSize; x++ ) {
|
|
for( y = 0; y < mat->rowSize; y++ ) {
|
|
dot += mat->matrix[y][x] * vec->vec[y];
|
|
}
|
|
vecNew[z] = dot;
|
|
z++;
|
|
dot = 0;
|
|
}
|
|
|
|
retval = ( PyObject * ) newVectorObject( vecNew, vec->size );
|
|
|
|
PyMem_Free( vecNew );
|
|
return retval;
|
|
}
|
|
|
|
static PyObject *M_Mathutils_ProjectVecs( PyObject * self, PyObject * args )
|
|
{
|
|
VectorObject *vec1;
|
|
VectorObject *vec2;
|
|
PyObject *retval;
|
|
float *vec;
|
|
float dot = 0.0f;
|
|
float dot2 = 0.0f;
|
|
int x;
|
|
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2 ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError, "expected vector types\n" ) );
|
|
if( vec1->size != vec2->size )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"vectors must be of the same size\n" ) );
|
|
|
|
vec = PyMem_Malloc( vec1->size * sizeof( float ) );
|
|
|
|
//dot of vec1 & vec2
|
|
for( x = 0; x < vec1->size; x++ ) {
|
|
dot += vec1->vec[x] * vec2->vec[x];
|
|
}
|
|
//dot of vec2 & vec2
|
|
for( x = 0; x < vec2->size; x++ ) {
|
|
dot2 += vec2->vec[x] * vec2->vec[x];
|
|
}
|
|
dot /= dot2;
|
|
for( x = 0; x < vec1->size; x++ ) {
|
|
vec[x] = dot * vec2->vec[x];
|
|
}
|
|
|
|
retval = ( PyObject * ) newVectorObject( vec, vec1->size );
|
|
PyMem_Free( vec );
|
|
return retval;
|
|
}
|
|
|
|
//End Vector Utils
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_Matrix // Python equivalent: Blender.Mathutils.Matrix
|
|
//***************************************************************************
|
|
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
|
static PyObject *M_Mathutils_Matrix( PyObject * self, PyObject * args )
|
|
{
|
|
|
|
PyObject *rowA = NULL;
|
|
PyObject *rowB = NULL;
|
|
PyObject *rowC = NULL;
|
|
PyObject *rowD = NULL;
|
|
PyObject *checkOb = NULL;
|
|
PyObject *retval = NULL;
|
|
int x, rowSize, colSize;
|
|
float *mat;
|
|
int OK;
|
|
|
|
if( !PyArg_ParseTuple( args, "|O!O!O!O!", &PyList_Type, &rowA,
|
|
&PyList_Type, &rowB,
|
|
&PyList_Type, &rowC, &PyList_Type, &rowD ) ) {
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected 0, 2,3 or 4 lists\n" ) );
|
|
}
|
|
|
|
if( !rowA )
|
|
return newMatrixObject( NULL, 4, 4 );
|
|
|
|
if( !rowB )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected 0, 2,3 or 4 lists\n" ) );
|
|
|
|
//get rowSize
|
|
if( rowC ) {
|
|
if( rowD ) {
|
|
rowSize = 4;
|
|
} else {
|
|
rowSize = 3;
|
|
}
|
|
} else {
|
|
rowSize = 2;
|
|
}
|
|
|
|
//check size and get colSize
|
|
OK = 0;
|
|
if( ( PyList_Size( rowA ) == PyList_Size( rowB ) ) ) {
|
|
if( rowC ) {
|
|
if( ( PyList_Size( rowA ) == PyList_Size( rowC ) ) ) {
|
|
if( rowD ) {
|
|
if( ( PyList_Size( rowA ) ==
|
|
PyList_Size( rowD ) ) ) {
|
|
OK = 1;
|
|
}
|
|
}
|
|
OK = 1;
|
|
}
|
|
} else
|
|
OK = 1;
|
|
}
|
|
|
|
if( !OK )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"each row of vector must contain the same number of parameters\n" );
|
|
colSize = PyList_Size( rowA );
|
|
|
|
//check for numeric types
|
|
/* PyList_GetItem() returns borrowed ref */
|
|
for( x = 0; x < colSize; x++ ) {
|
|
checkOb = PyList_GetItem( rowA, x );
|
|
if( !PyInt_Check( checkOb ) && !PyFloat_Check( checkOb ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"1st list - expected list of numbers\n" ) );
|
|
checkOb = PyList_GetItem( rowB, x );
|
|
if( !PyInt_Check( checkOb ) && !PyFloat_Check( checkOb ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"2nd list - expected list of numbers\n" ) );
|
|
if( rowC ) {
|
|
checkOb = PyList_GetItem( rowC, x );
|
|
if( !PyInt_Check( checkOb )
|
|
&& !PyFloat_Check( checkOb ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"3rd list - expected list of numbers\n" ) );
|
|
}
|
|
if( rowD ) {
|
|
checkOb = PyList_GetItem( rowD, x );
|
|
if( !PyInt_Check( checkOb )
|
|
&& !PyFloat_Check( checkOb ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"4th list - expected list of numbers\n" ) );
|
|
}
|
|
}
|
|
|
|
//allocate space for 1D array
|
|
mat = PyMem_Malloc( rowSize * colSize * sizeof( float ) );
|
|
|
|
//parse rows
|
|
for( x = 0; x < colSize; x++ ) {
|
|
if( !PyArg_Parse( PyList_GetItem( rowA, x ), "f", &mat[x] ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"rowA - python list not parseable\n" );
|
|
}
|
|
for( x = 0; x < colSize; x++ ) {
|
|
if( !PyArg_Parse
|
|
( PyList_GetItem( rowB, x ), "f", &mat[( colSize + x )] ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"rowB - python list not parseable\n" );
|
|
}
|
|
if( rowC ) {
|
|
for( x = 0; x < colSize; x++ ) {
|
|
if( !PyArg_Parse
|
|
( PyList_GetItem( rowC, x ), "f",
|
|
&mat[( ( 2 * colSize ) + x )] ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"rowC - python list not parseable\n" );
|
|
}
|
|
}
|
|
if( rowD ) {
|
|
for( x = 0; x < colSize; x++ ) {
|
|
if( !PyArg_Parse
|
|
( PyList_GetItem( rowD, x ), "f",
|
|
&mat[( ( 3 * colSize ) + x )] ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"rowD - python list not parseable\n" );
|
|
}
|
|
}
|
|
//pass to matrix creation
|
|
retval = newMatrixObject( mat, rowSize, colSize );
|
|
|
|
PyMem_Free( mat);
|
|
return retval;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_RotationMatrix
|
|
// Python equivalent: Blender.Mathutils.RotationMatrix
|
|
//***************************************************************************
|
|
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
|
static PyObject *M_Mathutils_RotationMatrix( PyObject * self, PyObject * args )
|
|
{
|
|
PyObject *retval;
|
|
float *mat;
|
|
float angle = 0.0f;
|
|
char *axis = NULL;
|
|
VectorObject *vec = NULL;
|
|
int matSize;
|
|
float norm = 0.0f;
|
|
float cosAngle = 0.0f;
|
|
float sinAngle = 0.0f;
|
|
|
|
if( !PyArg_ParseTuple
|
|
( args, "fi|sO!", &angle, &matSize, &axis, &vector_Type, &vec ) ) {
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"expected float int and optional string and vector\n" ) );
|
|
}
|
|
if( angle < -360.0f || angle > 360.0f )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"angle size not appropriate\n" );
|
|
if( matSize != 2 && matSize != 3 && matSize != 4 )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"can only return a 2x2 3x3 or 4x4 matrix\n" );
|
|
if( matSize == 2 && ( axis != NULL || vec != NULL ) )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"cannot create a 2x2 rotation matrix around arbitrary axis\n" );
|
|
if( ( matSize == 3 || matSize == 4 ) && axis == NULL )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"please choose an axis of rotation\n" );
|
|
if( axis ) {
|
|
if( ( ( strcmp( axis, "r" ) == 0 ) ||
|
|
( strcmp( axis, "R" ) == 0 ) ) && vec == NULL )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"please define the arbitrary axis of rotation\n" );
|
|
}
|
|
if( vec ) {
|
|
if( vec->size != 3 )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"the arbitrary axis must be a 3D vector\n" );
|
|
}
|
|
|
|
mat = PyMem_Malloc( matSize * matSize * sizeof( float ) );
|
|
|
|
//convert to radians
|
|
angle = angle * ( float ) ( Py_PI / 180 );
|
|
|
|
if( axis == NULL && matSize == 2 ) {
|
|
//2D rotation matrix
|
|
mat[0] = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
mat[1] = ( ( float ) sin( ( double ) ( angle ) ) );
|
|
mat[2] = ( -( ( float ) sin( ( double ) ( angle ) ) ) );
|
|
mat[3] = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
} else if( ( strcmp( axis, "x" ) == 0 ) ||
|
|
( strcmp( axis, "X" ) == 0 ) ) {
|
|
//rotation around X
|
|
mat[0] = 1.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 0.0f;
|
|
mat[4] = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
mat[5] = ( ( float ) sin( ( double ) ( angle ) ) );
|
|
mat[6] = 0.0f;
|
|
mat[7] = ( -( ( float ) sin( ( double ) ( angle ) ) ) );
|
|
mat[8] = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
} else if( ( strcmp( axis, "y" ) == 0 ) ||
|
|
( strcmp( axis, "Y" ) == 0 ) ) {
|
|
//rotation around Y
|
|
mat[0] = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
mat[1] = 0.0f;
|
|
mat[2] = ( -( ( float ) sin( ( double ) ( angle ) ) ) );
|
|
mat[3] = 0.0f;
|
|
mat[4] = 1.0f;
|
|
mat[5] = 0.0f;
|
|
mat[6] = ( ( float ) sin( ( double ) ( angle ) ) );
|
|
mat[7] = 0.0f;
|
|
mat[8] = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
} else if( ( strcmp( axis, "z" ) == 0 ) ||
|
|
( strcmp( axis, "Z" ) == 0 ) ) {
|
|
//rotation around Z
|
|
mat[0] = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
mat[1] = ( ( float ) sin( ( double ) ( angle ) ) );
|
|
mat[2] = 0.0f;
|
|
mat[3] = ( -( ( float ) sin( ( double ) ( angle ) ) ) );
|
|
mat[4] = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
mat[5] = 0.0f;
|
|
mat[6] = 0.0f;
|
|
mat[7] = 0.0f;
|
|
mat[8] = 1.0f;
|
|
} else if( ( strcmp( axis, "r" ) == 0 ) ||
|
|
( strcmp( axis, "R" ) == 0 ) ) {
|
|
//arbitrary rotation
|
|
//normalize arbitrary axis
|
|
norm = ( float ) sqrt( vec->vec[0] * vec->vec[0] +
|
|
vec->vec[1] * vec->vec[1] +
|
|
vec->vec[2] * vec->vec[2] );
|
|
vec->vec[0] /= norm;
|
|
vec->vec[1] /= norm;
|
|
vec->vec[2] /= norm;
|
|
|
|
//create matrix
|
|
cosAngle = ( ( float ) cos( ( double ) ( angle ) ) );
|
|
sinAngle = ( ( float ) sin( ( double ) ( angle ) ) );
|
|
mat[0] = ( ( vec->vec[0] * vec->vec[0] ) * ( 1 - cosAngle ) ) +
|
|
cosAngle;
|
|
mat[1] = ( ( vec->vec[0] * vec->vec[1] ) * ( 1 - cosAngle ) ) +
|
|
( vec->vec[2] * sinAngle );
|
|
mat[2] = ( ( vec->vec[0] * vec->vec[2] ) * ( 1 - cosAngle ) ) -
|
|
( vec->vec[1] * sinAngle );
|
|
mat[3] = ( ( vec->vec[0] * vec->vec[1] ) * ( 1 - cosAngle ) ) -
|
|
( vec->vec[2] * sinAngle );
|
|
mat[4] = ( ( vec->vec[1] * vec->vec[1] ) * ( 1 - cosAngle ) ) +
|
|
cosAngle;
|
|
mat[5] = ( ( vec->vec[1] * vec->vec[2] ) * ( 1 - cosAngle ) ) +
|
|
( vec->vec[0] * sinAngle );
|
|
mat[6] = ( ( vec->vec[0] * vec->vec[2] ) * ( 1 - cosAngle ) ) +
|
|
( vec->vec[1] * sinAngle );
|
|
mat[7] = ( ( vec->vec[1] * vec->vec[2] ) * ( 1 - cosAngle ) ) -
|
|
( vec->vec[0] * sinAngle );
|
|
mat[8] = ( ( vec->vec[2] * vec->vec[2] ) * ( 1 - cosAngle ) ) +
|
|
cosAngle;
|
|
} else {
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"unrecognizable axis of rotation type - expected x,y,z or r\n" );
|
|
}
|
|
if( matSize == 4 ) {
|
|
//resize matrix
|
|
mat[15] = 1.0f;
|
|
mat[14] = 0.0f;
|
|
mat[13] = 0.0f;
|
|
mat[12] = 0.0f;
|
|
mat[11] = 0.0f;
|
|
mat[10] = mat[8];
|
|
mat[9] = mat[7];
|
|
mat[8] = mat[6];
|
|
mat[7] = 0.0f;
|
|
mat[6] = mat[5];
|
|
mat[5] = mat[4];
|
|
mat[4] = mat[3];
|
|
mat[3] = 0.0f;
|
|
}
|
|
//pass to matrix creation
|
|
retval = newMatrixObject( mat, matSize, matSize );
|
|
|
|
PyMem_Free( mat );
|
|
return retval;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_TranslationMatrix
|
|
// Python equivalent: Blender.Mathutils.TranslationMatrix
|
|
//***************************************************************************
|
|
static PyObject *M_Mathutils_TranslationMatrix( PyObject * self,
|
|
PyObject * args )
|
|
{
|
|
VectorObject *vec;
|
|
PyObject *retval;
|
|
float *mat;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!", &vector_Type, &vec ) ) {
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected vector\n" ) );
|
|
}
|
|
if( vec->size != 3 && vec->size != 4 ) {
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"vector must be 3D or 4D\n" );
|
|
}
|
|
|
|
mat = PyMem_Malloc( 4 * 4 * sizeof( float ) );
|
|
Mat4One( ( float ( * )[4] ) mat );
|
|
|
|
mat[12] = vec->vec[0];
|
|
mat[13] = vec->vec[1];
|
|
mat[14] = vec->vec[2];
|
|
|
|
retval = newMatrixObject( mat, 4, 4 );
|
|
|
|
PyMem_Free( mat );
|
|
return retval;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_ScaleMatrix
|
|
// Python equivalent: Blender.Mathutils.ScaleMatrix
|
|
//***************************************************************************
|
|
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
|
static PyObject *M_Mathutils_ScaleMatrix( PyObject * self, PyObject * args )
|
|
{
|
|
float factor;
|
|
int matSize;
|
|
VectorObject *vec = NULL;
|
|
float *mat;
|
|
float norm = 0.0f;
|
|
int x;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple
|
|
( args, "fi|O!", &factor, &matSize, &vector_Type, &vec ) ) {
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"expected float int and optional vector\n" ) );
|
|
}
|
|
if( matSize != 2 && matSize != 3 && matSize != 4 )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"can only return a 2x2 3x3 or 4x4 matrix\n" );
|
|
if( vec ) {
|
|
if( vec->size > 2 && matSize == 2 )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"please use 2D vectors when scaling in 2D\n" );
|
|
}
|
|
mat = PyMem_Malloc( matSize * matSize * sizeof( float ) );
|
|
|
|
if( vec == NULL ) { //scaling along axis
|
|
if( matSize == 2 ) {
|
|
mat[0] = factor;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = factor;
|
|
} else {
|
|
mat[0] = factor;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 0.0f;
|
|
mat[4] = factor;
|
|
mat[5] = 0.0f;
|
|
mat[6] = 0.0f;
|
|
mat[7] = 0.0f;
|
|
mat[8] = factor;
|
|
}
|
|
} else { //scaling in arbitrary direction
|
|
|
|
//normalize arbitrary axis
|
|
for( x = 0; x < vec->size; x++ ) {
|
|
norm += vec->vec[x] * vec->vec[x];
|
|
}
|
|
norm = ( float ) sqrt( norm );
|
|
for( x = 0; x < vec->size; x++ ) {
|
|
vec->vec[x] /= norm;
|
|
}
|
|
if( matSize == 2 ) {
|
|
mat[0] = 1 +
|
|
( ( factor -
|
|
1 ) * ( vec->vec[0] * vec->vec[0] ) );
|
|
mat[1] = ( ( factor -
|
|
1 ) * ( vec->vec[0] * vec->vec[1] ) );
|
|
mat[2] = ( ( factor -
|
|
1 ) * ( vec->vec[0] * vec->vec[1] ) );
|
|
mat[3] = 1 +
|
|
( ( factor -
|
|
1 ) * ( vec->vec[1] * vec->vec[1] ) );
|
|
} else {
|
|
mat[0] = 1 +
|
|
( ( factor -
|
|
1 ) * ( vec->vec[0] * vec->vec[0] ) );
|
|
mat[1] = ( ( factor -
|
|
1 ) * ( vec->vec[0] * vec->vec[1] ) );
|
|
mat[2] = ( ( factor -
|
|
1 ) * ( vec->vec[0] * vec->vec[2] ) );
|
|
mat[3] = ( ( factor -
|
|
1 ) * ( vec->vec[0] * vec->vec[1] ) );
|
|
mat[4] = 1 +
|
|
( ( factor -
|
|
1 ) * ( vec->vec[1] * vec->vec[1] ) );
|
|
mat[5] = ( ( factor -
|
|
1 ) * ( vec->vec[1] * vec->vec[2] ) );
|
|
mat[6] = ( ( factor -
|
|
1 ) * ( vec->vec[0] * vec->vec[2] ) );
|
|
mat[7] = ( ( factor -
|
|
1 ) * ( vec->vec[1] * vec->vec[2] ) );
|
|
mat[8] = 1 +
|
|
( ( factor -
|
|
1 ) * ( vec->vec[2] * vec->vec[2] ) );
|
|
}
|
|
}
|
|
if( matSize == 4 ) {
|
|
//resize matrix
|
|
mat[15] = 1.0f;
|
|
mat[14] = 0.0f;
|
|
mat[13] = 0.0f;
|
|
mat[12] = 0.0f;
|
|
mat[11] = 0.0f;
|
|
mat[10] = mat[8];
|
|
mat[9] = mat[7];
|
|
mat[8] = mat[6];
|
|
mat[7] = 0.0f;
|
|
mat[6] = mat[5];
|
|
mat[5] = mat[4];
|
|
mat[4] = mat[3];
|
|
mat[3] = 0.0f;
|
|
}
|
|
//pass to matrix creation
|
|
retval = newMatrixObject( mat, matSize, matSize );
|
|
|
|
PyMem_Free( mat );
|
|
return retval;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_OrthoProjectionMatrix
|
|
// Python equivalent: Blender.Mathutils.OrthoProjectionMatrix
|
|
//***************************************************************************
|
|
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
|
static PyObject *M_Mathutils_OrthoProjectionMatrix( PyObject * self,
|
|
PyObject * args )
|
|
{
|
|
char *plane;
|
|
int matSize;
|
|
float *mat;
|
|
VectorObject *vec = NULL;
|
|
float norm = 0.0f;
|
|
int x;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple
|
|
( args, "si|O!", &plane, &matSize, &vector_Type, &vec ) ) {
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"expected string and int and optional vector\n" ) );
|
|
}
|
|
if( matSize != 2 && matSize != 3 && matSize != 4 )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"can only return a 2x2 3x3 or 4x4 matrix\n" );
|
|
if( vec ) {
|
|
if( vec->size > 2 && matSize == 2 )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"please use 2D vectors when scaling in 2D\n" );
|
|
}
|
|
if( vec == NULL ) { //ortho projection onto cardinal plane
|
|
if( ( ( strcmp( plane, "x" ) == 0 )
|
|
|| ( strcmp( plane, "X" ) == 0 ) ) && matSize == 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize *
|
|
sizeof( float ) );
|
|
mat[0] = 1.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 0.0f;
|
|
} else if( ( ( strcmp( plane, "y" ) == 0 )
|
|
|| ( strcmp( plane, "Y" ) == 0 ) )
|
|
&& matSize == 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize *
|
|
sizeof( float ) );
|
|
mat[0] = 0.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 1.0f;
|
|
} else if( ( ( strcmp( plane, "xy" ) == 0 )
|
|
|| ( strcmp( plane, "XY" ) == 0 ) )
|
|
&& matSize > 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize *
|
|
sizeof( float ) );
|
|
mat[0] = 1.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 0.0f;
|
|
mat[4] = 1.0f;
|
|
mat[5] = 0.0f;
|
|
mat[6] = 0.0f;
|
|
mat[7] = 0.0f;
|
|
mat[8] = 0.0f;
|
|
} else if( ( ( strcmp( plane, "xz" ) == 0 )
|
|
|| ( strcmp( plane, "XZ" ) == 0 ) )
|
|
&& matSize > 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize *
|
|
sizeof( float ) );
|
|
mat[0] = 1.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 0.0f;
|
|
mat[4] = 0.0f;
|
|
mat[5] = 0.0f;
|
|
mat[6] = 0.0f;
|
|
mat[7] = 0.0f;
|
|
mat[8] = 1.0f;
|
|
} else if( ( ( strcmp( plane, "yz" ) == 0 )
|
|
|| ( strcmp( plane, "YZ" ) == 0 ) )
|
|
&& matSize > 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize *
|
|
sizeof( float ) );
|
|
mat[0] = 0.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 0.0f;
|
|
mat[4] = 1.0f;
|
|
mat[5] = 0.0f;
|
|
mat[6] = 0.0f;
|
|
mat[7] = 0.0f;
|
|
mat[8] = 1.0f;
|
|
} else {
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"unknown plane - expected: x, y, xy, xz, yz\n" );
|
|
}
|
|
} else { //arbitrary plane
|
|
//normalize arbitrary axis
|
|
for( x = 0; x < vec->size; x++ ) {
|
|
norm += vec->vec[x] * vec->vec[x];
|
|
}
|
|
norm = ( float ) sqrt( norm );
|
|
|
|
for( x = 0; x < vec->size; x++ ) {
|
|
vec->vec[x] /= norm;
|
|
}
|
|
|
|
if( ( ( strcmp( plane, "r" ) == 0 )
|
|
|| ( strcmp( plane, "R" ) == 0 ) ) && matSize == 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize *
|
|
sizeof( float ) );
|
|
mat[0] = 1 - ( vec->vec[0] * vec->vec[0] );
|
|
mat[1] = -( vec->vec[0] * vec->vec[1] );
|
|
mat[2] = -( vec->vec[0] * vec->vec[1] );
|
|
mat[3] = 1 - ( vec->vec[1] * vec->vec[1] );
|
|
} else if( ( ( strcmp( plane, "r" ) == 0 )
|
|
|| ( strcmp( plane, "R" ) == 0 ) )
|
|
&& matSize > 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize *
|
|
sizeof( float ) );
|
|
mat[0] = 1 - ( vec->vec[0] * vec->vec[0] );
|
|
mat[1] = -( vec->vec[0] * vec->vec[1] );
|
|
mat[2] = -( vec->vec[0] * vec->vec[2] );
|
|
mat[3] = -( vec->vec[0] * vec->vec[1] );
|
|
mat[4] = 1 - ( vec->vec[1] * vec->vec[1] );
|
|
mat[5] = -( vec->vec[1] * vec->vec[2] );
|
|
mat[6] = -( vec->vec[0] * vec->vec[2] );
|
|
mat[7] = -( vec->vec[1] * vec->vec[2] );
|
|
mat[8] = 1 - ( vec->vec[2] * vec->vec[2] );
|
|
} else {
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"unknown plane - expected: 'r' expected for axis designation\n" );
|
|
}
|
|
}
|
|
|
|
if( matSize == 4 ) {
|
|
//resize matrix
|
|
mat[15] = 1.0f;
|
|
mat[14] = 0.0f;
|
|
mat[13] = 0.0f;
|
|
mat[12] = 0.0f;
|
|
mat[11] = 0.0f;
|
|
mat[10] = mat[8];
|
|
mat[9] = mat[7];
|
|
mat[8] = mat[6];
|
|
mat[7] = 0.0f;
|
|
mat[6] = mat[5];
|
|
mat[5] = mat[4];
|
|
mat[4] = mat[3];
|
|
mat[3] = 0.0f;
|
|
}
|
|
//pass to matrix creation
|
|
retval = newMatrixObject( mat, matSize, matSize );
|
|
|
|
PyMem_Free( mat );
|
|
return retval;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_ShearMatrix
|
|
// Python equivalent: Blender.Mathutils.ShearMatrix
|
|
//***************************************************************************
|
|
static PyObject *M_Mathutils_ShearMatrix( PyObject * self, PyObject * args )
|
|
{
|
|
float factor;
|
|
int matSize;
|
|
char *plane;
|
|
float *mat;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple( args, "sfi", &plane, &factor, &matSize ) ) {
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected string float and int\n" ) );
|
|
}
|
|
|
|
if( matSize != 2 && matSize != 3 && matSize != 4 )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"can only return a 2x2 3x3 or 4x4 matrix\n" );
|
|
|
|
if( ( ( strcmp( plane, "x" ) == 0 ) || ( strcmp( plane, "X" ) == 0 ) )
|
|
&& matSize == 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize * sizeof( float ) );
|
|
mat[0] = 1.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = factor;
|
|
mat[3] = 1.0f;
|
|
} else if( ( ( strcmp( plane, "y" ) == 0 )
|
|
|| ( strcmp( plane, "Y" ) == 0 ) ) && matSize == 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize * sizeof( float ) );
|
|
mat[0] = 1.0f;
|
|
mat[1] = factor;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 1.0f;
|
|
} else if( ( ( strcmp( plane, "xy" ) == 0 )
|
|
|| ( strcmp( plane, "XY" ) == 0 ) ) && matSize > 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize * sizeof( float ) );
|
|
mat[0] = 1.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = 0.0f;
|
|
mat[4] = 1.0f;
|
|
mat[5] = 0.0f;
|
|
mat[6] = factor;
|
|
mat[7] = factor;
|
|
mat[8] = 0.0f;
|
|
} else if( ( ( strcmp( plane, "xz" ) == 0 )
|
|
|| ( strcmp( plane, "XZ" ) == 0 ) ) && matSize > 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize * sizeof( float ) );
|
|
mat[0] = 1.0f;
|
|
mat[1] = 0.0f;
|
|
mat[2] = 0.0f;
|
|
mat[3] = factor;
|
|
mat[4] = 1.0f;
|
|
mat[5] = factor;
|
|
mat[6] = 0.0f;
|
|
mat[7] = 0.0f;
|
|
mat[8] = 1.0f;
|
|
} else if( ( ( strcmp( plane, "yz" ) == 0 )
|
|
|| ( strcmp( plane, "YZ" ) == 0 ) ) && matSize > 2 ) {
|
|
mat = PyMem_Malloc( matSize * matSize * sizeof( float ) );
|
|
mat[0] = 1.0f;
|
|
mat[1] = factor;
|
|
mat[2] = factor;
|
|
mat[3] = 0.0f;
|
|
mat[4] = 1.0f;
|
|
mat[5] = 0.0f;
|
|
mat[6] = 0.0f;
|
|
mat[7] = 0.0f;
|
|
mat[8] = 1.0f;
|
|
} else {
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n" );
|
|
}
|
|
|
|
if( matSize == 4 ) {
|
|
//resize matrix
|
|
mat[15] = 1.0f;
|
|
mat[14] = 0.0f;
|
|
mat[13] = 0.0f;
|
|
mat[12] = 0.0f;
|
|
mat[11] = 0.0f;
|
|
mat[10] = mat[8];
|
|
mat[9] = mat[7];
|
|
mat[8] = mat[6];
|
|
mat[7] = 0.0f;
|
|
mat[6] = mat[5];
|
|
mat[5] = mat[4];
|
|
mat[4] = mat[3];
|
|
mat[3] = 0.0f;
|
|
}
|
|
//pass to matrix creation
|
|
retval = newMatrixObject( mat, matSize, matSize );
|
|
|
|
PyMem_Free( mat );
|
|
return retval;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//Begin Matrix Utils
|
|
|
|
static PyObject *M_Mathutils_CopyMat( PyObject * self, PyObject * args )
|
|
{
|
|
MatrixObject *matrix;
|
|
float *mat;
|
|
int x, y, z;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!", &matrix_Type, &matrix ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected matrix\n" ) );
|
|
|
|
mat = PyMem_Malloc( matrix->rowSize * matrix->colSize *
|
|
sizeof( float ) );
|
|
|
|
z = 0;
|
|
for( x = 0; x < matrix->rowSize; x++ ) {
|
|
for( y = 0; y < matrix->colSize; y++ ) {
|
|
mat[z] = matrix->matrix[x][y];
|
|
z++;
|
|
}
|
|
}
|
|
|
|
retval = ( PyObject * ) newMatrixObject( mat, matrix->rowSize,
|
|
matrix->colSize );
|
|
PyMem_Free( mat );
|
|
return retval;
|
|
}
|
|
|
|
static PyObject *M_Mathutils_MatMultVec( PyObject * self, PyObject * args )
|
|
{
|
|
|
|
PyObject *ob1 = NULL;
|
|
PyObject *ob2 = NULL;
|
|
MatrixObject *mat;
|
|
VectorObject *vec;
|
|
PyObject *retval;
|
|
float *vecNew;
|
|
int x, y;
|
|
int z = 0;
|
|
float dot = 0.0f;
|
|
|
|
//get pyObjects
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!O!", &matrix_Type, &ob1, &vector_Type, &ob2 ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"matrix and vector object expected - in that order\n" ) );
|
|
|
|
mat = ( MatrixObject * ) ob1;
|
|
vec = ( VectorObject * ) ob2;
|
|
|
|
if( mat->rowSize != vec->size )
|
|
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"matrix row size and vector size must be the same\n" ) );
|
|
|
|
vecNew = PyMem_Malloc( vec->size * sizeof( float ) );
|
|
|
|
for( x = 0; x < mat->rowSize; x++ ) {
|
|
for( y = 0; y < mat->colSize; y++ ) {
|
|
dot += mat->matrix[x][y] * vec->vec[y];
|
|
}
|
|
vecNew[z] = dot;
|
|
z++;
|
|
dot = 0;
|
|
}
|
|
|
|
retval = ( PyObject * ) newVectorObject( vecNew, vec->size );
|
|
|
|
PyMem_Free( vecNew );
|
|
return retval;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_Quaternion
|
|
// Python equivalent: Blender.Mathutils.Quaternion
|
|
//***************************************************************************
|
|
static PyObject *M_Mathutils_Quaternion( PyObject * self, PyObject * args )
|
|
{
|
|
PyObject *listObject;
|
|
float *vec = NULL;
|
|
float *quat = NULL;
|
|
float angle = 0.0f;
|
|
int x;
|
|
float norm;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!|f", &PyList_Type, &listObject, &angle ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"expected list and optional float\n" ) );
|
|
|
|
if( PyList_Size( listObject ) != 4 && PyList_Size( listObject ) != 3 )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"3 or 4 expected floats for the quaternion\n" ) );
|
|
|
|
vec = PyMem_Malloc( PyList_Size( listObject ) * sizeof( float ) );
|
|
for( x = 0; x < PyList_Size( listObject ); x++ ) {
|
|
if( !PyArg_Parse
|
|
( PyList_GetItem( listObject, x ), "f", &vec[x] ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"python list not parseable\n" );
|
|
}
|
|
|
|
if( PyList_Size( listObject ) == 3 ) { //an axis of rotation
|
|
norm = ( float ) sqrt( vec[0] * vec[0] + vec[1] * vec[1] +
|
|
vec[2] * vec[2] );
|
|
|
|
vec[0] /= norm;
|
|
vec[1] /= norm;
|
|
vec[2] /= norm;
|
|
|
|
angle = angle * ( float ) ( Py_PI / 180 );
|
|
quat = PyMem_Malloc( 4 * sizeof( float ) );
|
|
quat[0] = ( float ) ( cos( ( double ) ( angle ) / 2 ) );
|
|
quat[1] =
|
|
( float ) ( sin( ( double ) ( angle ) / 2 ) ) * vec[0];
|
|
quat[2] =
|
|
( float ) ( sin( ( double ) ( angle ) / 2 ) ) * vec[1];
|
|
quat[3] =
|
|
( float ) ( sin( ( double ) ( angle ) / 2 ) ) * vec[2];
|
|
|
|
retval = newQuaternionObject( quat );
|
|
} else
|
|
retval = newQuaternionObject( vec );
|
|
|
|
/* freeing a NULL ptr is ok */
|
|
PyMem_Free( vec );
|
|
PyMem_Free( quat );
|
|
|
|
return retval;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//Begin Quaternion Utils
|
|
|
|
static PyObject *M_Mathutils_CopyQuat( PyObject * self, PyObject * args )
|
|
{
|
|
QuaternionObject *quatU;
|
|
float *quat = NULL;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!", &quaternion_Type, &quatU ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected Quaternion type" ) );
|
|
|
|
quat = PyMem_Malloc( 4 * sizeof( float ) );
|
|
quat[0] = quatU->quat[0];
|
|
quat[1] = quatU->quat[1];
|
|
quat[2] = quatU->quat[2];
|
|
quat[3] = quatU->quat[3];
|
|
|
|
retval = ( PyObject * ) newQuaternionObject( quat );
|
|
PyMem_Free( quat );
|
|
return retval;
|
|
}
|
|
|
|
static PyObject *M_Mathutils_CrossQuats( PyObject * self, PyObject * args )
|
|
{
|
|
QuaternionObject *quatU;
|
|
QuaternionObject *quatV;
|
|
float *quat = NULL;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!O!", &quaternion_Type, &quatU,
|
|
&quaternion_Type, &quatV ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected Quaternion types" ) );
|
|
quat = PyMem_Malloc( 4 * sizeof( float ) );
|
|
QuatMul( quat, quatU->quat, quatV->quat );
|
|
|
|
retval = ( PyObject * ) newQuaternionObject( quat );
|
|
PyMem_Free( quat );
|
|
return retval;
|
|
}
|
|
|
|
static PyObject *M_Mathutils_DotQuats( PyObject * self, PyObject * args )
|
|
{
|
|
QuaternionObject *quatU;
|
|
QuaternionObject *quatV;
|
|
int x;
|
|
float dot = 0.0f;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!O!", &quaternion_Type, &quatU,
|
|
&quaternion_Type, &quatV ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected Quaternion types" ) );
|
|
|
|
for( x = 0; x < 4; x++ ) {
|
|
dot += quatU->quat[x] * quatV->quat[x];
|
|
}
|
|
|
|
return PyFloat_FromDouble( ( double ) ( dot ) );
|
|
}
|
|
|
|
static PyObject *M_Mathutils_DifferenceQuats( PyObject * self,
|
|
PyObject * args )
|
|
{
|
|
QuaternionObject *quatU;
|
|
QuaternionObject *quatV;
|
|
float *quat = NULL;
|
|
float *tempQuat = NULL;
|
|
PyObject *retval;
|
|
int x;
|
|
float dot = 0.0f;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!O!", &quaternion_Type,
|
|
&quatU, &quaternion_Type, &quatV ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected Quaternion types" ) );
|
|
|
|
quat = PyMem_Malloc( 4 * sizeof( float ) );
|
|
tempQuat = PyMem_Malloc( 4 * sizeof( float ) );
|
|
|
|
tempQuat[0] = quatU->quat[0];
|
|
tempQuat[1] = -quatU->quat[1];
|
|
tempQuat[2] = -quatU->quat[2];
|
|
tempQuat[3] = -quatU->quat[3];
|
|
|
|
dot = ( float ) sqrt( ( double ) tempQuat[0] * ( double ) tempQuat[0] +
|
|
( double ) tempQuat[1] * ( double ) tempQuat[1] +
|
|
( double ) tempQuat[2] * ( double ) tempQuat[2] +
|
|
( double ) tempQuat[3] *
|
|
( double ) tempQuat[3] );
|
|
|
|
for( x = 0; x < 4; x++ ) {
|
|
tempQuat[x] /= ( dot * dot );
|
|
}
|
|
QuatMul( quat, tempQuat, quatV->quat );
|
|
|
|
retval = ( PyObject * ) newQuaternionObject( quat );
|
|
|
|
PyMem_Free( quat );
|
|
PyMem_Free( tempQuat );
|
|
return retval;
|
|
}
|
|
|
|
static PyObject *M_Mathutils_Slerp( PyObject * self, PyObject * args )
|
|
{
|
|
QuaternionObject *quatU;
|
|
QuaternionObject *quatV;
|
|
float *quat = NULL;
|
|
PyObject *retval;
|
|
float param, x, y, cosD, sinD, deltaD, IsinD, val;
|
|
int flag, z;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!O!f", &quaternion_Type,
|
|
&quatU, &quaternion_Type, &quatV, ¶m ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected Quaternion types and float" ) );
|
|
|
|
quat = PyMem_Malloc( 4 * sizeof( float ) );
|
|
|
|
cosD = quatU->quat[0] * quatV->quat[0] +
|
|
quatU->quat[1] * quatV->quat[1] +
|
|
quatU->quat[2] * quatV->quat[2] +
|
|
quatU->quat[3] * quatV->quat[3];
|
|
|
|
flag = 0;
|
|
if( cosD < 0.0f ) {
|
|
flag = 1;
|
|
cosD = -cosD;
|
|
}
|
|
if( cosD > .99999f ) {
|
|
x = 1.0f - param;
|
|
y = param;
|
|
} else {
|
|
sinD = ( float ) sqrt( 1.0f - cosD * cosD );
|
|
deltaD = ( float ) atan2( sinD, cosD );
|
|
IsinD = 1.0f / sinD;
|
|
x = ( float ) sin( ( 1.0f - param ) * deltaD ) * IsinD;
|
|
y = ( float ) sin( param * deltaD ) * IsinD;
|
|
}
|
|
for( z = 0; z < 4; z++ ) {
|
|
val = quatV->quat[z];
|
|
if( val )
|
|
val = -val;
|
|
quat[z] = ( quatU->quat[z] * x ) + ( val * y );
|
|
}
|
|
retval = ( PyObject * ) newQuaternionObject( quat );
|
|
PyMem_Free( quat );
|
|
return retval;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: M_Mathutils_Euler
|
|
// Python equivalent: Blender.Mathutils.Euler
|
|
//***************************************************************************
|
|
static PyObject *M_Mathutils_Euler( PyObject * self, PyObject * args )
|
|
{
|
|
PyObject *listObject;
|
|
float *vec = NULL;
|
|
PyObject *retval;
|
|
int x;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!", &PyList_Type, &listObject ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected list\n" ) );
|
|
|
|
if( PyList_Size( listObject ) != 3 )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"only 3d eulers are supported\n" );
|
|
|
|
vec = PyMem_Malloc( 3 * sizeof( float ) );
|
|
for( x = 0; x < 3; x++ ) {
|
|
if( !PyArg_Parse
|
|
( PyList_GetItem( listObject, x ), "f", &vec[x] ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"python list not parseable\n" );
|
|
}
|
|
|
|
retval = ( PyObject * ) newEulerObject( vec );
|
|
|
|
PyMem_Free( vec );
|
|
return retval;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//Begin Euler Util
|
|
|
|
static PyObject *M_Mathutils_CopyEuler( PyObject * self, PyObject * args )
|
|
{
|
|
EulerObject *eulU;
|
|
float *eul = NULL;
|
|
PyObject *retval;
|
|
|
|
if( !PyArg_ParseTuple( args, "O!", &euler_Type, &eulU ) )
|
|
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected Euler types" ) );
|
|
|
|
eul = PyMem_Malloc( 3 * sizeof( float ) );
|
|
eul[0] = eulU->eul[0];
|
|
eul[1] = eulU->eul[1];
|
|
eul[2] = eulU->eul[2];
|
|
|
|
retval = ( PyObject * ) newEulerObject( eul );
|
|
PyMem_Free( eul );
|
|
return retval;
|
|
}
|
|
|
|
static PyObject *M_Mathutils_RotateEuler( PyObject * self, PyObject * args )
|
|
{
|
|
EulerObject *Eul;
|
|
float angle;
|
|
char *axis;
|
|
int x;
|
|
|
|
if( !PyArg_ParseTuple
|
|
( args, "O!fs", &euler_Type, &Eul, &angle, &axis ) )
|
|
return ( EXPP_ReturnPyObjError
|
|
( PyExc_TypeError,
|
|
"expected euler type & float & string" ) );
|
|
|
|
angle *= ( float ) ( Py_PI / 180 );
|
|
for( x = 0; x < 3; x++ ) {
|
|
Eul->eul[x] *= ( float ) ( Py_PI / 180 );
|
|
}
|
|
euler_rot( Eul->eul, angle, *axis );
|
|
for( x = 0; x < 3; x++ ) {
|
|
Eul->eul[x] *= ( float ) ( 180 / Py_PI );
|
|
}
|
|
|
|
return EXPP_incr_ret( Py_None );
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: Mathutils_Init
|
|
//***************************************************************************
|
|
PyObject *Mathutils_Init( void )
|
|
{
|
|
PyObject *mod =
|
|
Py_InitModule3( "Blender.Mathutils", M_Mathutils_methods,
|
|
M_Mathutils_doc );
|
|
return ( mod );
|
|
}
|