svn merge -r38400:38500 https://svn.blender.org/svnroot/bf-blender/trunk/blender
This commit is contained in:
52
source/blender/python/mathutils/CMakeLists.txt
Normal file
52
source/blender/python/mathutils/CMakeLists.txt
Normal 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}")
|
||||
384
source/blender/python/mathutils/mathutils.c
Normal file
384
source/blender/python/mathutils/mathutils.c
Normal 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;
|
||||
}
|
||||
111
source/blender/python/mathutils/mathutils.h
Normal file
111
source/blender/python/mathutils/mathutils.h
Normal 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 */
|
||||
870
source/blender/python/mathutils/mathutils_Color.c
Normal file
870
source/blender/python/mathutils/mathutils_Color.c
Normal 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;
|
||||
}
|
||||
55
source/blender/python/mathutils/mathutils_Color.h
Normal file
55
source/blender/python/mathutils/mathutils_Color.h
Normal 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 */
|
||||
721
source/blender/python/mathutils/mathutils_Euler.c
Normal file
721
source/blender/python/mathutils/mathutils_Euler.c
Normal 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;
|
||||
}
|
||||
60
source/blender/python/mathutils/mathutils_Euler.h
Normal file
60
source/blender/python/mathutils/mathutils_Euler.h
Normal 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 */
|
||||
2035
source/blender/python/mathutils/mathutils_Matrix.c
Normal file
2035
source/blender/python/mathutils/mathutils_Matrix.c
Normal 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;
|
||||
}
|
||||
63
source/blender/python/mathutils/mathutils_Matrix.h
Normal file
63
source/blender/python/mathutils/mathutils_Matrix.h
Normal 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 */
|
||||
1164
source/blender/python/mathutils/mathutils_Quaternion.c
Normal file
1164
source/blender/python/mathutils/mathutils_Quaternion.c
Normal 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;
|
||||
}
|
||||
|
||||
55
source/blender/python/mathutils/mathutils_Quaternion.h
Normal file
55
source/blender/python/mathutils/mathutils_Quaternion.h
Normal 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 */
|
||||
2410
source/blender/python/mathutils/mathutils_Vector.c
Normal file
2410
source/blender/python/mathutils/mathutils_Vector.c
Normal 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;
|
||||
}
|
||||
52
source/blender/python/mathutils/mathutils_Vector.h
Normal file
52
source/blender/python/mathutils/mathutils_Vector.h
Normal 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 */
|
||||
1135
source/blender/python/mathutils/mathutils_geometry.c
Normal file
1135
source/blender/python/mathutils/mathutils_geometry.c
Normal 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;
|
||||
}
|
||||
43
source/blender/python/mathutils/mathutils_geometry.h
Normal file
43
source/blender/python/mathutils/mathutils_geometry.h
Normal 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 */
|
||||
Reference in New Issue
Block a user