Mathutils library for the python API
- support for quaternions, euler, vector, matrix operations. - euler supports unique rotation calculation - new matrix memory construction and internal functions - quaternion slerp and diff calculation - 2d, 3d, 4d vector construction and handling - full conversion support between types - update to object/window to reflect to matrix type - update to types/blender/module to reflect new module
This commit is contained in:
		
							
								
								
									
										504
									
								
								source/blender/python/api2_2x/quat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										504
									
								
								source/blender/python/api2_2x/quat.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,504 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version. The Blender
 | 
			
		||||
 * Foundation also sells licenses for use in proprietary software under
 | 
			
		||||
 * the Blender License.  See http://www.blender.org/BL/ for information
 | 
			
		||||
 * about this.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): Joseph Gilbert
 | 
			
		||||
 *
 | 
			
		||||
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "quat.h"
 | 
			
		||||
 | 
			
		||||
//doc strings
 | 
			
		||||
char Quaternion_Identity_doc[] =
 | 
			
		||||
"() - set the quaternion to it's identity (1, vector)";
 | 
			
		||||
char Quaternion_Negate_doc[] =
 | 
			
		||||
"() - set all values in the quaternion to their negative";
 | 
			
		||||
char Quaternion_Conjugate_doc[] =
 | 
			
		||||
"() - set the quaternion to it's conjugate";
 | 
			
		||||
char Quaternion_Inverse_doc[] =
 | 
			
		||||
"() - set the quaternion to it's inverse";
 | 
			
		||||
char Quaternion_Normalize_doc[] =
 | 
			
		||||
"() - normalize the vector portion of the quaternion";
 | 
			
		||||
char Quaternion_ToEuler_doc[] =
 | 
			
		||||
"() - return a euler rotation representing the quaternion";
 | 
			
		||||
char Quaternion_ToMatrix_doc[] =
 | 
			
		||||
"() - return a rotation matrix representing the quaternion";
 | 
			
		||||
 | 
			
		||||
//methods table
 | 
			
		||||
struct PyMethodDef Quaternion_methods[] = {
 | 
			
		||||
	{"identity",(PyCFunction)Quaternion_Identity, METH_NOARGS,
 | 
			
		||||
				Quaternion_Identity_doc},
 | 
			
		||||
	{"negate",(PyCFunction)Quaternion_Negate, METH_NOARGS,
 | 
			
		||||
				Quaternion_Negate_doc},
 | 
			
		||||
	{"conjugate",(PyCFunction)Quaternion_Conjugate, METH_NOARGS,
 | 
			
		||||
				Quaternion_Conjugate_doc},
 | 
			
		||||
	{"inverse",(PyCFunction)Quaternion_Inverse, METH_NOARGS,
 | 
			
		||||
				Quaternion_Inverse_doc},
 | 
			
		||||
	{"normalize",(PyCFunction)Quaternion_Normalize, METH_NOARGS,
 | 
			
		||||
				Quaternion_Normalize_doc},
 | 
			
		||||
	{"toEuler",(PyCFunction)Quaternion_ToEuler, METH_NOARGS,
 | 
			
		||||
				Quaternion_ToEuler_doc},
 | 
			
		||||
	{"toMatrix",(PyCFunction)Quaternion_ToMatrix, METH_NOARGS,
 | 
			
		||||
				Quaternion_ToMatrix_doc},
 | 
			
		||||
	{NULL, NULL, 0, NULL}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*****************************/
 | 
			
		||||
//    Quaternion Python Object   
 | 
			
		||||
/*****************************/
 | 
			
		||||
 | 
			
		||||
PyObject *Quaternion_ToEuler(QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
	float *eul;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	eul = PyMem_Malloc(3*sizeof(float));
 | 
			
		||||
	QuatToEul(self->quat, eul);
 | 
			
		||||
 | 
			
		||||
	for(x = 0; x < 3; x++){
 | 
			
		||||
		eul[x] *= (float)(180/Py_PI);
 | 
			
		||||
	}
 | 
			
		||||
	return (PyObject*)newEulerObject(eul);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyObject *Quaternion_ToMatrix(QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
	float *mat;
 | 
			
		||||
 | 
			
		||||
	mat = PyMem_Malloc(3*3*sizeof(float));
 | 
			
		||||
	QuatToMat3(self->quat, (float(*)[3])mat);
 | 
			
		||||
 | 
			
		||||
	return (PyObject*)newMatrixObject(mat, 3,3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//normalize the axis of rotation of [theta,vector]
 | 
			
		||||
PyObject *Quaternion_Normalize(QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
	NormalQuat(self->quat);
 | 
			
		||||
	return EXPP_incr_ret(Py_None);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyObject *Quaternion_Inverse(QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
	float mag = 0.0f;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	for(x = 1; x < 4; x++){
 | 
			
		||||
		self->quat[x] = -self->quat[x];
 | 
			
		||||
	}
 | 
			
		||||
	for(x = 0; x < 4; x++){
 | 
			
		||||
		mag += (self->quat[x] * self->quat[x]);
 | 
			
		||||
	}
 | 
			
		||||
	mag = (float)sqrt(mag);
 | 
			
		||||
	for(x = 0; x < 4; x++){
 | 
			
		||||
		self->quat[x] /= (mag * mag);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return EXPP_incr_ret(Py_None);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyObject *Quaternion_Identity(QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
	self->quat[0] = 1.0;
 | 
			
		||||
	self->quat[1] = 0.0; self->quat[2] = 0.0; self->quat[3] = 0.0;
 | 
			
		||||
 | 
			
		||||
	return EXPP_incr_ret(Py_None);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyObject *Quaternion_Negate(QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	for(x = 0; x < 4; x++){
 | 
			
		||||
		self->quat[x] = -self->quat[x];
 | 
			
		||||
	}
 | 
			
		||||
	return EXPP_incr_ret(Py_None);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyObject *Quaternion_Conjugate(QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	for(x = 1; x < 4; x++){
 | 
			
		||||
		self->quat[x] = -self->quat[x];
 | 
			
		||||
	}
 | 
			
		||||
	return EXPP_incr_ret(Py_None);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Quaternion_dealloc(QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
  PyObject_DEL (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyObject *Quaternion_getattr(QuaternionObject *self, char *name)
 | 
			
		||||
{
 | 
			
		||||
	double mag = 0.0f;
 | 
			
		||||
	float *vec;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	if (ELEM4(name[0], 'w', 'x', 'y', 'z') && name[1]==0){
 | 
			
		||||
		return PyFloat_FromDouble(self->quat[name[0]-'w']);
 | 
			
		||||
	}
 | 
			
		||||
	if(strcmp(name,"magnitude") == 0){
 | 
			
		||||
		for(x = 0; x < 4; x++){
 | 
			
		||||
			mag += self->quat[x] * self->quat[x];
 | 
			
		||||
		}
 | 
			
		||||
		mag = (float)sqrt(mag);
 | 
			
		||||
		return PyFloat_FromDouble(mag);
 | 
			
		||||
	}
 | 
			
		||||
	if(strcmp(name,"angle") == 0){
 | 
			
		||||
 | 
			
		||||
		mag = self->quat[0];
 | 
			
		||||
		mag = 2 * (acos(mag));
 | 
			
		||||
		mag *= (180/Py_PI);
 | 
			
		||||
		return PyFloat_FromDouble(mag);
 | 
			
		||||
	}
 | 
			
		||||
	if(strcmp(name,"axis") == 0){
 | 
			
		||||
 | 
			
		||||
		mag = (double)(self->quat[0] * (Py_PI/180));
 | 
			
		||||
		mag = 2 * (acos(mag));
 | 
			
		||||
		mag = sin(mag/2);
 | 
			
		||||
		vec = PyMem_Malloc(3*sizeof(float));
 | 
			
		||||
		for(x = 0; x < 3; x++){
 | 
			
		||||
			vec[x] = (self->quat[x + 1]/((float)(mag)));
 | 
			
		||||
		}
 | 
			
		||||
		Normalise(vec);
 | 
			
		||||
		return (PyObject*)newVectorObject(vec,3);
 | 
			
		||||
	}
 | 
			
		||||
	return Py_FindMethod(Quaternion_methods, (PyObject*)self, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int Quaternion_setattr(QuaternionObject *self, char *name, PyObject *v)
 | 
			
		||||
{
 | 
			
		||||
	float val;
 | 
			
		||||
 | 
			
		||||
	if(!PyFloat_Check(v) && !PyInt_Check(v)){
 | 
			
		||||
			return EXPP_ReturnIntError(PyExc_TypeError,"int or float expected\n");
 | 
			
		||||
	}else{
 | 
			
		||||
		if (!PyArg_Parse(v, "f", &val))
 | 
			
		||||
			return EXPP_ReturnIntError(PyExc_TypeError,	"unable to parse float argument\n");
 | 
			
		||||
	}
 | 
			
		||||
	if (ELEM4(name[0], 'w', 'x', 'y', 'z') && name[1]==0){
 | 
			
		||||
		self->quat[name[0]-'w']= val;
 | 
			
		||||
	}else return -1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Quaternions Sequence methods */
 | 
			
		||||
static PyObject *Quaternion_item(QuaternionObject *self, int i)
 | 
			
		||||
{
 | 
			
		||||
	if (i < 0 || i >= 4)
 | 
			
		||||
	  return EXPP_ReturnPyObjError (PyExc_IndexError, "array index out of range\n");
 | 
			
		||||
 | 
			
		||||
	return Py_BuildValue("f", self->quat[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end)
 | 
			
		||||
{
 | 
			
		||||
	PyObject *list;
 | 
			
		||||
	int count;
 | 
			
		||||
  
 | 
			
		||||
	if (begin < 0) begin= 0;
 | 
			
		||||
	if (end > 4) end= 4;
 | 
			
		||||
	if (begin > end) begin= end;
 | 
			
		||||
 | 
			
		||||
	list= PyList_New(end-begin);
 | 
			
		||||
 | 
			
		||||
	for (count = begin; count < end; count++){
 | 
			
		||||
		PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->quat[count]));
 | 
			
		||||
	}
 | 
			
		||||
	return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob)
 | 
			
		||||
{
 | 
			
		||||
	if (i < 0 || i >= 4)
 | 
			
		||||
		return EXPP_ReturnIntError(PyExc_IndexError,
 | 
			
		||||
					"array assignment index out of range\n");
 | 
			
		||||
	if (!PyNumber_Check(ob))
 | 
			
		||||
		return EXPP_ReturnIntError(PyExc_IndexError,
 | 
			
		||||
					"Quaternion member must be a number\n");
 | 
			
		||||
 | 
			
		||||
	if(!PyFloat_Check(ob) && !PyInt_Check(ob)){
 | 
			
		||||
			return EXPP_ReturnIntError(PyExc_TypeError,"int or float expected\n");
 | 
			
		||||
	}else{
 | 
			
		||||
		self->quat[i]= (float)PyFloat_AsDouble(ob);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq)
 | 
			
		||||
{
 | 
			
		||||
	int count, z;
 | 
			
		||||
 | 
			
		||||
	if (begin < 0) begin= 0;
 | 
			
		||||
	if (end > 4) end= 4;
 | 
			
		||||
	if (begin > end) begin= end;
 | 
			
		||||
 | 
			
		||||
	if (!PySequence_Check(seq))
 | 
			
		||||
		return EXPP_ReturnIntError(PyExc_TypeError,
 | 
			
		||||
					"illegal argument type for built-in operation\n");
 | 
			
		||||
	if (PySequence_Length(seq) != (end - begin))
 | 
			
		||||
		return EXPP_ReturnIntError(PyExc_TypeError,
 | 
			
		||||
					"size mismatch in slice assignment\n");
 | 
			
		||||
 | 
			
		||||
	z = 0;
 | 
			
		||||
	for (count = begin; count < end; count++) {
 | 
			
		||||
		PyObject *ob = PySequence_GetItem(seq, z); z++;
 | 
			
		||||
 | 
			
		||||
		if(!PyFloat_Check(ob) && !PyInt_Check(ob)){
 | 
			
		||||
			Py_DECREF(ob);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}else{
 | 
			
		||||
			if (!PyArg_Parse(ob, "f", &self->quat[count])) {
 | 
			
		||||
				Py_DECREF(ob);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyObject *Quaternion_repr (QuaternionObject *self)
 | 
			
		||||
{
 | 
			
		||||
	int i, maxindex = 4 - 1;
 | 
			
		||||
	char ftoa[24];
 | 
			
		||||
	PyObject *str1, *str2;
 | 
			
		||||
 | 
			
		||||
	str1 = PyString_FromString ("[");
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < maxindex; i++) {
 | 
			
		||||
		sprintf(ftoa, "%.4f, ", self->quat[i]);
 | 
			
		||||
		str2 = PyString_FromString (ftoa);
 | 
			
		||||
		if (!str1 || !str2) goto error; 
 | 
			
		||||
		PyString_ConcatAndDel (&str1, str2);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sprintf(ftoa, "%.4f]\n", self->quat[maxindex]);
 | 
			
		||||
	str2 = PyString_FromString (ftoa);
 | 
			
		||||
	if (!str1 || !str2) goto error; 
 | 
			
		||||
	PyString_ConcatAndDel (&str1, str2);
 | 
			
		||||
 | 
			
		||||
	if (str1) return str1;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	Py_XDECREF (str1);
 | 
			
		||||
	Py_XDECREF (str2);
 | 
			
		||||
	return EXPP_ReturnPyObjError (PyExc_MemoryError,
 | 
			
		||||
			"couldn't create PyString!\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PyObject * Quaternion_add(PyObject *q1, PyObject *q2)
 | 
			
		||||
{
 | 
			
		||||
	float * quat;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
 | 
			
		||||
		return EXPP_ReturnPyObjError (PyExc_TypeError,
 | 
			
		||||
				"unsupported type for this operation\n");
 | 
			
		||||
	if(((QuaternionObject*)q1)->flag > 0 || ((QuaternionObject*)q2)->flag > 0)
 | 
			
		||||
		return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
 | 
			
		||||
			"cannot add a scalar and a quat\n");
 | 
			
		||||
 | 
			
		||||
	quat = PyMem_Malloc (4*sizeof(float));
 | 
			
		||||
	for(x = 0; x < 4; x++){
 | 
			
		||||
		quat[x] =  (((QuaternionObject*)q1)->quat[x]) +  (((QuaternionObject*)q2)->quat[x]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (PyObject*)newQuaternionObject(quat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyObject * Quaternion_sub(PyObject *q1, PyObject *q2)
 | 
			
		||||
{
 | 
			
		||||
	float * quat;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
 | 
			
		||||
		return EXPP_ReturnPyObjError (PyExc_TypeError,
 | 
			
		||||
				"unsupported type for this operation\n");
 | 
			
		||||
	if(((QuaternionObject*)q1)->flag > 0 || ((QuaternionObject*)q2)->flag > 0)
 | 
			
		||||
		return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
 | 
			
		||||
			"cannot subtract a scalar and a quat\n");
 | 
			
		||||
 | 
			
		||||
	quat = PyMem_Malloc (4*sizeof(float));
 | 
			
		||||
	for(x = 0; x < 4; x++){
 | 
			
		||||
		quat[x] =  (((QuaternionObject*)q1)->quat[x]) -  (((QuaternionObject*)q2)->quat[x]);
 | 
			
		||||
	}
 | 
			
		||||
	return (PyObject*)newQuaternionObject(quat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyObject * Quaternion_mul(PyObject *q1, PyObject * q2)
 | 
			
		||||
{
 | 
			
		||||
	float * quat;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
 | 
			
		||||
		return EXPP_ReturnPyObjError (PyExc_TypeError,
 | 
			
		||||
				"unsupported type for this operation\n");
 | 
			
		||||
	if(((QuaternionObject*)q1)->flag == 0 && ((QuaternionObject*)q2)->flag == 0)
 | 
			
		||||
		return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
 | 
			
		||||
			"please use the dot or cross product to multiply quaternions\n");
 | 
			
		||||
 | 
			
		||||
	quat = PyMem_Malloc (4*sizeof(float));
 | 
			
		||||
	//scalar mult by quat
 | 
			
		||||
	for(x = 0; x < 4; x++){
 | 
			
		||||
		quat[x] = ((QuaternionObject*)q1)->quat[x] * ((QuaternionObject*)q2)->quat[x];
 | 
			
		||||
	}
 | 
			
		||||
	return (PyObject*)newQuaternionObject(quat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//coercion of unknown types to type QuaternionObject for numeric protocols
 | 
			
		||||
int Quaternion_coerce(PyObject **q1, PyObject **q2)
 | 
			
		||||
{ 
 | 
			
		||||
	long *tempI;
 | 
			
		||||
	double *tempF;
 | 
			
		||||
	float *quat;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	if (QuaternionObject_Check(*q1)) {
 | 
			
		||||
		if (QuaternionObject_Check(*q2)) { //two Quaternions
 | 
			
		||||
			Py_INCREF(*q1);
 | 
			
		||||
			Py_INCREF(*q2);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}else{
 | 
			
		||||
			if(PyNumber_Check(*q2)){
 | 
			
		||||
				if(PyInt_Check(*q2)){ //cast scalar to Quaternion
 | 
			
		||||
					tempI = PyMem_Malloc(1*sizeof(long));
 | 
			
		||||
					*tempI = PyInt_AsLong(*q2);
 | 
			
		||||
					quat = PyMem_Malloc (4*sizeof (float));
 | 
			
		||||
					for(x = 0; x < 4; x++){
 | 
			
		||||
						quat[x] = (float)*tempI;
 | 
			
		||||
					}
 | 
			
		||||
					PyMem_Free(tempI);
 | 
			
		||||
					*q2 = newQuaternionObject(quat);
 | 
			
		||||
					((QuaternionObject*)*q2)->flag = 1;	//int coercion
 | 
			
		||||
					Py_INCREF(*q1);
 | 
			
		||||
					return 0;
 | 
			
		||||
				}else if(PyFloat_Check(*q2)){ //cast scalar to Quaternion
 | 
			
		||||
					tempF = PyMem_Malloc(1*sizeof(double));
 | 
			
		||||
					*tempF = PyFloat_AsDouble(*q2);
 | 
			
		||||
					quat = PyMem_Malloc (4*sizeof (float));
 | 
			
		||||
					for(x = 0; x < 4; x++){
 | 
			
		||||
						quat[x] = (float)*tempF;
 | 
			
		||||
					}
 | 
			
		||||
					PyMem_Free(tempF);
 | 
			
		||||
					*q2 = newQuaternionObject(quat);
 | 
			
		||||
					((QuaternionObject*)*q2)->flag = 2;	//float coercion
 | 
			
		||||
					Py_INCREF(*q1);
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			//unknown type or numeric cast failure
 | 
			
		||||
			printf("attempting quaternion operation with unsupported type...\n");
 | 
			
		||||
			Py_INCREF(*q1);
 | 
			
		||||
			return 0; //operation will type check
 | 
			
		||||
		}
 | 
			
		||||
	}else{
 | 
			
		||||
		printf("numeric protocol failure...\n");
 | 
			
		||||
		return -1; //this should not occur - fail
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PySequenceMethods Quaternion_SeqMethods =
 | 
			
		||||
{
 | 
			
		||||
	(inquiry)       0,                          /* sq_length */
 | 
			
		||||
	(binaryfunc)    0,                          /* sq_concat */
 | 
			
		||||
	(intargfunc)    0,                          /* sq_repeat */
 | 
			
		||||
	(intargfunc)    Quaternion_item,            /* sq_item */
 | 
			
		||||
	(intintargfunc)   Quaternion_slice,         /* sq_slice */
 | 
			
		||||
	(intobjargproc)   Quaternion_ass_item,      /* sq_ass_item */
 | 
			
		||||
	(intintobjargproc)  Quaternion_ass_slice,   /* sq_ass_slice */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static PyNumberMethods Quaternion_NumMethods =
 | 
			
		||||
{
 | 
			
		||||
    (binaryfunc)	Quaternion_add,           /* __add__ */
 | 
			
		||||
    (binaryfunc)	Quaternion_sub,           /* __sub__ */
 | 
			
		||||
    (binaryfunc)	Quaternion_mul,           /* __mul__ */
 | 
			
		||||
    (binaryfunc)	0,		                  /* __div__ */
 | 
			
		||||
    (binaryfunc)	0,				          /* __mod__ */
 | 
			
		||||
    (binaryfunc)	0,                        /* __divmod__ */
 | 
			
		||||
    (ternaryfunc)	0,                        /* __pow__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __neg__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __pos__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __abs__ */
 | 
			
		||||
    (inquiry)		0,                        /* __nonzero__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __invert__ */
 | 
			
		||||
    (binaryfunc)	0,                        /* __lshift__ */
 | 
			
		||||
    (binaryfunc)	0,                        /* __rshift__ */
 | 
			
		||||
    (binaryfunc)	0,                        /* __and__ */
 | 
			
		||||
    (binaryfunc)	0,                        /* __xor__ */
 | 
			
		||||
    (binaryfunc)	0,                        /* __or__ */
 | 
			
		||||
    (coercion)		Quaternion_coerce,        /* __coerce__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __int__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __long__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __float__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __oct__ */
 | 
			
		||||
    (unaryfunc)		0,                        /* __hex__ */
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
PyTypeObject quaternion_Type =
 | 
			
		||||
{
 | 
			
		||||
  PyObject_HEAD_INIT(NULL)
 | 
			
		||||
  0,                                /*ob_size*/
 | 
			
		||||
  "quaternion",                    /*tp_name*/
 | 
			
		||||
  sizeof(QuaternionObject),        /*tp_basicsize*/
 | 
			
		||||
  0,                               /*tp_itemsize*/
 | 
			
		||||
  (destructor)  Quaternion_dealloc, /*tp_dealloc*/
 | 
			
		||||
  (printfunc)   0,                  /*tp_print*/
 | 
			
		||||
  (getattrfunc) Quaternion_getattr, /*tp_getattr*/
 | 
			
		||||
  (setattrfunc) Quaternion_setattr, /*tp_setattr*/
 | 
			
		||||
  0,                                /*tp_compare*/
 | 
			
		||||
  (reprfunc)    Quaternion_repr,    /*tp_repr*/
 | 
			
		||||
  &Quaternion_NumMethods,           /*tp_as_number*/
 | 
			
		||||
  &Quaternion_SeqMethods,           /*tp_as_sequence*/
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
PyObject *newQuaternionObject(float *quat)
 | 
			
		||||
{
 | 
			
		||||
  QuaternionObject *self;
 | 
			
		||||
  int x;
 | 
			
		||||
 | 
			
		||||
  quaternion_Type.ob_type = &PyType_Type;
 | 
			
		||||
 | 
			
		||||
  self = PyObject_NEW(QuaternionObject, &quaternion_Type);
 | 
			
		||||
 | 
			
		||||
  if(!quat){
 | 
			
		||||
	  self->quat = PyMem_Malloc (4 *sizeof (float));
 | 
			
		||||
	  for(x = 0; x < 4; x++){
 | 
			
		||||
		  self->quat[x] = 0.0f;
 | 
			
		||||
	  }
 | 
			
		||||
	  self->quat[3] = 1.0f;
 | 
			
		||||
  }else{
 | 
			
		||||
	self->quat = quat;
 | 
			
		||||
  }
 | 
			
		||||
  self->flag = 0;
 | 
			
		||||
 
 | 
			
		||||
  return (PyObject*) self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user