2004-02-29 13:20:34 +00:00
|
|
|
/*
|
2004-09-18 18:47:03 +00:00
|
|
|
* $Id$
|
|
|
|
|
*
|
2004-02-29 13:20:34 +00:00
|
|
|
* ***** 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);
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-11 08:26:44 +00:00
|
|
|
sprintf(ftoa, "%.4f]", self->quat[maxindex]);
|
2004-02-29 13:20:34 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|