This commit is contained in:
Campbell Barton
2011-07-26 03:55:23 +00:00
133 changed files with 1504 additions and 935 deletions

View File

@@ -0,0 +1,52 @@
# ***** BEGIN GPL 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.
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Contributor(s): Campbell Barton
#
# ***** END GPL LICENSE BLOCK *****
set(INC
.
../../blenlib
../../blenkernel
../../makesdna
../../../../intern/guardedalloc
)
set(INC_SYS
${PYTHON_INCLUDE_DIRS}
)
set(SRC
mathutils.c
mathutils_Color.c
mathutils_Euler.c
mathutils_Matrix.c
mathutils_Quaternion.c
mathutils_Vector.c
mathutils_geometry.c
mathutils.h
mathutils_Color.h
mathutils_Euler.h
mathutils_Matrix.h
mathutils_Quaternion.h
mathutils_Vector.h
mathutils_geometry.h
)
blender_add_lib(bf_python_mathutils "${SRC}" "${INC}" "${INC_SYS}")

View File

@@ -0,0 +1,384 @@
/*
* $Id: mathutils.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
PyDoc_STRVAR(M_Mathutils_doc,
"This module provides access to matrices, eulers, quaternions and vectors."
);
static int mathutils_array_parse_fast(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{
PyObject *value_fast= NULL;
PyObject *item;
int i, size;
/* non list/tuple cases */
if(!(value_fast=PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
size= PySequence_Fast_GET_SIZE(value_fast);
if(size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected %d",
error_prefix, size, array_max);
}
else {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected [%d - %d]",
error_prefix, size, array_min, array_max);
}
Py_DECREF(value_fast);
return -1;
}
i= size;
do {
i--;
if(((array[i]= PyFloat_AsDouble((item= PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"%.200s: sequence index %d expected a number, "
"found '%.200s' type, ",
error_prefix, i, Py_TYPE(item)->tp_name);
Py_DECREF(value_fast);
return -1;
}
} while(i);
Py_XDECREF(value_fast);
return size;
}
/* helper functionm returns length of the 'value', -1 on error */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{
#if 1 /* approx 6x speedup for mathutils types */
int size;
if( (VectorObject_Check(value) && (size= ((VectorObject *)value)->size)) ||
(EulerObject_Check(value) && (size= 3)) ||
(QuaternionObject_Check(value) && (size= 4)) ||
(ColorObject_Check(value) && (size= 3))
) {
if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
if(size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected %d",
error_prefix, size, array_max);
}
else {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected [%d - %d]",
error_prefix, size, array_min, array_max);
}
return -1;
}
memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
return size;
}
else
#endif
{
return mathutils_array_parse_fast(array, array_min, array_max, value, error_prefix);
}
}
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
{
if(EulerObject_Check(value)) {
if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
else {
eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order);
return 0;
}
}
else if (QuaternionObject_Check(value)) {
if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
else {
float tquat[4];
normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat);
quat_to_mat3(rmat, tquat);
return 0;
}
}
else if (MatrixObject_Check(value)) {
if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
else if(((MatrixObject *)value)->col_size < 3 || ((MatrixObject *)value)->row_size < 3) {
PyErr_Format(PyExc_ValueError,
"%.200s: matrix must have minimum 3x3 dimensions",
error_prefix);
return -1;
}
else {
matrix_as_3x3(rmat, (MatrixObject *)value);
normalize_m3(rmat);
return 0;
}
}
else {
PyErr_Format(PyExc_TypeError,
"%.200s: expected a Euler, Quaternion or Matrix type, "
"found %.200s", error_prefix, Py_TYPE(value)->tp_name);
return -1;
}
}
//----------------------------------MATRIX FUNCTIONS--------------------
/* Utility functions */
// LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon
#define SIGNMASK(i) (-(int)(((unsigned int)(i))>>31))
int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
{ // solid, fast routine across all platforms
// with constant time behavior
int ai = *(int *)(&af);
int bi = *(int *)(&bf);
int test = SIGNMASK(ai^bi);
int diff, v1, v2;
assert((0 == test) || (0xFFFFFFFF == test));
diff = (ai ^ (test & 0x7fffffff)) - bi;
v1 = maxDiff + diff;
v2 = maxDiff - diff;
return (v1|v2) >= 0;
}
/*---------------------- EXPP_VectorsAreEqual -------------------------
Builds on EXPP_FloatsAreEqual to test vectors */
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps)
{
int x;
for (x=0; x< size; x++){
if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
return 0;
}
return 1;
}
/* Mathutils Callbacks */
/* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
static Mathutils_Callback *mathutils_callbacks[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
int Mathutils_RegisterCallback(Mathutils_Callback *cb)
{
int i;
/* find the first free slot */
for(i= 0; mathutils_callbacks[i]; i++) {
if(mathutils_callbacks[i]==cb) /* already registered? */
return i;
}
mathutils_callbacks[i] = cb;
return i;
}
/* use macros to check for NULL */
int _BaseMathObject_ReadCallback(BaseMathObject *self)
{
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
if(cb->get(self, self->cb_subtype) != -1)
return 0;
if(!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError,
"%s read, user has become invalid",
Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_WriteCallback(BaseMathObject *self)
{
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
if(cb->set(self, self->cb_subtype) != -1)
return 0;
if(!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError,
"%s write, user has become invalid",
Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
{
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
if(cb->get_index(self, self->cb_subtype, index) != -1)
return 0;
if(!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError,
"%s read index, user has become invalid",
Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
{
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
if(cb->set_index(self, self->cb_subtype, index) != -1)
return 0;
if(!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError,
"%s write index, user has become invalid",
Py_TYPE(self)->tp_name);
}
return -1;
}
/* BaseMathObject generic functions for all mathutils types */
char BaseMathObject_Owner_doc[] = "The item this is wrapping or None (readonly).";
PyObject *BaseMathObject_getOwner(BaseMathObject *self, void *UNUSED(closure))
{
PyObject *ret= self->cb_user ? self->cb_user : Py_None;
Py_INCREF(ret);
return ret;
}
char BaseMathObject_Wrapped_doc[] = "True when this object wraps external data (readonly).\n\n:type: boolean";
PyObject *BaseMathObject_getWrapped(BaseMathObject *self, void *UNUSED(closure))
{
return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0);
}
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
{
Py_VISIT(self->cb_user);
return 0;
}
int BaseMathObject_clear(BaseMathObject *self)
{
Py_CLEAR(self->cb_user);
return 0;
}
void BaseMathObject_dealloc(BaseMathObject *self)
{
/* only free non wrapped */
if(self->wrapped != Py_WRAP) {
PyMem_Free(self->data);
}
if(self->cb_user) {
PyObject_GC_UnTrack(self);
BaseMathObject_clear(self);
}
Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes
}
/*----------------------------MODULE INIT-------------------------*/
static struct PyMethodDef M_Mathutils_methods[] = {
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef M_Mathutils_module_def = {
PyModuleDef_HEAD_INIT,
"mathutils", /* m_name */
M_Mathutils_doc, /* m_doc */
0, /* m_size */
M_Mathutils_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyMODINIT_FUNC PyInit_mathutils(void)
{
PyObject *submodule;
PyObject *item;
if(PyType_Ready(&vector_Type) < 0)
return NULL;
if(PyType_Ready(&matrix_Type) < 0)
return NULL;
if(PyType_Ready(&euler_Type) < 0)
return NULL;
if(PyType_Ready(&quaternion_Type) < 0)
return NULL;
if(PyType_Ready(&color_Type) < 0)
return NULL;
submodule = PyModule_Create(&M_Mathutils_module_def);
/* each type has its own new() function */
PyModule_AddObject(submodule, "Vector", (PyObject *)&vector_Type);
PyModule_AddObject(submodule, "Matrix", (PyObject *)&matrix_Type);
PyModule_AddObject(submodule, "Euler", (PyObject *)&euler_Type);
PyModule_AddObject(submodule, "Quaternion", (PyObject *)&quaternion_Type);
PyModule_AddObject(submodule, "Color", (PyObject *)&color_Type);
/* submodule */
PyModule_AddObject(submodule, "geometry", (item=PyInit_mathutils_geometry()));
/* XXX, python doesnt do imports with this usefully yet
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
PyDict_SetItemString(PyThreadState_GET()->interp->modules, "mathutils.geometry", item);
Py_INCREF(item);
mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
return submodule;
}

View File

@@ -0,0 +1,111 @@
/*
* $Id: mathutils.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils.h
* \ingroup pygen
*/
//Include this file for access to vector, quat, matrix, euler, etc...
#ifndef MATHUTILS_H
#define MATHUTILS_H
/* Can cast different mathutils types to this, use for generic funcs */
extern char BaseMathObject_Wrapped_doc[];
extern char BaseMathObject_Owner_doc[];
#define BASE_MATH_MEMBERS(_data) \
PyObject_VAR_HEAD \
float *_data; /* array of data (alias), wrapped status depends on wrapped status */ \
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ \
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ \
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ \
unsigned char wrapped; /* wrapped data type? */ \
typedef struct {
BASE_MATH_MEMBERS(data)
} BaseMathObject;
#include "mathutils_Vector.h"
#include "mathutils_Matrix.h"
#include "mathutils_Quaternion.h"
#include "mathutils_Euler.h"
#include "mathutils_Color.h"
#include "mathutils_geometry.h"
PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * );
PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * );
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg);
int BaseMathObject_clear(BaseMathObject *self);
void BaseMathObject_dealloc(BaseMathObject * self);
PyMODINIT_FUNC PyInit_mathutils(void);
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
#define Py_NEW 1
#define Py_WRAP 2
typedef struct Mathutils_Callback Mathutils_Callback;
typedef int (*BaseMathCheckFunc)(BaseMathObject *); /* checks the user is still valid */
typedef int (*BaseMathGetFunc)(BaseMathObject *, int); /* gets the vector from the user */
typedef int (*BaseMathSetFunc)(BaseMathObject *, int); /* sets the users vector values once the vector is modified */
typedef int (*BaseMathGetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */
typedef int (*BaseMathSetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */
struct Mathutils_Callback {
BaseMathCheckFunc check;
BaseMathGetFunc get;
BaseMathSetFunc set;
BaseMathGetIndexFunc get_index;
BaseMathSetIndexFunc set_index;
};
int Mathutils_RegisterCallback(Mathutils_Callback *cb);
int _BaseMathObject_ReadCallback(BaseMathObject *self);
int _BaseMathObject_WriteCallback(BaseMathObject *self);
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index);
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
/* since this is called so often avoid where possible */
#define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):0))
#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):0))
#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):0))
#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):0))
/* utility func */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix);
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix);
#endif /* MATHUTILS_H */

View File

@@ -0,0 +1,870 @@
/*
* $Id: mathutils_Color.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_Color.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#define COLOR_SIZE 3
//----------------------------------mathutils.Color() -------------------
//makes a new color for you to play with
static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
float col[3]= {0.0f, 0.0f, 0.0f};
if(kwds && PyDict_Size(kwds)) {
PyErr_SetString(PyExc_TypeError,
"mathutils.Color(): "
"takes no keyword args");
return NULL;
}
switch(PyTuple_GET_SIZE(args)) {
case 0:
break;
case 1:
if((mathutils_array_parse(col, COLOR_SIZE, COLOR_SIZE, PyTuple_GET_ITEM(args, 0), "mathutils.Color()")) == -1)
return NULL;
break;
default:
PyErr_SetString(PyExc_TypeError,
"mathutils.Color(): "
"more then a single arg given");
return NULL;
}
return newColorObject(col, Py_NEW, type);
}
//-----------------------------METHODS----------------------------
/* note: BaseMath_ReadCallback must be called beforehand */
static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits)
{
PyObject *ret;
int i;
ret= PyTuple_New(COLOR_SIZE);
if(ndigits >= 0) {
for(i= 0; i < COLOR_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->col[i], ndigits)));
}
}
else {
for(i= 0; i < COLOR_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->col[i]));
}
}
return ret;
}
PyDoc_STRVAR(Color_copy_doc,
".. function:: copy()\n"
"\n"
" Returns a copy of this color.\n"
"\n"
" :return: A copy of the color.\n"
" :rtype: :class:`Color`\n"
"\n"
" .. note:: use this to get a copy of a wrapped color with\n"
" no reference to the original data.\n"
);
static PyObject *Color_copy(ColorObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return newColorObject(self->col, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Color_repr(ColorObject * self)
{
PyObject *ret, *tuple;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
tuple= Color_ToTupleExt(self, -1);
ret= PyUnicode_FromFormat("Color(%R)", tuple);
Py_DECREF(tuple);
return ret;
}
//------------------------tp_richcmpr
//returns -1 execption, 0 false, 1 true
static PyObject* Color_richcmpr(PyObject *a, PyObject *b, int op)
{
PyObject *res;
int ok= -1; /* zero is true */
if (ColorObject_Check(a) && ColorObject_Check(b)) {
ColorObject *colA= (ColorObject*)a;
ColorObject *colB= (ColorObject*)b;
if(BaseMath_ReadCallback(colA) == -1 || BaseMath_ReadCallback(colB) == -1)
return NULL;
ok= EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1;
}
switch (op) {
case Py_NE:
ok = !ok; /* pass through */
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
case Py_LT:
case Py_LE:
case Py_GT:
case Py_GE:
res = Py_NotImplemented;
break;
default:
PyErr_BadArgument();
return NULL;
}
return Py_INCREF(res), res;
}
//---------------------SEQUENCE PROTOCOLS------------------------
//----------------------------len(object)------------------------
//sequence length
static int Color_len(ColorObject *UNUSED(self))
{
return COLOR_SIZE;
}
//----------------------------object[]---------------------------
//sequence accessor (get)
static PyObject *Color_item(ColorObject * self, int i)
{
if(i<0) i= COLOR_SIZE-i;
if(i < 0 || i >= COLOR_SIZE) {
PyErr_SetString(PyExc_IndexError,
"color[attribute]: "
"array index out of range");
return NULL;
}
if(BaseMath_ReadIndexCallback(self, i) == -1)
return NULL;
return PyFloat_FromDouble(self->col[i]);
}
//----------------------------object[]-------------------------
//sequence accessor (set)
static int Color_ass_item(ColorObject * self, int i, PyObject *value)
{
float f = PyFloat_AsDouble(value);
if(f == -1 && PyErr_Occurred()) { // parsed item not a number
PyErr_SetString(PyExc_TypeError,
"color[attribute] = x: "
"argument not a number");
return -1;
}
if(i<0) i= COLOR_SIZE-i;
if(i < 0 || i >= COLOR_SIZE){
PyErr_SetString(PyExc_IndexError, "color[attribute] = x: "
"array assignment index out of range");
return -1;
}
self->col[i] = f;
if(BaseMath_WriteIndexCallback(self, i) == -1)
return -1;
return 0;
}
//----------------------------object[z:y]------------------------
//sequence slice (get)
static PyObject *Color_slice(ColorObject * self, int begin, int end)
{
PyObject *tuple;
int count;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
CLAMP(begin, 0, COLOR_SIZE);
if (end<0) end= (COLOR_SIZE + 1) + end;
CLAMP(end, 0, COLOR_SIZE);
begin= MIN2(begin, end);
tuple= PyTuple_New(end - begin);
for(count= begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->col[count]));
}
return tuple;
}
//----------------------------object[z:y]------------------------
//sequence slice (set)
static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq)
{
int i, size;
float col[COLOR_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return -1;
CLAMP(begin, 0, COLOR_SIZE);
if (end<0) end= (COLOR_SIZE + 1) + end;
CLAMP(end, 0, COLOR_SIZE);
begin = MIN2(begin, end);
if((size=mathutils_array_parse(col, 0, COLOR_SIZE, seq, "mathutils.Color[begin:end] = []")) == -1)
return -1;
if(size != (end - begin)){
PyErr_SetString(PyExc_ValueError,
"color[begin:end] = []: "
"size mismatch in slice assignment");
return -1;
}
for(i= 0; i < COLOR_SIZE; i++)
self->col[begin + i] = col[i];
(void)BaseMath_WriteCallback(self);
return 0;
}
static PyObject *Color_subscript(ColorObject *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += COLOR_SIZE;
return Color_item(self, i);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0)
return NULL;
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
return Color_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with color");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"color indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return NULL;
}
}
static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *value)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += COLOR_SIZE;
return Color_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0)
return -1;
if (step == 1)
return Color_ass_slice(self, start, stop, value);
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with color");
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"color indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return -1;
}
}
//-----------------PROTCOL DECLARATIONS--------------------------
static PySequenceMethods Color_SeqMethods = {
(lenfunc) Color_len, /* sq_length */
(binaryfunc) NULL, /* sq_concat */
(ssizeargfunc) NULL, /* sq_repeat */
(ssizeargfunc) Color_item, /* sq_item */
NULL, /* sq_slice, deprecated */
(ssizeobjargproc) Color_ass_item, /* sq_ass_item */
NULL, /* sq_ass_slice, deprecated */
(objobjproc) NULL, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */
(ssizeargfunc) NULL, /* sq_inplace_repeat */
};
static PyMappingMethods Color_AsMapping = {
(lenfunc)Color_len,
(binaryfunc)Color_subscript,
(objobjargproc)Color_ass_subscript
};
/* numeric */
/* addition: obj + obj */
static PyObject *Color_add(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL, *color2 = NULL;
float col[COLOR_SIZE];
if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
PyErr_SetString(PyExc_TypeError,
"Color addition: "
"arguments not valid for this operation");
return NULL;
}
color1 = (ColorObject*)v1;
color2 = (ColorObject*)v2;
if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
return newColorObject(col, Py_NEW, Py_TYPE(v1));
}
/* addition in-place: obj += obj */
static PyObject *Color_iadd(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL, *color2 = NULL;
if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
PyErr_SetString(PyExc_TypeError,
"Color addition: "
"arguments not valid for this operation");
return NULL;
}
color1 = (ColorObject*)v1;
color2 = (ColorObject*)v2;
if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
add_vn_vn(color1->col, color2->col, COLOR_SIZE);
(void)BaseMath_WriteCallback(color1);
Py_INCREF(v1);
return v1;
}
/* subtraction: obj - obj */
static PyObject *Color_sub(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL, *color2 = NULL;
float col[COLOR_SIZE];
if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
PyErr_SetString(PyExc_TypeError,
"Color subtraction: "
"arguments not valid for this operation");
return NULL;
}
color1 = (ColorObject*)v1;
color2 = (ColorObject*)v2;
if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
return newColorObject(col, Py_NEW, Py_TYPE(v1));
}
/* subtraction in-place: obj -= obj */
static PyObject *Color_isub(PyObject *v1, PyObject *v2)
{
ColorObject *color1= NULL, *color2= NULL;
if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
PyErr_SetString(PyExc_TypeError,
"Color subtraction: "
"arguments not valid for this operation");
return NULL;
}
color1 = (ColorObject*)v1;
color2 = (ColorObject*)v2;
if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1)
return NULL;
sub_vn_vn(color1->col, color2->col, COLOR_SIZE);
(void)BaseMath_WriteCallback(color1);
Py_INCREF(v1);
return v1;
}
static PyObject *color_mul_float(ColorObject *color, const float scalar)
{
float tcol[COLOR_SIZE];
mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar);
return newColorObject(tcol, Py_NEW, Py_TYPE(color));
}
static PyObject *Color_mul(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL, *color2 = NULL;
float scalar;
if ColorObject_Check(v1) {
color1= (ColorObject *)v1;
if(BaseMath_ReadCallback(color1) == -1)
return NULL;
}
if ColorObject_Check(v2) {
color2= (ColorObject *)v2;
if(BaseMath_ReadCallback(color2) == -1)
return NULL;
}
/* make sure v1 is always the vector */
if (color1 && color2) {
/* col * col, dont support yet! */
}
else if (color1) {
if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR * FLOAT */
return color_mul_float(color1, scalar);
}
}
else if (color2) {
if (((scalar= PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred())==0) { /* FLOAT * COLOR */
return color_mul_float(color2, scalar);
}
}
else {
BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
"Color multiplication: not supported between "
"'%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
}
static PyObject *Color_div(PyObject *v1, PyObject *v2)
{
ColorObject *color1 = NULL;
float scalar;
if ColorObject_Check(v1) {
color1= (ColorObject *)v1;
if(BaseMath_ReadCallback(color1) == -1)
return NULL;
}
else {
PyErr_SetString(PyExc_TypeError,
"Color division not supported in this order");
return NULL;
}
/* make sure v1 is always the vector */
if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR * FLOAT */
if(scalar==0.0f) {
PyErr_SetString(PyExc_ZeroDivisionError,
"Color division: divide by zero error");
return NULL;
}
return color_mul_float(color1, 1.0f / scalar);
}
PyErr_Format(PyExc_TypeError,
"Color multiplication: not supported between "
"'%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
}
/* mulplication in-place: obj *= obj */
static PyObject *Color_imul(PyObject *v1, PyObject *v2)
{
ColorObject *color = (ColorObject *)v1;
float scalar;
if(BaseMath_ReadCallback(color) == -1)
return NULL;
/* only support color *= float */
if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR *= FLOAT */
mul_vn_fl(color->col, COLOR_SIZE, scalar);
}
else {
PyErr_SetString(PyExc_TypeError,
"Color multiplication: "
"arguments not acceptable for this operation");
return NULL;
}
(void)BaseMath_WriteCallback(color);
Py_INCREF(v1);
return v1;
}
/* mulplication in-place: obj *= obj */
static PyObject *Color_idiv(PyObject *v1, PyObject *v2)
{
ColorObject *color = (ColorObject *)v1;
float scalar;
if(BaseMath_ReadCallback(color) == -1)
return NULL;
/* only support color /= float */
if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR /= FLOAT */
if(scalar==0.0f) {
PyErr_SetString(PyExc_ZeroDivisionError,
"Color division: divide by zero error");
return NULL;
}
mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar);
}
else {
PyErr_SetString(PyExc_TypeError,
"Color multiplication: "
"arguments not acceptable for this operation");
return NULL;
}
(void)BaseMath_WriteCallback(color);
Py_INCREF(v1);
return v1;
}
/* -obj
returns the negative of this object*/
static PyObject *Color_neg(ColorObject *self)
{
float tcol[COLOR_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
negate_vn_vn(tcol, self->col, COLOR_SIZE);
return newColorObject(tcol, Py_NEW, Py_TYPE(self));
}
static PyNumberMethods Color_NumMethods = {
(binaryfunc) Color_add, /*nb_add*/
(binaryfunc) Color_sub, /*nb_subtract*/
(binaryfunc) Color_mul, /*nb_multiply*/
NULL, /*nb_remainder*/
NULL, /*nb_divmod*/
NULL, /*nb_power*/
(unaryfunc) Color_neg, /*nb_negative*/
(unaryfunc) NULL, /*tp_positive*/
(unaryfunc) NULL, /*tp_absolute*/
(inquiry) NULL, /*tp_bool*/
(unaryfunc) NULL, /*nb_invert*/
NULL, /*nb_lshift*/
(binaryfunc)NULL, /*nb_rshift*/
NULL, /*nb_and*/
NULL, /*nb_xor*/
NULL, /*nb_or*/
NULL, /*nb_int*/
NULL, /*nb_reserved*/
NULL, /*nb_float*/
Color_iadd, /* nb_inplace_add */
Color_isub, /* nb_inplace_subtract */
Color_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
NULL, /* nb_inplace_rshift */
NULL, /* nb_inplace_and */
NULL, /* nb_inplace_xor */
NULL, /* nb_inplace_or */
NULL, /* nb_floor_divide */
Color_div, /* nb_true_divide */
NULL, /* nb_inplace_floor_divide */
Color_idiv, /* nb_inplace_true_divide */
NULL, /* nb_index */
};
/* color channel, vector.r/g/b */
static PyObject *Color_getChannel(ColorObject * self, void *type)
{
return Color_item(self, GET_INT_FROM_POINTER(type));
}
static int Color_setChannel(ColorObject * self, PyObject *value, void * type)
{
return Color_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
/* color channel (HSV), color.h/s/v */
static PyObject *Color_getChannelHSV(ColorObject * self, void *type)
{
float hsv[3];
int i= GET_INT_FROM_POINTER(type);
if(BaseMath_ReadCallback(self) == -1)
return NULL;
rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
return PyFloat_FromDouble(hsv[i]);
}
static int Color_setChannelHSV(ColorObject * self, PyObject *value, void * type)
{
float hsv[3];
int i= GET_INT_FROM_POINTER(type);
float f = PyFloat_AsDouble(value);
if(f == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"color.h/s/v = value: "
"argument not a number");
return -1;
}
if(BaseMath_ReadCallback(self) == -1)
return -1;
rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
CLAMP(f, 0.0f, 1.0f);
hsv[i] = f;
hsv_to_rgb(hsv[0], hsv[1], hsv[2], &(self->col[0]), &(self->col[1]), &(self->col[2]));
if(BaseMath_WriteCallback(self) == -1)
return -1;
return 0;
}
/* color channel (HSV), color.h/s/v */
static PyObject *Color_getHSV(ColorObject * self, void *UNUSED(closure))
{
float hsv[3];
PyObject *ret;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
ret= PyTuple_New(3);
PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(hsv[0]));
PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(hsv[1]));
PyTuple_SET_ITEM(ret, 2, PyFloat_FromDouble(hsv[2]));
return ret;
}
static int Color_setHSV(ColorObject * self, PyObject *value, void *UNUSED(closure))
{
float hsv[3];
if(mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -1)
return -1;
CLAMP(hsv[0], 0.0f, 1.0f);
CLAMP(hsv[1], 0.0f, 1.0f);
CLAMP(hsv[2], 0.0f, 1.0f);
hsv_to_rgb(hsv[0], hsv[1], hsv[2], &(self->col[0]), &(self->col[1]), &(self->col[2]));
if(BaseMath_WriteCallback(self) == -1)
return -1;
return 0;
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Color_getseters[] = {
{(char *)"r", (getter)Color_getChannel, (setter)Color_setChannel, (char *)"Red color channel.\n\n:type: float", (void *)0},
{(char *)"g", (getter)Color_getChannel, (setter)Color_setChannel, (char *)"Green color channel.\n\n:type: float", (void *)1},
{(char *)"b", (getter)Color_getChannel, (setter)Color_setChannel, (char *)"Blue color channel.\n\n:type: float", (void *)2},
{(char *)"h", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, (char *)"HSV Hue component in [0, 1].\n\n:type: float", (void *)0},
{(char *)"s", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, (char *)"HSV Saturation component in [0, 1].\n\n:type: float", (void *)1},
{(char *)"v", (getter)Color_getChannelHSV, (setter)Color_setChannelHSV, (char *)"HSV Value component in [0, 1].\n\n:type: float", (void *)2},
{(char *)"hsv", (getter)Color_getHSV, (setter)Color_setHSV, (char *)"HSV Values in [0, 1].\n\n:type: float triplet", (void *)0},
{(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Color_methods[] = {
{"__copy__", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc},
{"copy", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc},
{NULL, NULL, 0, NULL}
};
//------------------PY_OBECT DEFINITION--------------------------
PyDoc_STRVAR(color_doc,
"This object gives access to Colors in Blender."
);
PyTypeObject color_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Color", //tp_name
sizeof(ColorObject), //tp_basicsize
0, //tp_itemsize
(destructor)BaseMathObject_dealloc, //tp_dealloc
NULL, //tp_print
NULL, //tp_getattr
NULL, //tp_setattr
NULL, //tp_compare
(reprfunc) Color_repr, //tp_repr
&Color_NumMethods, //tp_as_number
&Color_SeqMethods, //tp_as_sequence
&Color_AsMapping, //tp_as_mapping
NULL, //tp_hash
NULL, //tp_call
NULL, //tp_str
NULL, //tp_getattro
NULL, //tp_setattro
NULL, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags
color_doc, //tp_doc
(traverseproc)BaseMathObject_traverse, //tp_traverse
(inquiry)BaseMathObject_clear, //tp_clear
(richcmpfunc)Color_richcmpr, //tp_richcompare
0, //tp_weaklistoffset
NULL, //tp_iter
NULL, //tp_iternext
Color_methods, //tp_methods
NULL, //tp_members
Color_getseters, //tp_getset
NULL, //tp_base
NULL, //tp_dict
NULL, //tp_descr_get
NULL, //tp_descr_set
0, //tp_dictoffset
NULL, //tp_init
NULL, //tp_alloc
Color_new, //tp_new
NULL, //tp_free
NULL, //tp_is_gc
NULL, //tp_bases
NULL, //tp_mro
NULL, //tp_cache
NULL, //tp_subclasses
NULL, //tp_weaklist
NULL //tp_del
};
//------------------------newColorObject (internal)-------------
//creates a new color object
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newColorObject(float *col, int type, PyTypeObject *base_type)
{
ColorObject *self;
self= base_type ? (ColorObject *)base_type->tp_alloc(base_type, 0) :
(ColorObject *)PyObject_GC_New(ColorObject, &color_Type);
if(self) {
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP){
self->col = col;
self->wrapped = Py_WRAP;
}
else if (type == Py_NEW){
self->col = PyMem_Malloc(COLOR_SIZE * sizeof(float));
if(col)
copy_v3_v3(self->col, col);
else
zero_v3(self->col);
self->wrapped = Py_NEW;
}
else {
Py_FatalError("Color(): invalid type!");
}
}
return (PyObject *)self;
}
PyObject *newColorObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
{
ColorObject *self= (ColorObject *)newColorObject(NULL, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
PyObject_GC_Track(self);
}
return (PyObject *)self;
}

View File

@@ -0,0 +1,55 @@
/*
* $Id: mathutils_Color.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Color.h
* \ingroup pygen
*/
#ifndef MATHUTILS_COLOR_H
#define MATHUTILS_COLOR_H
extern PyTypeObject color_Type;
#define ColorObject_Check(_v) PyObject_TypeCheck((_v), &color_Type)
typedef struct {
BASE_MATH_MEMBERS(col)
} ColorObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newColorObject( float *col, int type, PyTypeObject *base_type);
PyObject *newColorObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* MATHUTILS_COLOR_H */

View File

@@ -0,0 +1,721 @@
/*
* $Id: mathutils_Euler.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_Euler.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#define EULER_SIZE 3
//----------------------------------mathutils.Euler() -------------------
//makes a new euler for you to play with
static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *seq= NULL;
const char *order_str= NULL;
float eul[EULER_SIZE]= {0.0f, 0.0f, 0.0f};
short order= EULER_ORDER_XYZ;
if(kwds && PyDict_Size(kwds)) {
PyErr_SetString(PyExc_TypeError,
"mathutils.Euler(): "
"takes no keyword args");
return NULL;
}
if(!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str))
return NULL;
switch(PyTuple_GET_SIZE(args)) {
case 0:
break;
case 2:
if((order=euler_order_from_string(order_str, "mathutils.Euler()")) == -1)
return NULL;
/* intentionally pass through */
case 1:
if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1)
return NULL;
break;
}
return newEulerObject(eul, order, Py_NEW, type);
}
/* internal use, assuem read callback is done */
static const char *euler_order_str(EulerObject *self)
{
static const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
return order[self->order-EULER_ORDER_XYZ];
}
short euler_order_from_string(const char *str, const char *error_prefix)
{
if((str[0] && str[1] && str[2] && str[3]=='\0')) {
switch(*((PY_INT32_T *)str)) {
case 'X'|'Y'<<8|'Z'<<16: return EULER_ORDER_XYZ;
case 'X'|'Z'<<8|'Y'<<16: return EULER_ORDER_XZY;
case 'Y'|'X'<<8|'Z'<<16: return EULER_ORDER_YXZ;
case 'Y'|'Z'<<8|'X'<<16: return EULER_ORDER_YZX;
case 'Z'|'X'<<8|'Y'<<16: return EULER_ORDER_ZXY;
case 'Z'|'Y'<<8|'X'<<16: return EULER_ORDER_ZYX;
}
}
PyErr_Format(PyExc_ValueError,
"%s: invalid euler order '%s'",
error_prefix, str);
return -1;
}
/* note: BaseMath_ReadCallback must be called beforehand */
static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
{
PyObject *ret;
int i;
ret= PyTuple_New(EULER_SIZE);
if(ndigits >= 0) {
for(i= 0; i < EULER_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->eul[i], ndigits)));
}
}
else {
for(i= 0; i < EULER_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->eul[i]));
}
}
return ret;
}
//-----------------------------METHODS----------------------------
//return a quaternion representation of the euler
PyDoc_STRVAR(Euler_to_quaternion_doc,
".. method:: to_quaternion()\n"
"\n"
" Return a quaternion representation of the euler.\n"
"\n"
" :return: Quaternion representation of the euler.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Euler_to_quaternion(EulerObject * self)
{
float quat[4];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
eulO_to_quat(quat, self->eul, self->order);
return newQuaternionObject(quat, Py_NEW, NULL);
}
//return a matrix representation of the euler
PyDoc_STRVAR(Euler_to_matrix_doc,
".. method:: to_matrix()\n"
"\n"
" Return a matrix representation of the euler.\n"
"\n"
" :return: A 3x3 roation matrix representation of the euler.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Euler_to_matrix(EulerObject * self)
{
float mat[9];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
}
PyDoc_STRVAR(Euler_zero_doc,
".. method:: zero()\n"
"\n"
" Set all values to zero.\n"
);
static PyObject *Euler_zero(EulerObject * self)
{
zero_v3(self->eul);
if(BaseMath_WriteCallback(self) == -1)
return NULL;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Euler_rotate_axis_doc,
".. method:: rotate_axis(axis, angle)\n"
"\n"
" Rotates the euler a certain amount and returning a unique euler rotation\n"
" (no 720 degree pitches).\n"
"\n"
" :arg axis: single character in ['X, 'Y', 'Z'].\n"
" :type axis: string\n"
" :arg angle: angle in radians.\n"
" :type angle: float\n"
);
static PyObject *Euler_rotate_axis(EulerObject * self, PyObject *args)
{
float angle = 0.0f;
const char *axis;
if(!PyArg_ParseTuple(args, "sf:rotate", &axis, &angle)){
PyErr_SetString(PyExc_TypeError,
"euler.rotate(): "
"expected angle (float) and axis (x, y, z)");
return NULL;
}
if(!(ELEM3(*axis, 'X', 'Y', 'Z') && axis[1]=='\0')){
PyErr_SetString(PyExc_ValueError, "euler.rotate(): "
"expected axis to be 'X', 'Y' or 'Z'");
return NULL;
}
if(BaseMath_ReadCallback(self) == -1)
return NULL;
rotate_eulO(self->eul, self->order, *axis, angle);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Euler_rotate_doc,
".. method:: rotate(other)\n"
"\n"
" Rotates the euler a by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
);
static PyObject *Euler_rotate(EulerObject * self, PyObject *value)
{
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1)
return NULL;
eulO_to_mat3(self_rmat, self->eul, self->order);
mul_m3_m3m3(rmat, self_rmat, other_rmat);
mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Euler_make_compatible_doc,
".. method:: make_compatible(other)\n"
"\n"
" Make this euler compatible with another,\n"
" so interpolating between them works as intended.\n"
"\n"
" .. note:: the rotation order is not taken into account for this function.\n"
);
static PyObject *Euler_make_compatible(EulerObject * self, PyObject *value)
{
float teul[EULER_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value, "euler.make_compatible(other), invalid 'other' arg") == -1)
return NULL;
compatible_eul(self->eul, teul);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
//----------------------------Euler.rotate()-----------------------
// return a copy of the euler
PyDoc_STRVAR(Euler_copy_doc,
".. function:: copy()\n"
"\n"
" Returns a copy of this euler.\n"
"\n"
" :return: A copy of the euler.\n"
" :rtype: :class:`Euler`\n"
"\n"
" .. note:: use this to get a copy of a wrapped euler with\n"
" no reference to the original data.\n"
);
static PyObject *Euler_copy(EulerObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return newEulerObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Euler_repr(EulerObject * self)
{
PyObject *ret, *tuple;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
tuple= Euler_ToTupleExt(self, -1);
ret= PyUnicode_FromFormat("Euler(%R, '%s')", tuple, euler_order_str(self));
Py_DECREF(tuple);
return ret;
}
static PyObject* Euler_richcmpr(PyObject *a, PyObject *b, int op)
{
PyObject *res;
int ok= -1; /* zero is true */
if (EulerObject_Check(a) && EulerObject_Check(b)) {
EulerObject *eulA= (EulerObject*)a;
EulerObject *eulB= (EulerObject*)b;
if(BaseMath_ReadCallback(eulA) == -1 || BaseMath_ReadCallback(eulB) == -1)
return NULL;
ok= ((eulA->order == eulB->order) && EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ? 0 : -1;
}
switch (op) {
case Py_NE:
ok = !ok; /* pass through */
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
case Py_LT:
case Py_LE:
case Py_GT:
case Py_GE:
res = Py_NotImplemented;
break;
default:
PyErr_BadArgument();
return NULL;
}
return Py_INCREF(res), res;
}
//---------------------SEQUENCE PROTOCOLS------------------------
//----------------------------len(object)------------------------
//sequence length
static int Euler_len(EulerObject *UNUSED(self))
{
return EULER_SIZE;
}
//----------------------------object[]---------------------------
//sequence accessor (get)
static PyObject *Euler_item(EulerObject * self, int i)
{
if(i<0) i= EULER_SIZE-i;
if(i < 0 || i >= EULER_SIZE) {
PyErr_SetString(PyExc_IndexError,
"euler[attribute]: "
"array index out of range");
return NULL;
}
if(BaseMath_ReadIndexCallback(self, i) == -1)
return NULL;
return PyFloat_FromDouble(self->eul[i]);
}
//----------------------------object[]-------------------------
//sequence accessor (set)
static int Euler_ass_item(EulerObject * self, int i, PyObject *value)
{
float f = PyFloat_AsDouble(value);
if(f == -1 && PyErr_Occurred()) { // parsed item not a number
PyErr_SetString(PyExc_TypeError,
"euler[attribute] = x: "
"argument not a number");
return -1;
}
if(i<0) i= EULER_SIZE-i;
if(i < 0 || i >= EULER_SIZE){
PyErr_SetString(PyExc_IndexError,
"euler[attribute] = x: "
"array assignment index out of range");
return -1;
}
self->eul[i] = f;
if(BaseMath_WriteIndexCallback(self, i) == -1)
return -1;
return 0;
}
//----------------------------object[z:y]------------------------
//sequence slice (get)
static PyObject *Euler_slice(EulerObject * self, int begin, int end)
{
PyObject *tuple;
int count;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
CLAMP(begin, 0, EULER_SIZE);
if (end<0) end= (EULER_SIZE + 1) + end;
CLAMP(end, 0, EULER_SIZE);
begin= MIN2(begin, end);
tuple= PyTuple_New(end - begin);
for(count = begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->eul[count]));
}
return tuple;
}
//----------------------------object[z:y]------------------------
//sequence slice (set)
static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
{
int i, size;
float eul[EULER_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return -1;
CLAMP(begin, 0, EULER_SIZE);
if (end<0) end= (EULER_SIZE + 1) + end;
CLAMP(end, 0, EULER_SIZE);
begin = MIN2(begin, end);
if((size=mathutils_array_parse(eul, 0, EULER_SIZE, seq, "mathutils.Euler[begin:end] = []")) == -1)
return -1;
if(size != (end - begin)){
PyErr_SetString(PyExc_ValueError,
"euler[begin:end] = []: "
"size mismatch in slice assignment");
return -1;
}
for(i= 0; i < EULER_SIZE; i++)
self->eul[begin + i] = eul[i];
(void)BaseMath_WriteCallback(self);
return 0;
}
static PyObject *Euler_subscript(EulerObject *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += EULER_SIZE;
return Euler_item(self, i);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
return NULL;
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
return Euler_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with eulers");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"euler indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return NULL;
}
}
static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += EULER_SIZE;
return Euler_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
return -1;
if (step == 1)
return Euler_ass_slice(self, start, stop, value);
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with euler");
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"euler indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return -1;
}
}
//-----------------PROTCOL DECLARATIONS--------------------------
static PySequenceMethods Euler_SeqMethods = {
(lenfunc) Euler_len, /* sq_length */
(binaryfunc) NULL, /* sq_concat */
(ssizeargfunc) NULL, /* sq_repeat */
(ssizeargfunc) Euler_item, /* sq_item */
(ssizessizeargfunc) NULL, /* sq_slice, deprecated */
(ssizeobjargproc) Euler_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) NULL, /* sq_ass_slice, deprecated */
(objobjproc) NULL, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */
(ssizeargfunc) NULL, /* sq_inplace_repeat */
};
static PyMappingMethods Euler_AsMapping = {
(lenfunc)Euler_len,
(binaryfunc)Euler_subscript,
(objobjargproc)Euler_ass_subscript
};
/*
* euler axis, euler.x/y/z
*/
static PyObject *Euler_getAxis(EulerObject *self, void *type)
{
return Euler_item(self, GET_INT_FROM_POINTER(type));
}
static int Euler_setAxis(EulerObject *self, PyObject *value, void *type)
{
return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
/* rotation order */
static PyObject *Euler_getOrder(EulerObject *self, void *UNUSED(closure))
{
if(BaseMath_ReadCallback(self) == -1) /* can read order too */
return NULL;
return PyUnicode_FromString(euler_order_str(self));
}
static int Euler_setOrder(EulerObject *self, PyObject *value, void *UNUSED(closure))
{
const char *order_str= _PyUnicode_AsString(value);
short order= euler_order_from_string(order_str, "euler.order");
if(order == -1)
return -1;
self->order= order;
(void)BaseMath_WriteCallback(self); /* order can be written back */
return 0;
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Euler_getseters[] = {
{(char *)"x", (getter)Euler_getAxis, (setter)Euler_setAxis, (char *)"Euler X axis in radians.\n\n:type: float", (void *)0},
{(char *)"y", (getter)Euler_getAxis, (setter)Euler_setAxis, (char *)"Euler Y axis in radians.\n\n:type: float", (void *)1},
{(char *)"z", (getter)Euler_getAxis, (setter)Euler_setAxis, (char *)"Euler Z axis in radians.\n\n:type: float", (void *)2},
{(char *)"order", (getter)Euler_getOrder, (setter)Euler_setOrder, (char *)"Euler rotation order.\n\n:type: string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']", (void *)NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Euler_methods[] = {
{"zero", (PyCFunction) Euler_zero, METH_NOARGS, Euler_zero_doc},
{"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
{"to_quaternion", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc},
{"rotate_axis", (PyCFunction) Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
{"rotate", (PyCFunction) Euler_rotate, METH_O, Euler_rotate_doc},
{"make_compatible", (PyCFunction) Euler_make_compatible, METH_O, Euler_make_compatible_doc},
{"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
{"copy", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
{NULL, NULL, 0, NULL}
};
//------------------PY_OBECT DEFINITION--------------------------
PyDoc_STRVAR(euler_doc,
"This object gives access to Eulers in Blender."
);
PyTypeObject euler_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Euler", //tp_name
sizeof(EulerObject), //tp_basicsize
0, //tp_itemsize
(destructor)BaseMathObject_dealloc, //tp_dealloc
NULL, //tp_print
NULL, //tp_getattr
NULL, //tp_setattr
NULL, //tp_compare
(reprfunc) Euler_repr, //tp_repr
NULL, //tp_as_number
&Euler_SeqMethods, //tp_as_sequence
&Euler_AsMapping, //tp_as_mapping
NULL, //tp_hash
NULL, //tp_call
NULL, //tp_str
NULL, //tp_getattro
NULL, //tp_setattro
NULL, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags
euler_doc, //tp_doc
(traverseproc)BaseMathObject_traverse, //tp_traverse
(inquiry)BaseMathObject_clear, //tp_clear
(richcmpfunc)Euler_richcmpr, //tp_richcompare
0, //tp_weaklistoffset
NULL, //tp_iter
NULL, //tp_iternext
Euler_methods, //tp_methods
NULL, //tp_members
Euler_getseters, //tp_getset
NULL, //tp_base
NULL, //tp_dict
NULL, //tp_descr_get
NULL, //tp_descr_set
0, //tp_dictoffset
NULL, //tp_init
NULL, //tp_alloc
Euler_new, //tp_new
NULL, //tp_free
NULL, //tp_is_gc
NULL, //tp_bases
NULL, //tp_mro
NULL, //tp_cache
NULL, //tp_subclasses
NULL, //tp_weaklist
NULL //tp_del
};
//------------------------newEulerObject (internal)-------------
//creates a new euler object
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newEulerObject(float *eul, short order, int type, PyTypeObject *base_type)
{
EulerObject *self;
self= base_type ? (EulerObject *)base_type->tp_alloc(base_type, 0) :
(EulerObject *)PyObject_GC_New(EulerObject, &euler_Type);
if(self) {
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP) {
self->eul = eul;
self->wrapped = Py_WRAP;
}
else if (type == Py_NEW) {
self->eul = PyMem_Malloc(EULER_SIZE * sizeof(float));
if(eul) {
copy_v3_v3(self->eul, eul);
}
else {
zero_v3(self->eul);
}
self->wrapped = Py_NEW;
}
else {
Py_FatalError("Euler(): invalid type!");
}
self->order= order;
}
return (PyObject *)self;
}
PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype)
{
EulerObject *self= (EulerObject *)newEulerObject(NULL, order, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
PyObject_GC_Track(self);
}
return (PyObject *)self;
}

View File

@@ -0,0 +1,60 @@
/*
* $Id: mathutils_Euler.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Euler.h
* \ingroup pygen
*/
#ifndef MATHUTILS_EULER_H
#define MATHUTILS_EULER_H
extern PyTypeObject euler_Type;
#define EulerObject_Check(_v) PyObject_TypeCheck((_v), &euler_Type)
typedef struct {
BASE_MATH_MEMBERS(eul)
unsigned char order; /* rotation order */
} EulerObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newEulerObject( float *eul, short order, int type, PyTypeObject *base_type);
PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype);
short euler_order_from_string(const char *str, const char *error_prefix);
#endif /* MATHUTILS_EULER_H */

View File

@@ -0,0 +1,2035 @@
/*
* $Id: mathutils_Matrix.c 38527 2011-07-20 06:41:51Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* Contributor(s): Michel Selten & Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_Matrix.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
static PyObject *Matrix_copy(MatrixObject *self);
static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value);
static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self);
/* matrix vector callbacks */
int mathutils_matrix_vector_cb_index= -1;
static int mathutils_matrix_vector_check(BaseMathObject *bmo)
{
MatrixObject *self= (MatrixObject *)bmo->cb_user;
return BaseMath_ReadCallback(self);
}
static int mathutils_matrix_vector_get(BaseMathObject *bmo, int subtype)
{
MatrixObject *self= (MatrixObject *)bmo->cb_user;
int i;
if(BaseMath_ReadCallback(self) == -1)
return -1;
for(i=0; i < self->col_size; i++)
bmo->data[i]= self->matrix[subtype][i];
return 0;
}
static int mathutils_matrix_vector_set(BaseMathObject *bmo, int subtype)
{
MatrixObject *self= (MatrixObject *)bmo->cb_user;
int i;
if(BaseMath_ReadCallback(self) == -1)
return -1;
for(i=0; i < self->col_size; i++)
self->matrix[subtype][i]= bmo->data[i];
(void)BaseMath_WriteCallback(self);
return 0;
}
static int mathutils_matrix_vector_get_index(BaseMathObject *bmo, int subtype, int index)
{
MatrixObject *self= (MatrixObject *)bmo->cb_user;
if(BaseMath_ReadCallback(self) == -1)
return -1;
bmo->data[index]= self->matrix[subtype][index];
return 0;
}
static int mathutils_matrix_vector_set_index(BaseMathObject *bmo, int subtype, int index)
{
MatrixObject *self= (MatrixObject *)bmo->cb_user;
if(BaseMath_ReadCallback(self) == -1)
return -1;
self->matrix[subtype][index]= bmo->data[index];
(void)BaseMath_WriteCallback(self);
return 0;
}
Mathutils_Callback mathutils_matrix_vector_cb = {
mathutils_matrix_vector_check,
mathutils_matrix_vector_get,
mathutils_matrix_vector_set,
mathutils_matrix_vector_get_index,
mathutils_matrix_vector_set_index
};
/* matrix vector callbacks, this is so you can do matrix[i][j] = val */
//----------------------------------mathutils.Matrix() -----------------
//mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
//create a new matrix type
static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
if(kwds && PyDict_Size(kwds)) {
PyErr_SetString(PyExc_TypeError,
"mathutils.Matrix(): "
"takes no keyword args");
return NULL;
}
switch(PyTuple_GET_SIZE(args)) {
case 0:
return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW, type);
case 1:
{
PyObject *arg= PyTuple_GET_ITEM(args, 0);
/* -1 is an error, size checks will accunt for this */
const unsigned short row_size= PySequence_Size(arg);
if(row_size >= 2 && row_size <= 4) {
PyObject *item= PySequence_GetItem(arg, 0);
const unsigned short col_size= PySequence_Size(item);
Py_XDECREF(item);
if(col_size >= 2 && col_size <= 4) {
/* sane row & col size, new matrix and assign as slice */
PyObject *matrix= newMatrixObject(NULL, row_size, col_size, Py_NEW, type);
if(Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
return matrix;
}
else { /* matrix ok, slice assignment not */
Py_DECREF(matrix);
}
}
}
}
}
/* will overwrite error */
PyErr_SetString(PyExc_TypeError,
"mathutils.Matrix(): "
"expects no args or 2-4 numeric sequences");
return NULL;
}
static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self)
{
PyObject *ret= Matrix_copy(self);
PyObject *ret_dummy= matrix_func(ret);
if(ret_dummy) {
Py_DECREF(ret_dummy);
return (PyObject *)ret;
}
else { /* error */
Py_DECREF(ret);
return NULL;
}
}
/* when a matrix is 4x4 size but initialized as a 3x3, re-assign values for 4x4 */
static void matrix_3x3_as_4x4(float mat[16])
{
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;
}
/*-----------------------CLASS-METHODS----------------------------*/
//mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
PyDoc_STRVAR(C_Matrix_Rotation_doc,
".. classmethod:: Rotation(angle, size, axis)\n"
"\n"
" Create a matrix representing a rotation.\n"
"\n"
" :arg angle: The angle of rotation desired, in radians.\n"
" :type angle: float\n"
" :arg size: The size of the rotation matrix to construct [2, 4].\n"
" :type size: int\n"
" :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object\n"
" (optional when size is 2).\n"
" :type axis: string or :class:`Vector`\n"
" :return: A new rotation matrix.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args)
{
PyObject *vec= NULL;
const char *axis= NULL;
int matSize;
double angle; /* use double because of precision problems at high values */
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
if(!PyArg_ParseTuple(args, "di|O", &angle, &matSize, &vec)) {
PyErr_SetString(PyExc_TypeError,
"mathutils.RotationMatrix(angle, size, axis): "
"expected float int and a string or vector");
return NULL;
}
if(vec && PyUnicode_Check(vec)) {
axis= _PyUnicode_AsString((PyObject *)vec);
if(axis==NULL || axis[0]=='\0' || axis[1]!='\0' || axis[0] < 'X' || axis[0] > 'Z') {
PyErr_SetString(PyExc_ValueError,
"mathutils.RotationMatrix(): "
"3rd argument axis value must be a 3D vector "
"or a string in 'X', 'Y', 'Z'");
return NULL;
}
else {
/* use the string */
vec= NULL;
}
}
angle= angle_wrap_rad(angle);
if(matSize != 2 && matSize != 3 && matSize != 4) {
PyErr_SetString(PyExc_ValueError,
"mathutils.RotationMatrix(): "
"can only return a 2x2 3x3 or 4x4 matrix");
return NULL;
}
if(matSize == 2 && (vec != NULL)) {
PyErr_SetString(PyExc_ValueError,
"mathutils.RotationMatrix(): "
"cannot create a 2x2 rotation matrix around arbitrary axis");
return NULL;
}
if((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) {
PyErr_SetString(PyExc_ValueError,
"mathutils.RotationMatrix(): "
"axis of rotation for 3d and 4d matrices is required");
return NULL;
}
/* check for valid vector/axis above */
if(vec) {
float tvec[3];
if (mathutils_array_parse(tvec, 3, 3, vec, "mathutils.RotationMatrix(angle, size, axis), invalid 'axis' arg") == -1)
return NULL;
axis_angle_to_mat3((float (*)[3])mat, tvec, angle);
}
else if(matSize == 2) {
//2D rotation matrix
mat[0] = (float) cos (angle);
mat[1] = (float) sin (angle);
mat[2] = -((float) sin(angle));
mat[3] = (float) cos(angle);
}
else if(strcmp(axis, "X") == 0) {
//rotation around X
mat[0] = 1.0f;
mat[4] = (float) cos(angle);
mat[5] = (float) sin(angle);
mat[7] = -((float) sin(angle));
mat[8] = (float) cos(angle);
}
else if(strcmp(axis, "Y") == 0) {
//rotation around Y
mat[0] = (float) cos(angle);
mat[2] = -((float) sin(angle));
mat[4] = 1.0f;
mat[6] = (float) sin(angle);
mat[8] = (float) cos(angle);
}
else if(strcmp(axis, "Z") == 0) {
//rotation around Z
mat[0] = (float) cos(angle);
mat[1] = (float) sin(angle);
mat[3] = -((float) sin(angle));
mat[4] = (float) cos(angle);
mat[8] = 1.0f;
}
else {
/* should never get here */
PyErr_SetString(PyExc_ValueError,
"mathutils.RotationMatrix(): unknown error");
return NULL;
}
if(matSize == 4) {
matrix_3x3_as_4x4(mat);
}
//pass to matrix creation
return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Matrix_Translation_doc,
".. classmethod:: Translation(vector)\n"
"\n"
" Create a matrix representing a translation.\n"
"\n"
" :arg vector: The translation vector.\n"
" :type vector: :class:`Vector`\n"
" :return: An identity matrix with a translation.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value)
{
float mat[16], tvec[3];
if (mathutils_array_parse(tvec, 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1)
return NULL;
/* create a identity matrix and add translation */
unit_m4((float(*)[4]) mat);
copy_v3_v3(mat + 12, tvec); /* 12, 13, 14 */
return newMatrixObject(mat, 4, 4, Py_NEW, (PyTypeObject *)cls);
}
//----------------------------------mathutils.Matrix.Scale() -------------
//mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
PyDoc_STRVAR(C_Matrix_Scale_doc,
".. classmethod:: Scale(factor, size, axis)\n"
"\n"
" Create a matrix representing a scaling.\n"
"\n"
" :arg factor: The factor of scaling to apply.\n"
" :type factor: float\n"
" :arg size: The size of the scale matrix to construct [2, 4].\n"
" :type size: int\n"
" :arg axis: Direction to influence scale. (optional).\n"
" :type axis: :class:`Vector`\n"
" :return: A new scale matrix.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
{
PyObject *vec= NULL;
int vec_size;
float tvec[3];
float factor;
int matSize;
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
if(!PyArg_ParseTuple(args, "fi|O:Matrix.Scale", &factor, &matSize, &vec)) {
return NULL;
}
if(matSize != 2 && matSize != 3 && matSize != 4) {
PyErr_SetString(PyExc_ValueError,
"Matrix.Scale(): "
"can only return a 2x2 3x3 or 4x4 matrix");
return NULL;
}
if(vec) {
vec_size= (matSize == 2 ? 2 : 3);
if(mathutils_array_parse(tvec, vec_size, vec_size, vec, "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1) {
return NULL;
}
}
if(vec == NULL) { //scaling along axis
if(matSize == 2) {
mat[0] = factor;
mat[3] = factor;
}
else {
mat[0] = factor;
mat[4] = factor;
mat[8] = factor;
}
}
else { //scaling in arbitrary direction
//normalize arbitrary axis
float norm = 0.0f;
int x;
for(x = 0; x < vec_size; x++) {
norm += tvec[x] * tvec[x];
}
norm = (float) sqrt(norm);
for(x = 0; x < vec_size; x++) {
tvec[x] /= norm;
}
if(matSize == 2) {
mat[0] = 1 + ((factor - 1) *(tvec[0] * tvec[0]));
mat[1] = ((factor - 1) *(tvec[0] * tvec[1]));
mat[2] = ((factor - 1) *(tvec[0] * tvec[1]));
mat[3] = 1 + ((factor - 1) *(tvec[1] * tvec[1]));
}
else {
mat[0] = 1 + ((factor - 1) *(tvec[0] * tvec[0]));
mat[1] = ((factor - 1) *(tvec[0] * tvec[1]));
mat[2] = ((factor - 1) *(tvec[0] * tvec[2]));
mat[3] = ((factor - 1) *(tvec[0] * tvec[1]));
mat[4] = 1 + ((factor - 1) *(tvec[1] * tvec[1]));
mat[5] = ((factor - 1) *(tvec[1] * tvec[2]));
mat[6] = ((factor - 1) *(tvec[0] * tvec[2]));
mat[7] = ((factor - 1) *(tvec[1] * tvec[2]));
mat[8] = 1 + ((factor - 1) *(tvec[2] * tvec[2]));
}
}
if(matSize == 4) {
matrix_3x3_as_4x4(mat);
}
//pass to matrix creation
return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
}
//----------------------------------mathutils.Matrix.OrthoProjection() ---
//mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
PyDoc_STRVAR(C_Matrix_OrthoProjection_doc,
".. classmethod:: OrthoProjection(axis, size)\n"
"\n"
" Create a matrix to represent an orthographic projection.\n"
"\n"
" :arg axis: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
" where a single axis is for a 2D matrix.\n"
" Or a vector for an arbitrary axis\n"
" :type axis: string or :class:`Vector`\n"
" :arg size: The size of the projection matrix to construct [2, 4].\n"
" :type size: int\n"
" :return: A new projection matrix.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
{
PyObject *axis;
int matSize, x;
float norm = 0.0f;
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
if(!PyArg_ParseTuple(args, "Oi:Matrix.OrthoProjection", &axis, &matSize)) {
return NULL;
}
if(matSize != 2 && matSize != 3 && matSize != 4) {
PyErr_SetString(PyExc_ValueError,
"mathutils.Matrix.OrthoProjection(): "
"can only return a 2x2 3x3 or 4x4 matrix");
return NULL;
}
if(PyUnicode_Check(axis)) { //ortho projection onto cardinal plane
Py_ssize_t plane_len;
const char *plane= _PyUnicode_AsStringAndSize(axis, &plane_len);
if(matSize == 2) {
if(plane_len == 1 && plane[0]=='X') {
mat[0]= 1.0f;
}
else if (plane_len == 1 && plane[0]=='Y') {
mat[3]= 1.0f;
}
else {
PyErr_Format(PyExc_ValueError,
"mathutils.Matrix.OrthoProjection(): "
"unknown plane, expected: X, Y, not '%.200s'",
plane);
return NULL;
}
}
else {
if(plane_len == 2 && plane[0]=='X' && plane[1]=='Y') {
mat[0]= 1.0f;
mat[4]= 1.0f;
}
else if (plane_len == 2 && plane[0]=='X' && plane[1]=='Z') {
mat[0]= 1.0f;
mat[8]= 1.0f;
}
else if (plane_len == 2 && plane[0]=='Y' && plane[1]=='Z') {
mat[4]= 1.0f;
mat[8]= 1.0f;
}
else {
PyErr_Format(PyExc_ValueError,
"mathutils.Matrix.OrthoProjection(): "
"unknown plane, expected: XY, XZ, YZ, not '%.200s'",
plane);
return NULL;
}
}
}
else {
//arbitrary plane
int vec_size= (matSize == 2 ? 2 : 3);
float tvec[4];
if(mathutils_array_parse(tvec, vec_size, vec_size, axis, "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) {
return NULL;
}
//normalize arbitrary axis
for(x = 0; x < vec_size; x++) {
norm += tvec[x] * tvec[x];
}
norm = (float) sqrt(norm);
for(x = 0; x < vec_size; x++) {
tvec[x] /= norm;
}
if(matSize == 2) {
mat[0] = 1 - (tvec[0] * tvec[0]);
mat[1] = -(tvec[0] * tvec[1]);
mat[2] = -(tvec[0] * tvec[1]);
mat[3] = 1 - (tvec[1] * tvec[1]);
}
else if(matSize > 2) {
mat[0] = 1 - (tvec[0] * tvec[0]);
mat[1] = -(tvec[0] * tvec[1]);
mat[2] = -(tvec[0] * tvec[2]);
mat[3] = -(tvec[0] * tvec[1]);
mat[4] = 1 - (tvec[1] * tvec[1]);
mat[5] = -(tvec[1] * tvec[2]);
mat[6] = -(tvec[0] * tvec[2]);
mat[7] = -(tvec[1] * tvec[2]);
mat[8] = 1 - (tvec[2] * tvec[2]);
}
}
if(matSize == 4) {
matrix_3x3_as_4x4(mat);
}
//pass to matrix creation
return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Matrix_Shear_doc,
".. classmethod:: Shear(plane, size, factor)\n"
"\n"
" Create a matrix to represent an shear transformation.\n"
"\n"
" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
" where a single axis is for a 2D matrix only.\n"
" :type plane: string\n"
" :arg size: The size of the shear matrix to construct [2, 4].\n"
" :type size: int\n"
" :arg factor: The factor of shear to apply. For a 3 or 4 *size* matrix\n"
" pass a pair of floats corrasponding with the *plane* axis.\n"
" :type factor: float or float pair\n"
" :return: A new shear matrix.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
{
int matSize;
const char *plane;
PyObject *fac;
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
if(!PyArg_ParseTuple(args, "siO:Matrix.Shear", &plane, &matSize, &fac)) {
return NULL;
}
if(matSize != 2 && matSize != 3 && matSize != 4) {
PyErr_SetString(PyExc_ValueError,
"mathutils.Matrix.Shear(): "
"can only return a 2x2 3x3 or 4x4 matrix");
return NULL;
}
if(matSize == 2) {
float const factor= PyFloat_AsDouble(fac);
if(factor==-1.0f && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"mathutils.Matrix.Shear(): "
"the factor to be a float");
return NULL;
}
/* unit */
mat[0] = 1.0f;
mat[3] = 1.0f;
if(strcmp(plane, "X") == 0) {
mat[2] = factor;
}
else if(strcmp(plane, "Y") == 0) {
mat[1] = factor;
}
else {
PyErr_SetString(PyExc_ValueError,
"Matrix.Shear(): "
"expected: X, Y or wrong matrix size for shearing plane");
return NULL;
}
}
else {
/* 3 or 4, apply as 3x3, resize later if needed */
float factor[2];
if(mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") < 0) {
return NULL;
}
/* unit */
mat[0] = 1.0f;
mat[4] = 1.0f;
mat[8] = 1.0f;
if(strcmp(plane, "XY") == 0) {
mat[6] = factor[0];
mat[7] = factor[1];
}
else if(strcmp(plane, "XZ") == 0) {
mat[3] = factor[0];
mat[5] = factor[1];
}
else if(strcmp(plane, "YZ") == 0) {
mat[1] = factor[0];
mat[2] = factor[1];
}
else {
PyErr_SetString(PyExc_ValueError,
"mathutils.Matrix.Shear(): "
"expected: X, Y, XY, XZ, YZ");
return NULL;
}
}
if(matSize == 4) {
matrix_3x3_as_4x4(mat);
}
//pass to matrix creation
return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
}
void matrix_as_3x3(float mat[3][3], MatrixObject *self)
{
copy_v3_v3(mat[0], self->matrix[0]);
copy_v3_v3(mat[1], self->matrix[1]);
copy_v3_v3(mat[2], self->matrix[2]);
}
/* assumes rowsize == colsize is checked and the read callback has run */
static float matrix_determinant_internal(MatrixObject *self)
{
if(self->row_size == 2) {
return determinant_m2(self->matrix[0][0], self->matrix[0][1],
self->matrix[1][0], self->matrix[1][1]);
}
else if(self->row_size == 3) {
return determinant_m3(self->matrix[0][0], self->matrix[0][1],
self->matrix[0][2], self->matrix[1][0],
self->matrix[1][1], self->matrix[1][2],
self->matrix[2][0], self->matrix[2][1],
self->matrix[2][2]);
}
else {
return determinant_m4((float (*)[4])self->contigPtr);
}
}
/*-----------------------------METHODS----------------------------*/
PyDoc_STRVAR(Matrix_to_quaternion_doc,
".. method:: to_quaternion()\n"
"\n"
" Return a quaternion representation of the rotation matrix.\n"
"\n"
" :return: Quaternion representation of the rotation matrix.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Matrix_to_quaternion(MatrixObject *self)
{
float quat[4];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
/*must be 3-4 cols, 3-4 rows, square matrix*/
if((self->col_size < 3) || (self->row_size < 3) || (self->col_size != self->row_size)) {
PyErr_SetString(PyExc_ValueError,
"matrix.to_quat(): "
"inappropriate matrix size - expects 3x3 or 4x4 matrix");
return NULL;
}
if(self->col_size == 3){
mat3_to_quat(quat, (float (*)[3])self->contigPtr);
}
else {
mat4_to_quat(quat, (float (*)[4])self->contigPtr);
}
return newQuaternionObject(quat, Py_NEW, NULL);
}
/*---------------------------matrix.toEuler() --------------------*/
PyDoc_STRVAR(Matrix_to_euler_doc,
".. method:: to_euler(order, euler_compat)\n"
"\n"
" Return an Euler representation of the rotation matrix\n"
" (3x3 or 4x4 matrix only).\n"
"\n"
" :arg order: Optional rotation order argument in\n"
" ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
" :type order: string\n"
" :arg euler_compat: Optional euler argument the new euler will be made\n"
" compatible with (no axis flipping between them).\n"
" Useful for converting a series of matrices to animation curves.\n"
" :type euler_compat: :class:`Euler`\n"
" :return: Euler representation of the matrix.\n"
" :rtype: :class:`Euler`\n"
);
static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args)
{
const char *order_str= NULL;
short order= EULER_ORDER_XYZ;
float eul[3], eul_compatf[3];
EulerObject *eul_compat = NULL;
float tmat[3][3];
float (*mat)[3];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
return NULL;
if(eul_compat) {
if(BaseMath_ReadCallback(eul_compat) == -1)
return NULL;
copy_v3_v3(eul_compatf, eul_compat->eul);
}
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->col_size ==3 && self->row_size ==3) {
mat= (float (*)[3])self->contigPtr;
}
else if (self->col_size ==4 && self->row_size ==4) {
copy_m3_m4(tmat, (float (*)[4])self->contigPtr);
mat= tmat;
}
else {
PyErr_SetString(PyExc_ValueError,
"matrix.to_euler(): "
"inappropriate matrix size - expects 3x3 or 4x4 matrix");
return NULL;
}
if(order_str) {
order= euler_order_from_string(order_str, "matrix.to_euler()");
if(order == -1)
return NULL;
}
if(eul_compat) {
if(order == 1) mat3_to_compatible_eul(eul, eul_compatf, mat);
else mat3_to_compatible_eulO(eul, eul_compatf, order, mat);
}
else {
if(order == 1) mat3_to_eul(eul, mat);
else mat3_to_eulO(eul, order, mat);
}
return newEulerObject(eul, order, Py_NEW, NULL);
}
PyDoc_STRVAR(Matrix_resize_4x4_doc,
".. method:: resize_4x4()\n"
"\n"
" Resize the matrix to 4x4.\n"
);
static PyObject *Matrix_resize_4x4(MatrixObject *self)
{
int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
if(self->wrapped==Py_WRAP){
PyErr_SetString(PyExc_TypeError,
"cannot resize wrapped data - make a copy and resize that");
return NULL;
}
if(self->cb_user){
PyErr_SetString(PyExc_TypeError,
"cannot resize owned data - make a copy and resize that");
return NULL;
}
self->contigPtr = PyMem_Realloc(self->contigPtr, (sizeof(float) * 16));
if(self->contigPtr == NULL) {
PyErr_SetString(PyExc_MemoryError,
"matrix.resize_4x4(): problem allocating pointer space");
return NULL;
}
/*set row pointers*/
for(x = 0; x < 4; x++) {
self->matrix[x] = self->contigPtr + (x * 4);
}
/*move data to new spot in array + clean*/
for(blank_rows = (4 - self->row_size); blank_rows > 0; blank_rows--){
for(x = 0; x < 4; x++){
index = (4 * (self->row_size + (blank_rows - 1))) + x;
if (index == 10 || index == 15){
self->contigPtr[index] = 1.0f;
}
else {
self->contigPtr[index] = 0.0f;
}
}
}
for(x = 1; x <= self->row_size; x++){
first_row_elem = (self->col_size * (self->row_size - x));
curr_pos = (first_row_elem + (self->col_size -1));
new_pos = (4 * (self->row_size - x)) + (curr_pos - first_row_elem);
for(blank_columns = (4 - self->col_size); blank_columns > 0; blank_columns--){
self->contigPtr[new_pos + blank_columns] = 0.0f;
}
for( ; curr_pos >= first_row_elem; curr_pos--){
self->contigPtr[new_pos] = self->contigPtr[curr_pos];
new_pos--;
}
}
self->row_size = 4;
self->col_size = 4;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Matrix_to_4x4_doc,
".. method:: to_4x4()\n"
"\n"
" Return a 4x4 copy of this matrix.\n"
"\n"
" :return: a new matrix.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Matrix_to_4x4(MatrixObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(self->col_size==4 && self->row_size==4) {
return (PyObject *)newMatrixObject(self->contigPtr, 4, 4, Py_NEW, Py_TYPE(self));
}
else if(self->col_size==3 && self->row_size==3) {
float mat[4][4];
copy_m4_m3(mat, (float (*)[3])self->contigPtr);
return (PyObject *)newMatrixObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self));
}
/* TODO, 2x2 matrix */
PyErr_SetString(PyExc_TypeError,
"matrix.to_4x4(): inappropriate matrix size");
return NULL;
}
PyDoc_STRVAR(Matrix_to_3x3_doc,
".. method:: to_3x3()\n"
"\n"
" Return a 3x3 copy of this matrix.\n"
"\n"
" :return: a new matrix.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Matrix_to_3x3(MatrixObject *self)
{
float mat[3][3];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if((self->col_size < 3) || (self->row_size < 3)) {
PyErr_SetString(PyExc_TypeError,
"matrix.to_3x3(): inappropriate matrix size");
return NULL;
}
matrix_as_3x3(mat, self);
return newMatrixObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Matrix_to_translation_doc,
".. method:: to_translation()\n"
"\n"
" Return a the translation part of a 4 row matrix.\n"
"\n"
" :return: Return a the translation of a matrix.\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Matrix_to_translation(MatrixObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if((self->col_size < 3) || self->row_size < 4){
PyErr_SetString(PyExc_TypeError,
"matrix.to_translation(): "
"inappropriate matrix size");
return NULL;
}
return newVectorObject(self->matrix[3], 3, Py_NEW, NULL);
}
PyDoc_STRVAR(Matrix_to_scale_doc,
".. method:: to_scale()\n"
"\n"
" Return a the scale part of a 3x3 or 4x4 matrix.\n"
"\n"
" :return: Return a the scale of a matrix.\n"
" :rtype: :class:`Vector`\n"
"\n"
" .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
);
static PyObject *Matrix_to_scale(MatrixObject *self)
{
float rot[3][3];
float mat[3][3];
float size[3];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
/*must be 3-4 cols, 3-4 rows, square matrix*/
if((self->col_size < 3) || (self->row_size < 3)) {
PyErr_SetString(PyExc_TypeError,
"matrix.to_scale(): "
"inappropriate matrix size, 3x3 minimum size");
return NULL;
}
matrix_as_3x3(mat, self);
/* compatible mat4_to_loc_rot_size */
mat3_to_rot_size(rot, size, mat);
return newVectorObject(size, 3, Py_NEW, NULL);
}
/*---------------------------matrix.invert() ---------------------*/
PyDoc_STRVAR(Matrix_invert_doc,
".. method:: invert()\n"
"\n"
" Set the matrix to its inverse.\n"
"\n"
" .. note:: :exc:`ValueError` exception is raised.\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n"
);
static PyObject *Matrix_invert(MatrixObject *self)
{
int x, y, z = 0;
float det = 0.0f;
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(self->row_size != self->col_size){
PyErr_SetString(PyExc_TypeError,
"matrix.invert(ed): "
"only square matrices are supported");
return NULL;
}
/*calculate the determinant*/
det = matrix_determinant_internal(self);
if(det != 0) {
/*calculate the classical adjoint*/
if(self->row_size == 2) {
mat[0] = self->matrix[1][1];
mat[1] = -self->matrix[0][1];
mat[2] = -self->matrix[1][0];
mat[3] = self->matrix[0][0];
} else if(self->row_size == 3) {
adjoint_m3_m3((float (*)[3]) mat,(float (*)[3])self->contigPtr);
} else if(self->row_size == 4) {
adjoint_m4_m4((float (*)[4]) mat, (float (*)[4])self->contigPtr);
}
/*divide by determinate*/
for(x = 0; x < (self->row_size * self->col_size); x++) {
mat[x] /= det;
}
/*set values*/
for(x = 0; x < self->row_size; x++) {
for(y = 0; y < self->col_size; y++) {
self->matrix[x][y] = mat[z];
z++;
}
}
/*transpose
Matrix_transpose(self);*/
}
else {
PyErr_SetString(PyExc_ValueError,
"matrix does not have an inverse");
return NULL;
}
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Matrix_inverted_doc,
".. method:: inverted()\n"
"\n"
" Return an inverted copy of the matrix.\n"
"\n"
" :return: the inverted matrix.\n"
" :rtype: :class:`Matrix`\n"
"\n"
" .. note:: :exc:`ValueError` exception is raised.\n"
);
static PyObject *Matrix_inverted(MatrixObject *self)
{
return matrix__apply_to_copy((PyNoArgsFunction)Matrix_invert, self);
}
PyDoc_STRVAR(Matrix_rotate_doc,
".. method:: rotate(other)\n"
"\n"
" Rotates the matrix a by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
"\n"
" .. note:: If any of the columns are not unit length this may not have desired results.\n"
);
static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
{
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1)
return NULL;
if(self->col_size != 3 || self->row_size != 3) {
PyErr_SetString(PyExc_TypeError,
"Matrix must have 3x3 dimensions");
return NULL;
}
matrix_as_3x3(self_rmat, self);
mul_m3_m3m3(rmat, self_rmat, other_rmat);
copy_m3_m3((float (*)[3])(self->contigPtr), rmat);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
/*---------------------------matrix.decompose() ---------------------*/
PyDoc_STRVAR(Matrix_decompose_doc,
".. method:: decompose()\n"
"\n"
" Return the location, rotaion and scale components of this matrix.\n"
"\n"
" :return: loc, rot, scale triple.\n"
" :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)"
);
static PyObject *Matrix_decompose(MatrixObject *self)
{
PyObject *ret;
float loc[3];
float rot[3][3];
float quat[4];
float size[3];
if(self->col_size != 4 || self->row_size != 4) {
PyErr_SetString(PyExc_TypeError,
"matrix.decompose(): "
"inappropriate matrix size - expects 4x4 matrix");
return NULL;
}
if(BaseMath_ReadCallback(self) == -1)
return NULL;
mat4_to_loc_rot_size(loc, rot, size, (float (*)[4])self->contigPtr);
mat3_to_quat(quat, rot);
ret= PyTuple_New(3);
PyTuple_SET_ITEM(ret, 0, newVectorObject(loc, 3, Py_NEW, NULL));
PyTuple_SET_ITEM(ret, 1, newQuaternionObject(quat, Py_NEW, NULL));
PyTuple_SET_ITEM(ret, 2, newVectorObject(size, 3, Py_NEW, NULL));
return ret;
}
PyDoc_STRVAR(Matrix_lerp_doc,
".. function:: lerp(other, factor)\n"
"\n"
" Returns the interpolation of two matricies.\n"
"\n"
" :arg other: value to interpolate with.\n"
" :type other: :class:`Matrix`\n"
" :arg factor: The interpolation value in [0.0, 1.0].\n"
" :type factor: float\n"
" :return: The interpolated rotation.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
{
MatrixObject *mat2 = NULL;
float fac, mat[MATRIX_MAX_DIM*MATRIX_MAX_DIM];
if(!PyArg_ParseTuple(args, "O!f:lerp", &matrix_Type, &mat2, &fac))
return NULL;
if(self->row_size != mat2->row_size || self->col_size != mat2->col_size) {
PyErr_SetString(PyExc_ValueError,
"matrix.lerp(): "
"expects both matrix objects of the same dimensions");
return NULL;
}
if(BaseMath_ReadCallback(self) == -1 || BaseMath_ReadCallback(mat2) == -1)
return NULL;
/* TODO, different sized matrix */
if(self->row_size==4 && self->col_size==4) {
blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->contigPtr, (float (*)[4])mat2->contigPtr, fac);
}
else if (self->row_size==3 && self->col_size==3) {
blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->contigPtr, (float (*)[3])mat2->contigPtr, fac);
}
else {
PyErr_SetString(PyExc_ValueError,
"matrix.lerp(): "
"only 3x3 and 4x4 matrices supported");
return NULL;
}
return (PyObject*)newMatrixObject(mat, self->row_size, self->col_size, Py_NEW, Py_TYPE(self));
}
/*---------------------------matrix.determinant() ----------------*/
PyDoc_STRVAR(Matrix_determinant_doc,
".. method:: determinant()\n"
"\n"
" Return the determinant of a matrix.\n"
"\n"
" :return: Return a the determinant of a matrix.\n"
" :rtype: float\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n"
);
static PyObject *Matrix_determinant(MatrixObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(self->row_size != self->col_size){
PyErr_SetString(PyExc_TypeError,
"matrix.determinant: "
"only square matrices are supported");
return NULL;
}
return PyFloat_FromDouble((double)matrix_determinant_internal(self));
}
/*---------------------------matrix.transpose() ------------------*/
PyDoc_STRVAR(Matrix_transpose_doc,
".. method:: transpose()\n"
"\n"
" Set the matrix to its transpose.\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n"
);
static PyObject *Matrix_transpose(MatrixObject *self)
{
float t = 0.0f;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(self->row_size != self->col_size){
PyErr_SetString(PyExc_TypeError,
"matrix.transpose(d): "
"only square matrices are supported");
return NULL;
}
if(self->row_size == 2) {
t = self->matrix[1][0];
self->matrix[1][0] = self->matrix[0][1];
self->matrix[0][1] = t;
} else if(self->row_size == 3) {
transpose_m3((float (*)[3])self->contigPtr);
}
else {
transpose_m4((float (*)[4])self->contigPtr);
}
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Matrix_transposed_doc,
".. method:: transposed()\n"
"\n"
" Return a new, transposed matrix.\n"
"\n"
" :return: a transposed matrix\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Matrix_transposed(MatrixObject *self)
{
return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self);
}
/*---------------------------matrix.zero() -----------------------*/
PyDoc_STRVAR(Matrix_zero_doc,
".. method:: zero()\n"
"\n"
" Set all the matrix values to zero.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Matrix_zero(MatrixObject *self)
{
fill_vn(self->contigPtr, self->row_size * self->col_size, 0.0f);
if(BaseMath_WriteCallback(self) == -1)
return NULL;
Py_RETURN_NONE;
}
/*---------------------------matrix.identity(() ------------------*/
PyDoc_STRVAR(Matrix_identity_doc,
".. method:: identity()\n"
"\n"
" Set the matrix to the identity matrix.\n"
"\n"
" .. note:: An object with zero location and rotation, a scale of one,\n"
" will have an identity matrix.\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Identity_matrix>\n"
);
static PyObject *Matrix_identity(MatrixObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(self->row_size != self->col_size){
PyErr_SetString(PyExc_TypeError,
"matrix.identity: "
"only square matrices are supported");
return NULL;
}
if(self->row_size == 2) {
self->matrix[0][0] = 1.0f;
self->matrix[0][1] = 0.0f;
self->matrix[1][0] = 0.0f;
self->matrix[1][1] = 1.0f;
} else if(self->row_size == 3) {
unit_m3((float (*)[3])self->contigPtr);
}
else {
unit_m4((float (*)[4])self->contigPtr);
}
if(BaseMath_WriteCallback(self) == -1)
return NULL;
Py_RETURN_NONE;
}
/*---------------------------Matrix.copy() ------------------*/
PyDoc_STRVAR(Matrix_copy_doc,
".. method:: copy()\n"
"\n"
" Returns a copy of this matrix.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Matrix_copy(MatrixObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return (PyObject*)newMatrixObject((float (*))self->contigPtr, self->row_size, self->col_size, Py_NEW, Py_TYPE(self));
}
/*----------------------------print object (internal)-------------*/
/*print the object to screen*/
static PyObject *Matrix_repr(MatrixObject *self)
{
int x, y;
PyObject *rows[MATRIX_MAX_DIM]= {NULL};
if(BaseMath_ReadCallback(self) == -1)
return NULL;
for(x = 0; x < self->row_size; x++){
rows[x]= PyTuple_New(self->col_size);
for(y = 0; y < self->col_size; y++) {
PyTuple_SET_ITEM(rows[x], y, PyFloat_FromDouble(self->matrix[x][y]));
}
}
switch(self->row_size) {
case 2: return PyUnicode_FromFormat("Matrix(%R,\n"
" %R)", rows[0], rows[1]);
case 3: return PyUnicode_FromFormat("Matrix(%R,\n"
" %R,\n"
" %R)", rows[0], rows[1], rows[2]);
case 4: return PyUnicode_FromFormat("Matrix(%R,\n"
" %R,\n"
" %R,\n"
" %R)", rows[0], rows[1], rows[2], rows[3]);
}
PyErr_SetString(PyExc_RuntimeError,
"internal error!");
return NULL;
}
static PyObject* Matrix_richcmpr(PyObject *a, PyObject *b, int op)
{
PyObject *res;
int ok= -1; /* zero is true */
if (MatrixObject_Check(a) && MatrixObject_Check(b)) {
MatrixObject *matA= (MatrixObject*)a;
MatrixObject *matB= (MatrixObject*)b;
if(BaseMath_ReadCallback(matA) == -1 || BaseMath_ReadCallback(matB) == -1)
return NULL;
ok= ( (matA->col_size == matB->col_size) &&
(matA->row_size == matB->row_size) &&
EXPP_VectorsAreEqual(matA->contigPtr, matB->contigPtr, (matA->row_size * matA->col_size), 1)
) ? 0 : -1;
}
switch (op) {
case Py_NE:
ok = !ok; /* pass through */
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
case Py_LT:
case Py_LE:
case Py_GT:
case Py_GE:
res = Py_NotImplemented;
break;
default:
PyErr_BadArgument();
return NULL;
}
return Py_INCREF(res), res;
}
/*---------------------SEQUENCE PROTOCOLS------------------------
----------------------------len(object)------------------------
sequence length*/
static int Matrix_len(MatrixObject *self)
{
return (self->row_size);
}
/*----------------------------object[]---------------------------
sequence accessor (get)
the wrapped vector gives direct access to the matrix data*/
static PyObject *Matrix_item(MatrixObject *self, int i)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(i < 0 || i >= self->row_size) {
PyErr_SetString(PyExc_IndexError,
"matrix[attribute]: "
"array index out of range");
return NULL;
}
return newVectorObject_cb((PyObject *)self, self->col_size, mathutils_matrix_vector_cb_index, i);
}
/*----------------------------object[]-------------------------
sequence accessor (set) */
static int Matrix_ass_item(MatrixObject *self, int i, PyObject *value)
{
float vec[4];
if(BaseMath_ReadCallback(self) == -1)
return -1;
if(i >= self->row_size || i < 0){
PyErr_SetString(PyExc_IndexError,
"matrix[attribute] = x: bad column");
return -1;
}
if(mathutils_array_parse(vec, self->col_size, self->col_size, value, "matrix[i] = value assignment") < 0) {
return -1;
}
memcpy(self->matrix[i], vec, self->col_size *sizeof(float));
(void)BaseMath_WriteCallback(self);
return 0;
}
/*----------------------------object[z:y]------------------------
sequence slice (get)*/
static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
{
PyObject *tuple;
int count;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
CLAMP(begin, 0, self->row_size);
CLAMP(end, 0, self->row_size);
begin= MIN2(begin, end);
tuple= PyTuple_New(end - begin);
for(count= begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin,
newVectorObject_cb((PyObject *)self, self->col_size, mathutils_matrix_vector_cb_index, count));
}
return tuple;
}
/*----------------------------object[z:y]------------------------
sequence slice (set)*/
static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value)
{
PyObject *value_fast= NULL;
if(BaseMath_ReadCallback(self) == -1)
return -1;
CLAMP(begin, 0, self->row_size);
CLAMP(end, 0, self->row_size);
begin = MIN2(begin, end);
/* non list/tuple cases */
if(!(value_fast=PySequence_Fast(value, "matrix[begin:end] = value"))) {
/* PySequence_Fast sets the error */
return -1;
}
else {
const int size= end - begin;
int i;
float mat[16];
if(PySequence_Fast_GET_SIZE(value_fast) != size) {
Py_DECREF(value_fast);
PyErr_SetString(PyExc_ValueError,
"matrix[begin:end] = []: "
"size mismatch in slice assignment");
return -1;
}
/*parse sub items*/
for (i = 0; i < size; i++) {
/*parse each sub sequence*/
PyObject *item= PySequence_Fast_GET_ITEM(value_fast, i);
if(mathutils_array_parse(&mat[i * self->col_size], self->col_size, self->col_size, item, "matrix[begin:end] = value assignment") < 0) {
return -1;
}
}
Py_DECREF(value_fast);
/*parsed well - now set in matrix*/
memcpy(self->contigPtr + (begin * self->col_size), mat, sizeof(float) * (size * self->col_size));
(void)BaseMath_WriteCallback(self);
return 0;
}
}
/*------------------------NUMERIC PROTOCOLS----------------------
------------------------obj + obj------------------------------*/
static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
{
float mat[16];
MatrixObject *mat1 = NULL, *mat2 = NULL;
mat1 = (MatrixObject*)m1;
mat2 = (MatrixObject*)m2;
if(!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
PyErr_SetString(PyExc_TypeError,
"Matrix addition: "
"arguments not valid for this operation");
return NULL;
}
if(BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1)
return NULL;
if(mat1->row_size != mat2->row_size || mat1->col_size != mat2->col_size){
PyErr_SetString(PyExc_TypeError,
"Matrix addition: "
"matrices must have the same dimensions for this operation");
return NULL;
}
add_vn_vnvn(mat, mat1->contigPtr, mat2->contigPtr, mat1->row_size * mat1->col_size);
return newMatrixObject(mat, mat1->row_size, mat1->col_size, Py_NEW, Py_TYPE(mat1));
}
/*------------------------obj - obj------------------------------
subtraction*/
static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
{
float mat[16];
MatrixObject *mat1 = NULL, *mat2 = NULL;
mat1 = (MatrixObject*)m1;
mat2 = (MatrixObject*)m2;
if(!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
PyErr_SetString(PyExc_TypeError,
"Matrix addition: "
"arguments not valid for this operation");
return NULL;
}
if(BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1)
return NULL;
if(mat1->row_size != mat2->row_size || mat1->col_size != mat2->col_size){
PyErr_SetString(PyExc_TypeError,
"Matrix addition: "
"matrices must have the same dimensions for this operation");
return NULL;
}
sub_vn_vnvn(mat, mat1->contigPtr, mat2->contigPtr, mat1->row_size * mat1->col_size);
return newMatrixObject(mat, mat1->row_size, mat1->col_size, Py_NEW, Py_TYPE(mat1));
}
/*------------------------obj * obj------------------------------
mulplication*/
static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
{
float tmat[16];
mul_vn_vn_fl(tmat, mat->contigPtr, mat->row_size * mat->col_size, scalar);
return newMatrixObject(tmat, mat->row_size, mat->col_size, Py_NEW, Py_TYPE(mat));
}
static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
{
float scalar;
MatrixObject *mat1 = NULL, *mat2 = NULL;
if(MatrixObject_Check(m1)) {
mat1 = (MatrixObject*)m1;
if(BaseMath_ReadCallback(mat1) == -1)
return NULL;
}
if(MatrixObject_Check(m2)) {
mat2 = (MatrixObject*)m2;
if(BaseMath_ReadCallback(mat2) == -1)
return NULL;
}
if(mat1 && mat2) {
/*MATRIX * MATRIX*/
if(mat2->row_size != mat1->col_size){
PyErr_SetString(PyExc_ValueError,
"Matrix multiplication: "
"matrix A rowsize must equal matrix B colsize");
return NULL;
}
else {
float mat[16]= {0.0f};
int x, y, z;
for(x = 0; x < mat2->row_size; x++) {
for(y = 0; y < mat1->col_size; y++) {
for(z = 0; z < mat1->row_size; z++) {
mat[x * mat2->col_size + y] += (mat2->matrix[x][z] * mat1->matrix[z][y]);
}
}
}
return newMatrixObject(mat, mat1->row_size, mat2->col_size, Py_NEW, Py_TYPE(mat1));
}
}
else if(mat2) {
/*FLOAT/INT * MATRIX */
if (((scalar= PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred())==0) {
return matrix_mul_float(mat2, scalar);
}
}
else if(mat1) {
/*FLOAT/INT * MATRIX */
if (((scalar= PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred())==0) {
return matrix_mul_float(mat1, scalar);
}
}
else {
BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
"Matrix multiplication: "
"not supported between '%.200s' and '%.200s' types",
Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
return NULL;
}
static PyObject* Matrix_inv(MatrixObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return Matrix_invert(self);
}
/*-----------------PROTOCOL DECLARATIONS--------------------------*/
static PySequenceMethods Matrix_SeqMethods = {
(lenfunc) Matrix_len, /* sq_length */
(binaryfunc) NULL, /* sq_concat */
(ssizeargfunc) NULL, /* sq_repeat */
(ssizeargfunc) Matrix_item, /* sq_item */
(ssizessizeargfunc) NULL, /* sq_slice, deprecated */
(ssizeobjargproc) Matrix_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) NULL, /* sq_ass_slice, deprecated */
(objobjproc) NULL, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */
(ssizeargfunc) NULL, /* sq_inplace_repeat */
};
static PyObject *Matrix_subscript(MatrixObject* self, PyObject* item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += self->row_size;
return Matrix_item(self, i);
} else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, self->row_size, &start, &stop, &step, &slicelength) < 0)
return NULL;
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
return Matrix_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with matricies");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"matrix indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return NULL;
}
}
static int Matrix_ass_subscript(MatrixObject* self, PyObject* item, PyObject* value)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += self->row_size;
return Matrix_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, self->row_size, &start, &stop, &step, &slicelength) < 0)
return -1;
if (step == 1)
return Matrix_ass_slice(self, start, stop, value);
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with matricies");
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"matrix indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return -1;
}
}
static PyMappingMethods Matrix_AsMapping = {
(lenfunc)Matrix_len,
(binaryfunc)Matrix_subscript,
(objobjargproc)Matrix_ass_subscript
};
static PyNumberMethods Matrix_NumMethods = {
(binaryfunc) Matrix_add, /*nb_add*/
(binaryfunc) Matrix_sub, /*nb_subtract*/
(binaryfunc) Matrix_mul, /*nb_multiply*/
NULL, /*nb_remainder*/
NULL, /*nb_divmod*/
NULL, /*nb_power*/
(unaryfunc) 0, /*nb_negative*/
(unaryfunc) 0, /*tp_positive*/
(unaryfunc) 0, /*tp_absolute*/
(inquiry) 0, /*tp_bool*/
(unaryfunc) Matrix_inv, /*nb_invert*/
NULL, /*nb_lshift*/
(binaryfunc)0, /*nb_rshift*/
NULL, /*nb_and*/
NULL, /*nb_xor*/
NULL, /*nb_or*/
NULL, /*nb_int*/
NULL, /*nb_reserved*/
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
NULL, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
NULL, /* nb_inplace_rshift */
NULL, /* nb_inplace_and */
NULL, /* nb_inplace_xor */
NULL, /* nb_inplace_or */
NULL, /* nb_floor_divide */
NULL, /* nb_true_divide */
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
};
static PyObject *Matrix_getRowSize(MatrixObject *self, void *UNUSED(closure))
{
return PyLong_FromLong((long) self->row_size);
}
static PyObject *Matrix_getColSize(MatrixObject *self, void *UNUSED(closure))
{
return PyLong_FromLong((long) self->col_size);
}
static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure))
{
float mat[3][3];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
/*must be 3-4 cols, 3-4 rows, square matrix*/
if((self->col_size < 3) || (self->row_size < 3)) {
PyErr_SetString(PyExc_AttributeError,
"matrix.median_scale: "
"inappropriate matrix size, 3x3 minimum");
return NULL;
}
matrix_as_3x3(mat, self);
return PyFloat_FromDouble(mat3_to_scale(mat));
}
static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure))
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->col_size == 4 && self->row_size == 4)
return PyBool_FromLong(is_negative_m4((float (*)[4])self->contigPtr));
else if(self->col_size == 3 && self->row_size == 3)
return PyBool_FromLong(is_negative_m3((float (*)[3])self->contigPtr));
else {
PyErr_SetString(PyExc_AttributeError,
"matrix.is_negative: "
"inappropriate matrix size - expects 3x3 or 4x4 matrix");
return NULL;
}
}
static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closure))
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->col_size == 4 && self->row_size == 4)
return PyBool_FromLong(is_orthogonal_m4((float (*)[4])self->contigPtr));
else if(self->col_size == 3 && self->row_size == 3)
return PyBool_FromLong(is_orthogonal_m3((float (*)[3])self->contigPtr));
else {
PyErr_SetString(PyExc_AttributeError,
"matrix.is_orthogonal: "
"inappropriate matrix size - expects 3x3 or 4x4 matrix");
return NULL;
}
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Matrix_getseters[] = {
{(char *)"row_size", (getter)Matrix_getRowSize, (setter)NULL, (char *)"The row size of the matrix (readonly).\n\n:type: int", NULL},
{(char *)"col_size", (getter)Matrix_getColSize, (setter)NULL, (char *)"The column size of the matrix (readonly).\n\n:type: int", NULL},
{(char *)"median_scale", (getter)Matrix_median_scale_get, (setter)NULL, (char *)"The average scale applied to each axis (readonly).\n\n:type: float", NULL},
{(char *)"is_negative", (getter)Matrix_is_negative_get, (setter)NULL, (char *)"True if this matrix results in a negative scale, 3x3 and 4x4 only, (readonly).\n\n:type: bool", NULL},
{(char *)"is_orthogonal", (getter)Matrix_is_orthogonal_get, (setter)NULL, (char *)"True if this matrix is orthogonal, 3x3 and 4x4 only, (readonly).\n\n:type: bool", NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL},
{(char *)"owner",(getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
/*-----------------------METHOD DEFINITIONS ----------------------*/
static struct PyMethodDef Matrix_methods[] = {
/* derived values */
{"determinant", (PyCFunction) Matrix_determinant, METH_NOARGS, Matrix_determinant_doc},
{"decompose", (PyCFunction) Matrix_decompose, METH_NOARGS, Matrix_decompose_doc},
/* in place only */
{"zero", (PyCFunction) Matrix_zero, METH_NOARGS, Matrix_zero_doc},
{"identity", (PyCFunction) Matrix_identity, METH_NOARGS, Matrix_identity_doc},
/* operate on original or copy */
{"transpose", (PyCFunction) Matrix_transpose, METH_NOARGS, Matrix_transpose_doc},
{"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc},
{"invert", (PyCFunction) Matrix_invert, METH_NOARGS, Matrix_invert_doc},
{"inverted", (PyCFunction) Matrix_inverted, METH_NOARGS, Matrix_inverted_doc},
{"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc},
// TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc},
{"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc},
{"resize_4x4", (PyCFunction) Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc},
{"rotate", (PyCFunction) Matrix_rotate, METH_O, Matrix_rotate_doc},
/* return converted representation */
{"to_euler", (PyCFunction) Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc},
{"to_quaternion", (PyCFunction) Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc},
{"to_scale", (PyCFunction) Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc},
{"to_translation", (PyCFunction) Matrix_to_translation, METH_NOARGS, Matrix_to_translation_doc},
/* operation between 2 or more types */
{"lerp", (PyCFunction) Matrix_lerp, METH_VARARGS, Matrix_lerp_doc},
{"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
{"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
/* class methods */
{"Rotation", (PyCFunction) C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc},
{"Scale", (PyCFunction) C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc},
{"Shear", (PyCFunction) C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc},
{"Translation", (PyCFunction) C_Matrix_Translation, METH_O | METH_CLASS, C_Matrix_Translation_doc},
{"OrthoProjection", (PyCFunction) C_Matrix_OrthoProjection, METH_VARARGS | METH_CLASS, C_Matrix_OrthoProjection_doc},
{NULL, NULL, 0, NULL}
};
/*------------------PY_OBECT DEFINITION--------------------------*/
PyDoc_STRVAR(matrix_doc,
"This object gives access to Matrices in Blender."
);
PyTypeObject matrix_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Matrix", /*tp_name*/
sizeof(MatrixObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)BaseMathObject_dealloc, /*tp_dealloc*/
NULL, /*tp_print*/
NULL, /*tp_getattr*/
NULL, /*tp_setattr*/
NULL, /*tp_compare*/
(reprfunc) Matrix_repr, /*tp_repr*/
&Matrix_NumMethods, /*tp_as_number*/
&Matrix_SeqMethods, /*tp_as_sequence*/
&Matrix_AsMapping, /*tp_as_mapping*/
NULL, /*tp_hash*/
NULL, /*tp_call*/
NULL, /*tp_str*/
NULL, /*tp_getattro*/
NULL, /*tp_setattro*/
NULL, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
matrix_doc, /*tp_doc*/
(traverseproc)BaseMathObject_traverse, //tp_traverse
(inquiry)BaseMathObject_clear, //tp_clear
(richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
NULL, /*tp_iter*/
NULL, /*tp_iternext*/
Matrix_methods, /*tp_methods*/
NULL, /*tp_members*/
Matrix_getseters, /*tp_getset*/
NULL, /*tp_base*/
NULL, /*tp_dict*/
NULL, /*tp_descr_get*/
NULL, /*tp_descr_set*/
0, /*tp_dictoffset*/
NULL, /*tp_init*/
NULL, /*tp_alloc*/
Matrix_new, /*tp_new*/
NULL, /*tp_free*/
NULL, /*tp_is_gc*/
NULL, /*tp_bases*/
NULL, /*tp_mro*/
NULL, /*tp_cache*/
NULL, /*tp_subclasses*/
NULL, /*tp_weaklist*/
NULL /*tp_del*/
};
/*------------------------newMatrixObject (internal)-------------
creates a new matrix object
self->matrix self->contiguous_ptr (reference to data.xxx)
[0]------------->[0]
[1]
[2]
[1]------------->[3]
[4]
[5]
self->matrix[1][1] = self->contigPtr[4] */
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newMatrixObject(float *mat, const unsigned short rowSize, const unsigned short colSize, int type, PyTypeObject *base_type)
{
MatrixObject *self;
int x, row, col;
/*matrix objects can be any 2-4row x 2-4col matrix*/
if(rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4) {
PyErr_SetString(PyExc_RuntimeError,
"Matrix(): "
"row and column sizes must be between 2 and 4");
return NULL;
}
self= base_type ? (MatrixObject *)base_type->tp_alloc(base_type, 0) :
(MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type);
if(self) {
self->row_size = rowSize;
self->col_size = colSize;
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP){
self->contigPtr = mat;
/*pointer array points to contigous memory*/
for(x = 0; x < rowSize; x++) {
self->matrix[x] = self->contigPtr + (x * colSize);
}
self->wrapped = Py_WRAP;
}
else if (type == Py_NEW){
self->contigPtr = PyMem_Malloc(rowSize * colSize * sizeof(float));
if(self->contigPtr == NULL) { /*allocation failure*/
PyErr_SetString(PyExc_MemoryError,
"Matrix(): "
"problem allocating pointer space");
return NULL;
}
/*pointer array points to contigous memory*/
for(x = 0; x < rowSize; x++) {
self->matrix[x] = self->contigPtr + (x * colSize);
}
/*parse*/
if(mat) { /*if a float array passed*/
for(row = 0; row < rowSize; row++) {
for(col = 0; col < colSize; col++) {
self->matrix[row][col] = mat[(row * colSize) + col];
}
}
}
else if (rowSize == colSize) { /*or if no arguments are passed return identity matrix for square matrices */
PyObject *ret_dummy= Matrix_identity(self);
Py_DECREF(ret_dummy);
}
self->wrapped = Py_NEW;
}
else {
Py_FatalError("Matrix(): invalid type!");
return NULL;
}
}
return (PyObject *) self;
}
PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb_type, int cb_subtype)
{
MatrixObject *self= (MatrixObject *)newMatrixObject(NULL, rowSize, colSize, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
PyObject_GC_Track(self);
}
return (PyObject *) self;
}

View File

@@ -0,0 +1,63 @@
/*
* $Id: mathutils_Matrix.h 38409 2011-07-15 04:01:47Z campbellbarton $
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Matrix.h
* \ingroup pygen
*/
#ifndef MATHUTILS_MATRIX_H
#define MATHUTILS_MATRIX_H
extern PyTypeObject matrix_Type;
#define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type)
#define MATRIX_MAX_DIM 4
typedef struct {
BASE_MATH_MEMBERS(contigPtr)
float *matrix[MATRIX_MAX_DIM]; /* ptr to the contigPtr (accessor) */
unsigned short row_size;
unsigned short col_size;
} MatrixObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
/*prototypes*/
PyObject *newMatrixObject(float *mat, const unsigned short row_size, const unsigned short col_size, int type, PyTypeObject *base_type);
PyObject *newMatrixObject_cb(PyObject *user, int row_size, int col_size, int cb_type, int cb_subtype);
extern int mathutils_matrix_vector_cb_index;
extern struct Mathutils_Callback mathutils_matrix_vector_cb;
void matrix_as_3x3(float mat[3][3], MatrixObject *self);
#endif /* MATHUTILS_MATRIX_H */

View File

@@ -0,0 +1,1164 @@
/*
* $Id: mathutils_Quaternion.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_Quaternion.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#define QUAT_SIZE 4
static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self);
static PyObject *Quaternion_copy(QuaternionObject *self);
//-----------------------------METHODS------------------------------
/* note: BaseMath_ReadCallback must be called beforehand */
static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits)
{
PyObject *ret;
int i;
ret= PyTuple_New(QUAT_SIZE);
if(ndigits >= 0) {
for(i= 0; i < QUAT_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->quat[i], ndigits)));
}
}
else {
for(i= 0; i < QUAT_SIZE; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->quat[i]));
}
}
return ret;
}
PyDoc_STRVAR(Quaternion_to_euler_doc,
".. method:: to_euler(order, euler_compat)\n"
"\n"
" Return Euler representation of the quaternion.\n"
"\n"
" :arg order: Optional rotation order argument in\n"
" ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
" :type order: string\n"
" :arg euler_compat: Optional euler argument the new euler will be made\n"
" compatible with (no axis flipping between them).\n"
" Useful for converting a series of matrices to animation curves.\n"
" :type euler_compat: :class:`Euler`\n"
" :return: Euler representation of the quaternion.\n"
" :rtype: :class:`Euler`\n"
);
static PyObject *Quaternion_to_euler(QuaternionObject *self, PyObject *args)
{
float tquat[4];
float eul[3];
const char *order_str= NULL;
short order= EULER_ORDER_XYZ;
EulerObject *eul_compat = NULL;
if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
return NULL;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(order_str) {
order= euler_order_from_string(order_str, "Matrix.to_euler()");
if(order == -1)
return NULL;
}
normalize_qt_qt(tquat, self->quat);
if(eul_compat) {
float mat[3][3];
if(BaseMath_ReadCallback(eul_compat) == -1)
return NULL;
quat_to_mat3(mat, tquat);
if(order == EULER_ORDER_XYZ) mat3_to_compatible_eul(eul, eul_compat->eul, mat);
else mat3_to_compatible_eulO(eul, eul_compat->eul, order, mat);
}
else {
if(order == EULER_ORDER_XYZ) quat_to_eul(eul, tquat);
else quat_to_eulO(eul, order, tquat);
}
return newEulerObject(eul, order, Py_NEW, NULL);
}
//----------------------------Quaternion.toMatrix()------------------
PyDoc_STRVAR(Quaternion_to_matrix_doc,
".. method:: to_matrix()\n"
"\n"
" Return a matrix representation of the quaternion.\n"
"\n"
" :return: A 3x3 rotation matrix representation of the quaternion.\n"
" :rtype: :class:`Matrix`\n"
);
static PyObject *Quaternion_to_matrix(QuaternionObject *self)
{
float mat[9]; /* all values are set */
if(BaseMath_ReadCallback(self) == -1)
return NULL;
quat_to_mat3((float (*)[3])mat, self->quat);
return newMatrixObject(mat, 3, 3, Py_NEW, NULL);
}
//----------------------------Quaternion.cross(other)------------------
PyDoc_STRVAR(Quaternion_cross_doc,
".. method:: cross(other)\n"
"\n"
" Return the cross product of this quaternion and another.\n"
"\n"
" :arg other: The other quaternion to perform the cross product with.\n"
" :type other: :class:`Quaternion`\n"
" :return: The cross product.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value)
{
float quat[QUAT_SIZE], tquat[QUAT_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.cross(other), invalid 'other' arg") == -1)
return NULL;
mul_qt_qtqt(quat, self->quat, tquat);
return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
}
//----------------------------Quaternion.dot(other)------------------
PyDoc_STRVAR(Quaternion_dot_doc,
".. method:: dot(other)\n"
"\n"
" Return the dot product of this quaternion and another.\n"
"\n"
" :arg other: The other quaternion to perform the dot product with.\n"
" :type other: :class:`Quaternion`\n"
" :return: The dot product.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_dot(QuaternionObject *self, PyObject *value)
{
float tquat[QUAT_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.dot(other), invalid 'other' arg") == -1)
return NULL;
return PyFloat_FromDouble(dot_qtqt(self->quat, tquat));
}
PyDoc_STRVAR(Quaternion_rotation_difference_doc,
".. function:: difference(other)\n"
"\n"
" Returns a quaternion representing the rotational difference.\n"
"\n"
" :arg other: second quaternion.\n"
" :type other: :class:`Quaternion`\n"
" :return: the rotational difference between the two quat rotations.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_rotation_difference(QuaternionObject *self, PyObject *value)
{
float tquat[QUAT_SIZE], quat[QUAT_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.difference(other), invalid 'other' arg") == -1)
return NULL;
rotation_between_quats_to_quat(quat, self->quat, tquat);
return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Quaternion_slerp_doc,
".. function:: slerp(other, factor)\n"
"\n"
" Returns the interpolation of two quaternions.\n"
"\n"
" :arg other: value to interpolate with.\n"
" :type other: :class:`Quaternion`\n"
" :arg factor: The interpolation value in [0.0, 1.0].\n"
" :type factor: float\n"
" :return: The interpolated rotation.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args)
{
PyObject *value;
float tquat[QUAT_SIZE], quat[QUAT_SIZE], fac;
if(!PyArg_ParseTuple(args, "Of:slerp", &value, &fac)) {
PyErr_SetString(PyExc_TypeError,
"quat.slerp(): "
"expected Quaternion types and float");
return NULL;
}
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.slerp(other), invalid 'other' arg") == -1)
return NULL;
if(fac > 1.0f || fac < 0.0f) {
PyErr_SetString(PyExc_ValueError,
"quat.slerp(): "
"interpolation factor must be between 0.0 and 1.0");
return NULL;
}
interp_qt_qtqt(quat, self->quat, tquat, fac);
return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Quaternion_rotate_doc,
".. method:: rotate(other)\n"
"\n"
" Rotates the quaternion a by another mathutils value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
);
static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value)
{
float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
float tquat[4], length;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_any_to_rotmat(other_rmat, value, "quaternion.rotate(value)") == -1)
return NULL;
length= normalize_qt_qt(tquat, self->quat);
quat_to_mat3(self_rmat, tquat);
mul_m3_m3m3(rmat, self_rmat, other_rmat);
mat3_to_quat(self->quat, rmat);
mul_qt_fl(self->quat, length); /* maintain length after rotating */
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
//----------------------------Quaternion.normalize()----------------
//normalize the axis of rotation of [theta, vector]
PyDoc_STRVAR(Quaternion_normalize_doc,
".. function:: normalize()\n"
"\n"
" Normalize the quaternion.\n"
);
static PyObject *Quaternion_normalize(QuaternionObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
normalize_qt(self->quat);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Quaternion_normalized_doc,
".. function:: normalized()\n"
"\n"
" Return a new normalized quaternion.\n"
"\n"
" :return: a normalized copy.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_normalized(QuaternionObject *self)
{
return quat__apply_to_copy((PyNoArgsFunction)Quaternion_normalize, self);
}
//----------------------------Quaternion.invert()------------------
PyDoc_STRVAR(Quaternion_invert_doc,
".. function:: invert()\n"
"\n"
" Set the quaternion to its inverse.\n"
);
static PyObject *Quaternion_invert(QuaternionObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
invert_qt(self->quat);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Quaternion_inverted_doc,
".. function:: inverted()\n"
"\n"
" Return a new, inverted quaternion.\n"
"\n"
" :return: the inverted value.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_inverted(QuaternionObject *self)
{
return quat__apply_to_copy((PyNoArgsFunction)Quaternion_invert, self);
}
//----------------------------Quaternion.identity()-----------------
PyDoc_STRVAR(Quaternion_identity_doc,
".. function:: identity()\n"
"\n"
" Set the quaternion to an identity quaternion.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_identity(QuaternionObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
unit_qt(self->quat);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
//----------------------------Quaternion.negate()-------------------
PyDoc_STRVAR(Quaternion_negate_doc,
".. function:: negate()\n"
"\n"
" Set the quaternion to its negative.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_negate(QuaternionObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
mul_qt_fl(self->quat, -1.0f);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
//----------------------------Quaternion.conjugate()----------------
PyDoc_STRVAR(Quaternion_conjugate_doc,
".. function:: conjugate()\n"
"\n"
" Set the quaternion to its conjugate (negate x, y, z).\n"
);
static PyObject *Quaternion_conjugate(QuaternionObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
conjugate_qt(self->quat);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Quaternion_conjugated_doc,
".. function:: conjugated()\n"
"\n"
" Return a new conjugated quaternion.\n"
"\n"
" :return: a new quaternion.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Quaternion_conjugated(QuaternionObject *self)
{
return quat__apply_to_copy((PyNoArgsFunction)Quaternion_conjugate, self);
}
//----------------------------Quaternion.copy()----------------
PyDoc_STRVAR(Quaternion_copy_doc,
".. function:: copy()\n"
"\n"
" Returns a copy of this quaternion.\n"
"\n"
" :return: A copy of the quaternion.\n"
" :rtype: :class:`Quaternion`\n"
"\n"
" .. note:: use this to get a copy of a wrapped quaternion with\n"
" no reference to the original data.\n"
);
static PyObject *Quaternion_copy(QuaternionObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return newQuaternionObject(self->quat, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Quaternion_repr(QuaternionObject *self)
{
PyObject *ret, *tuple;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
tuple= Quaternion_to_tuple_ext(self, -1);
ret= PyUnicode_FromFormat("Quaternion(%R)", tuple);
Py_DECREF(tuple);
return ret;
}
static PyObject* Quaternion_richcmpr(PyObject *a, PyObject *b, int op)
{
PyObject *res;
int ok= -1; /* zero is true */
if (QuaternionObject_Check(a) && QuaternionObject_Check(b)) {
QuaternionObject *quatA= (QuaternionObject *)a;
QuaternionObject *quatB= (QuaternionObject *)b;
if(BaseMath_ReadCallback(quatA) == -1 || BaseMath_ReadCallback(quatB) == -1)
return NULL;
ok= (EXPP_VectorsAreEqual(quatA->quat, quatB->quat, QUAT_SIZE, 1)) ? 0 : -1;
}
switch (op) {
case Py_NE:
ok = !ok; /* pass through */
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
case Py_LT:
case Py_LE:
case Py_GT:
case Py_GE:
res = Py_NotImplemented;
break;
default:
PyErr_BadArgument();
return NULL;
}
return Py_INCREF(res), res;
}
//---------------------SEQUENCE PROTOCOLS------------------------
//----------------------------len(object)------------------------
//sequence length
static int Quaternion_len(QuaternionObject *UNUSED(self))
{
return QUAT_SIZE;
}
//----------------------------object[]---------------------------
//sequence accessor (get)
static PyObject *Quaternion_item(QuaternionObject *self, int i)
{
if(i<0) i= QUAT_SIZE-i;
if(i < 0 || i >= QUAT_SIZE) {
PyErr_SetString(PyExc_IndexError,
"quaternion[attribute]: "
"array index out of range");
return NULL;
}
if(BaseMath_ReadIndexCallback(self, i) == -1)
return NULL;
return PyFloat_FromDouble(self->quat[i]);
}
//----------------------------object[]-------------------------
//sequence accessor (set)
static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob)
{
float scalar= (float)PyFloat_AsDouble(ob);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"quaternion[index] = x: "
"index argument not a number");
return -1;
}
if(i<0) i= QUAT_SIZE-i;
if(i < 0 || i >= QUAT_SIZE){
PyErr_SetString(PyExc_IndexError,
"quaternion[attribute] = x: "
"array assignment index out of range");
return -1;
}
self->quat[i] = scalar;
if(BaseMath_WriteIndexCallback(self, i) == -1)
return -1;
return 0;
}
//----------------------------object[z:y]------------------------
//sequence slice (get)
static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end)
{
PyObject *tuple;
int count;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
CLAMP(begin, 0, QUAT_SIZE);
if (end<0) end= (QUAT_SIZE + 1) + end;
CLAMP(end, 0, QUAT_SIZE);
begin= MIN2(begin, end);
tuple= PyTuple_New(end - begin);
for(count= begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->quat[count]));
}
return tuple;
}
//----------------------------object[z:y]------------------------
//sequence slice (set)
static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq)
{
int i, size;
float quat[QUAT_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return -1;
CLAMP(begin, 0, QUAT_SIZE);
if (end<0) end= (QUAT_SIZE + 1) + end;
CLAMP(end, 0, QUAT_SIZE);
begin = MIN2(begin, end);
if((size=mathutils_array_parse(quat, 0, QUAT_SIZE, seq, "mathutils.Quaternion[begin:end] = []")) == -1)
return -1;
if(size != (end - begin)){
PyErr_SetString(PyExc_ValueError,
"quaternion[begin:end] = []: "
"size mismatch in slice assignment");
return -1;
}
/* parsed well - now set in vector */
for(i= 0; i < size; i++)
self->quat[begin + i] = quat[i];
(void)BaseMath_WriteCallback(self);
return 0;
}
static PyObject *Quaternion_subscript(QuaternionObject *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += QUAT_SIZE;
return Quaternion_item(self, i);
} else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0)
return NULL;
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
return Quaternion_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with quaternions");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"quaternion indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return NULL;
}
}
static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyObject *value)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += QUAT_SIZE;
return Quaternion_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0)
return -1;
if (step == 1)
return Quaternion_ass_slice(self, start, stop, value);
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with quaternion");
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"quaternion indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return -1;
}
}
//------------------------NUMERIC PROTOCOLS----------------------
//------------------------obj + obj------------------------------
//addition
static PyObject *Quaternion_add(PyObject *q1, PyObject *q2)
{
float quat[QUAT_SIZE];
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
PyErr_SetString(PyExc_TypeError,
"Quaternion addition: "
"arguments not valid for this operation");
return NULL;
}
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1)
return NULL;
add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f);
return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1));
}
//------------------------obj - obj------------------------------
//subtraction
static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2)
{
int x;
float quat[QUAT_SIZE];
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
PyErr_SetString(PyExc_TypeError,
"Quaternion addition: "
"arguments not valid for this operation");
return NULL;
}
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1)
return NULL;
for(x = 0; x < QUAT_SIZE; x++) {
quat[x] = quat1->quat[x] - quat2->quat[x];
}
return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1));
}
static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
{
float tquat[4];
copy_qt_qt(tquat, quat->quat);
mul_qt_fl(tquat, scalar);
return newQuaternionObject(tquat, Py_NEW, Py_TYPE(quat));
}
//------------------------obj * obj------------------------------
//mulplication
static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
{
float quat[QUAT_SIZE], scalar;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if(QuaternionObject_Check(q1)) {
quat1 = (QuaternionObject*)q1;
if(BaseMath_ReadCallback(quat1) == -1)
return NULL;
}
if(QuaternionObject_Check(q2)) {
quat2 = (QuaternionObject*)q2;
if(BaseMath_ReadCallback(quat2) == -1)
return NULL;
}
if(quat1 && quat2) { /* QUAT*QUAT (cross product) */
mul_qt_qtqt(quat, quat1->quat, quat2->quat);
return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1));
}
/* the only case this can happen (for a supported type is "FLOAT*QUAT") */
else if(quat2) { /* FLOAT*QUAT */
if(((scalar= PyFloat_AsDouble(q1)) == -1.0f && PyErr_Occurred())==0) {
return quat_mul_float(quat2, scalar);
}
}
else if (quat1) { /* QUAT*FLOAT */
if((((scalar= PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred())==0)) {
return quat_mul_float(quat1, scalar);
}
}
else {
BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
"Quaternion multiplication: "
"not supported between '%.200s' and '%.200s' types",
Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
return NULL;
}
/* -obj
returns the negative of this object*/
static PyObject *Quaternion_neg(QuaternionObject *self)
{
float tquat[QUAT_SIZE];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
negate_v4_v4(tquat, self->quat);
return newQuaternionObject(tquat, Py_NEW, Py_TYPE(self));
}
//-----------------PROTOCOL DECLARATIONS--------------------------
static PySequenceMethods Quaternion_SeqMethods = {
(lenfunc) Quaternion_len, /* sq_length */
(binaryfunc) NULL, /* sq_concat */
(ssizeargfunc) NULL, /* sq_repeat */
(ssizeargfunc) Quaternion_item, /* sq_item */
(ssizessizeargfunc) NULL, /* sq_slice, deprecated */
(ssizeobjargproc) Quaternion_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) NULL, /* sq_ass_slice, deprecated */
(objobjproc) NULL, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */
(ssizeargfunc) NULL, /* sq_inplace_repeat */
};
static PyMappingMethods Quaternion_AsMapping = {
(lenfunc)Quaternion_len,
(binaryfunc)Quaternion_subscript,
(objobjargproc)Quaternion_ass_subscript
};
static PyNumberMethods Quaternion_NumMethods = {
(binaryfunc) Quaternion_add, /*nb_add*/
(binaryfunc) Quaternion_sub, /*nb_subtract*/
(binaryfunc) Quaternion_mul, /*nb_multiply*/
NULL, /*nb_remainder*/
NULL, /*nb_divmod*/
NULL, /*nb_power*/
(unaryfunc) Quaternion_neg, /*nb_negative*/
(unaryfunc) 0, /*tp_positive*/
(unaryfunc) 0, /*tp_absolute*/
(inquiry) 0, /*tp_bool*/
(unaryfunc) 0, /*nb_invert*/
NULL, /*nb_lshift*/
(binaryfunc)0, /*nb_rshift*/
NULL, /*nb_and*/
NULL, /*nb_xor*/
NULL, /*nb_or*/
NULL, /*nb_int*/
NULL, /*nb_reserved*/
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
NULL, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
NULL, /* nb_inplace_rshift */
NULL, /* nb_inplace_and */
NULL, /* nb_inplace_xor */
NULL, /* nb_inplace_or */
NULL, /* nb_floor_divide */
NULL, /* nb_true_divide */
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
};
static PyObject *Quaternion_getAxis(QuaternionObject *self, void *type)
{
return Quaternion_item(self, GET_INT_FROM_POINTER(type));
}
static int Quaternion_setAxis(QuaternionObject *self, PyObject *value, void *type)
{
return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
static PyObject *Quaternion_getMagnitude(QuaternionObject *self, void *UNUSED(closure))
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return PyFloat_FromDouble(sqrt(dot_qtqt(self->quat, self->quat)));
}
static PyObject *Quaternion_getAngle(QuaternionObject *self, void *UNUSED(closure))
{
float tquat[4];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
normalize_qt_qt(tquat, self->quat);
return PyFloat_FromDouble(2.0f * (saacos(tquat[0])));
}
static int Quaternion_setAngle(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
{
float tquat[4];
float len;
float axis[3], angle_dummy;
double angle;
if(BaseMath_ReadCallback(self) == -1)
return -1;
len= normalize_qt_qt(tquat, self->quat);
quat_to_axis_angle(axis, &angle_dummy, tquat);
angle= PyFloat_AsDouble(value);
if(angle==-1.0 && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"quaternion.angle = value: float expected");
return -1;
}
angle= angle_wrap_rad(angle);
/* If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations */
if( EXPP_FloatsAreEqual(axis[0], 0.0f, 10) &&
EXPP_FloatsAreEqual(axis[1], 0.0f, 10) &&
EXPP_FloatsAreEqual(axis[2], 0.0f, 10)
) {
axis[0] = 1.0f;
}
axis_angle_to_quat(self->quat, axis, angle);
mul_qt_fl(self->quat, len);
if(BaseMath_WriteCallback(self) == -1)
return -1;
return 0;
}
static PyObject *Quaternion_getAxisVec(QuaternionObject *self, void *UNUSED(closure))
{
float tquat[4];
float axis[3];
float angle;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
normalize_qt_qt(tquat, self->quat);
quat_to_axis_angle(axis, &angle, tquat);
/* If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations */
if( EXPP_FloatsAreEqual(axis[0], 0.0f, 10) &&
EXPP_FloatsAreEqual(axis[1], 0.0f, 10) &&
EXPP_FloatsAreEqual(axis[2], 0.0f, 10)
) {
axis[0] = 1.0f;
}
return (PyObject *) newVectorObject(axis, 3, Py_NEW, NULL);
}
static int Quaternion_setAxisVec(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
{
float tquat[4];
float len;
float axis[3];
float angle;
if(BaseMath_ReadCallback(self) == -1)
return -1;
len= normalize_qt_qt(tquat, self->quat);
quat_to_axis_angle(axis, &angle, tquat); /* axis value is unused */
if (mathutils_array_parse(axis, 3, 3, value, "quat.axis = other") == -1)
return -1;
axis_angle_to_quat(self->quat, axis, angle);
mul_qt_fl(self->quat, len);
if(BaseMath_WriteCallback(self) == -1)
return -1;
return 0;
}
//----------------------------------mathutils.Quaternion() --------------
static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *seq= NULL;
double angle = 0.0f;
float quat[QUAT_SIZE]= {0.0f, 0.0f, 0.0f, 0.0f};
if(kwds && PyDict_Size(kwds)) {
PyErr_SetString(PyExc_TypeError,
"mathutils.Quaternion(): "
"takes no keyword args");
return NULL;
}
if(!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle))
return NULL;
switch(PyTuple_GET_SIZE(args)) {
case 0:
break;
case 1:
if (mathutils_array_parse(quat, QUAT_SIZE, QUAT_SIZE, seq, "mathutils.Quaternion()") == -1)
return NULL;
break;
case 2:
if (mathutils_array_parse(quat, 3, 3, seq, "mathutils.Quaternion()") == -1)
return NULL;
angle= angle_wrap_rad(angle); /* clamp because of precision issues */
axis_angle_to_quat(quat, quat, angle);
break;
/* PyArg_ParseTuple assures no more then 2 */
}
return newQuaternionObject(quat, Py_NEW, type);
}
static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self)
{
PyObject *ret= Quaternion_copy(self);
PyObject *ret_dummy= quat_func(ret);
if(ret_dummy) {
Py_DECREF(ret_dummy);
return (PyObject *)ret;
}
else { /* error */
Py_DECREF(ret);
return NULL;
}
}
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Quaternion_methods[] = {
/* in place only */
{"identity", (PyCFunction) Quaternion_identity, METH_NOARGS, Quaternion_identity_doc},
{"negate", (PyCFunction) Quaternion_negate, METH_NOARGS, Quaternion_negate_doc},
/* operate on original or copy */
{"conjugate", (PyCFunction) Quaternion_conjugate, METH_NOARGS, Quaternion_conjugate_doc},
{"conjugated", (PyCFunction) Quaternion_conjugated, METH_NOARGS, Quaternion_conjugated_doc},
{"invert", (PyCFunction) Quaternion_invert, METH_NOARGS, Quaternion_invert_doc},
{"inverted", (PyCFunction) Quaternion_inverted, METH_NOARGS, Quaternion_inverted_doc},
{"normalize", (PyCFunction) Quaternion_normalize, METH_NOARGS, Quaternion_normalize_doc},
{"normalized", (PyCFunction) Quaternion_normalized, METH_NOARGS, Quaternion_normalized_doc},
/* return converted representation */
{"to_euler", (PyCFunction) Quaternion_to_euler, METH_VARARGS, Quaternion_to_euler_doc},
{"to_matrix", (PyCFunction) Quaternion_to_matrix, METH_NOARGS, Quaternion_to_matrix_doc},
/* operation between 2 or more types */
{"cross", (PyCFunction) Quaternion_cross, METH_O, Quaternion_cross_doc},
{"dot", (PyCFunction) Quaternion_dot, METH_O, Quaternion_dot_doc},
{"rotation_difference", (PyCFunction) Quaternion_rotation_difference, METH_O, Quaternion_rotation_difference_doc},
{"slerp", (PyCFunction) Quaternion_slerp, METH_VARARGS, Quaternion_slerp_doc},
{"rotate", (PyCFunction) Quaternion_rotate, METH_O, Quaternion_rotate_doc},
{"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{NULL, NULL, 0, NULL}
};
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Quaternion_getseters[] = {
{(char *)"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (char *)"Quaternion W value.\n\n:type: float", (void *)0},
{(char *)"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (char *)"Quaternion X axis.\n\n:type: float", (void *)1},
{(char *)"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (char *)"Quaternion Y axis.\n\n:type: float", (void *)2},
{(char *)"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (char *)"Quaternion Z axis.\n\n:type: float", (void *)3},
{(char *)"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, (char *)"Size of the quaternion (readonly).\n\n:type: float", NULL},
{(char *)"angle", (getter)Quaternion_getAngle, (setter)Quaternion_setAngle, (char *)"angle of the quaternion.\n\n:type: float", NULL},
{(char *)"axis",(getter)Quaternion_getAxisVec, (setter)Quaternion_setAxisVec, (char *)"quaternion axis as a vector.\n\n:type: :class:`Vector`", NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
//------------------PY_OBECT DEFINITION--------------------------
PyDoc_STRVAR(quaternion_doc,
"This object gives access to Quaternions in Blender."
);
PyTypeObject quaternion_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mathutils.Quaternion", //tp_name
sizeof(QuaternionObject), //tp_basicsize
0, //tp_itemsize
(destructor)BaseMathObject_dealloc, //tp_dealloc
NULL, //tp_print
NULL, //tp_getattr
NULL, //tp_setattr
NULL, //tp_compare
(reprfunc) Quaternion_repr, //tp_repr
&Quaternion_NumMethods, //tp_as_number
&Quaternion_SeqMethods, //tp_as_sequence
&Quaternion_AsMapping, //tp_as_mapping
NULL, //tp_hash
NULL, //tp_call
NULL, //tp_str
NULL, //tp_getattro
NULL, //tp_setattro
NULL, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags
quaternion_doc, //tp_doc
(traverseproc)BaseMathObject_traverse, //tp_traverse
(inquiry)BaseMathObject_clear, //tp_clear
(richcmpfunc)Quaternion_richcmpr, //tp_richcompare
0, //tp_weaklistoffset
NULL, //tp_iter
NULL, //tp_iternext
Quaternion_methods, //tp_methods
NULL, //tp_members
Quaternion_getseters, //tp_getset
NULL, //tp_base
NULL, //tp_dict
NULL, //tp_descr_get
NULL, //tp_descr_set
0, //tp_dictoffset
NULL, //tp_init
NULL, //tp_alloc
Quaternion_new, //tp_new
NULL, //tp_free
NULL, //tp_is_gc
NULL, //tp_bases
NULL, //tp_mro
NULL, //tp_cache
NULL, //tp_subclasses
NULL, //tp_weaklist
NULL, //tp_del
};
//------------------------newQuaternionObject (internal)-------------
//creates a new quaternion object
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type)
{
QuaternionObject *self;
self= base_type ? (QuaternionObject *)base_type->tp_alloc(base_type, 0) :
(QuaternionObject *)PyObject_GC_New(QuaternionObject, &quaternion_Type);
if(self) {
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP){
self->quat = quat;
self->wrapped = Py_WRAP;
}
else if (type == Py_NEW){
self->quat = PyMem_Malloc(QUAT_SIZE * sizeof(float));
if(!quat) { //new empty
unit_qt(self->quat);
}
else {
QUATCOPY(self->quat, quat);
}
self->wrapped = Py_NEW;
}
else {
Py_FatalError("Quaternion(): invalid type!");
}
}
return (PyObject *) self;
}
PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
{
QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
PyObject_GC_Track(self);
}
return (PyObject *)self;
}

View File

@@ -0,0 +1,55 @@
/*
* $Id: mathutils_Quaternion.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Quaternion.h
* \ingroup pygen
*/
#ifndef MATHUTILS_QUAT_H
#define MATHUTILS_QUAT_H
extern PyTypeObject quaternion_Type;
#define QuaternionObject_Check(_v) PyObject_TypeCheck((_v), &quaternion_Type)
typedef struct {
BASE_MATH_MEMBERS(quat)
} QuaternionObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newQuaternionObject( float *quat, int type, PyTypeObject *base_type);
PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* MATHUTILS_QUAT_H */

View File

@@ -0,0 +1,2410 @@
/*
* $Id: mathutils_Vector.c 38409 2011-07-15 04:01:47Z campbellbarton $
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
* Contributor(s): Willian P. Germano, Joseph Gilbert, Ken Hughes, Alex Fraser, Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_Vector.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#define MAX_DIMENSIONS 4
/* Swizzle axes get packed into a single value that is used as a closure. Each
axis uses SWIZZLE_BITS_PER_AXIS bits. The first bit (SWIZZLE_VALID_AXIS) is
used as a sentinel: if it is unset, the axis is not valid. */
#define SWIZZLE_BITS_PER_AXIS 3
#define SWIZZLE_VALID_AXIS 0x4
#define SWIZZLE_AXIS 0x3
static PyObject *Vector_copy(VectorObject *self);
static PyObject *Vector_to_tuple_ext(VectorObject *self, int ndigits);
/* 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 *Vector_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds))
{
float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f};
int size= 3; /* default to a 3D vector */
switch(PyTuple_GET_SIZE(args)) {
case 0:
break;
case 1:
if((size=mathutils_array_parse(vec, 2, 4, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1)
return NULL;
break;
default:
PyErr_SetString(PyExc_TypeError,
"mathutils.Vector(): "
"more then a single arg given");
return NULL;
}
return newVectorObject(vec, size, Py_NEW, type);
}
static PyObject *vec__apply_to_copy(PyNoArgsFunction vec_func, VectorObject *self)
{
PyObject *ret= Vector_copy(self);
PyObject *ret_dummy= vec_func(ret);
if(ret_dummy) {
Py_DECREF(ret_dummy);
return (PyObject *)ret;
}
else { /* error */
Py_DECREF(ret);
return NULL;
}
}
/*-----------------------------METHODS---------------------------- */
PyDoc_STRVAR(Vector_zero_doc,
".. method:: zero()\n"
"\n"
" Set all values to zero.\n"
);
static PyObject *Vector_zero(VectorObject *self)
{
fill_vn(self->vec, self->size, 0.0f);
if(BaseMath_WriteCallback(self) == -1)
return NULL;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Vector_normalize_doc,
".. method:: normalize()\n"
"\n"
" Normalize the vector, making the length of the vector always 1.0.\n"
"\n"
" .. warning:: Normalizing a vector where all values are zero results\n"
" in all axis having a nan value (not a number).\n"
"\n"
" .. note:: Normalize works for vectors of all sizes,\n"
" however 4D Vectors w axis is left untouched.\n"
);
static PyObject *Vector_normalize(VectorObject *self)
{
int i;
float norm = 0.0f;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
for(i = 0; i < self->size; i++) {
norm += self->vec[i] * self->vec[i];
}
norm = (float) sqrt(norm);
for(i = 0; i < self->size; i++) {
self->vec[i] /= norm;
}
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Vector_normalized_doc,
".. method:: normalized()\n"
"\n"
" Return a new, normalized vector.\n"
"\n"
" :return: a normalized copy of the vector\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_normalized(VectorObject *self)
{
return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self);
}
PyDoc_STRVAR(Vector_resize_2d_doc,
".. method:: resize_2d()\n"
"\n"
" Resize the vector to 2D (x, y).\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_resize_2d(VectorObject *self)
{
if(self->wrapped==Py_WRAP) {
PyErr_SetString(PyExc_TypeError,
"vector.resize_2d(): "
"cannot resize wrapped data - only python vectors");
return NULL;
}
if(self->cb_user) {
PyErr_SetString(PyExc_TypeError,
"vector.resize_2d(): "
"cannot resize a vector that has an owner");
return NULL;
}
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vector.resize_2d(): "
"problem allocating pointer space");
return NULL;
}
self->size = 2;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Vector_resize_3d_doc,
".. method:: resize_3d()\n"
"\n"
" Resize the vector to 3D (x, y, z).\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_resize_3d(VectorObject *self)
{
if (self->wrapped==Py_WRAP) {
PyErr_SetString(PyExc_TypeError,
"vector.resize_3d(): "
"cannot resize wrapped data - only python vectors");
return NULL;
}
if(self->cb_user) {
PyErr_SetString(PyExc_TypeError,
"vector.resize_3d(): "
"cannot resize a vector that has an owner");
return NULL;
}
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vector.resize_3d(): "
"problem allocating pointer space");
return NULL;
}
if(self->size == 2)
self->vec[2] = 0.0f;
self->size = 3;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Vector_resize_4d_doc,
".. method:: resize_4d()\n"
"\n"
" Resize the vector to 4D (x, y, z, w).\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_resize_4d(VectorObject *self)
{
if(self->wrapped==Py_WRAP) {
PyErr_SetString(PyExc_TypeError,
"vector.resize_4d(): "
"cannot resize wrapped data - only python vectors");
return NULL;
}
if(self->cb_user) {
PyErr_SetString(PyExc_TypeError,
"vector.resize_4d(): "
"cannot resize a vector that has an owner");
return NULL;
}
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vector.resize_4d(): "
"problem allocating pointer space");
return NULL;
}
if(self->size == 2){
self->vec[2] = 0.0f;
self->vec[3] = 1.0f;
}
else if(self->size == 3){
self->vec[3] = 1.0f;
}
self->size = 4;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Vector_to_2d_doc,
".. method:: to_2d()\n"
"\n"
" Return a 2d copy of the vector.\n"
"\n"
" :return: a new vector\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_to_2d(VectorObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return newVectorObject(self->vec, 2, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_3d_doc,
".. method:: to_3d()\n"
"\n"
" Return a 3d copy of the vector.\n"
"\n"
" :return: a new vector\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_to_3d(VectorObject *self)
{
float tvec[3]= {0.0f};
if(BaseMath_ReadCallback(self) == -1)
return NULL;
memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 3));
return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_4d_doc,
".. method:: to_4d()\n"
"\n"
" Return a 4d copy of the vector.\n"
"\n"
" :return: a new vector\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_to_4d(VectorObject *self)
{
float tvec[4]= {0.0f, 0.0f, 0.0f, 1.0f};
if(BaseMath_ReadCallback(self) == -1)
return NULL;
memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 4));
return newVectorObject(tvec, 4, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_tuple_doc,
".. method:: to_tuple(precision=-1)\n"
"\n"
" Return this vector as a tuple with.\n"
"\n"
" :arg precision: The number to round the value to in [-1, 21].\n"
" :type precision: int\n"
" :return: the values of the vector rounded by *precision*\n"
" :rtype: tuple\n"
);
/* note: BaseMath_ReadCallback must be called beforehand */
static PyObject *Vector_to_tuple_ext(VectorObject *self, int ndigits)
{
PyObject *ret;
int i;
ret= PyTuple_New(self->size);
if(ndigits >= 0) {
for(i = 0; i < self->size; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->vec[i], ndigits)));
}
}
else {
for(i = 0; i < self->size; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->vec[i]));
}
}
return ret;
}
static PyObject *Vector_to_tuple(VectorObject *self, PyObject *args)
{
int ndigits= 0;
if(!PyArg_ParseTuple(args, "|i:to_tuple", &ndigits))
return NULL;
if(ndigits > 22 || ndigits < 0) {
PyErr_SetString(PyExc_ValueError,
"vector.to_tuple(ndigits): "
"ndigits must be between 0 and 21");
return NULL;
}
if(PyTuple_GET_SIZE(args)==0)
ndigits= -1;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return Vector_to_tuple_ext(self, ndigits);
}
PyDoc_STRVAR(Vector_to_track_quat_doc,
".. method:: to_track_quat(track, up)\n"
"\n"
" Return a quaternion rotation from the vector and the track and up axis.\n"
"\n"
" :arg track: Track axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'].\n"
" :type track: string\n"
" :arg up: Up axis in ['X', 'Y', 'Z'].\n"
" :type up: string\n"
" :return: rotation from the vector and the track and up axis.\n"
" :rtype: :class:`Quaternion`\n"
);
static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
{
float vec[3], quat[4];
const char *strack, *sup;
short track = 2, up = 1;
if(!PyArg_ParseTuple(args, "|ss:to_track_quat", &strack, &sup))
return NULL;
if (self->size != 3) {
PyErr_SetString(PyExc_TypeError,
"vector.to_track_quat(): "
"only for 3D vectors");
return NULL;
}
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if (strack) {
const char *axis_err_msg= "only X, -X, Y, -Y, Z or -Z for track axis";
if (strlen(strack) == 2) {
if (strack[0] == '-') {
switch(strack[1]) {
case 'X':
track = 3;
break;
case 'Y':
track = 4;
break;
case 'Z':
track = 5;
break;
default:
PyErr_SetString(PyExc_ValueError, axis_err_msg);
return NULL;
}
}
else {
PyErr_SetString(PyExc_ValueError, axis_err_msg);
return NULL;
}
}
else if (strlen(strack) == 1) {
switch(strack[0]) {
case '-':
case 'X':
track = 0;
break;
case 'Y':
track = 1;
break;
case 'Z':
track = 2;
break;
default:
PyErr_SetString(PyExc_ValueError, axis_err_msg);
return NULL;
}
}
else {
PyErr_SetString(PyExc_ValueError, axis_err_msg);
return NULL;
}
}
if (sup) {
const char *axis_err_msg= "only X, Y or Z for up axis";
if (strlen(sup) == 1) {
switch(*sup) {
case 'X':
up = 0;
break;
case 'Y':
up = 1;
break;
case 'Z':
up = 2;
break;
default:
PyErr_SetString(PyExc_ValueError, axis_err_msg);
return NULL;
}
}
else {
PyErr_SetString(PyExc_ValueError, axis_err_msg);
return NULL;
}
}
if (track == up) {
PyErr_SetString(PyExc_ValueError,
"Can't have the same axis for track and up");
return NULL;
}
/*
flip vector around, since vectoquat expect a vector from target to tracking object
and the python function expects the inverse (a vector to the target).
*/
negate_v3_v3(vec, self->vec);
vec_to_quat(quat, vec, track, up);
return newQuaternionObject(quat, Py_NEW, NULL);
}
/*
* Vector.reflect(mirror): return a reflected vector on the mirror normal
* vec - ((2 * DotVecs(vec, mirror)) * mirror)
*/
PyDoc_STRVAR(Vector_reflect_doc,
".. method:: reflect(mirror)\n"
"\n"
" Return the reflection vector from the *mirror* argument.\n"
"\n"
" :arg mirror: This vector could be a normal from the reflecting surface.\n"
" :type mirror: :class:`Vector`\n"
" :return: The reflected vector matching the size of this vector.\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
{
int value_size;
float mirror[3], vec[3];
float reflect[3] = {0.0f};
float tvec[MAX_DIMENSIONS];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if((value_size= mathutils_array_parse(tvec, 2, 4, value, "vector.reflect(other), invalid 'other' arg")) == -1)
return NULL;
mirror[0] = tvec[0];
mirror[1] = tvec[1];
if (value_size > 2) mirror[2] = tvec[2];
else mirror[2] = 0.0;
vec[0] = self->vec[0];
vec[1] = self->vec[1];
if (self->size > 2) vec[2] = self->vec[2];
else vec[2] = 0.0;
normalize_v3(mirror);
reflect_v3_v3v3(reflect, vec, mirror);
return newVectorObject(reflect, self->size, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_cross_doc,
".. method:: cross(other)\n"
"\n"
" Return the cross product of this vector and another.\n"
"\n"
" :arg other: The other vector to perform the cross product with.\n"
" :type other: :class:`Vector`\n"
" :return: The cross product.\n"
" :rtype: :class:`Vector`\n"
"\n"
" .. note:: both vectors must be 3D\n"
);
static PyObject *Vector_cross(VectorObject *self, PyObject *value)
{
VectorObject *ret;
float tvec[MAX_DIMENSIONS];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(tvec, self->size, self->size, value, "vector.cross(other), invalid 'other' arg") == -1)
return NULL;
ret= (VectorObject *)newVectorObject(NULL, 3, Py_NEW, Py_TYPE(self));
cross_v3_v3v3(ret->vec, self->vec, tvec);
return (PyObject *)ret;
}
PyDoc_STRVAR(Vector_dot_doc,
".. method:: dot(other)\n"
"\n"
" Return the dot product of this vector and another.\n"
"\n"
" :arg other: The other vector to perform the dot product with.\n"
" :type other: :class:`Vector`\n"
" :return: The dot product.\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_dot(VectorObject *self, PyObject *value)
{
float tvec[MAX_DIMENSIONS];
double dot = 0.0;
int x;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(tvec, self->size, self->size, value, "vector.dot(other), invalid 'other' arg") == -1)
return NULL;
for(x = 0; x < self->size; x++) {
dot += (double)(self->vec[x] * tvec[x]);
}
return PyFloat_FromDouble(dot);
}
PyDoc_STRVAR(Vector_angle_doc,
".. function:: angle(other, fallback)\n"
"\n"
" Return the angle between two vectors.\n"
"\n"
" :arg other: another vector to compare the angle with\n"
" :type other: :class:`Vector`\n"
" :arg fallback: return this value when the angle cant be calculated\n"
" (zero length vector)\n"
" :type fallback: any\n"
" :return: angle in radians or fallback when given\n"
" :rtype: float\n"
"\n"
" .. note:: Zero length vectors raise an :exc:`AttributeError`.\n"
);
static PyObject *Vector_angle(VectorObject *self, PyObject *args)
{
const int size= self->size;
float tvec[MAX_DIMENSIONS];
PyObject *value;
double dot = 0.0f, test_v1 = 0.0f, test_v2 = 0.0f;
int x;
PyObject *fallback= NULL;
if(!PyArg_ParseTuple(args, "O|O:angle", &value, &fallback))
return NULL;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(tvec, size, size, value, "vector.angle(other), invalid 'other' arg") == -1)
return NULL;
for(x = 0; x < size; x++) {
test_v1 += (double)(self->vec[x] * self->vec[x]);
test_v2 += (double)(tvec[x] * tvec[x]);
}
if (!test_v1 || !test_v2){
/* avoid exception */
if(fallback) {
Py_INCREF(fallback);
return fallback;
}
else {
PyErr_SetString(PyExc_ValueError,
"vector.angle(other): "
"zero length vectors have no valid angle");
return NULL;
}
}
//dot product
for(x = 0; x < self->size; x++) {
dot += (double)(self->vec[x] * tvec[x]);
}
dot /= (sqrt(test_v1) * sqrt(test_v2));
return PyFloat_FromDouble(saacos(dot));
}
PyDoc_STRVAR(Vector_rotation_difference_doc,
".. function:: difference(other)\n"
"\n"
" Returns a quaternion representing the rotational difference between this\n"
" vector and another.\n"
"\n"
" :arg other: second vector.\n"
" :type other: :class:`Vector`\n"
" :return: the rotational difference between the two vectors.\n"
" :rtype: :class:`Quaternion`\n"
"\n"
" .. note:: 2D vectors raise an :exc:`AttributeError`.\n"
);
static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value)
{
float quat[4], vec_a[3], vec_b[3];
if(self->size < 3) {
PyErr_SetString(PyExc_ValueError,
"vec.difference(value): "
"expects both vectors to be size 3 or 4");
return NULL;
}
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(vec_b, 3, MAX_DIMENSIONS, value, "vector.difference(other), invalid 'other' arg") == -1)
return NULL;
normalize_v3_v3(vec_a, self->vec);
normalize_v3(vec_b);
rotation_between_vecs_to_quat(quat, vec_a, vec_b);
return newQuaternionObject(quat, Py_NEW, NULL);
}
PyDoc_STRVAR(Vector_project_doc,
".. function:: project(other)\n"
"\n"
" Return the projection of this vector onto the *other*.\n"
"\n"
" :arg other: second vector.\n"
" :type other: :class:`Vector`\n"
" :return: the parallel projection vector\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_project(VectorObject *self, PyObject *value)
{
const int size= self->size;
float tvec[MAX_DIMENSIONS];
float vec[MAX_DIMENSIONS];
double dot = 0.0f, dot2 = 0.0f;
int x;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_array_parse(tvec, size, size, value, "vector.project(other), invalid 'other' arg") == -1)
return NULL;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
//get dot products
for(x = 0; x < size; x++) {
dot += (double)(self->vec[x] * tvec[x]);
dot2 += (double)(tvec[x] * tvec[x]);
}
//projection
dot /= dot2;
for(x = 0; x < size; x++) {
vec[x] = (float)dot * tvec[x];
}
return newVectorObject(vec, size, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_lerp_doc,
".. function:: lerp(other, factor)\n"
"\n"
" Returns the interpolation of two vectors.\n"
"\n"
" :arg other: value to interpolate with.\n"
" :type other: :class:`Vector`\n"
" :arg factor: The interpolation value in [0.0, 1.0].\n"
" :type factor: float\n"
" :return: The interpolated rotation.\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
{
const int size= self->size;
PyObject *value= NULL;
float fac, ifac;
float tvec[MAX_DIMENSIONS], vec[MAX_DIMENSIONS];
int x;
if(!PyArg_ParseTuple(args, "Of:lerp", &value, &fac))
return NULL;
if(mathutils_array_parse(tvec, size, size, value, "vector.lerp(other), invalid 'other' arg") == -1)
return NULL;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
ifac= 1.0f - fac;
for(x = 0; x < size; x++) {
vec[x] = (ifac * self->vec[x]) + (fac * tvec[x]);
}
return newVectorObject(vec, size, Py_NEW, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_rotate_doc,
".. function:: rotate(other)\n"
"\n"
" Return vector by a rotation value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
);
static PyObject *Vector_rotate(VectorObject *self, PyObject *value)
{
float other_rmat[3][3];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
if(mathutils_any_to_rotmat(other_rmat, value, "vector.rotate(value)") == -1)
return NULL;
if(self->size < 3) {
PyErr_SetString(PyExc_ValueError,
"Vector must be 3D or 4D");
return NULL;
}
mul_m3_v3(other_rmat, self->vec);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Vector_copy_doc,
".. function:: copy()\n"
"\n"
" Returns a copy of this vector.\n"
"\n"
" :return: A copy of the vector.\n"
" :rtype: :class:`Vector`\n"
"\n"
" .. note:: use this to get a copy of a wrapped vector with\n"
" no reference to the original data.\n"
);
static PyObject *Vector_copy(VectorObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
return newVectorObject(self->vec, self->size, Py_NEW, Py_TYPE(self));
}
static PyObject *Vector_repr(VectorObject *self)
{
PyObject *ret, *tuple;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
tuple= Vector_to_tuple_ext(self, -1);
ret= PyUnicode_FromFormat("Vector(%R)", tuple);
Py_DECREF(tuple);
return ret;
}
/* Sequence Protocol */
/* sequence length len(vector) */
static int Vector_len(VectorObject *self)
{
return self->size;
}
/* sequence accessor (get): vector[index] */
static PyObject *vector_item_internal(VectorObject *self, int i, const int is_attr)
{
if(i<0) i= self->size-i;
if(i < 0 || i >= self->size) {
if(is_attr) {
PyErr_Format(PyExc_AttributeError,
"vector.%c: unavailable on %dd vector",
*(((char *)"xyzw") + i), self->size);
}
else {
PyErr_SetString(PyExc_IndexError,
"vector[index]: out of range");
}
return NULL;
}
if(BaseMath_ReadIndexCallback(self, i) == -1)
return NULL;
return PyFloat_FromDouble(self->vec[i]);
}
static PyObject *Vector_item(VectorObject *self, int i)
{
return vector_item_internal(self, i, FALSE);
}
/* sequence accessor (set): vector[index] = value */
static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, const int is_attr)
{
float scalar;
if((scalar=PyFloat_AsDouble(value))==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"vector[index] = x: "
"index argument not a number");
return -1;
}
if(i<0) i= self->size-i;
if(i < 0 || i >= self->size){
if(is_attr) {
PyErr_Format(PyExc_AttributeError,
"vector.%c = x: unavailable on %dd vector",
*(((char *)"xyzw") + i), self->size);
}
else {
PyErr_SetString(PyExc_IndexError,
"vector[index] = x: "
"assignment index out of range");
}
return -1;
}
self->vec[i] = scalar;
if(BaseMath_WriteIndexCallback(self, i) == -1)
return -1;
return 0;
}
static int Vector_ass_item(VectorObject *self, int i, PyObject *value)
{
return vector_ass_item_internal(self, i, value, FALSE);
}
/* sequence slice (get): vector[a:b] */
static PyObject *Vector_slice(VectorObject *self, int begin, int end)
{
PyObject *tuple;
int count;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
CLAMP(begin, 0, self->size);
if (end<0) end= self->size+end+1;
CLAMP(end, 0, self->size);
begin= MIN2(begin, end);
tuple= PyTuple_New(end - begin);
for(count = begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->vec[count]));
}
return tuple;
}
/* sequence slice (set): vector[a:b] = value */
static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
{
int y, size = 0;
float vec[MAX_DIMENSIONS];
if(BaseMath_ReadCallback(self) == -1)
return -1;
CLAMP(begin, 0, self->size);
CLAMP(end, 0, self->size);
begin = MIN2(begin, end);
size = (end - begin);
if(mathutils_array_parse(vec, size, size, seq, "vector[begin:end] = [...]") == -1)
return -1;
/*parsed well - now set in vector*/
for(y = 0; y < size; y++){
self->vec[begin + y] = vec[y];
}
if(BaseMath_WriteCallback(self) == -1)
return -1;
return 0;
}
/* Numeric Protocols */
/* addition: obj + obj */
static PyObject *Vector_add(PyObject *v1, PyObject *v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float vec[MAX_DIMENSIONS];
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
PyErr_SetString(PyExc_AttributeError,
"Vector addition: "
"arguments not valid for this operation");
return NULL;
}
vec1 = (VectorObject*)v1;
vec2 = (VectorObject*)v2;
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1)
return NULL;
/*VECTOR + VECTOR*/
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError,
"Vector addition: "
"vectors must have the same dimensions for this operation");
return NULL;
}
add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size);
return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1));
}
/* addition in-place: obj += obj */
static PyObject *Vector_iadd(PyObject *v1, PyObject *v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
PyErr_SetString(PyExc_AttributeError,
"Vector addition: "
"arguments not valid for this operation");
return NULL;
}
vec1 = (VectorObject*)v1;
vec2 = (VectorObject*)v2;
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError,
"Vector addition: "
"vectors must have the same dimensions for this operation");
return NULL;
}
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1)
return NULL;
add_vn_vn(vec1->vec, vec2->vec, vec1->size);
(void)BaseMath_WriteCallback(vec1);
Py_INCREF(v1);
return v1;
}
/* subtraction: obj - obj */
static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float vec[MAX_DIMENSIONS];
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
PyErr_SetString(PyExc_AttributeError,
"Vector subtraction: "
"arguments not valid for this operation");
return NULL;
}
vec1 = (VectorObject*)v1;
vec2 = (VectorObject*)v2;
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1)
return NULL;
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError,
"Vector subtraction: "
"vectors must have the same dimensions for this operation");
return NULL;
}
sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size);
return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1));
}
/* subtraction in-place: obj -= obj */
static PyObject *Vector_isub(PyObject *v1, PyObject *v2)
{
VectorObject *vec1= NULL, *vec2= NULL;
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
PyErr_SetString(PyExc_AttributeError,
"Vector subtraction: "
"arguments not valid for this operation");
return NULL;
}
vec1 = (VectorObject*)v1;
vec2 = (VectorObject*)v2;
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError,
"Vector subtraction: "
"vectors must have the same dimensions for this operation");
return NULL;
}
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1)
return NULL;
sub_vn_vn(vec1->vec, vec2->vec, vec1->size);
(void)BaseMath_WriteCallback(vec1);
Py_INCREF(v1);
return v1;
}
/*------------------------obj * obj------------------------------
mulplication*/
/* COLUMN VECTOR Multiplication (Vector X Matrix)
* [a] * [1][4][7]
* [b] * [2][5][8]
* [c] * [3][6][9]
*
* note: vector/matrix multiplication IS NOT COMMUTATIVE!!!!
* note: assume read callbacks have been done first.
*/
static int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec, MatrixObject * mat)
{
float vec_cpy[MAX_DIMENSIONS];
double dot = 0.0f;
int x, y, z = 0;
if(mat->row_size != vec->size){
if(mat->row_size == 4 && vec->size == 3) {
vec_cpy[3] = 1.0f;
}
else {
PyErr_SetString(PyExc_TypeError,
"matrix * vector: "
"matrix.row_size and len(vector) must be the same, "
"except for 3D vector * 4x4 matrix.");
return -1;
}
}
memcpy(vec_cpy, vec->vec, vec->size * sizeof(float));
rvec[3] = 1.0f;
for(x = 0; x < mat->col_size; x++) {
for(y = 0; y < mat->row_size; y++) {
dot += (double)(mat->matrix[y][x] * vec_cpy[y]);
}
rvec[z++] = (float)dot;
dot = 0.0f;
}
return 0;
}
static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
{
float tvec[MAX_DIMENSIONS];
mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
return newVectorObject(tvec, vec->size, Py_NEW, Py_TYPE(vec));
}
static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
if VectorObject_Check(v1) {
vec1= (VectorObject *)v1;
if(BaseMath_ReadCallback(vec1) == -1)
return NULL;
}
if VectorObject_Check(v2) {
vec2= (VectorObject *)v2;
if(BaseMath_ReadCallback(vec2) == -1)
return NULL;
}
/* make sure v1 is always the vector */
if (vec1 && vec2) {
int i;
double dot = 0.0f;
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
"vectors must have the same dimensions for this operation");
return NULL;
}
/*dot product*/
for(i = 0; i < vec1->size; i++) {
dot += (double)(vec1->vec[i] * vec2->vec[i]);
}
return PyFloat_FromDouble(dot);
}
else if (vec1) {
if (MatrixObject_Check(v2)) {
/* VEC * MATRIX */
float tvec[MAX_DIMENSIONS];
if(BaseMath_ReadCallback((MatrixObject *)v2) == -1)
return NULL;
if(column_vector_multiplication(tvec, vec1, (MatrixObject*)v2) == -1) {
return NULL;
}
return newVectorObject(tvec, vec1->size, Py_NEW, Py_TYPE(vec1));
}
else if (QuaternionObject_Check(v2)) {
/* VEC * QUAT */
QuaternionObject *quat2 = (QuaternionObject*)v2;
float tvec[3];
if(vec1->size != 3) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
"only 3D vector rotations (with quats) currently supported");
return NULL;
}
if(BaseMath_ReadCallback(quat2) == -1) {
return NULL;
}
copy_v3_v3(tvec, vec1->vec);
mul_qt_v3(quat2->quat, tvec);
return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(vec1));
}
else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC * FLOAT */
return vector_mul_float(vec1, scalar);
}
}
else if (vec2) {
if (((scalar= PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred())==0) { /* FLOAT * VEC */
return vector_mul_float(vec2, scalar);
}
}
else {
BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
"Vector multiplication: "
"not supported between '%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
}
/* mulplication in-place: obj *= obj */
static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
{
VectorObject *vec = (VectorObject *)v1;
float scalar;
if(BaseMath_ReadCallback(vec) == -1)
return NULL;
/* only support vec*=float and vec*=mat
vec*=vec result is a float so that wont work */
if (MatrixObject_Check(v2)) {
float rvec[MAX_DIMENSIONS];
if(BaseMath_ReadCallback((MatrixObject *)v2) == -1)
return NULL;
if(column_vector_multiplication(rvec, vec, (MatrixObject*)v2) == -1)
return NULL;
memcpy(vec->vec, rvec, sizeof(float) * vec->size);
}
else if (QuaternionObject_Check(v2)) {
/* VEC *= QUAT */
QuaternionObject *quat2 = (QuaternionObject*)v2;
if(vec->size != 3) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
"only 3D vector rotations (with quats) currently supported");
return NULL;
}
if(BaseMath_ReadCallback(quat2) == -1) {
return NULL;
}
mul_qt_v3(quat2->quat, vec->vec);
}
else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC *= FLOAT */
mul_vn_fl(vec->vec, vec->size, scalar);
}
else {
PyErr_SetString(PyExc_TypeError,
"Vector multiplication: "
"arguments not acceptable for this operation");
return NULL;
}
(void)BaseMath_WriteCallback(vec);
Py_INCREF(v1);
return v1;
}
/* divid: obj / obj */
static PyObject *Vector_div(PyObject *v1, PyObject *v2)
{
int i;
float vec[4], scalar;
VectorObject *vec1 = NULL;
if(!VectorObject_Check(v1)) { /* not a vector */
PyErr_SetString(PyExc_TypeError,
"Vector division: "
"Vector must be divided by a float");
return NULL;
}
vec1 = (VectorObject*)v1; /* vector */
if(BaseMath_ReadCallback(vec1) == -1)
return NULL;
if((scalar=PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"Vector division: "
"Vector must be divided by a float");
return NULL;
}
if(scalar==0.0f) {
PyErr_SetString(PyExc_ZeroDivisionError,
"Vector division: "
"divide by zero error");
return NULL;
}
for(i = 0; i < vec1->size; i++) {
vec[i] = vec1->vec[i] / scalar;
}
return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1));
}
/* divide in-place: obj /= obj */
static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
{
int i;
float scalar;
VectorObject *vec1 = (VectorObject*)v1;
if(BaseMath_ReadCallback(vec1) == -1)
return NULL;
if((scalar=PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"Vector division: "
"Vector must be divided by a float");
return NULL;
}
if(scalar==0.0f) {
PyErr_SetString(PyExc_ZeroDivisionError,
"Vector division: "
"divide by zero error");
return NULL;
}
for(i = 0; i < vec1->size; i++) {
vec1->vec[i] /= scalar;
}
(void)BaseMath_WriteCallback(vec1);
Py_INCREF(v1);
return v1;
}
/* -obj
returns the negative of this object*/
static PyObject *Vector_neg(VectorObject *self)
{
float tvec[MAX_DIMENSIONS];
if(BaseMath_ReadCallback(self) == -1)
return NULL;
negate_vn_vn(tvec, self->vec, self->size);
return newVectorObject(tvec, self->size, Py_NEW, Py_TYPE(self));
}
/*------------------------vec_magnitude_nosqrt (internal) - for comparing only */
static double vec_magnitude_nosqrt(float *data, int size)
{
double dot = 0.0f;
int i;
for(i=0; i<size; i++){
dot += (double)data[i];
}
/*return (double)sqrt(dot);*/
/* warning, line above removed because we are not using the length,
rather the comparing the sizes and for this we do not need the sqrt
for the actual length, the dot must be sqrt'd */
return dot;
}
/*------------------------tp_richcmpr
returns -1 execption, 0 false, 1 true */
static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
{
VectorObject *vecA = NULL, *vecB = NULL;
int result = 0;
double epsilon = .000001f;
double lenA, lenB;
if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
vecA = (VectorObject*)objectA;
vecB = (VectorObject*)objectB;
if(BaseMath_ReadCallback(vecA) == -1 || BaseMath_ReadCallback(vecB) == -1)
return NULL;
if (vecA->size != vecB->size){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
switch (comparison_type){
case Py_LT:
lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
if(lenA < lenB){
result = 1;
}
break;
case Py_LE:
lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
if(lenA < lenB){
result = 1;
}
else {
result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
}
break;
case Py_EQ:
result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
break;
case Py_NE:
result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
break;
case Py_GT:
lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
if(lenA > lenB){
result = 1;
}
break;
case Py_GE:
lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
if(lenA > lenB){
result = 1;
}
else {
result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
}
break;
default:
printf("The result of the comparison could not be evaluated");
break;
}
if (result == 1){
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
/*-----------------PROTCOL DECLARATIONS--------------------------*/
static PySequenceMethods Vector_SeqMethods = {
(lenfunc) Vector_len, /* sq_length */
(binaryfunc) NULL, /* sq_concat */
(ssizeargfunc) NULL, /* sq_repeat */
(ssizeargfunc) Vector_item, /* sq_item */
NULL, /* py3 deprecated slice func */
(ssizeobjargproc) Vector_ass_item, /* sq_ass_item */
NULL, /* py3 deprecated slice assign func */
(objobjproc) NULL, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */
(ssizeargfunc) NULL, /* sq_inplace_repeat */
};
static PyObject *Vector_subscript(VectorObject* self, PyObject* item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += self->size;
return Vector_item(self, i);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, self->size, &start, &stop, &step, &slicelength) < 0)
return NULL;
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
return Vector_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with vectors");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"vector indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return NULL;
}
}
static int Vector_ass_subscript(VectorObject* self, PyObject* item, PyObject* value)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += self->size;
return Vector_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, self->size, &start, &stop, &step, &slicelength) < 0)
return -1;
if (step == 1)
return Vector_ass_slice(self, start, stop, value);
else {
PyErr_SetString(PyExc_IndexError,
"slice steps not supported with vectors");
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"vector indices must be integers, not %.200s",
Py_TYPE(item)->tp_name);
return -1;
}
}
static PyMappingMethods Vector_AsMapping = {
(lenfunc)Vector_len,
(binaryfunc)Vector_subscript,
(objobjargproc)Vector_ass_subscript
};
static PyNumberMethods Vector_NumMethods = {
(binaryfunc) Vector_add, /*nb_add*/
(binaryfunc) Vector_sub, /*nb_subtract*/
(binaryfunc) Vector_mul, /*nb_multiply*/
NULL, /*nb_remainder*/
NULL, /*nb_divmod*/
NULL, /*nb_power*/
(unaryfunc) Vector_neg, /*nb_negative*/
(unaryfunc) NULL, /*tp_positive*/
(unaryfunc) NULL, /*tp_absolute*/
(inquiry) NULL, /*tp_bool*/
(unaryfunc) NULL, /*nb_invert*/
NULL, /*nb_lshift*/
(binaryfunc)NULL, /*nb_rshift*/
NULL, /*nb_and*/
NULL, /*nb_xor*/
NULL, /*nb_or*/
NULL, /*nb_int*/
NULL, /*nb_reserved*/
NULL, /*nb_float*/
Vector_iadd, /* nb_inplace_add */
Vector_isub, /* nb_inplace_subtract */
Vector_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
NULL, /* nb_inplace_rshift */
NULL, /* nb_inplace_and */
NULL, /* nb_inplace_xor */
NULL, /* nb_inplace_or */
NULL, /* nb_floor_divide */
Vector_div, /* nb_true_divide */
NULL, /* nb_inplace_floor_divide */
Vector_idiv, /* nb_inplace_true_divide */
NULL, /* nb_index */
};
/*------------------PY_OBECT DEFINITION--------------------------*/
/*
* vector axis, vector.x/y/z/w
*/
static PyObject *Vector_getAxis(VectorObject *self, void *type)
{
return vector_item_internal(self, GET_INT_FROM_POINTER(type), TRUE);
}
static int Vector_setAxis(VectorObject *self, PyObject *value, void *type)
{
return vector_ass_item_internal(self, GET_INT_FROM_POINTER(type), value, TRUE);
}
/* vector.length */
static PyObject *Vector_getLength(VectorObject *self, void *UNUSED(closure))
{
double dot = 0.0f;
int i;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
for(i = 0; i < self->size; i++){
dot += (double)(self->vec[i] * self->vec[i]);
}
return PyFloat_FromDouble(sqrt(dot));
}
static int Vector_setLength(VectorObject *self, PyObject *value)
{
double dot = 0.0f, param;
int i;
if(BaseMath_ReadCallback(self) == -1)
return -1;
if((param=PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"length must be set to a number");
return -1;
}
if (param < 0.0) {
PyErr_SetString(PyExc_ValueError,
"cannot set a vectors length to a negative value");
return -1;
}
if (param == 0.0) {
fill_vn(self->vec, self->size, 0.0f);
return 0;
}
for(i = 0; i < self->size; i++){
dot += (double)(self->vec[i] * self->vec[i]);
}
if (!dot) /* cant sqrt zero */
return 0;
dot = sqrt(dot);
if (dot==param)
return 0;
dot= dot/param;
for(i = 0; i < self->size; i++){
self->vec[i]= self->vec[i] / (float)dot;
}
(void)BaseMath_WriteCallback(self); /* checked already */
return 0;
}
/* Get a new Vector according to the provided swizzle. This function has little
error checking, as we are in control of the inputs: the closure is set by us
in Vector_createSwizzleGetSeter. */
static PyObject *Vector_getSwizzle(VectorObject *self, void *closure)
{
size_t axis_to;
size_t axis_from;
float vec[MAX_DIMENSIONS];
unsigned int swizzleClosure;
if(BaseMath_ReadCallback(self) == -1)
return NULL;
/* Unpack the axes from the closure into an array. */
axis_to = 0;
swizzleClosure = GET_INT_FROM_POINTER(closure);
while (swizzleClosure & SWIZZLE_VALID_AXIS)
{
axis_from = swizzleClosure & SWIZZLE_AXIS;
if(axis_from >= self->size) {
PyErr_SetString(PyExc_AttributeError,
"Vector swizzle: "
"specified axis not present");
return NULL;
}
vec[axis_to] = self->vec[axis_from];
swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
axis_to++;
}
return newVectorObject(vec, axis_to, Py_NEW, Py_TYPE(self));
}
/* Set the items of this vector using a swizzle.
- If value is a vector or list this operates like an array copy, except that
the destination is effectively re-ordered as defined by the swizzle. At
most min(len(source), len(dest)) values will be copied.
- If the value is scalar, it is copied to all axes listed in the swizzle.
- If an axis appears more than once in the swizzle, the final occurrence is
the one that determines its value.
Returns 0 on success and -1 on failure. On failure, the vector will be
unchanged. */
static int Vector_setSwizzle(VectorObject *self, PyObject *value, void *closure)
{
size_t size_from;
float scalarVal;
size_t axis_from;
size_t axis_to;
unsigned int swizzleClosure;
float tvec[MAX_DIMENSIONS];
float vec_assign[MAX_DIMENSIONS];
if(BaseMath_ReadCallback(self) == -1)
return -1;
/* Check that the closure can be used with this vector: even 2D vectors have
swizzles defined for axes z and w, but they would be invalid. */
swizzleClosure = GET_INT_FROM_POINTER(closure);
axis_from= 0;
while (swizzleClosure & SWIZZLE_VALID_AXIS) {
axis_to = swizzleClosure & SWIZZLE_AXIS;
if (axis_to >= self->size)
{
PyErr_SetString(PyExc_AttributeError,
"Vector swizzle: "
"specified axis not present");
return -1;
}
swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
axis_from++;
}
if (((scalarVal=PyFloat_AsDouble(value)) == -1 && PyErr_Occurred())==0) {
int i;
for(i=0; i < MAX_DIMENSIONS; i++)
vec_assign[i]= scalarVal;
size_from= axis_from;
}
else if(PyErr_Clear(), (size_from=mathutils_array_parse(vec_assign, 2, 4, value, "mathutils.Vector.**** = swizzle assignment")) == -1) {
return -1;
}
if(axis_from != size_from) {
PyErr_SetString(PyExc_AttributeError,
"Vector swizzle: size does not match swizzle");
return -1;
}
/* Copy vector contents onto swizzled axes. */
axis_from = 0;
swizzleClosure = GET_INT_FROM_POINTER(closure);
while (swizzleClosure & SWIZZLE_VALID_AXIS)
{
axis_to = swizzleClosure & SWIZZLE_AXIS;
tvec[axis_to] = vec_assign[axis_from];
swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
axis_from++;
}
memcpy(self->vec, tvec, axis_from * sizeof(float));
/* continue with BaseMathObject_WriteCallback at the end */
if(BaseMath_WriteCallback(self) == -1)
return -1;
else
return 0;
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Vector_getseters[] = {
{(char *)"x", (getter)Vector_getAxis, (setter)Vector_setAxis, (char *)"Vector X axis.\n\n:type: float", (void *)0},
{(char *)"y", (getter)Vector_getAxis, (setter)Vector_setAxis, (char *)"Vector Y axis.\n\n:type: float", (void *)1},
{(char *)"z", (getter)Vector_getAxis, (setter)Vector_setAxis, (char *)"Vector Z axis (3D Vectors only).\n\n:type: float", (void *)2},
{(char *)"w", (getter)Vector_getAxis, (setter)Vector_setAxis, (char *)"Vector W axis (4D Vectors only).\n\n:type: float", (void *)3},
{(char *)"length", (getter)Vector_getLength, (setter)Vector_setLength, (char *)"Vector Length.\n\n:type: float", NULL},
{(char *)"magnitude", (getter)Vector_getLength, (setter)Vector_setLength, (char *)"Vector Length.\n\n:type: float", NULL},
{(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL},
{(char *)"owner", (getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL},
/* autogenerated swizzle attrs, see python script below */
{(char *)"xx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 36
{(char *)"xxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 292
{(char *)"xxxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2340
{(char *)"xxxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2852
{(char *)"xxxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3364
{(char *)"xxxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3876
{(char *)"xxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 356
{(char *)"xxyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2404
{(char *)"xxyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2916
{(char *)"xxyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3428
{(char *)"xxyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3940
{(char *)"xxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 420
{(char *)"xxzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2468
{(char *)"xxzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2980
{(char *)"xxzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3492
{(char *)"xxzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4004
{(char *)"xxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 484
{(char *)"xxwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2532
{(char *)"xxwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3044
{(char *)"xxwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3556
{(char *)"xxww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4068
{(char *)"xy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 44
{(char *)"xyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 300
{(char *)"xyxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2348
{(char *)"xyxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2860
{(char *)"xyxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3372
{(char *)"xyxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3884
{(char *)"xyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 364
{(char *)"xyyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2412
{(char *)"xyyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2924
{(char *)"xyyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3436
{(char *)"xyyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3948
{(char *)"xyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 428
{(char *)"xyzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2476
{(char *)"xyzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2988
{(char *)"xyzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3500
{(char *)"xyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4012
{(char *)"xyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 492
{(char *)"xywx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2540
{(char *)"xywy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3052
{(char *)"xywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3564
{(char *)"xyww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4076
{(char *)"xz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 52
{(char *)"xzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 308
{(char *)"xzxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2356
{(char *)"xzxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2868
{(char *)"xzxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3380
{(char *)"xzxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3892
{(char *)"xzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 372
{(char *)"xzyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2420
{(char *)"xzyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2932
{(char *)"xzyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3444
{(char *)"xzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3956
{(char *)"xzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 436
{(char *)"xzzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2484
{(char *)"xzzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2996
{(char *)"xzzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3508
{(char *)"xzzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4020
{(char *)"xzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 500
{(char *)"xzwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2548
{(char *)"xzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3060
{(char *)"xzwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3572
{(char *)"xzww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4084
{(char *)"xw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 60
{(char *)"xwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 316
{(char *)"xwxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2364
{(char *)"xwxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2876
{(char *)"xwxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3388
{(char *)"xwxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3900
{(char *)"xwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 380
{(char *)"xwyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2428
{(char *)"xwyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2940
{(char *)"xwyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3452
{(char *)"xwyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3964
{(char *)"xwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 444
{(char *)"xwzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2492
{(char *)"xwzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3004
{(char *)"xwzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3516
{(char *)"xwzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4028
{(char *)"xww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 508
{(char *)"xwwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2556
{(char *)"xwwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3068
{(char *)"xwwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3580
{(char *)"xwww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4092
{(char *)"yx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 37
{(char *)"yxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 293
{(char *)"yxxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2341
{(char *)"yxxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2853
{(char *)"yxxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3365
{(char *)"yxxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3877
{(char *)"yxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 357
{(char *)"yxyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2405
{(char *)"yxyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2917
{(char *)"yxyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3429
{(char *)"yxyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3941
{(char *)"yxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 421
{(char *)"yxzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2469
{(char *)"yxzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2981
{(char *)"yxzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3493
{(char *)"yxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4005
{(char *)"yxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 485
{(char *)"yxwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2533
{(char *)"yxwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3045
{(char *)"yxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3557
{(char *)"yxww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4069
{(char *)"yy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 45
{(char *)"yyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 301
{(char *)"yyxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2349
{(char *)"yyxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2861
{(char *)"yyxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3373
{(char *)"yyxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3885
{(char *)"yyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 365
{(char *)"yyyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2413
{(char *)"yyyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2925
{(char *)"yyyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3437
{(char *)"yyyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3949
{(char *)"yyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 429
{(char *)"yyzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2477
{(char *)"yyzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2989
{(char *)"yyzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3501
{(char *)"yyzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4013
{(char *)"yyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 493
{(char *)"yywx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2541
{(char *)"yywy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3053
{(char *)"yywz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3565
{(char *)"yyww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4077
{(char *)"yz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 53
{(char *)"yzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 309
{(char *)"yzxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2357
{(char *)"yzxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2869
{(char *)"yzxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3381
{(char *)"yzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3893
{(char *)"yzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 373
{(char *)"yzyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2421
{(char *)"yzyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2933
{(char *)"yzyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3445
{(char *)"yzyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3957
{(char *)"yzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 437
{(char *)"yzzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2485
{(char *)"yzzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2997
{(char *)"yzzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3509
{(char *)"yzzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4021
{(char *)"yzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 501
{(char *)"yzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2549
{(char *)"yzwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3061
{(char *)"yzwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3573
{(char *)"yzww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4085
{(char *)"yw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 61
{(char *)"ywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 317
{(char *)"ywxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2365
{(char *)"ywxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2877
{(char *)"ywxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3389
{(char *)"ywxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3901
{(char *)"ywy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 381
{(char *)"ywyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2429
{(char *)"ywyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2941
{(char *)"ywyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3453
{(char *)"ywyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3965
{(char *)"ywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 445
{(char *)"ywzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2493
{(char *)"ywzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3005
{(char *)"ywzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3517
{(char *)"ywzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4029
{(char *)"yww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 509
{(char *)"ywwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2557
{(char *)"ywwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3069
{(char *)"ywwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3581
{(char *)"ywww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4093
{(char *)"zx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 38
{(char *)"zxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 294
{(char *)"zxxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2342
{(char *)"zxxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2854
{(char *)"zxxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3366
{(char *)"zxxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3878
{(char *)"zxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 358
{(char *)"zxyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2406
{(char *)"zxyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2918
{(char *)"zxyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3430
{(char *)"zxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3942
{(char *)"zxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 422
{(char *)"zxzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2470
{(char *)"zxzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2982
{(char *)"zxzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3494
{(char *)"zxzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4006
{(char *)"zxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 486
{(char *)"zxwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2534
{(char *)"zxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3046
{(char *)"zxwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3558
{(char *)"zxww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4070
{(char *)"zy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 46
{(char *)"zyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 302
{(char *)"zyxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2350
{(char *)"zyxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2862
{(char *)"zyxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3374
{(char *)"zyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3886
{(char *)"zyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 366
{(char *)"zyyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2414
{(char *)"zyyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2926
{(char *)"zyyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3438
{(char *)"zyyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3950
{(char *)"zyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 430
{(char *)"zyzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2478
{(char *)"zyzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2990
{(char *)"zyzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3502
{(char *)"zyzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4014
{(char *)"zyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 494
{(char *)"zywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2542
{(char *)"zywy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3054
{(char *)"zywz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3566
{(char *)"zyww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4078
{(char *)"zz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 54
{(char *)"zzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 310
{(char *)"zzxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2358
{(char *)"zzxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2870
{(char *)"zzxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3382
{(char *)"zzxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3894
{(char *)"zzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 374
{(char *)"zzyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2422
{(char *)"zzyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2934
{(char *)"zzyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3446
{(char *)"zzyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3958
{(char *)"zzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 438
{(char *)"zzzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2486
{(char *)"zzzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2998
{(char *)"zzzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3510
{(char *)"zzzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4022
{(char *)"zzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 502
{(char *)"zzwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2550
{(char *)"zzwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3062
{(char *)"zzwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3574
{(char *)"zzww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4086
{(char *)"zw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 62
{(char *)"zwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 318
{(char *)"zwxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2366
{(char *)"zwxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2878
{(char *)"zwxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3390
{(char *)"zwxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3902
{(char *)"zwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 382
{(char *)"zwyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2430
{(char *)"zwyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2942
{(char *)"zwyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3454
{(char *)"zwyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3966
{(char *)"zwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 446
{(char *)"zwzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2494
{(char *)"zwzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3006
{(char *)"zwzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3518
{(char *)"zwzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4030
{(char *)"zww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 510
{(char *)"zwwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2558
{(char *)"zwwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3070
{(char *)"zwwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3582
{(char *)"zwww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4094
{(char *)"wx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 39
{(char *)"wxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 295
{(char *)"wxxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2343
{(char *)"wxxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2855
{(char *)"wxxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3367
{(char *)"wxxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3879
{(char *)"wxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 359
{(char *)"wxyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2407
{(char *)"wxyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2919
{(char *)"wxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3431
{(char *)"wxyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3943
{(char *)"wxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 423
{(char *)"wxzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2471
{(char *)"wxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2983
{(char *)"wxzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3495
{(char *)"wxzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4007
{(char *)"wxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 487
{(char *)"wxwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2535
{(char *)"wxwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3047
{(char *)"wxwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3559
{(char *)"wxww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4071
{(char *)"wy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 47
{(char *)"wyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 303
{(char *)"wyxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2351
{(char *)"wyxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2863
{(char *)"wyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3375
{(char *)"wyxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3887
{(char *)"wyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 367
{(char *)"wyyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2415
{(char *)"wyyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2927
{(char *)"wyyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3439
{(char *)"wyyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3951
{(char *)"wyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 431
{(char *)"wyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2479
{(char *)"wyzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2991
{(char *)"wyzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3503
{(char *)"wyzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4015
{(char *)"wyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 495
{(char *)"wywx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2543
{(char *)"wywy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3055
{(char *)"wywz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3567
{(char *)"wyww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4079
{(char *)"wz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 55
{(char *)"wzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 311
{(char *)"wzxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2359
{(char *)"wzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2871
{(char *)"wzxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3383
{(char *)"wzxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3895
{(char *)"wzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 375
{(char *)"wzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2423
{(char *)"wzyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2935
{(char *)"wzyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3447
{(char *)"wzyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3959
{(char *)"wzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 439
{(char *)"wzzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2487
{(char *)"wzzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2999
{(char *)"wzzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3511
{(char *)"wzzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4023
{(char *)"wzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 503
{(char *)"wzwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2551
{(char *)"wzwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3063
{(char *)"wzwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3575
{(char *)"wzww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4087
{(char *)"ww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, // 63
{(char *)"wwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 319
{(char *)"wwxx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2367
{(char *)"wwxy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2879
{(char *)"wwxz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3391
{(char *)"wwxw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3903
{(char *)"wwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 383
{(char *)"wwyx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2431
{(char *)"wwyy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2943
{(char *)"wwyz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3455
{(char *)"wwyw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3967
{(char *)"wwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 447
{(char *)"wwzx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2495
{(char *)"wwzy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3007
{(char *)"wwzz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3519
{(char *)"wwzw", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4031
{(char *)"www", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, // 511
{(char *)"wwwx", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 2559
{(char *)"wwwy", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3071
{(char *)"wwwz", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 3583
{(char *)"wwww", (getter)Vector_getSwizzle, (setter)NULL, NULL, SET_INT_IN_POINTER(((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, // 4095
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
/* Python script used to make swizzle array */
/*
SWIZZLE_BITS_PER_AXIS = 3
SWIZZLE_VALID_AXIS = 0x4
axis_dict = {}
axis_pos = {'x':0, 'y':1, 'z':2, 'w':3}
axises = 'xyzw'
while len(axises) >= 2:
for axis_0 in axises:
axis_0_pos = axis_pos[axis_0]
for axis_1 in axises:
axis_1_pos = axis_pos[axis_1]
axis_dict[axis_0+axis_1] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS))' % (axis_0_pos, axis_1_pos)
if len(axises)>2:
for axis_2 in axises:
axis_2_pos = axis_pos[axis_2]
axis_dict[axis_0+axis_1+axis_2] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)))' % (axis_0_pos, axis_1_pos, axis_2_pos)
if len(axises)>3:
for axis_3 in axises:
axis_3_pos = axis_pos[axis_3]
axis_dict[axis_0+axis_1+axis_2+axis_3] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) ' % (axis_0_pos, axis_1_pos, axis_2_pos, axis_3_pos)
axises = axises[:-1]
items = axis_dict.items()
items.sort(key = lambda a: a[0].replace('x', '0').replace('y', '1').replace('z', '2').replace('w', '3'))
unique = set()
for key, val in items:
num = eval(val)
set_str = 'Vector_setSwizzle' if (len(set(key)) == len(key)) else 'NULL'
print '\t{"%s", %s(getter)Vector_getSwizzle, (setter)%s, NULL, SET_INT_IN_POINTER(%s)}, // %s' % (key, (' '*(4-len(key))), set_str, axis_dict[key], num)
unique.add(num)
if len(unique) != len(items):
print "ERROR"
*/
#if 0
//ROW VECTOR Multiplication - Vector X Matrix
//[x][y][z] * [1][4][7]
// [2][5][8]
// [3][6][9]
//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
static int row_vector_multiplication(float rvec[4], VectorObject* vec, MatrixObject * mat)
{
float vec_cpy[4];
double dot = 0.0f;
int x, y, z = 0, vec_size = vec->size;
if(mat->colSize != vec_size){
if(mat->colSize == 4 && vec_size != 3){
PyErr_SetString(PyExc_ValueError,
"vector * matrix: matrix column size "
"and the vector size must be the same");
return -1;
}
else {
vec_cpy[3] = 1.0f;
}
}
if(BaseMath_ReadCallback(vec) == -1 || BaseMath_ReadCallback(mat) == -1)
return -1;
memcpy(vec_cpy, vec->vec, vec_size * sizeof(float));
rvec[3] = 1.0f;
//muliplication
for(x = 0; x < mat->rowSize; x++) {
for(y = 0; y < mat->colSize; y++) {
dot += mat->matrix[x][y] * vec_cpy[y];
}
rvec[z++] = (float)dot;
dot = 0.0f;
}
return 0;
}
#endif
/*----------------------------Vector.negate() -------------------- */
PyDoc_STRVAR(Vector_negate_doc,
".. method:: negate()\n"
"\n"
" Set all values to their negative.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Vector`\n"
);
static PyObject *Vector_negate(VectorObject *self)
{
if(BaseMath_ReadCallback(self) == -1)
return NULL;
negate_vn(self->vec, self->size);
(void)BaseMath_WriteCallback(self); // already checked for error
Py_RETURN_NONE;
}
static struct PyMethodDef Vector_methods[] = {
/* in place only */
{"zero", (PyCFunction) Vector_zero, METH_NOARGS, Vector_zero_doc},
{"negate", (PyCFunction) Vector_negate, METH_NOARGS, Vector_negate_doc},
/* operate on original or copy */
{"normalize", (PyCFunction) Vector_normalize, METH_NOARGS, Vector_normalize_doc},
{"normalized", (PyCFunction) Vector_normalized, METH_NOARGS, Vector_normalized_doc},
{"to_2d", (PyCFunction) Vector_to_2d, METH_NOARGS, Vector_to_2d_doc},
{"resize_2d", (PyCFunction) Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc},
{"to_3d", (PyCFunction) Vector_to_3d, METH_NOARGS, Vector_to_3d_doc},
{"resize_3d", (PyCFunction) Vector_resize_3d, METH_NOARGS, Vector_resize_3d_doc},
{"to_4d", (PyCFunction) Vector_to_4d, METH_NOARGS, Vector_to_4d_doc},
{"resize_4d", (PyCFunction) Vector_resize_4d, METH_NOARGS, Vector_resize_4d_doc},
{"to_tuple", (PyCFunction) Vector_to_tuple, METH_VARARGS, Vector_to_tuple_doc},
{"to_track_quat", (PyCFunction) Vector_to_track_quat, METH_VARARGS, Vector_to_track_quat_doc},
/* operation between 2 or more types */
{"reflect", (PyCFunction) Vector_reflect, METH_O, Vector_reflect_doc},
{"cross", (PyCFunction) Vector_cross, METH_O, Vector_cross_doc},
{"dot", (PyCFunction) Vector_dot, METH_O, Vector_dot_doc},
{"angle", (PyCFunction) Vector_angle, METH_VARARGS, Vector_angle_doc},
{"rotation_difference", (PyCFunction) Vector_rotation_difference, METH_O, Vector_rotation_difference_doc},
{"project", (PyCFunction) Vector_project, METH_O, Vector_project_doc},
{"lerp", (PyCFunction) Vector_lerp, METH_VARARGS, Vector_lerp_doc},
{"rotate", (PyCFunction) Vector_rotate, METH_O, Vector_rotate_doc},
{"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
{"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL}
};
/* Note
Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing
but this means for eg that
vec*mat and mat*vec both get sent to Vector_mul and it neesd to sort out the order
*/
PyDoc_STRVAR(vector_doc,
"This object gives access to Vectors in Blender."
);
PyTypeObject vector_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"mathutils.Vector", /* char *tp_name; */
sizeof(VectorObject), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
/* Methods to implement standard operations */
(destructor) BaseMathObject_dealloc,/* destructor tp_dealloc; */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
(reprfunc)Vector_repr, /* reprfunc tp_repr; */
/* Method suites for standard classes */
&Vector_NumMethods, /* PyNumberMethods *tp_as_number; */
&Vector_SeqMethods, /* PySequenceMethods *tp_as_sequence; */
&Vector_AsMapping, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
vector_doc, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
(traverseproc)BaseMathObject_traverse, //tp_traverse
/* delete references to contained objects */
(inquiry)BaseMathObject_clear, //tp_clear
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons ***/
(richcmpfunc)Vector_richcmpr, /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0, /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
Vector_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
Vector_getseters, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
NULL, /* descrsetfunc tp_descr_set; */
0, /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
Vector_new, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
/* method resolution order */
NULL, /* PyObject *tp_mro; */
NULL, /* PyObject *tp_cache; */
NULL, /* PyObject *tp_subclasses; */
NULL, /* PyObject *tp_weaklist; */
NULL
};
/*------------------------newVectorObject (internal)-------------
creates a new vector object
pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newVectorObject(float *vec, const int size, const int type, PyTypeObject *base_type)
{
VectorObject *self;
if(size > 4 || size < 2) {
PyErr_SetString(PyExc_RuntimeError,
"Vector(): invalid size");
return NULL;
}
self= base_type ? (VectorObject *)base_type->tp_alloc(base_type, 0) :
(VectorObject *)PyObject_GC_New(VectorObject, &vector_Type);
if(self) {
self->size = size;
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP) {
self->vec = vec;
self->wrapped = Py_WRAP;
}
else if (type == Py_NEW) {
self->vec= PyMem_Malloc(size * sizeof(float));
if(vec) {
memcpy(self->vec, vec, size * sizeof(float));
}
else { /* new empty */
fill_vn(self->vec, size, 0.0f);
if(size == 4) { /* do the homogenous thing */
self->vec[3] = 1.0f;
}
}
self->wrapped = Py_NEW;
}
else {
Py_FatalError("Vector(): invalid type!");
}
}
return (PyObject *) self;
}
PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_subtype)
{
float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* dummy init vector, callbacks will be used on access */
VectorObject *self= (VectorObject *)newVectorObject(dummy, size, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
PyObject_GC_Track(self);
}
return (PyObject *)self;
}

View File

@@ -0,0 +1,52 @@
/*
* $Id: mathutils_Vector.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Willian P. Germano & Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/python/generic/mathutils_Vector.h
* \ingroup pygen
*/
#ifndef MATHUTILS_VECTOR_H
#define MATHUTILS_VECTOR_H
extern PyTypeObject vector_Type;
#define VectorObject_Check(_v) PyObject_TypeCheck((_v), &vector_Type)
typedef struct {
BASE_MATH_MEMBERS(vec)
unsigned char size; /* vec size 2,3 or 4 */
} VectorObject;
/*prototypes*/
PyObject *newVectorObject(float *vec, const int size, const int type, PyTypeObject *base_type);
PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype);
#endif /* MATHUTILS_VECTOR_H */

View File

@@ -0,0 +1,1135 @@
/*
* $Id: mathutils_geometry.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_geometry.c
* \ingroup pygen
*/
#include <Python.h>
#include "mathutils_geometry.h"
/* Used for PolyFill */
#ifndef MATH_STANDALONE /* define when building outside blender */
# include "MEM_guardedalloc.h"
# include "BLI_blenlib.h"
# include "BLI_boxpack2d.h"
# include "BKE_displist.h"
# include "BKE_curve.h"
#endif
#include "BLI_math.h"
#include "BLI_utildefines.h"
#define SWAP_FLOAT(a, b, tmp) tmp=a; a=b; b=tmp
#define eps 0.000001
/*-------------------------DOC STRINGS ---------------------------*/
PyDoc_STRVAR(M_Geometry_doc,
"The Blender geometry module"
);
//---------------------------------INTERSECTION FUNCTIONS--------------------
PyDoc_STRVAR(M_Geometry_intersect_ray_tri_doc,
".. function:: intersect_ray_tri(v1, v2, v3, ray, orig, clip=True)\n"
"\n"
" Returns the intersection between a ray and a triangle, if possible, returns None otherwise.\n"
"\n"
" :arg v1: Point1\n"
" :type v1: :class:`mathutils.Vector`\n"
" :arg v2: Point2\n"
" :type v2: :class:`mathutils.Vector`\n"
" :arg v3: Point3\n"
" :type v3: :class:`mathutils.Vector`\n"
" :arg ray: Direction of the projection\n"
" :type ray: :class:`mathutils.Vector`\n"
" :arg orig: Origin\n"
" :type orig: :class:`mathutils.Vector`\n"
" :arg clip: When False, don't restrict the intersection to the area of the triangle, use the infinite plane defined by the triangle.\n"
" :type clip: boolean\n"
" :return: The point of intersection or None if no intersection is found\n"
" :rtype: :class:`mathutils.Vector` or None\n"
);
static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *ray, *ray_off, *vec1, *vec2, *vec3;
float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
float det, inv_det, u, v, t;
int clip= 1;
if(!PyArg_ParseTuple(args, "O!O!O!O!O!|i:intersect_ray_tri", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off , &clip)) {
return NULL;
}
if(vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
PyErr_SetString(PyExc_ValueError,
"only 3D vectors for all parameters");
return NULL;
}
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(ray) == -1 || BaseMath_ReadCallback(ray_off) == -1)
return NULL;
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
VECCOPY(dir, ray->vec);
normalize_v3(dir);
VECCOPY(orig, ray_off->vec);
/* find vectors for two edges sharing v1 */
sub_v3_v3v3(e1, v2, v1);
sub_v3_v3v3(e2, v3, v1);
/* begin calculating determinant - also used to calculated U parameter */
cross_v3_v3v3(pvec, dir, e2);
/* if determinant is near zero, ray lies in plane of triangle */
det= dot_v3v3(e1, pvec);
if (det > -0.000001f && det < 0.000001f) {
Py_RETURN_NONE;
}
inv_det= 1.0f / det;
/* calculate distance from v1 to ray origin */
sub_v3_v3v3(tvec, orig, v1);
/* calculate U parameter and test bounds */
u= dot_v3v3(tvec, pvec) * inv_det;
if (clip && (u < 0.0f || u > 1.0f)) {
Py_RETURN_NONE;
}
/* prepare to test the V parameter */
cross_v3_v3v3(qvec, tvec, e1);
/* calculate V parameter and test bounds */
v= dot_v3v3(dir, qvec) * inv_det;
if (clip && (v < 0.0f || u + v > 1.0f)) {
Py_RETURN_NONE;
}
/* calculate t, ray intersects triangle */
t= dot_v3v3(e2, qvec) * inv_det;
mul_v3_fl(dir, t);
add_v3_v3v3(pvec, orig, dir);
return newVectorObject(pvec, 3, Py_NEW, NULL);
}
/* Line-Line intersection using algorithm from mathworld.wolfram.com */
PyDoc_STRVAR(M_Geometry_intersect_line_line_doc,
".. function:: intersect_line_line(v1, v2, v3, v4)\n"
"\n"
" Returns a tuple with the points on each line respectively closest to the other.\n"
"\n"
" :arg v1: First point of the first line\n"
" :type v1: :class:`mathutils.Vector`\n"
" :arg v2: Second point of the first line\n"
" :type v2: :class:`mathutils.Vector`\n"
" :arg v3: First point of the second line\n"
" :type v3: :class:`mathutils.Vector`\n"
" :arg v4: Second point of the second line\n"
" :type v4: :class:`mathutils.Vector`\n"
" :rtype: tuple of :class:`mathutils.Vector`'s\n"
);
static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject *args)
{
PyObject *tuple;
VectorObject *vec1, *vec2, *vec3, *vec4;
float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3];
if(!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4)) {
return NULL;
}
if(vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) {
PyErr_SetString(PyExc_ValueError,
"vectors must be of the same size");
return NULL;
}
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(vec4) == -1)
return NULL;
if(vec1->size == 3 || vec1->size == 2) {
int result;
if (vec1->size == 3) {
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
VECCOPY(v4, vec4->vec);
}
else {
v1[0]= vec1->vec[0];
v1[1]= vec1->vec[1];
v1[2]= 0.0f;
v2[0]= vec2->vec[0];
v2[1]= vec2->vec[1];
v2[2]= 0.0f;
v3[0]= vec3->vec[0];
v3[1]= vec3->vec[1];
v3[2]= 0.0f;
v4[0]= vec4->vec[0];
v4[1]= vec4->vec[1];
v4[2]= 0.0f;
}
result= isect_line_line_v3(v1, v2, v3, v4, i1, i2);
if (result == 0) {
/* colinear */
Py_RETURN_NONE;
}
else {
tuple= PyTuple_New(2);
PyTuple_SET_ITEM(tuple, 0, newVectorObject(i1, vec1->size, Py_NEW, NULL));
PyTuple_SET_ITEM(tuple, 1, newVectorObject(i2, vec1->size, Py_NEW, NULL));
return tuple;
}
}
else {
PyErr_SetString(PyExc_ValueError,
"2D/3D vectors only");
return NULL;
}
}
//----------------------------geometry.normal() -------------------
PyDoc_STRVAR(M_Geometry_normal_doc,
".. function:: normal(v1, v2, v3, v4=None)\n"
"\n"
" Returns the normal of the 3D tri or quad.\n"
"\n"
" :arg v1: Point1\n"
" :type v1: :class:`mathutils.Vector`\n"
" :arg v2: Point2\n"
" :type v2: :class:`mathutils.Vector`\n"
" :arg v3: Point3\n"
" :type v3: :class:`mathutils.Vector`\n"
" :arg v4: Point4 (optional)\n"
" :type v4: :class:`mathutils.Vector`\n"
" :rtype: :class:`mathutils.Vector`\n"
);
static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *vec1, *vec2, *vec3, *vec4;
float n[3];
if(PyTuple_GET_SIZE(args) == 3) {
if(!PyArg_ParseTuple(args, "O!O!O!:normal", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3)) {
return NULL;
}
if(vec1->size != vec2->size || vec1->size != vec3->size) {
PyErr_SetString(PyExc_ValueError,
"vectors must be of the same size");
return NULL;
}
if(vec1->size < 3) {
PyErr_SetString(PyExc_ValueError,
"2D vectors unsupported");
return NULL;
}
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1)
return NULL;
normal_tri_v3(n, vec1->vec, vec2->vec, vec3->vec);
}
else {
if(!PyArg_ParseTuple(args, "O!O!O!O!:normal", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4)) {
return NULL;
}
if(vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
PyErr_SetString(PyExc_ValueError,
"vectors must be of the same size");
return NULL;
}
if(vec1->size < 3) {
PyErr_SetString(PyExc_ValueError,
"2D vectors unsupported");
return NULL;
}
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(vec4) == -1)
return NULL;
normal_quad_v3(n, vec1->vec, vec2->vec, vec3->vec, vec4->vec);
}
return newVectorObject(n, 3, Py_NEW, NULL);
}
//--------------------------------- AREA FUNCTIONS--------------------
PyDoc_STRVAR(M_Geometry_area_tri_doc,
".. function:: area_tri(v1, v2, v3)\n"
"\n"
" Returns the area size of the 2D or 3D triangle defined.\n"
"\n"
" :arg v1: Point1\n"
" :type v1: :class:`mathutils.Vector`\n"
" :arg v2: Point2\n"
" :type v2: :class:`mathutils.Vector`\n"
" :arg v3: Point3\n"
" :type v3: :class:`mathutils.Vector`\n"
" :rtype: float\n"
);
static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *vec1, *vec2, *vec3;
if(!PyArg_ParseTuple(args, "O!O!O!:area_tri", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3)) {
return NULL;
}
if(vec1->size != vec2->size || vec1->size != vec3->size) {
PyErr_SetString(PyExc_ValueError,
"vectors must be of the same size");
return NULL;
}
if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1)
return NULL;
if (vec1->size == 3) {
return PyFloat_FromDouble(area_tri_v3(vec1->vec, vec2->vec, vec3->vec));
}
else if (vec1->size == 2) {
return PyFloat_FromDouble(area_tri_v2(vec1->vec, vec2->vec, vec3->vec));
}
else {
PyErr_SetString(PyExc_ValueError,
"only 2D,3D vectors are supported");
return NULL;
}
}
PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc,
".. function:: intersect_line_line_2d(lineA_p1, lineA_p2, lineB_p1, lineB_p2)\n"
"\n"
" Takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None.\n"
"\n"
" :arg lineA_p1: First point of the first line\n"
" :type lineA_p1: :class:`mathutils.Vector`\n"
" :arg lineA_p2: Second point of the first line\n"
" :type lineA_p2: :class:`mathutils.Vector`\n"
" :arg lineB_p1: First point of the second line\n"
" :type lineB_p1: :class:`mathutils.Vector`\n"
" :arg lineB_p2: Second point of the second line\n"
" :type lineB_p2: :class:`mathutils.Vector`\n"
" :return: The point of intersection or None when not found\n"
" :rtype: :class:`mathutils.Vector` or None\n"
);
static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *line_a1, *line_a2, *line_b1, *line_b2;
float vi[2];
if(!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line_2d",
&vector_Type, &line_a1,
&vector_Type, &line_a2,
&vector_Type, &line_b1,
&vector_Type, &line_b2)
) {
return NULL;
}
if(BaseMath_ReadCallback(line_a1) == -1 || BaseMath_ReadCallback(line_a2) == -1 || BaseMath_ReadCallback(line_b1) == -1 || BaseMath_ReadCallback(line_b2) == -1)
return NULL;
if(isect_seg_seg_v2_point(line_a1->vec, line_a2->vec, line_b1->vec, line_b2->vec, vi) == 1) {
return newVectorObject(vi, 2, Py_NEW, NULL);
}
else {
Py_RETURN_NONE;
}
}
PyDoc_STRVAR(M_Geometry_intersect_line_plane_doc,
".. function:: intersect_line_plane(line_a, line_b, plane_co, plane_no, no_flip=False)\n"
"\n"
" Takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None.\n"
"\n"
" :arg line_a: First point of the first line\n"
" :type line_a: :class:`mathutils.Vector`\n"
" :arg line_b: Second point of the first line\n"
" :type line_b: :class:`mathutils.Vector`\n"
" :arg plane_co: A point on the plane\n"
" :type plane_co: :class:`mathutils.Vector`\n"
" :arg plane_no: The direction the plane is facing\n"
" :type plane_no: :class:`mathutils.Vector`\n"
" :arg no_flip: Always return an intersection on the directon defined bt line_a -> line_b\n"
" :type no_flip: :boolean\n"
" :return: The point of intersection or None when not found\n"
" :rtype: :class:`mathutils.Vector` or None\n"
);
static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *line_a, *line_b, *plane_co, *plane_no;
int no_flip= 0;
float isect[3];
if(!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane",
&vector_Type, &line_a,
&vector_Type, &line_b,
&vector_Type, &plane_co,
&vector_Type, &plane_no,
&no_flip)
) {
return NULL;
}
if( BaseMath_ReadCallback(line_a) == -1 ||
BaseMath_ReadCallback(line_b) == -1 ||
BaseMath_ReadCallback(plane_co) == -1 ||
BaseMath_ReadCallback(plane_no) == -1
) {
return NULL;
}
if(ELEM4(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_line_plane(...): "
" can't use 2D Vectors");
return NULL;
}
if(isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec, no_flip) == 1) {
return newVectorObject(isect, 3, Py_NEW, NULL);
}
else {
Py_RETURN_NONE;
}
}
PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc,
".. function:: intersect_line_sphere(line_a, line_b, sphere_co, sphere_radius, clip=True)\n"
"\n"
" Takes a lines (as 2 vectors), a sphere as a point and a radius and\n"
" returns the intersection\n"
"\n"
" :arg line_a: First point of the first line\n"
" :type line_a: :class:`mathutils.Vector`\n"
" :arg line_b: Second point of the first line\n"
" :type line_b: :class:`mathutils.Vector`\n"
" :arg sphere_co: The center of the sphere\n"
" :type sphere_co: :class:`mathutils.Vector`\n"
" :arg sphere_radius: Radius of the sphere\n"
" :type sphere_radius: sphere_radius\n"
" :return: The intersection points as a pair of vectors or None when there is no intersection\n"
" :rtype: A tuple pair containing :class:`mathutils.Vector` or None\n"
);
static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *line_a, *line_b, *sphere_co;
float sphere_radius;
int clip= TRUE;
float isect_a[3];
float isect_b[3];
if(!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere",
&vector_Type, &line_a,
&vector_Type, &line_b,
&vector_Type, &sphere_co,
&sphere_radius, &clip)
) {
return NULL;
}
if( BaseMath_ReadCallback(line_a) == -1 ||
BaseMath_ReadCallback(line_b) == -1 ||
BaseMath_ReadCallback(sphere_co) == -1
) {
return NULL;
}
if(ELEM3(2, line_a->size, line_b->size, sphere_co->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_line_sphere(...): "
" can't use 2D Vectors");
return NULL;
}
else {
short use_a= TRUE;
short use_b= TRUE;
float lambda;
PyObject *ret= PyTuple_New(2);
switch(isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
case 1:
if(!(!clip || (((lambda= line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE;
use_b= FALSE;
break;
case 2:
if(!(!clip || (((lambda= line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE;
if(!(!clip || (((lambda= line_point_factor_v3(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b= FALSE;
break;
default:
use_a= FALSE;
use_b= FALSE;
}
if(use_a) { PyTuple_SET_ITEM(ret, 0, newVectorObject(isect_a, 3, Py_NEW, NULL)); }
else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); }
if(use_b) { PyTuple_SET_ITEM(ret, 1, newVectorObject(isect_b, 3, Py_NEW, NULL)); }
else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None); }
return ret;
}
}
/* keep in sync with M_Geometry_intersect_line_sphere */
PyDoc_STRVAR(M_Geometry_intersect_line_sphere_2d_doc,
".. function:: intersect_line_sphere_2d(line_a, line_b, sphere_co, sphere_radius, clip=True)\n"
"\n"
" Takes a lines (as 2 vectors), a sphere as a point and a radius and\n"
" returns the intersection\n"
"\n"
" :arg line_a: First point of the first line\n"
" :type line_a: :class:`mathutils.Vector`\n"
" :arg line_b: Second point of the first line\n"
" :type line_b: :class:`mathutils.Vector`\n"
" :arg sphere_co: The center of the sphere\n"
" :type sphere_co: :class:`mathutils.Vector`\n"
" :arg sphere_radius: Radius of the sphere\n"
" :type sphere_radius: sphere_radius\n"
" :return: The intersection points as a pair of vectors or None when there is no intersection\n"
" :rtype: A tuple pair containing :class:`mathutils.Vector` or None\n"
);
static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *line_a, *line_b, *sphere_co;
float sphere_radius;
int clip= TRUE;
float isect_a[3];
float isect_b[3];
if(!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere_2d",
&vector_Type, &line_a,
&vector_Type, &line_b,
&vector_Type, &sphere_co,
&sphere_radius, &clip)
) {
return NULL;
}
if( BaseMath_ReadCallback(line_a) == -1 ||
BaseMath_ReadCallback(line_b) == -1 ||
BaseMath_ReadCallback(sphere_co) == -1
) {
return NULL;
}
else {
short use_a= TRUE;
short use_b= TRUE;
float lambda;
PyObject *ret= PyTuple_New(2);
switch(isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
case 1:
if(!(!clip || (((lambda= line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE;
use_b= FALSE;
break;
case 2:
if(!(!clip || (((lambda= line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE;
if(!(!clip || (((lambda= line_point_factor_v2(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b= FALSE;
break;
default:
use_a= FALSE;
use_b= FALSE;
}
if(use_a) { PyTuple_SET_ITEM(ret, 0, newVectorObject(isect_a, 2, Py_NEW, NULL)); }
else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); }
if(use_b) { PyTuple_SET_ITEM(ret, 1, newVectorObject(isect_b, 2, Py_NEW, NULL)); }
else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None); }
return ret;
}
}
PyDoc_STRVAR(M_Geometry_intersect_point_line_doc,
".. function:: intersect_point_line(pt, line_p1, line_p2)\n"
"\n"
" Takes a point and a line and returns a tuple with the closest point on the line and its distance from the first point of the line as a percentage of the length of the line.\n"
"\n"
" :arg pt: Point\n"
" :type pt: :class:`mathutils.Vector`\n"
" :arg line_p1: First point of the line\n"
" :type line_p1: :class:`mathutils.Vector`\n"
" :arg line_p1: Second point of the line\n"
" :type line_p1: :class:`mathutils.Vector`\n"
" :rtype: (:class:`mathutils.Vector`, float)\n"
);
static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *pt, *line_1, *line_2;
float pt_in[3], pt_out[3], l1[3], l2[3];
float lambda;
PyObject *ret;
if(!PyArg_ParseTuple(args, "O!O!O!:intersect_point_line",
&vector_Type, &pt,
&vector_Type, &line_1,
&vector_Type, &line_2)
) {
return NULL;
}
if(BaseMath_ReadCallback(pt) == -1 || BaseMath_ReadCallback(line_1) == -1 || BaseMath_ReadCallback(line_2) == -1)
return NULL;
/* accept 2d verts */
if (pt->size==3) { VECCOPY(pt_in, pt->vec);}
else { pt_in[2]=0.0; VECCOPY2D(pt_in, pt->vec) }
if (line_1->size==3) { VECCOPY(l1, line_1->vec);}
else { l1[2]=0.0; VECCOPY2D(l1, line_1->vec) }
if (line_2->size==3) { VECCOPY(l2, line_2->vec);}
else { l2[2]=0.0; VECCOPY2D(l2, line_2->vec) }
/* do the calculation */
lambda= closest_to_line_v3(pt_out, pt_in, l1, l2);
ret= PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, newVectorObject(pt_out, 3, Py_NEW, NULL));
PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(lambda));
return ret;
}
PyDoc_STRVAR(M_Geometry_intersect_point_tri_2d_doc,
".. function:: intersect_point_tri_2d(pt, tri_p1, tri_p2, tri_p3)\n"
"\n"
" Takes 4 vectors (using only the x and y coordinates): one is the point and the next 3 define the triangle. Returns 1 if the point is within the triangle, otherwise 0.\n"
"\n"
" :arg pt: Point\n"
" :type v1: :class:`mathutils.Vector`\n"
" :arg tri_p1: First point of the triangle\n"
" :type tri_p1: :class:`mathutils.Vector`\n"
" :arg tri_p2: Second point of the triangle\n"
" :type tri_p2: :class:`mathutils.Vector`\n"
" :arg tri_p3: Third point of the triangle\n"
" :type tri_p3: :class:`mathutils.Vector`\n"
" :rtype: int\n"
);
static PyObject *M_Geometry_intersect_point_tri_2d(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
if(!PyArg_ParseTuple(args, "O!O!O!O!:intersect_point_tri_2d",
&vector_Type, &pt_vec,
&vector_Type, &tri_p1,
&vector_Type, &tri_p2,
&vector_Type, &tri_p3)
) {
return NULL;
}
if(BaseMath_ReadCallback(pt_vec) == -1 || BaseMath_ReadCallback(tri_p1) == -1 || BaseMath_ReadCallback(tri_p2) == -1 || BaseMath_ReadCallback(tri_p3) == -1)
return NULL;
return PyLong_FromLong(isect_point_tri_v2(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
}
PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
".. function:: intersect_point_quad_2d(pt, quad_p1, quad_p2, quad_p3, quad_p4)\n"
"\n"
" Takes 5 vectors (using only the x and y coordinates): one is the point and the next 4 define the quad, only the x and y are used from the vectors. Returns 1 if the point is within the quad, otherwise 0.\n"
"\n"
" :arg pt: Point\n"
" :type v1: :class:`mathutils.Vector`\n"
" :arg quad_p1: First point of the quad\n"
" :type quad_p1: :class:`mathutils.Vector`\n"
" :arg quad_p2: Second point of the quad\n"
" :type quad_p2: :class:`mathutils.Vector`\n"
" :arg quad_p3: Third point of the quad\n"
" :type quad_p3: :class:`mathutils.Vector`\n"
" :arg quad_p4: Forth point of the quad\n"
" :type quad_p4: :class:`mathutils.Vector`\n"
" :rtype: int\n"
);
static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *pt_vec, *quad_p1, *quad_p2, *quad_p3, *quad_p4;
if(!PyArg_ParseTuple(args, "O!O!O!O!O!:intersect_point_quad_2d",
&vector_Type, &pt_vec,
&vector_Type, &quad_p1,
&vector_Type, &quad_p2,
&vector_Type, &quad_p3,
&vector_Type, &quad_p4)
) {
return NULL;
}
if(BaseMath_ReadCallback(pt_vec) == -1 || BaseMath_ReadCallback(quad_p1) == -1 || BaseMath_ReadCallback(quad_p2) == -1 || BaseMath_ReadCallback(quad_p3) == -1 || BaseMath_ReadCallback(quad_p4) == -1)
return NULL;
return PyLong_FromLong(isect_point_quad_v2(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
}
PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
".. function:: barycentric_transform(point, tri_a1, tri_a2, tri_a3, tri_b1, tri_b2, tri_b3)\n"
"\n"
" Return a transformed point, the transformation is defined by 2 triangles.\n"
"\n"
" :arg point: The point to transform.\n"
" :type point: :class:`mathutils.Vector`\n"
" :arg tri_a1: source triangle vertex.\n"
" :type tri_a1: :class:`mathutils.Vector`\n"
" :arg tri_a2: source triangle vertex.\n"
" :type tri_a2: :class:`mathutils.Vector`\n"
" :arg tri_a3: source triangle vertex.\n"
" :type tri_a3: :class:`mathutils.Vector`\n"
" :arg tri_a1: target triangle vertex.\n"
" :type tri_a1: :class:`mathutils.Vector`\n"
" :arg tri_a2: target triangle vertex.\n"
" :type tri_a2: :class:`mathutils.Vector`\n"
" :arg tri_a3: target triangle vertex.\n"
" :type tri_a3: :class:`mathutils.Vector`\n"
" :return: The transformed point\n"
" :rtype: :class:`mathutils.Vector`'s\n"
);
static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObject *args)
{
VectorObject *vec_pt;
VectorObject *vec_t1_tar, *vec_t2_tar, *vec_t3_tar;
VectorObject *vec_t1_src, *vec_t2_src, *vec_t3_src;
float vec[3];
if(!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!:barycentric_transform",
&vector_Type, &vec_pt,
&vector_Type, &vec_t1_src,
&vector_Type, &vec_t2_src,
&vector_Type, &vec_t3_src,
&vector_Type, &vec_t1_tar,
&vector_Type, &vec_t2_tar,
&vector_Type, &vec_t3_tar)
) {
return NULL;
}
if( vec_pt->size != 3 ||
vec_t1_src->size != 3 ||
vec_t2_src->size != 3 ||
vec_t3_src->size != 3 ||
vec_t1_tar->size != 3 ||
vec_t2_tar->size != 3 ||
vec_t3_tar->size != 3)
{
PyErr_SetString(PyExc_ValueError,
"One of more of the vector arguments wasn't a 3D vector");
return NULL;
}
barycentric_transform(vec, vec_pt->vec,
vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec,
vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec);
return newVectorObject(vec, 3, Py_NEW, NULL);
}
#ifndef MATH_STANDALONE
PyDoc_STRVAR(M_Geometry_interpolate_bezier_doc,
".. function:: interpolate_bezier(knot1, handle1, handle2, knot2, resolution)\n"
"\n"
" Interpolate a bezier spline segment.\n"
"\n"
" :arg knot1: First bezier spline point.\n"
" :type knot1: :class:`mathutils.Vector`\n"
" :arg handle1: First bezier spline handle.\n"
" :type handle1: :class:`mathutils.Vector`\n"
" :arg handle2: Second bezier spline handle.\n"
" :type handle2: :class:`mathutils.Vector`\n"
" :arg knot2: Second bezier spline point.\n"
" :type knot2: :class:`mathutils.Vector`\n"
" :arg resolution: Number of points to return.\n"
" :type resolution: int\n"
" :return: The interpolated points\n"
" :rtype: list of :class:`mathutils.Vector`'s\n"
);
static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject* args)
{
VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
int resolu;
int dims;
int i;
float *coord_array, *fp;
PyObject *list;
float k1[4]= {0.0, 0.0, 0.0, 0.0};
float h1[4]= {0.0, 0.0, 0.0, 0.0};
float k2[4]= {0.0, 0.0, 0.0, 0.0};
float h2[4]= {0.0, 0.0, 0.0, 0.0};
if(!PyArg_ParseTuple(args, "O!O!O!O!i:interpolate_bezier",
&vector_Type, &vec_k1,
&vector_Type, &vec_h1,
&vector_Type, &vec_h2,
&vector_Type, &vec_k2, &resolu)
) {
return NULL;
}
if(resolu <= 1) {
PyErr_SetString(PyExc_ValueError,
"resolution must be 2 or over");
return NULL;
}
if(BaseMath_ReadCallback(vec_k1) == -1 || BaseMath_ReadCallback(vec_h1) == -1 || BaseMath_ReadCallback(vec_k2) == -1 || BaseMath_ReadCallback(vec_h2) == -1)
return NULL;
dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i];
for(i=0; i < vec_h1->size; i++) h1[i]= vec_h1->vec[i];
for(i=0; i < vec_k2->size; i++) k2[i]= vec_k2->vec[i];
for(i=0; i < vec_h2->size; i++) h2[i]= vec_h2->vec[i];
coord_array= MEM_callocN(dims * (resolu) * sizeof(float), "interpolate_bezier");
for(i=0; i<dims; i++) {
forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array+i, resolu-1, sizeof(float)*dims);
}
list= PyList_New(resolu);
fp= coord_array;
for(i=0; i<resolu; i++, fp= fp+dims) {
PyList_SET_ITEM(list, i, newVectorObject(fp, dims, Py_NEW, NULL));
}
MEM_freeN(coord_array);
return list;
}
PyDoc_STRVAR(M_Geometry_tesselate_polygon_doc,
".. function:: tesselate_polygon(veclist_list)\n"
"\n"
" Takes a list of polylines (each point a vector) and returns the point indices for a polyline filled with triangles.\n"
"\n"
" :arg veclist_list: list of polylines\n"
" :rtype: list\n"
);
/* PolyFill function, uses Blenders scanfill to fill multiple poly lines */
static PyObject *M_Geometry_tesselate_polygon(PyObject *UNUSED(self), PyObject *polyLineSeq)
{
PyObject *tri_list; /*return this list of tri's */
PyObject *polyLine, *polyVec;
int i, len_polylines, len_polypoints, ls_error= 0;
/* display listbase */
ListBase dispbase={NULL, NULL};
DispList *dl;
float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */
int index, *dl_face, totpoints=0;
if(!PySequence_Check(polyLineSeq)) {
PyErr_SetString(PyExc_TypeError,
"expected a sequence of poly lines");
return NULL;
}
len_polylines= PySequence_Size(polyLineSeq);
for(i= 0; i < len_polylines; ++i) {
polyLine= PySequence_GetItem(polyLineSeq, i);
if (!PySequence_Check(polyLine)) {
freedisplist(&dispbase);
Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/
PyErr_SetString(PyExc_TypeError,
"One or more of the polylines is not a sequence of mathutils.Vector's");
return NULL;
}
len_polypoints= PySequence_Size(polyLine);
if (len_polypoints>0) { /* dont bother adding edges as polylines */
#if 0
if (EXPP_check_sequence_consistency(polyLine, &vector_Type) != 1) {
freedisplist(&dispbase);
Py_DECREF(polyLine);
PyErr_SetString(PyExc_TypeError,
"A point in one of the polylines is not a mathutils.Vector type");
return NULL;
}
#endif
dl= MEM_callocN(sizeof(DispList), "poly disp");
BLI_addtail(&dispbase, dl);
dl->type= DL_INDEX3;
dl->nr= len_polypoints;
dl->type= DL_POLY;
dl->parts= 1; /* no faces, 1 edge loop */
dl->col= 0; /* no material */
dl->verts= fp= MEM_callocN(sizeof(float)*3*len_polypoints, "dl verts");
dl->index= MEM_callocN(sizeof(int)*3*len_polypoints, "dl index");
for(index= 0; index<len_polypoints; ++index, fp+=3) {
polyVec= PySequence_GetItem(polyLine, index);
if(VectorObject_Check(polyVec)) {
if(BaseMath_ReadCallback((VectorObject *)polyVec) == -1)
ls_error= 1;
fp[0]= ((VectorObject *)polyVec)->vec[0];
fp[1]= ((VectorObject *)polyVec)->vec[1];
if(((VectorObject *)polyVec)->size > 2)
fp[2]= ((VectorObject *)polyVec)->vec[2];
else
fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */
}
else {
ls_error= 1;
}
totpoints++;
Py_DECREF(polyVec);
}
}
Py_DECREF(polyLine);
}
if(ls_error) {
freedisplist(&dispbase); /* possible some dl was allocated */
PyErr_SetString(PyExc_TypeError,
"A point in one of the polylines "
"is not a mathutils.Vector type");
return NULL;
}
else if (totpoints) {
/* now make the list to return */
filldisplist(&dispbase, &dispbase, 0);
/* The faces are stored in a new DisplayList
thats added to the head of the listbase */
dl= dispbase.first;
tri_list= PyList_New(dl->parts);
if(!tri_list) {
freedisplist(&dispbase);
PyErr_SetString(PyExc_RuntimeError,
"failed to make a new list");
return NULL;
}
index= 0;
dl_face= dl->index;
while(index < dl->parts) {
PyList_SET_ITEM(tri_list, index, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2]));
dl_face+= 3;
index++;
}
freedisplist(&dispbase);
}
else {
/* no points, do this so scripts dont barf */
freedisplist(&dispbase); /* possible some dl was allocated */
tri_list= PyList_New(0);
}
return tri_list;
}
static int boxPack_FromPyObject(PyObject *value, boxPack **boxarray)
{
int len, i;
PyObject *list_item, *item_1, *item_2;
boxPack *box;
/* Error checking must already be done */
if(!PyList_Check(value)) {
PyErr_SetString(PyExc_TypeError,
"can only back a list of [x, y, w, h]");
return -1;
}
len= PyList_Size(value);
(*boxarray)= MEM_mallocN(len*sizeof(boxPack), "boxPack box");
for(i= 0; i < len; i++) {
list_item= PyList_GET_ITEM(value, i);
if(!PyList_Check(list_item) || PyList_Size(list_item) < 4) {
MEM_freeN(*boxarray);
PyErr_SetString(PyExc_TypeError,
"can only pack a list of [x, y, w, h]");
return -1;
}
box= (*boxarray)+i;
item_1= PyList_GET_ITEM(list_item, 2);
item_2= PyList_GET_ITEM(list_item, 3);
box->w= (float)PyFloat_AsDouble(item_1);
box->h= (float)PyFloat_AsDouble(item_2);
box->index= i;
/* accounts for error case too and overwrites with own error */
if (box->w < 0.0f || box->h < 0.0f) {
MEM_freeN(*boxarray);
PyErr_SetString(PyExc_TypeError,
"error parsing width and height values from list: "
"[x, y, w, h], not numbers or below zero");
return -1;
}
/* verts will be added later */
}
return 0;
}
static void boxPack_ToPyObject(PyObject *value, boxPack **boxarray)
{
int len, i;
PyObject *list_item;
boxPack *box;
len= PyList_Size(value);
for(i= 0; i < len; i++) {
box= (*boxarray)+i;
list_item= PyList_GET_ITEM(value, box->index);
PyList_SET_ITEM(list_item, 0, PyFloat_FromDouble(box->x));
PyList_SET_ITEM(list_item, 1, PyFloat_FromDouble(box->y));
}
MEM_freeN(*boxarray);
}
PyDoc_STRVAR(M_Geometry_box_pack_2d_doc,
".. function:: box_pack_2d(boxes)\n"
"\n"
" Returns the normal of the 3D tri or quad.\n"
"\n"
" :arg boxes: list of boxes, each box is a list where the first 4 items are [x, y, width, height, ...] other items are ignored.\n"
" :type boxes: list\n"
" :return: the width and height of the packed bounding box\n"
" :rtype: tuple, pair of floats\n"
);
static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlist)
{
float tot_width= 0.0f, tot_height= 0.0f;
int len;
PyObject *ret;
if(!PyList_Check(boxlist)) {
PyErr_SetString(PyExc_TypeError,
"expected a list of boxes [[x, y, w, h], ... ]");
return NULL;
}
len= PyList_GET_SIZE(boxlist);
if (len) {
boxPack *boxarray= NULL;
if(boxPack_FromPyObject(boxlist, &boxarray) == -1) {
return NULL; /* exception set */
}
/* Non Python function */
boxPack2D(boxarray, len, &tot_width, &tot_height);
boxPack_ToPyObject(boxlist, &boxarray);
}
ret= PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(tot_width));
PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(tot_width));
return ret;
}
#endif /* MATH_STANDALONE */
static PyMethodDef M_Geometry_methods[]= {
{"intersect_ray_tri", (PyCFunction) M_Geometry_intersect_ray_tri, METH_VARARGS, M_Geometry_intersect_ray_tri_doc},
{"intersect_point_line", (PyCFunction) M_Geometry_intersect_point_line, METH_VARARGS, M_Geometry_intersect_point_line_doc},
{"intersect_point_tri_2d", (PyCFunction) M_Geometry_intersect_point_tri_2d, METH_VARARGS, M_Geometry_intersect_point_tri_2d_doc},
{"intersect_point_quad_2d", (PyCFunction) M_Geometry_intersect_point_quad_2d, METH_VARARGS, M_Geometry_intersect_point_quad_2d_doc},
{"intersect_line_line", (PyCFunction) M_Geometry_intersect_line_line, METH_VARARGS, M_Geometry_intersect_line_line_doc},
{"intersect_line_line_2d", (PyCFunction) M_Geometry_intersect_line_line_2d, METH_VARARGS, M_Geometry_intersect_line_line_2d_doc},
{"intersect_line_plane", (PyCFunction) M_Geometry_intersect_line_plane, METH_VARARGS, M_Geometry_intersect_line_plane_doc},
{"intersect_line_sphere", (PyCFunction) M_Geometry_intersect_line_sphere, METH_VARARGS, M_Geometry_intersect_line_sphere_doc},
{"intersect_line_sphere_2d", (PyCFunction) M_Geometry_intersect_line_sphere_2d, METH_VARARGS, M_Geometry_intersect_line_sphere_2d_doc},
{"area_tri", (PyCFunction) M_Geometry_area_tri, METH_VARARGS, M_Geometry_area_tri_doc},
{"normal", (PyCFunction) M_Geometry_normal, METH_VARARGS, M_Geometry_normal_doc},
{"barycentric_transform", (PyCFunction) M_Geometry_barycentric_transform, METH_VARARGS, M_Geometry_barycentric_transform_doc},
#ifndef MATH_STANDALONE
{"interpolate_bezier", (PyCFunction) M_Geometry_interpolate_bezier, METH_VARARGS, M_Geometry_interpolate_bezier_doc},
{"tesselate_polygon", (PyCFunction) M_Geometry_tesselate_polygon, METH_O, M_Geometry_tesselate_polygon_doc},
{"box_pack_2d", (PyCFunction) M_Geometry_box_pack_2d, METH_O, M_Geometry_box_pack_2d_doc},
#endif
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef M_Geometry_module_def= {
PyModuleDef_HEAD_INIT,
"mathutils.geometry", /* m_name */
M_Geometry_doc, /* m_doc */
0, /* m_size */
M_Geometry_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
/*----------------------------MODULE INIT-------------------------*/
PyMODINIT_FUNC PyInit_mathutils_geometry(void)
{
PyObject *submodule= PyModule_Create(&M_Geometry_module_def);
return submodule;
}

View File

@@ -0,0 +1,43 @@
/*
* $Id: mathutils_geometry.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/generic/mathutils_geometry.h
* \ingroup pygen
*/
/*Include this file for access to vector, quat, matrix, euler, etc...*/
#ifndef MATHUTILS_GEOMETRY_H
#define MATHUTILS_GEOMETRY_H
#include "mathutils.h"
PyMODINIT_FUNC PyInit_mathutils_geometry(void);
#endif /* MATHUTILS_GEOMETRY_H */