Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-01-25 12:44:04 +0300
committerCampbell Barton <ideasman42@gmail.com>2010-01-25 12:44:04 +0300
commit0a0f4c9d81cfa2a4b4a9999e1dc976bc417d7d54 (patch)
tree367f259b695955a514530d125ab495344724eafb /source/blender/python/generic
parenteed13d859b67185996569178ede9241a5695f215 (diff)
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac) - Mathutils.AngleBetweenVecs --> vector.angle(other) - Mathutils.ProjectVecs --> vector.project(other) - Mathutils.DifferenceQuats --> quat.difference(other) - Mathutils.Slerp --> quat.slerp(other, fac) - Mathutils.Rand: removed, use pythons random module - Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args - Matrix.scalePart --> Matrix.scale_part - Matrix.translationPart --> Matrix.translation_part - Matrix.rotationPart --> Matrix.rotation_part - toMatrix --> to_matrix - toEuler --> to_euler - toQuat --> to_quat - Vector.toTrackQuat --> Vector.to_track_quat
Diffstat (limited to 'source/blender/python/generic')
-rw-r--r--source/blender/python/generic/Geometry.c357
-rw-r--r--source/blender/python/generic/Mathutils.c842
-rw-r--r--source/blender/python/generic/euler.c90
-rw-r--r--source/blender/python/generic/matrix.c200
-rw-r--r--source/blender/python/generic/quat.c464
-rw-r--r--source/blender/python/generic/vector.c446
6 files changed, 1322 insertions, 1077 deletions
diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c
index 579c9d987cf..0dfddeee348 100644
--- a/source/blender/python/generic/Geometry.c
+++ b/source/blender/python/generic/Geometry.c
@@ -47,19 +47,14 @@
#define SWAP_FLOAT(a,b,tmp) tmp=a; a=b; b=tmp
#define eps 0.000001
-/*-- forward declarations -- */
-static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq );
-static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_BarycentricTransform( PyObject * self, PyObject * args );
-
/*-------------------------DOC STRINGS ---------------------------*/
static char M_Geometry_doc[] = "The Blender Geometry module\n\n";
+static char M_Geometry_Intersect_doc[] = "(v1, v2, v3, ray, orig, clip=1) - returns the intersection between a ray and a triangle, if possible, returns None otherwise";
+static char M_Geometry_TriangleArea_doc[] = "(v1, v2, v3) - returns the area size of the 2D or 3D triangle defined";
+static char M_Geometry_TriangleNormal_doc[] = "(v1, v2, v3) - returns the normal of the 3D triangle defined";
+static char M_Geometry_QuadNormal_doc[] = "(v1, v2, v3, v4) - returns the normal of the 3D quad defined";
+static char M_Geometry_LineIntersect_doc[] = "(v1, v2, v3, v4) - returns a tuple with the points on each line respectively closest to the other";
static char M_Geometry_PolyFill_doc[] = "(veclist_list) - takes a list of polylines (each point a vector) and returns the point indicies for a polyline filled with triangles";
static char M_Geometry_LineIntersect2D_doc[] = "(lineA_p1, lineA_p2, lineB_p1, lineB_p2) - takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None";
static char M_Geometry_ClosestPointOnLine_doc[] = "(pt, line_p1, line_p2) - takes a point and a line and returns a (Vector, float) for the point on the line, and the bool so you can know if the point was between the 2 points";
@@ -67,40 +62,280 @@ static char M_Geometry_PointInTriangle2D_doc[] = "(pt, tri_p1, tri_p2, tri_p3) -
static char M_Geometry_PointInQuad2D_doc[] = "(pt, quad_p1, quad_p2, quad_p3, quad_p4) - takes 5 vectors, one is the point and the next 4 define the quad, only the x and y are used from the vectors";
static char M_Geometry_BoxPack2D_doc[] = "";
static char M_Geometry_BezierInterp_doc[] = "";
-/*-----------------------METHOD DEFINITIONS ----------------------*/
-struct PyMethodDef M_Geometry_methods[] = {
- {"PolyFill", ( PyCFunction ) M_Geometry_PolyFill, METH_O, M_Geometry_PolyFill_doc},
- {"LineIntersect2D", ( PyCFunction ) M_Geometry_LineIntersect2D, METH_VARARGS, M_Geometry_LineIntersect2D_doc},
- {"ClosestPointOnLine", ( PyCFunction ) M_Geometry_ClosestPointOnLine, METH_VARARGS, M_Geometry_ClosestPointOnLine_doc},
- {"PointInTriangle2D", ( PyCFunction ) M_Geometry_PointInTriangle2D, METH_VARARGS, M_Geometry_PointInTriangle2D_doc},
- {"PointInQuad2D", ( PyCFunction ) M_Geometry_PointInQuad2D, METH_VARARGS, M_Geometry_PointInQuad2D_doc},
- {"BoxPack2D", ( PyCFunction ) M_Geometry_BoxPack2D, METH_O, M_Geometry_BoxPack2D_doc},
- {"BezierInterp", ( PyCFunction ) M_Geometry_BezierInterp, METH_VARARGS, M_Geometry_BezierInterp_doc},
- {"BarycentricTransform", ( PyCFunction ) M_Geometry_BarycentricTransform, METH_VARARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-static struct PyModuleDef M_Geometry_module_def = {
- PyModuleDef_HEAD_INIT,
- "Geometry", /* m_name */
- M_Geometry_doc, /* m_doc */
- 0, /* m_size */
- M_Geometry_methods, /* m_methods */
- 0, /* m_reload */
- 0, /* m_traverse */
- 0, /* m_clear */
- 0, /* m_free */
-};
+//---------------------------------INTERSECTION FUNCTIONS--------------------
+//----------------------------------Mathutils.Intersect() -------------------
+static PyObject *M_Geometry_Intersect( PyObject * 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;
-/*----------------------------MODULE INIT-------------------------*/
-PyObject *Geometry_Init(void)
+ if(!PyArg_ParseTuple(args, "O!O!O!O!O!|i", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off , &clip)) {
+ PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
+ return NULL;
+ }
+ if(vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
+ PyErr_SetString( PyExc_TypeError, "only 3D vectors for all parameters\n");
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(ray) || !BaseMath_ReadCallback(ray_off))
+ 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.000001 && det < 0.000001) {
+ 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);
+}
+//----------------------------------Mathutils.LineIntersect() -------------------
+/* Line-Line intersection using algorithm from mathworld.wolfram.com */
+static PyObject *M_Geometry_LineIntersect( PyObject * self, PyObject * args )
{
- PyObject *submodule;
-
- submodule = PyModule_Create(&M_Geometry_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), M_Geometry_module_def.m_name, submodule);
-
- return (submodule);
+ 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!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
+ PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+ return NULL;
+ }
+ if( vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) {
+ PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
+ 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_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW, NULL) );
+ PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW, NULL) );
+ return tuple;
+ }
+ }
+ else {
+ PyErr_SetString( PyExc_TypeError, "2D/3D vectors only\n" );
+ return NULL;
+ }
+}
+
+
+
+//---------------------------------NORMALS FUNCTIONS--------------------
+//----------------------------------Mathutils.QuadNormal() -------------------
+static PyObject *M_Geometry_QuadNormal( PyObject * self, PyObject * args )
+{
+ VectorObject *vec1;
+ VectorObject *vec2;
+ VectorObject *vec3;
+ VectorObject *vec4;
+ float v1[3], v2[3], v3[3], v4[3], e1[3], e2[3], n1[3], n2[3];
+
+ if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
+ PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
+ return NULL;
+ }
+ if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
+ PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
+ return NULL;
+ }
+ if( vec1->size != 3 ) {
+ PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
+ return NULL;
+
+ VECCOPY(v1, vec1->vec);
+ VECCOPY(v2, vec2->vec);
+ VECCOPY(v3, vec3->vec);
+ VECCOPY(v4, vec4->vec);
+
+ /* find vectors for two edges sharing v2 */
+ sub_v3_v3v3(e1, v1, v2);
+ sub_v3_v3v3(e2, v3, v2);
+
+ cross_v3_v3v3(n1, e2, e1);
+ normalize_v3(n1);
+
+ /* find vectors for two edges sharing v4 */
+ sub_v3_v3v3(e1, v3, v4);
+ sub_v3_v3v3(e2, v1, v4);
+
+ cross_v3_v3v3(n2, e2, e1);
+ normalize_v3(n2);
+
+ /* adding and averaging the normals of both triangles */
+ add_v3_v3v3(n1, n2, n1);
+ normalize_v3(n1);
+
+ return newVectorObject(n1, 3, Py_NEW, NULL);
+}
+
+//----------------------------Mathutils.TriangleNormal() -------------------
+static PyObject *M_Geometry_TriangleNormal( PyObject * self, PyObject * args )
+{
+ VectorObject *vec1, *vec2, *vec3;
+ float v1[3], v2[3], v3[3], e1[3], e2[3], n[3];
+
+ if( !PyArg_ParseTuple( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3 ) ) {
+ PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
+ return NULL;
+ }
+ if( vec1->size != vec2->size || vec1->size != vec3->size ) {
+ PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
+ return NULL;
+ }
+ if( vec1->size != 3 ) {
+ PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
+ return NULL;
+
+ VECCOPY(v1, vec1->vec);
+ VECCOPY(v2, vec2->vec);
+ VECCOPY(v3, vec3->vec);
+
+ /* find vectors for two edges sharing v2 */
+ sub_v3_v3v3(e1, v1, v2);
+ sub_v3_v3v3(e2, v3, v2);
+
+ cross_v3_v3v3(n, e2, e1);
+ normalize_v3(n);
+
+ return newVectorObject(n, 3, Py_NEW, NULL);
+}
+
+//--------------------------------- AREA FUNCTIONS--------------------
+//----------------------------------Mathutils.TriangleArea() -------------------
+static PyObject *M_Geometry_TriangleArea( PyObject * self, PyObject * args )
+{
+ VectorObject *vec1, *vec2, *vec3;
+ float v1[3], v2[3], v3[3];
+
+ if( !PyArg_ParseTuple
+ ( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
+ , &vector_Type, &vec3 ) ) {
+ PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n");
+ return NULL;
+ }
+ if( vec1->size != vec2->size || vec1->size != vec3->size ) {
+ PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
+ return NULL;
+
+ if (vec1->size == 3) {
+ VECCOPY(v1, vec1->vec);
+ VECCOPY(v2, vec2->vec);
+ VECCOPY(v3, vec3->vec);
+
+ return PyFloat_FromDouble( area_tri_v3(v1, v2, v3) );
+ }
+ else if (vec1->size == 2) {
+ v1[0] = vec1->vec[0];
+ v1[1] = vec1->vec[1];
+
+ v2[0] = vec2->vec[0];
+ v2[1] = vec2->vec[1];
+
+ v3[0] = vec3->vec[0];
+ v3[1] = vec3->vec[1];
+
+ return PyFloat_FromDouble( area_tri_v2(v1, v2, v3) );
+ }
+ else {
+ PyErr_SetString( PyExc_TypeError, "only 2D,3D vectors are supported\n" );
+ return NULL;
+ }
}
/*----------------------------------Geometry.PolyFill() -------------------*/
@@ -569,3 +804,43 @@ static PyObject *M_Geometry_BarycentricTransform(PyObject * self, PyObject * arg
return newVectorObject(vec, 3, Py_NEW, NULL);
}
+
+struct PyMethodDef M_Geometry_methods[] = {
+ {"Intersect", ( PyCFunction ) M_Geometry_Intersect, METH_VARARGS, M_Geometry_Intersect_doc},
+ {"TriangleArea", ( PyCFunction ) M_Geometry_TriangleArea, METH_VARARGS, M_Geometry_TriangleArea_doc},
+ {"TriangleNormal", ( PyCFunction ) M_Geometry_TriangleNormal, METH_VARARGS, M_Geometry_TriangleNormal_doc},
+ {"QuadNormal", ( PyCFunction ) M_Geometry_QuadNormal, METH_VARARGS, M_Geometry_QuadNormal_doc},
+ {"LineIntersect", ( PyCFunction ) M_Geometry_LineIntersect, METH_VARARGS, M_Geometry_LineIntersect_doc},
+ {"PolyFill", ( PyCFunction ) M_Geometry_PolyFill, METH_O, M_Geometry_PolyFill_doc},
+ {"LineIntersect2D", ( PyCFunction ) M_Geometry_LineIntersect2D, METH_VARARGS, M_Geometry_LineIntersect2D_doc},
+ {"ClosestPointOnLine", ( PyCFunction ) M_Geometry_ClosestPointOnLine, METH_VARARGS, M_Geometry_ClosestPointOnLine_doc},
+ {"PointInTriangle2D", ( PyCFunction ) M_Geometry_PointInTriangle2D, METH_VARARGS, M_Geometry_PointInTriangle2D_doc},
+ {"PointInQuad2D", ( PyCFunction ) M_Geometry_PointInQuad2D, METH_VARARGS, M_Geometry_PointInQuad2D_doc},
+ {"BoxPack2D", ( PyCFunction ) M_Geometry_BoxPack2D, METH_O, M_Geometry_BoxPack2D_doc},
+ {"BezierInterp", ( PyCFunction ) M_Geometry_BezierInterp, METH_VARARGS, M_Geometry_BezierInterp_doc},
+ {"BarycentricTransform", ( PyCFunction ) M_Geometry_BarycentricTransform, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyModuleDef M_Geometry_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "Geometry", /* m_name */
+ M_Geometry_doc, /* m_doc */
+ 0, /* m_size */
+ M_Geometry_methods, /* m_methods */
+ 0, /* m_reload */
+ 0, /* m_traverse */
+ 0, /* m_clear */
+ 0, /* m_free */
+};
+
+/*----------------------------MODULE INIT-------------------------*/
+PyObject *Geometry_Init(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&M_Geometry_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), M_Geometry_module_def.m_name, submodule);
+
+ return (submodule);
+}
diff --git a/source/blender/python/generic/Mathutils.c b/source/blender/python/generic/Mathutils.c
index b44d6450145..2e4b6dbb490 100644
--- a/source/blender/python/generic/Mathutils.c
+++ b/source/blender/python/generic/Mathutils.c
@@ -27,114 +27,34 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/* Note: Changes to Mathutils since 2.4x
+ * use radians rather then degrees
+ * - Mathutils.MidpointVecs --> vector.lerp(other, fac)
+ * - Mathutils.AngleBetweenVecs --> vector.angle(other)
+ * - Mathutils.ProjectVecs --> vector.project(other)
+ * - Mathutils.DifferenceQuats --> quat.difference(other)
+ * - Mathutils.Slerp --> quat.slerp(other, fac)
+ * - Mathutils.Rand: removed, use pythons random module
+ * - Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
+ * - Matrix.scalePart --> Matrix.scale_part
+ * - Matrix.translationPart --> Matrix.translation_part
+ * - Matrix.rotationPart --> Matrix.rotation_part
+ * - toMatrix --> to_matrix
+ * - toEuler --> to_euler
+ * - toQuat --> to_quat
+ * - Vector.toTrackQuat --> Vector.to_track_quat
+ *
+ * Moved to Geometry module: Intersect, TriangleArea, TriangleNormal, QuadNormal, LineIntersect
+ */
+
#include "Mathutils.h"
#include "BLI_math.h"
#include "PIL_time.h"
-#include "BLI_rand.h"
#include "BKE_utildefines.h"
//-------------------------DOC STRINGS ---------------------------
-static char M_Mathutils_doc[] = "The Blender Mathutils module\n\n";
-static char M_Mathutils_Rand_doc[] = "() - return a random number";
-static char M_Mathutils_AngleBetweenVecs_doc[] = "() - returns the angle between two vectors in degrees";
-static char M_Mathutils_MidpointVecs_doc[] = "() - return the vector to the midpoint between two vectors";
-static char M_Mathutils_ProjectVecs_doc[] = "() - returns the projection vector from the projection of vecA onto vecB";
-static char M_Mathutils_RotationMatrix_doc[] = "() - construct a rotation matrix from an angle and axis of rotation";
-static char M_Mathutils_ScaleMatrix_doc[] = "() - construct a scaling matrix from a scaling factor";
-static char M_Mathutils_OrthoProjectionMatrix_doc[] = "() - construct a orthographic projection matrix from a selected plane";
-static char M_Mathutils_ShearMatrix_doc[] = "() - construct a shearing matrix from a plane of shear and a shear factor";
-static char M_Mathutils_TranslationMatrix_doc[] = "(vec) - create a translation matrix from a vector";
-static char M_Mathutils_Slerp_doc[] = "() - returns the interpolation between two quaternions";
-static char M_Mathutils_DifferenceQuats_doc[] = "() - return the angular displacment difference between two quats";
-static char M_Mathutils_Intersect_doc[] = "(v1, v2, v3, ray, orig, clip=1) - returns the intersection between a ray and a triangle, if possible, returns None otherwise";
-static char M_Mathutils_TriangleArea_doc[] = "(v1, v2, v3) - returns the area size of the 2D or 3D triangle defined";
-static char M_Mathutils_TriangleNormal_doc[] = "(v1, v2, v3) - returns the normal of the 3D triangle defined";
-static char M_Mathutils_QuadNormal_doc[] = "(v1, v2, v3, v4) - returns the normal of the 3D quad defined";
-static char M_Mathutils_LineIntersect_doc[] = "(v1, v2, v3, v4) - returns a tuple with the points on each line respectively closest to the other";
-//-----------------------METHOD DEFINITIONS ----------------------
-
-static PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * value);
-static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args );
-static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args );
-static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args );
-static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args );
-static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args );
-
-struct PyMethodDef M_Mathutils_methods[] = {
- {"Rand", (PyCFunction) M_Mathutils_Rand, METH_VARARGS, M_Mathutils_Rand_doc},
- {"AngleBetweenVecs", (PyCFunction) M_Mathutils_AngleBetweenVecs, METH_VARARGS, M_Mathutils_AngleBetweenVecs_doc},
- {"MidpointVecs", (PyCFunction) M_Mathutils_MidpointVecs, METH_VARARGS, M_Mathutils_MidpointVecs_doc},
- {"ProjectVecs", (PyCFunction) M_Mathutils_ProjectVecs, METH_VARARGS, M_Mathutils_ProjectVecs_doc},
- {"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc},
- {"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc},
- {"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc},
- {"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc},
- {"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc},
- {"DifferenceQuats", (PyCFunction) M_Mathutils_DifferenceQuats, METH_VARARGS,M_Mathutils_DifferenceQuats_doc},
- {"Slerp", (PyCFunction) M_Mathutils_Slerp, METH_VARARGS, M_Mathutils_Slerp_doc},
- {"Intersect", ( PyCFunction ) M_Mathutils_Intersect, METH_VARARGS, M_Mathutils_Intersect_doc},
- {"TriangleArea", ( PyCFunction ) M_Mathutils_TriangleArea, METH_VARARGS, M_Mathutils_TriangleArea_doc},
- {"TriangleNormal", ( PyCFunction ) M_Mathutils_TriangleNormal, METH_VARARGS, M_Mathutils_TriangleNormal_doc},
- {"QuadNormal", ( PyCFunction ) M_Mathutils_QuadNormal, METH_VARARGS, M_Mathutils_QuadNormal_doc},
- {"LineIntersect", ( PyCFunction ) M_Mathutils_LineIntersect, METH_VARARGS, M_Mathutils_LineIntersect_doc},
- {NULL, NULL, 0, NULL}
-};
-
-/*----------------------------MODULE INIT-------------------------*/
-/* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */
-
-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 */
- 0, /* m_reload */
- 0, /* m_traverse */
- 0, /* m_clear */
- 0, /* m_free */
-};
-
-PyObject *Mathutils_Init(void)
-{
- PyObject *submodule;
-
- //seed the generator for the rand function
- BLI_srand((unsigned int) (PIL_check_seconds_timer() * 0x7FFFFFFF));
-
- 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;
-
- submodule = PyModule_Create(&M_Mathutils_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), M_Mathutils_module_def.m_name, submodule);
-
- /* 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 );
-
- mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
-
- return (submodule);
-}
+static char M_Mathutils_doc[] = "This module provides access to matrices, eulers, quaternions and vectors.";
//-----------------------------METHODS----------------------------
//-----------------quat_rotation (internal)-----------
@@ -204,164 +124,49 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
}
-//----------------------------------Mathutils.Rand() --------------------
-//returns a random number between a high and low value
-static PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args)
-{
- float high, low, range;
- double drand;
- //initializers
- high = 1.0;
- low = 0.0;
-
- if(!PyArg_ParseTuple(args, "|ff", &low, &high)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Rand(): expected nothing or optional (float, float)\n");
- return NULL;
- }
-
- if((high < low) || (high < 0 && low > 0)) {
- PyErr_SetString(PyExc_ValueError, "Mathutils.Rand(): high value should be larger than low value\n");
- return NULL;
- }
- //get the random number 0 - 1
- drand = BLI_drand();
-
- //set it to range
- range = high - low;
- drand = drand * range;
- drand = drand + low;
-
- return PyFloat_FromDouble(drand);
-}
-//----------------------------------VECTOR FUNCTIONS---------------------
-//----------------------------------Mathutils.AngleBetweenVecs() ---------
-//calculates the angle between 2 vectors
-static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
-{
- VectorObject *vec1 = NULL, *vec2 = NULL;
- double dot = 0.0f, angleRads, test_v1 = 0.0f, test_v2 = 0.0f;
- int x, size;
-
- if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
- goto AttributeError1; //not vectors
- if(vec1->size != vec2->size)
- goto AttributeError1; //bad sizes
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
- //since size is the same....
- size = vec1->size;
-
- for(x = 0; x < size; x++) {
- test_v1 += vec1->vec[x] * vec1->vec[x];
- test_v2 += vec2->vec[x] * vec2->vec[x];
- }
- if (!test_v1 || !test_v2){
- goto AttributeError2; //zero-length vector
- }
-
- //dot product
- for(x = 0; x < size; x++) {
- dot += vec1->vec[x] * vec2->vec[x];
- }
- dot /= (sqrt(test_v1) * sqrt(test_v2));
-
- angleRads = (double)saacos(dot);
-
-#ifdef USE_MATHUTILS_DEG
- return PyFloat_FromDouble(angleRads * (180/ Py_PI));
-#else
- return PyFloat_FromDouble(angleRads);
-#endif
-AttributeError1:
- PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n");
- return NULL;
-
-AttributeError2:
- PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): zero length vectors are not acceptable arguments\n");
- return NULL;
-}
-//----------------------------------Mathutils.MidpointVecs() -------------
-//calculates the midpoint between 2 vectors
-static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
-{
- VectorObject *vec1 = NULL, *vec2 = NULL;
- float vec[4];
- int x;
-
- if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
- return NULL;
- }
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
- for(x = 0; x < vec1->size; x++) {
- vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]);
- }
- return newVectorObject(vec, vec1->size, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.ProjectVecs() -------------
-//projects vector 1 onto vector 2
-static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
-{
- VectorObject *vec1 = NULL, *vec2 = NULL;
- float vec[4];
- double dot = 0.0f, dot2 = 0.0f;
- int x, size;
-
- if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
- return NULL;
- }
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
-
- //since they are the same size...
- size = vec1->size;
-
- //get dot products
- for(x = 0; x < size; x++) {
- dot += vec1->vec[x] * vec2->vec[x];
- dot2 += vec2->vec[x] * vec2->vec[x];
- }
- //projection
- dot /= dot2;
- for(x = 0; x < size; x++) {
- vec[x] = (float)(dot * vec2->vec[x]);
- }
- return newVectorObject(vec, size, Py_NEW, NULL);
-}
//----------------------------------MATRIX FUNCTIONS--------------------
//----------------------------------Mathutils.RotationMatrix() ----------
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
-//creates a rotation matrix
+static char M_Mathutils_RotationMatrix_doc[] =
+".. function:: RotationMatrix(angle, size, axis)\n"
+"\n"
+" Create a matrix representing a rotation.\n"
+"\n"
+" :arg angle: The angle of rotation desired.\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 (optional when size is 2).\n"
+" :type axis: string or vector\n"
+" :return: A new rotation matrix.\n"
+" :rtype: Matrix\n";
+
static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
{
- VectorObject *vec = NULL;
- char *axis = NULL;
+ VectorObject *vec= NULL;
+ char *axis= NULL;
int matSize;
float angle = 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, "fi|sO!", &angle, &matSize, &axis, &vector_Type, &vec)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): expected float int and optional string and vector\n");
+ if(!PyArg_ParseTuple(args, "fi|O", &angle, &matSize, &vec)) {
+ PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(angle, size, axis): expected float int and a string or vector\n");
return NULL;
}
+ if(vec && !VectorObject_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_TypeError, "Mathutils.RotationMatrix(): 3rd argument axis value must be a 3D vector or a string in 'X', 'Y', 'Z'\n");
+ return NULL;
+ }
+ else {
+ /* use the string */
+ vec= NULL;
+ }
+ }
+
#ifdef USE_MATHUTILS_DEG
/* Clamp to -360:360 */
while (angle<-360.0f)
@@ -379,23 +184,17 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
return NULL;
}
- if(matSize == 2 && (axis != NULL || vec != NULL)) {
+ if(matSize == 2 && (vec != NULL)) {
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n");
return NULL;
}
- if((matSize == 3 || matSize == 4) && axis == NULL) {
+ if((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) {
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n");
return NULL;
}
- if(axis) {
- if(((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) && vec == NULL) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please define the arbitrary axis of rotation\n");
- return NULL;
- }
- }
if(vec) {
if(vec->size != 3) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
+ PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the vector axis must be a 3D vector\n");
return NULL;
}
@@ -414,35 +213,32 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
mat[1] = (float) sin (angle);
mat[2] = -((float) sin(angle));
mat[3] = (float) cos(angle);
- } else if((strcmp(axis, "x") == 0) || (strcmp(axis, "X") == 0)) {
+ } 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) || (strcmp(axis, "Y") == 0)) {
+ } 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) || (strcmp(axis, "Z") == 0)) {
+ } 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 if((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) {
- //arbitrary rotation
- axis_angle_to_mat3( (float (*)[3])mat,vec->vec, angle);
-
} else {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): unrecognizable axis of rotation type - expected x,y,z or r\n");
- return NULL;
+ /* check for valid vector/axis above */
+ axis_angle_to_mat3( (float (*)[3])mat,vec->vec, angle);
}
+
if(matSize == 4) {
//resize matrix
mat[10] = mat[8];
@@ -457,8 +253,17 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
//pass to matrix creation
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
}
-//----------------------------------Mathutils.TranslationMatrix() -------
-//creates a translation matrix
+
+static char M_Mathutils_TranslationMatrix_doc[] =
+".. function:: TranslationMatrix(vector)\n"
+"\n"
+" Create a matrix representing a translation.\n"
+"\n"
+" :arg vector: The translation vector.\n"
+" :type vector: Vector\n"
+" :return: An identity matrix with a translation.\n"
+" :rtype: Matrix\n";
+
static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec)
{
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
@@ -486,7 +291,20 @@ static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * v
}
//----------------------------------Mathutils.ScaleMatrix() -------------
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
-//creates a scaling matrix
+static char M_Mathutils_ScaleMatrix_doc[] =
+".. function:: ScaleMatrix(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: Vector\n"
+" :return: A new scale matrix.\n"
+" :rtype: Matrix\n";
+
static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
{
VectorObject *vec = NULL;
@@ -564,7 +382,19 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
}
//----------------------------------Mathutils.OrthoProjectionMatrix() ---
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
-//creates an ortho projection matrix
+static char M_Mathutils_OrthoProjectionMatrix_doc[] =
+".. function:: OrthoProjectionMatrix(plane, size, axis)\n"
+"\n"
+" Create a matrix to represent an orthographic projection.\n"
+"\n"
+" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ', 'R'], where a single axis is for a 2D matrix and 'R' requires axis is given.\n"
+" :type plane: string\n"
+" :arg size: The size of the projection matrix to construct [2, 4].\n"
+" :type size: int\n"
+" :arg axis: Arbitrary perpendicular plane vector.\n"
+" :type axis: vector (optional)\n"
+" :return: A new projection matrix.\n"
+" :rtype: Matrix\n";
static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
{
VectorObject *vec = NULL;
@@ -593,30 +423,21 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
}
if(vec == NULL) { //ortho projection onto cardinal plane
- if(((strcmp(plane, "x") == 0)
- || (strcmp(plane, "X") == 0)) && matSize == 2) {
+ if((strcmp(plane, "X") == 0) && matSize == 2) {
mat[0] = 1.0f;
- } else if(((strcmp(plane, "y") == 0)
- || (strcmp(plane, "Y") == 0))
- && matSize == 2) {
+ } else if((strcmp(plane, "Y") == 0) && matSize == 2) {
mat[3] = 1.0f;
- } else if(((strcmp(plane, "xy") == 0)
- || (strcmp(plane, "XY") == 0))
- && matSize > 2) {
+ } else if((strcmp(plane, "XY") == 0) && matSize > 2) {
mat[0] = 1.0f;
mat[4] = 1.0f;
- } else if(((strcmp(plane, "xz") == 0)
- || (strcmp(plane, "XZ") == 0))
- && matSize > 2) {
+ } else if((strcmp(plane, "XZ") == 0) && matSize > 2) {
mat[0] = 1.0f;
mat[8] = 1.0f;
- } else if(((strcmp(plane, "yz") == 0)
- || (strcmp(plane, "YZ") == 0))
- && matSize > 2) {
+ } else if((strcmp(plane, "YZ") == 0) && matSize > 2) {
mat[4] = 1.0f;
mat[8] = 1.0f;
} else {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: x, y, xy, xz, yz\n");
+ PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: X, Y, XY, XZ, YZ\n");
return NULL;
}
} else { //arbitrary plane
@@ -628,15 +449,12 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
for(x = 0; x < vec->size; x++) {
vec->vec[x] /= norm;
}
- if(((strcmp(plane, "r") == 0)
- || (strcmp(plane, "R") == 0)) && matSize == 2) {
+ if((strcmp(plane, "R") == 0) && matSize == 2) {
mat[0] = 1 - (vec->vec[0] * vec->vec[0]);
mat[1] = -(vec->vec[0] * vec->vec[1]);
mat[2] = -(vec->vec[0] * vec->vec[1]);
mat[3] = 1 - (vec->vec[1] * vec->vec[1]);
- } else if(((strcmp(plane, "r") == 0)
- || (strcmp(plane, "R") == 0))
- && matSize > 2) {
+ } else if((strcmp(plane, "R") == 0) && matSize > 2) {
mat[0] = 1 - (vec->vec[0] * vec->vec[0]);
mat[1] = -(vec->vec[0] * vec->vec[1]);
mat[2] = -(vec->vec[0] * vec->vec[2]);
@@ -665,8 +483,21 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
//pass to matrix creation
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
}
-//----------------------------------Mathutils.ShearMatrix() -------------
-//creates a shear matrix
+
+static char M_Mathutils_ShearMatrix_doc[] =
+".. function:: ShearMatrix(plane, factor, size)\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'], where a single axis is for a 2D matrix.\n"
+" :type plane: string\n"
+" :arg factor: The factor of shear to apply.\n"
+" :type factor: float\n"
+" :arg size: The size of the shear matrix to construct [2, 4].\n"
+" :type size: int\n"
+" :return: A new shear matrix.\n"
+" :rtype: Matrix\n";
+
static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
{
int matSize;
@@ -684,31 +515,27 @@ static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
return NULL;
}
- if(((strcmp(plane, "x") == 0) || (strcmp(plane, "X") == 0))
+ if((strcmp(plane, "X") == 0)
&& matSize == 2) {
mat[0] = 1.0f;
mat[2] = factor;
mat[3] = 1.0f;
- } else if(((strcmp(plane, "y") == 0)
- || (strcmp(plane, "Y") == 0)) && matSize == 2) {
+ } else if((strcmp(plane, "Y") == 0) && matSize == 2) {
mat[0] = 1.0f;
mat[1] = factor;
mat[3] = 1.0f;
- } else if(((strcmp(plane, "xy") == 0)
- || (strcmp(plane, "XY") == 0)) && matSize > 2) {
+ } else if((strcmp(plane, "XY") == 0) && matSize > 2) {
mat[0] = 1.0f;
mat[4] = 1.0f;
mat[6] = factor;
mat[7] = factor;
- } else if(((strcmp(plane, "xz") == 0)
- || (strcmp(plane, "XZ") == 0)) && matSize > 2) {
+ } else if((strcmp(plane, "XZ") == 0) && matSize > 2) {
mat[0] = 1.0f;
mat[3] = factor;
mat[4] = 1.0f;
mat[5] = factor;
mat[8] = 1.0f;
- } else if(((strcmp(plane, "yz") == 0)
- || (strcmp(plane, "YZ") == 0)) && matSize > 2) {
+ } else if((strcmp(plane, "YZ") == 0) && matSize > 2) {
mat[0] = 1.0f;
mat[1] = factor;
mat[2] = factor;
@@ -732,375 +559,6 @@ static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
//pass to matrix creation
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
}
-//----------------------------------QUATERNION FUNCTIONS-----------------
-
-//----------------------------------Mathutils.DifferenceQuats() ---------
-//returns the difference between 2 quaternions
-static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
-{
- QuaternionObject *quatU = NULL, *quatV = NULL;
- float quat[4], tempQuat[4];
- double dot = 0.0f;
- int x;
-
- if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
- return NULL;
-
- tempQuat[0] = quatU->quat[0];
- tempQuat[1] = -quatU->quat[1];
- tempQuat[2] = -quatU->quat[2];
- tempQuat[3] = -quatU->quat[3];
-
- dot = sqrt(tempQuat[0] * tempQuat[0] + tempQuat[1] * tempQuat[1] +
- tempQuat[2] * tempQuat[2] + tempQuat[3] * tempQuat[3]);
-
- for(x = 0; x < 4; x++) {
- tempQuat[x] /= (float)(dot * dot);
- }
- mul_qt_qtqt(quat, tempQuat, quatV->quat);
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.Slerp() ------------------
-//attemps to interpolate 2 quaternions and return the result
-static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
-{
- QuaternionObject *quatU = NULL, *quatV = NULL;
- float quat[4], quat_u[4], quat_v[4], param;
- double x, y, dot, sinT, angle, IsinT;
- int z;
-
- if(!PyArg_ParseTuple(args, "O!O!f", &quaternion_Type, &quatU, &quaternion_Type, &quatV, &param)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
- return NULL;
-
- if(param > 1.0f || param < 0.0f) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
- return NULL;
- }
-
- //copy quats
- for(z = 0; z < 4; z++){
- quat_u[z] = quatU->quat[z];
- quat_v[z] = quatV->quat[z];
- }
-
- //dot product
- dot = quat_u[0] * quat_v[0] + quat_u[1] * quat_v[1] +
- quat_u[2] * quat_v[2] + quat_u[3] * quat_v[3];
-
- //if negative negate a quat (shortest arc)
- if(dot < 0.0f) {
- quat_v[0] = -quat_v[0];
- quat_v[1] = -quat_v[1];
- quat_v[2] = -quat_v[2];
- quat_v[3] = -quat_v[3];
- dot = -dot;
- }
- if(dot > .99999f) { //very close
- x = 1.0f - param;
- y = param;
- } else {
- //calculate sin of angle
- sinT = sqrt(1.0f - (dot * dot));
- //calculate angle
- angle = atan2(sinT, dot);
- //caluculate inverse of sin(theta)
- IsinT = 1.0f / sinT;
- x = sin((1.0f - param) * angle) * IsinT;
- y = sin(param * angle) * IsinT;
- }
- //interpolate
- quat[0] = (float)(quat_u[0] * x + quat_v[0] * y);
- quat[1] = (float)(quat_u[1] * x + quat_v[1] * y);
- quat[2] = (float)(quat_u[2] * x + quat_v[2] * y);
- quat[3] = (float)(quat_u[3] * x + quat_v[3] * y);
-
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-//----------------------------------EULER FUNCTIONS----------------------
-//---------------------------------INTERSECTION FUNCTIONS--------------------
-//----------------------------------Mathutils.Intersect() -------------------
-static PyObject *M_Mathutils_Intersect( PyObject * 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", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off , &clip)) {
- PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
- return NULL;
- }
- if(vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
- PyErr_SetString( PyExc_TypeError, "only 3D vectors for all parameters\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(ray) || !BaseMath_ReadCallback(ray_off))
- 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.000001 && det < 0.000001) {
- 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);
-}
-//----------------------------------Mathutils.LineIntersect() -------------------
-/* Line-Line intersection using algorithm from mathworld.wolfram.com */
-static PyObject *M_Mathutils_LineIntersect( PyObject * 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!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
- PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
- return NULL;
- }
- if( vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) {
- PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
- 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_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW, NULL) );
- PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW, NULL) );
- return tuple;
- }
- }
- else {
- PyErr_SetString( PyExc_TypeError, "2D/3D vectors only\n" );
- return NULL;
- }
-}
-
-
-
-//---------------------------------NORMALS FUNCTIONS--------------------
-//----------------------------------Mathutils.QuadNormal() -------------------
-static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
-{
- VectorObject *vec1;
- VectorObject *vec2;
- VectorObject *vec3;
- VectorObject *vec4;
- float v1[3], v2[3], v3[3], v4[3], e1[3], e2[3], n1[3], n2[3];
-
- if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
- PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
- return NULL;
- }
- if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
- PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
- return NULL;
- }
- if( vec1->size != 3 ) {
- PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
- return NULL;
-
- VECCOPY(v1, vec1->vec);
- VECCOPY(v2, vec2->vec);
- VECCOPY(v3, vec3->vec);
- VECCOPY(v4, vec4->vec);
-
- /* find vectors for two edges sharing v2 */
- sub_v3_v3v3(e1, v1, v2);
- sub_v3_v3v3(e2, v3, v2);
-
- cross_v3_v3v3(n1, e2, e1);
- normalize_v3(n1);
-
- /* find vectors for two edges sharing v4 */
- sub_v3_v3v3(e1, v3, v4);
- sub_v3_v3v3(e2, v1, v4);
-
- cross_v3_v3v3(n2, e2, e1);
- normalize_v3(n2);
-
- /* adding and averaging the normals of both triangles */
- add_v3_v3v3(n1, n2, n1);
- normalize_v3(n1);
-
- return newVectorObject(n1, 3, Py_NEW, NULL);
-}
-
-//----------------------------Mathutils.TriangleNormal() -------------------
-static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
-{
- VectorObject *vec1, *vec2, *vec3;
- float v1[3], v2[3], v3[3], e1[3], e2[3], n[3];
-
- if( !PyArg_ParseTuple( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3 ) ) {
- PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
- return NULL;
- }
- if( vec1->size != vec2->size || vec1->size != vec3->size ) {
- PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
- return NULL;
- }
- if( vec1->size != 3 ) {
- PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
- return NULL;
-
- VECCOPY(v1, vec1->vec);
- VECCOPY(v2, vec2->vec);
- VECCOPY(v3, vec3->vec);
-
- /* find vectors for two edges sharing v2 */
- sub_v3_v3v3(e1, v1, v2);
- sub_v3_v3v3(e2, v3, v2);
-
- cross_v3_v3v3(n, e2, e1);
- normalize_v3(n);
-
- return newVectorObject(n, 3, Py_NEW, NULL);
-}
-
-//--------------------------------- AREA FUNCTIONS--------------------
-//----------------------------------Mathutils.TriangleArea() -------------------
-static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
-{
- VectorObject *vec1, *vec2, *vec3;
- float v1[3], v2[3], v3[3];
-
- if( !PyArg_ParseTuple
- ( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
- , &vector_Type, &vec3 ) ) {
- PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n");
- return NULL;
- }
- if( vec1->size != vec2->size || vec1->size != vec3->size ) {
- PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
- return NULL;
-
- if (vec1->size == 3) {
- VECCOPY(v1, vec1->vec);
- VECCOPY(v2, vec2->vec);
- VECCOPY(v3, vec3->vec);
-
- return PyFloat_FromDouble( area_tri_v3(v1, v2, v3) );
- }
- else if (vec1->size == 2) {
- v1[0] = vec1->vec[0];
- v1[1] = vec1->vec[1];
-
- v2[0] = vec2->vec[0];
- v2[1] = vec2->vec[1];
-
- v3[0] = vec3->vec[0];
- v3[1] = vec3->vec[1];
-
- return PyFloat_FromDouble( area_tri_v2(v1, v2, v3) );
- }
- else {
- PyErr_SetString( PyExc_TypeError, "only 2D,3D vectors are supported\n" );
- return NULL;
- }
-}
/* Utility functions */
@@ -1219,3 +677,51 @@ void BaseMathObject_dealloc(BaseMathObject * self)
Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes
}
+/*----------------------------MODULE INIT-------------------------*/
+struct PyMethodDef M_Mathutils_methods[] = {
+ {"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc},
+ {"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc},
+ {"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc},
+ {"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc},
+ {"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc},
+ {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 */
+ 0, /* m_reload */
+ 0, /* m_traverse */
+ 0, /* m_clear */
+ 0, /* m_free */
+};
+
+PyObject *Mathutils_Init(void)
+{
+ PyObject *submodule;
+
+ 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;
+
+ submodule = PyModule_Create(&M_Mathutils_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), M_Mathutils_module_def.m_name, submodule);
+
+ /* 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 );
+
+ mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
+
+ return (submodule);
+}
diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c
index ae7a6783358..b48c45b322f 100644
--- a/source/blender/python/generic/euler.c
+++ b/source/blender/python/generic/euler.c
@@ -33,29 +33,6 @@
#include "BLI_blenlib.h"
-//-------------------------DOC STRINGS ---------------------------
-
-static PyObject *Euler_Zero( EulerObject * self );
-static PyObject *Euler_Unique( EulerObject * self );
-static PyObject *Euler_ToMatrix( EulerObject * self );
-static PyObject *Euler_ToQuat( EulerObject * self );
-static PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
-static PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
-static PyObject *Euler_copy( EulerObject * self, PyObject *args );
-
-//-----------------------METHOD DEFINITIONS ----------------------
-static struct PyMethodDef Euler_methods[] = {
- {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, NULL},
- {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, NULL},
- {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, NULL},
- {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, NULL},
- {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL},
- {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, NULL},
- {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
- {"copy", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
//----------------------------------Mathutils.Euler() -------------------
//makes a new euler for you to play with
static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
@@ -108,6 +85,15 @@ static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwar
//-----------------------------METHODS----------------------------
//----------------------------Euler.toQuat()----------------------
//return a quaternion representation of the euler
+
+static char Euler_ToQuat_doc[] =
+".. method:: to_quat()\n"
+"\n"
+" Return a quaternion representation of the euler.\n"
+"\n"
+" :return: Quaternion representation of the euler.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Euler_ToQuat(EulerObject * self)
{
float quat[4];
@@ -132,6 +118,14 @@ static PyObject *Euler_ToQuat(EulerObject * self)
}
//----------------------------Euler.toMatrix()---------------------
//return a matrix representation of the euler
+static char Euler_ToMatrix_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: Matrix\n";
+
static PyObject *Euler_ToMatrix(EulerObject * self)
{
float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
@@ -156,6 +150,14 @@ static PyObject *Euler_ToMatrix(EulerObject * self)
}
//----------------------------Euler.unique()-----------------------
//sets the x,y,z values to a unique euler rotation
+
+static char Euler_Unique_doc[] =
+".. method:: unique()\n"
+"\n"
+" Calculate a unique rotation for this euler. Avoids gimble lock.\n"
+" :return: an instance of itself\n"
+" :rtype: Euler\n";
+
static PyObject *Euler_Unique(EulerObject * self)
{
#define PI_2 (Py_PI * 2.0)
@@ -220,6 +222,13 @@ static PyObject *Euler_Unique(EulerObject * self)
}
//----------------------------Euler.zero()-------------------------
//sets the euler to 0,0,0
+static char Euler_Zero_doc[] =
+".. method:: zero()\n"
+"\n"
+" Set all values to zero.\n"
+" :return: an instance of itself\n"
+" :rtype: Euler\n";
+
static PyObject *Euler_Zero(EulerObject * self)
{
self->eul[0] = 0.0;
@@ -278,6 +287,16 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
return (PyObject *)self;
}
+static char Euler_MakeCompatible_doc[] =
+".. method:: make_compatible(other)\n"
+"\n"
+" Make this euler compatible with another, so interpolating between them works as intended.\n"
+"\n"
+" :arg other: make compatible with this rotation.\n"
+" :type other: Euler\n"
+" :return: an instance of itself.\n"
+" :rtype: Euler\n";
+
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
{
#ifdef USE_MATHUTILS_DEG
@@ -317,6 +336,17 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
//----------------------------Euler.rotate()-----------------------
// return a copy of the euler
+
+static char Euler_copy_doc[] =
+".. function:: copy()\n"
+"\n"
+" Returns a copy of this euler.\n"
+"\n"
+" :return: A copy of the euler.\n"
+" :rtype: Euler\n"
+"\n"
+" .. note:: use this to get a copy of a wrapped euler with no reference to the original data.\n";
+
static PyObject *Euler_copy(EulerObject * self, PyObject *args)
{
if(!BaseMath_ReadCallback(self))
@@ -545,6 +575,20 @@ static PyGetSetDef Euler_getseters[] = {
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
+
+//-----------------------METHOD DEFINITIONS ----------------------
+static struct PyMethodDef Euler_methods[] = {
+ {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
+ {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
+ {"to_matrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
+ {"to_quat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
+ {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL},
+ {"make_compatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
+ {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
+ {"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
+ {NULL, NULL, 0, NULL}
+};
+
//------------------PY_OBECT DEFINITION--------------------------
PyTypeObject euler_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c
index 074a397b6d9..00749002e59 100644
--- a/source/blender/python/generic/matrix.c
+++ b/source/blender/python/generic/matrix.c
@@ -105,39 +105,6 @@ Mathutils_Callback mathutils_matrix_vector_cb = {
};
/* matrix vector callbacks, this is so you can do matrix[i][j] = val */
-/*-------------------------DOC STRINGS ---------------------------*/
-
-static PyObject *Matrix_Zero( MatrixObject * self );
-static PyObject *Matrix_Identity( MatrixObject * self );
-static PyObject *Matrix_Transpose( MatrixObject * self );
-static PyObject *Matrix_Determinant( MatrixObject * self );
-static PyObject *Matrix_Invert( MatrixObject * self );
-static PyObject *Matrix_TranslationPart( MatrixObject * self );
-static PyObject *Matrix_RotationPart( MatrixObject * self );
-static PyObject *Matrix_scalePart( MatrixObject * self );
-static PyObject *Matrix_Resize4x4( MatrixObject * self );
-static PyObject *Matrix_toEuler( MatrixObject * self, PyObject *args );
-static PyObject *Matrix_toQuat( MatrixObject * self );
-static PyObject *Matrix_copy( MatrixObject * self );
-
-/*-----------------------METHOD DEFINITIONS ----------------------*/
-static struct PyMethodDef Matrix_methods[] = {
- {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, NULL},
- {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, NULL},
- {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, NULL},
- {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, NULL},
- {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, NULL},
- {"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, NULL},
- {"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, NULL},
- {"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, NULL},
- {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, NULL},
- {"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, NULL},
- {"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, NULL},
- {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, NULL},
- {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
//----------------------------------Mathutils.Matrix() -----------------
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
//create a new matrix type
@@ -214,8 +181,33 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return newMatrixObject(matrix, argSize, seqSize, Py_NEW, NULL);
}
+/* assumes rowsize == colsize is checked and the read callback has run */
+static float matrix_determinant(MatrixObject * self)
+{
+ if(self->rowSize == 2) {
+ return determinant_m2(self->matrix[0][0], self->matrix[0][1],
+ self->matrix[1][0], self->matrix[1][1]);
+ } else if(self->rowSize == 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->matrix);
+ }
+}
+
+
/*-----------------------------METHODS----------------------------*/
-/*---------------------------Matrix.toQuat() ---------------------*/
+static char Matrix_toQuat_doc[] =
+".. method:: to_quat()\n"
+"\n"
+" Return a quaternion representation of the rotation matrix.\n"
+"\n"
+" :return: Quaternion representation of the rotation matrix.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Matrix_toQuat(MatrixObject * self)
{
float quat[4];
@@ -237,6 +229,16 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
return newQuaternionObject(quat, Py_NEW, NULL);
}
/*---------------------------Matrix.toEuler() --------------------*/
+static char Matrix_toEuler_doc[] =
+".. method:: to_euler(euler_compat)\n"
+"\n"
+" Return an Euler representation of the rotation matrix (3x3 or 4x4 matrix only).\n"
+"\n"
+" :arg euler_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.\n"
+" :type euler_compat: Euler\n"
+" :return: Euler representation of the matrix.\n"
+" :rtype: Euler\n";
+
PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
{
float eul[3], eul_compatf[3];
@@ -288,6 +290,13 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
return newEulerObject(eul, Py_NEW, NULL);
}
/*---------------------------Matrix.resize4x4() ------------------*/
+static char Matrix_Resize4x4_doc[] =
+".. method:: resize4x4()\n"
+"\n"
+" Resize the matrix to 4x4.\n"
+" :return: an instance of itself.\n"
+" :rtype: Vector\n";
+
PyObject *Matrix_Resize4x4(MatrixObject * self)
{
int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
@@ -345,6 +354,15 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
return (PyObject *)self;
}
/*---------------------------Matrix.translationPart() ------------*/
+static char Matrix_TranslationPart_doc[] =
+".. method:: translation_part()\n"
+"\n"
+" Return a the translation part of a 4 row matrix.\n"
+" :return: Return a the translation of a matrix.\n"
+" :rtype: Matrix\n"
+"\n"
+" .. note:: Note that the (4,4) element of a matrix can be used for uniform scaling too.\n";
+
PyObject *Matrix_TranslationPart(MatrixObject * self)
{
float vec[4];
@@ -364,6 +382,15 @@ PyObject *Matrix_TranslationPart(MatrixObject * self)
return newVectorObject(vec, 3, Py_NEW, NULL);
}
/*---------------------------Matrix.rotationPart() ---------------*/
+static char Matrix_RotationPart_doc[] =
+".. method:: rotation_part()\n"
+"\n"
+" Return the 3d submatrix corresponding to the linear term of the embedded affine transformation in 3d. This matrix represents rotation and scale.\n"
+" :return: Return the 3d matrix for rotation and scale.\n"
+" :rtype: Matrix\n"
+"\n"
+" .. note:: Note that the (4,4) element of a matrix can be used for uniform scaling too.\n";
+
PyObject *Matrix_RotationPart(MatrixObject * self)
{
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
@@ -390,6 +417,15 @@ PyObject *Matrix_RotationPart(MatrixObject * self)
return newMatrixObject(mat, 3, 3, Py_NEW, Py_TYPE(self));
}
/*---------------------------Matrix.scalePart() --------------------*/
+static char Matrix_scalePart_doc[] =
+".. method:: scale_part()\n"
+"\n"
+" Return a the scale part of a 3x3 or 4x4 matrix.\n"
+" :return: Return a the scale of a matrix.\n"
+" :rtype: 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";
+
PyObject *Matrix_scalePart(MatrixObject * self)
{
float scale[3], rot[3];
@@ -419,12 +455,22 @@ PyObject *Matrix_scalePart(MatrixObject * self)
return newVectorObject(scale, 3, Py_NEW, NULL);
}
/*---------------------------Matrix.invert() ---------------------*/
+static char Matrix_Invert_doc[] =
+".. method:: invert()\n"
+"\n"
+" Set the matrix to its inverse.\n"
+" :return: an instance of itself.\n"
+" :rtype: Matrix\n"
+"\n"
+" .. note:: :exc:`ValueError` exception is raised.\n"
+"\n"
+" .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n";
+
PyObject *Matrix_Invert(MatrixObject * self)
{
int x, y, z = 0;
float det = 0.0f;
- PyObject *f = NULL;
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};
@@ -437,9 +483,7 @@ PyObject *Matrix_Invert(MatrixObject * self)
}
/*calculate the determinant*/
- f = Matrix_Determinant(self);
- det = (float)PyFloat_AS_DOUBLE(f); /*Increfs, so we need to decref*/
- Py_DECREF(f);
+ det = matrix_determinant(self);
if(det != 0) {
/*calculate the classical adjoint*/
@@ -478,10 +522,17 @@ PyObject *Matrix_Invert(MatrixObject * self)
/*---------------------------Matrix.determinant() ----------------*/
+static char Matrix_Determinant_doc[] =
+".. method:: determinant()\n"
+"\n"
+" Return the determinant of a matrix.\n"
+" :return: Return a the determinant of a matrix.\n"
+" :rtype: float\n"
+"\n"
+" .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n";
+
PyObject *Matrix_Determinant(MatrixObject * self)
{
- float det = 0.0f;
-
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -490,22 +541,18 @@ PyObject *Matrix_Determinant(MatrixObject * self)
return NULL;
}
- if(self->rowSize == 2) {
- det = determinant_m2(self->matrix[0][0], self->matrix[0][1],
- self->matrix[1][0], self->matrix[1][1]);
- } else if(self->rowSize == 3) {
- det = 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 {
- det = determinant_m4((float (*)[4]) *self->matrix);
- }
-
- return PyFloat_FromDouble( (double) det );
+ return PyFloat_FromDouble((double)matrix_determinant(self));
}
/*---------------------------Matrix.transpose() ------------------*/
+static char Matrix_Transpose_doc[] =
+".. method:: transpose()\n"
+"\n"
+" Set the matrix to its transpose.\n"
+" :return: an instance of itself\n"
+" :rtype: Matrix\n"
+"\n"
+" .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n";
+
PyObject *Matrix_Transpose(MatrixObject * self)
{
float t = 0.0f;
@@ -535,6 +582,13 @@ PyObject *Matrix_Transpose(MatrixObject * self)
/*---------------------------Matrix.zero() -----------------------*/
+static char Matrix_Zero_doc[] =
+".. method:: zero()\n"
+"\n"
+" Set all the matrix values to zero.\n"
+" :return: an instance of itself\n"
+" :rtype: Matrix\n";
+
PyObject *Matrix_Zero(MatrixObject * self)
{
int row, col;
@@ -552,6 +606,17 @@ PyObject *Matrix_Zero(MatrixObject * self)
return (PyObject *)self;
}
/*---------------------------Matrix.identity(() ------------------*/
+static char Matrix_Identity_doc[] =
+".. method:: identity()\n"
+"\n"
+" Set the matrix to the identity matrix.\n"
+" :return: an instance of itself\n"
+" :rtype: Matrix\n"
+"\n"
+" .. note:: An object with zero location and rotation, a scale of one, will have an identity matrix.\n"
+"\n"
+" .. seealso:: <http://en.wikipedia.org/wiki/Identity_matrix>\n";
+
PyObject *Matrix_Identity(MatrixObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -580,7 +645,14 @@ PyObject *Matrix_Identity(MatrixObject * self)
return (PyObject *)self;
}
-/*---------------------------Matrix.inverted() ------------------*/
+/*---------------------------Matrix.copy() ------------------*/
+static char Matrix_copy_doc[] =
+".. method:: copy()\n"
+"\n"
+" Returns a copy of this matrix.\n"
+" :return: an instance of itself\n"
+" :rtype: Matrix\n";
+
PyObject *Matrix_copy(MatrixObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -1162,6 +1234,24 @@ static PyGetSetDef Matrix_getseters[] = {
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
+/*-----------------------METHOD DEFINITIONS ----------------------*/
+static struct PyMethodDef Matrix_methods[] = {
+ {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, Matrix_Zero_doc},
+ {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, Matrix_Identity_doc},
+ {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, Matrix_Transpose_doc},
+ {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, Matrix_Determinant_doc},
+ {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, Matrix_Invert_doc},
+ {"translation_part", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, Matrix_TranslationPart_doc},
+ {"rotation_part", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc},
+ {"scale_part", (PyCFunction) Matrix_scalePart, METH_NOARGS, Matrix_scalePart_doc},
+ {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc},
+ {"to_euler", (PyCFunction) Matrix_toEuler, METH_VARARGS, Matrix_toEuler_doc},
+ {"to_quat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc},
+ {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
+ {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
+ {NULL, NULL, 0, NULL}
+};
+
/*------------------PY_OBECT DEFINITION--------------------------*/
PyTypeObject matrix_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c
index e739e1a5036..7facc350625 100644
--- a/source/blender/python/generic/quat.c
+++ b/source/blender/python/generic/quat.c
@@ -32,137 +32,17 @@
#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
-
-//-------------------------DOC STRINGS ---------------------------
-
-static PyObject *Quaternion_Identity( QuaternionObject * self );
-static PyObject *Quaternion_Negate( QuaternionObject * self );
-static PyObject *Quaternion_Conjugate( QuaternionObject * self );
-static PyObject *Quaternion_Inverse( QuaternionObject * self );
-static PyObject *Quaternion_Normalize( QuaternionObject * self );
-static PyObject *Quaternion_ToEuler( QuaternionObject * self, PyObject *args );
-static PyObject *Quaternion_ToMatrix( QuaternionObject * self );
-static PyObject *Quaternion_Cross( QuaternionObject * self, QuaternionObject * value );
-static PyObject *Quaternion_Dot( QuaternionObject * self, QuaternionObject * value );
-static PyObject *Quaternion_copy( QuaternionObject * self );
-
-//-----------------------METHOD DEFINITIONS ----------------------
-static struct PyMethodDef Quaternion_methods[] = {
- {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, NULL},
- {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, NULL},
- {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, NULL},
- {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, NULL},
- {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, NULL},
- {"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, NULL},
- {"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, NULL},
- {"cross", (PyCFunction) Quaternion_Cross, METH_O, NULL},
- {"dot", (PyCFunction) Quaternion_Dot, METH_O, NULL},
- {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL},
- {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
-//----------------------------------Mathutils.Quaternion() --------------
-static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *listObject = NULL, *n, *q;
- int size, i;
- float quat[4];
- double angle = 0.0f;
-
- size = PyTuple_GET_SIZE(args);
- if (size == 1 || size == 2) { //seq?
- listObject = PyTuple_GET_ITEM(args, 0);
- if (PySequence_Check(listObject)) {
- size = PySequence_Length(listObject);
- if ((size == 4 && PySequence_Length(args) !=1) ||
- (size == 3 && PySequence_Length(args) !=2) || (size >4 || size < 3)) {
- // invalid args/size
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- if(size == 3){ //get angle in axis/angle
- n = PySequence_GetItem(args, 1);
- if(n == NULL) { // parsed item not a number or getItem fail
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
-
- angle = PyFloat_AsDouble(n);
- Py_DECREF(n);
-
- if (angle==-1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }
- }else{
- listObject = PyTuple_GET_ITEM(args, 1);
- if (size>1 && PySequence_Check(listObject)) {
- size = PySequence_Length(listObject);
- if (size != 3) {
- // invalid args/size
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- angle = PyFloat_AsDouble(PyTuple_GET_ITEM(args, 0));
-
- if (angle==-1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- } else { // argument was not a sequence
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }
- } else if (size == 0) { //returns a new empty quat
- return newQuaternionObject(NULL, Py_NEW, NULL);
- } else {
- listObject = args;
- }
-
- if (size == 3) { // invalid quat size
- if(PySequence_Length(args) != 2){
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }else{
- if(size != 4){
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }
-
- for (i=0; i<size; i++) { //parse
- q = PySequence_GetItem(listObject, i);
- if (q == NULL) { // Failed to read sequence
- PyErr_SetString(PyExc_RuntimeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
-
- quat[i] = PyFloat_AsDouble(q);
- Py_DECREF(q);
-
- if (quat[i]==-1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }
-
- if(size == 3) //calculate the quat based on axis/angle
-#ifdef USE_MATHUTILS_DEG
- axis_angle_to_quat(quat, quat, angle * (Py_PI / 180));
-#else
- axis_angle_to_quat(quat, quat, angle);
-#endif
-
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-
//-----------------------------METHODS------------------------------
-//----------------------------Quaternion.toEuler()------------------
-//return the quat as a euler
+static char Quaternion_ToEuler_doc[] =
+".. method:: to_euler(euler_compat)\n"
+"\n"
+" Return Euler representation of the quaternion.\n"
+"\n"
+" :arg euler_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.\n"
+" :type euler_compat: Euler\n"
+" :return: Euler representation of the quaternion.\n"
+" :rtype: Euler\n";
+
static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
{
float eul[3];
@@ -212,7 +92,14 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
return newEulerObject(eul, Py_NEW, NULL);
}
//----------------------------Quaternion.toMatrix()------------------
-//return the quat as a matrix
+static char Quaternion_ToMatrix_doc[] =
+".. method:: to_matrix(other)\n"
+"\n"
+" Return a matrix representation of the quaternion.\n"
+"\n"
+" :return: A 3x3 rotation matrix representation of the quaternion.\n"
+" :rtype: Matrix\n";
+
static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
{
float mat[9]; /* all values are set */
@@ -225,7 +112,16 @@ static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
}
//----------------------------Quaternion.cross(other)------------------
-//return the cross quat
+static char 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: Quaternion\n"
+" :return: The cross product.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
{
float quat[4];
@@ -243,7 +139,16 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va
}
//----------------------------Quaternion.dot(other)------------------
-//return the dot quat
+static char 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: Quaternion\n"
+" :return: The dot product.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
{
if (!QuaternionObject_Check(value)) {
@@ -257,8 +162,90 @@ static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * valu
return PyFloat_FromDouble(dot_qtqt(self->quat, value->quat));
}
+static char Quaternion_Difference_doc[] =
+".. function:: difference(other)\n"
+"\n"
+" Returns a quaternion representing the rotational difference.\n"
+"\n"
+" :arg other: second quaternion.\n"
+" :type other: Quaternion\n"
+" :return: the rotational difference between the two quat rotations.\n"
+" :rtype: Quaternion\n";
+
+static PyObject *Quaternion_Difference(QuaternionObject * self, QuaternionObject * value)
+{
+ float quat[4], tempQuat[4];
+ double dot = 0.0f;
+ int x;
+
+ if (!QuaternionObject_Check(value)) {
+ PyErr_SetString( PyExc_TypeError, "quat.difference(value): expected a quaternion argument" );
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
+ return NULL;
+
+ tempQuat[0] = self->quat[0];
+ tempQuat[1] = - self->quat[1];
+ tempQuat[2] = - self->quat[2];
+ tempQuat[3] = - self->quat[3];
+
+ dot = sqrt(tempQuat[0] * tempQuat[0] + tempQuat[1] * tempQuat[1] +
+ tempQuat[2] * tempQuat[2] + tempQuat[3] * tempQuat[3]);
+
+ for(x = 0; x < 4; x++) {
+ tempQuat[x] /= (float)(dot * dot);
+ }
+ mul_qt_qtqt(quat, tempQuat, value->quat);
+ return newQuaternionObject(quat, Py_NEW, NULL);
+}
+
+static char 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: Quaternion\n"
+" :arg factor: The interpolation value in [0.0, 1.0].\n"
+" :type factor: float\n"
+" :return: The interpolated rotation.\n"
+" :rtype: Quaternion\n";
+
+static PyObject *Quaternion_Slerp(QuaternionObject *self, PyObject *args)
+{
+ QuaternionObject *value;
+ float quat[4], fac;
+
+ if(!PyArg_ParseTuple(args, "O!f", &quaternion_Type, &value, &fac)) {
+ PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
+ return NULL;
+
+ if(fac > 1.0f || fac < 0.0f) {
+ PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
+ return NULL;
+ }
+
+ interp_qt_qtqt(quat, self->quat, value->quat, fac);
+
+ return newQuaternionObject(quat, Py_NEW, NULL);
+}
+
//----------------------------Quaternion.normalize()----------------
//normalize the axis of rotation of [theta,vector]
+static char Quaternion_Normalize_doc[] =
+".. function:: normalize()\n"
+"\n"
+" Normalize the quaternion.\n"
+"\n"
+" :return: an instance of itself.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Quaternion_Normalize(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -271,7 +258,14 @@ static PyObject *Quaternion_Normalize(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.inverse()------------------
-//invert the quat
+static char Quaternion_Inverse_doc[] =
+".. function:: inverse()\n"
+"\n"
+" Set the quaternion to its inverse.\n"
+"\n"
+" :return: an instance of itself.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Quaternion_Inverse(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -284,7 +278,14 @@ static PyObject *Quaternion_Inverse(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.identity()-----------------
-//generate the identity quaternion
+static char Quaternion_Identity_doc[] =
+".. function:: identity()\n"
+"\n"
+" Set the quaternion to an identity quaternion.\n"
+"\n"
+" :return: an instance of itself.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Quaternion_Identity(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -297,7 +298,14 @@ static PyObject *Quaternion_Identity(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.negate()-------------------
-//negate the quat
+static char Quaternion_Negate_doc[] =
+".. function:: negate()\n"
+"\n"
+" Set the quaternion to its negative.\n"
+"\n"
+" :return: an instance of itself.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Quaternion_Negate(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -310,7 +318,14 @@ static PyObject *Quaternion_Negate(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.conjugate()----------------
-//negate the vector part
+static char Quaternion_Conjugate_doc[] =
+".. function:: conjugate()\n"
+"\n"
+" Set the quaternion to its conjugate (negate x, y, z).\n"
+"\n"
+" :return: an instance of itself.\n"
+" :rtype: Quaternion\n";
+
static PyObject *Quaternion_Conjugate(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -323,7 +338,16 @@ static PyObject *Quaternion_Conjugate(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.copy()----------------
-//return a copy of the quat
+static char Quaternion_copy_doc[] =
+".. function:: copy()\n"
+"\n"
+" Returns a copy of this quaternion.\n"
+"\n"
+" :return: A copy of the quaternion.\n"
+" :rtype: Quaternion\n"
+"\n"
+" .. note:: use this to get a copy of a wrapped quaternion with no reference to the original data.\n";
+
static PyObject *Quaternion_copy(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -702,52 +726,139 @@ static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
return (PyObject *) newVectorObject(vec, 3, Py_NEW, NULL);
}
+//----------------------------------Mathutils.Quaternion() --------------
+static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *listObject = NULL, *n, *q;
+ int size, i;
+ float quat[4];
+ double angle = 0.0f;
+
+ size = PyTuple_GET_SIZE(args);
+ if (size == 1 || size == 2) { //seq?
+ listObject = PyTuple_GET_ITEM(args, 0);
+ if (PySequence_Check(listObject)) {
+ size = PySequence_Length(listObject);
+ if ((size == 4 && PySequence_Length(args) !=1) ||
+ (size == 3 && PySequence_Length(args) !=2) || (size >4 || size < 3)) {
+ // invalid args/size
+ PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+ if(size == 3){ //get angle in axis/angle
+ n = PySequence_GetItem(args, 1);
+ if(n == NULL) { // parsed item not a number or getItem fail
+ PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+
+ angle = PyFloat_AsDouble(n);
+ Py_DECREF(n);
+
+ if (angle==-1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+ }
+ }else{
+ listObject = PyTuple_GET_ITEM(args, 1);
+ if (size>1 && PySequence_Check(listObject)) {
+ size = PySequence_Length(listObject);
+ if (size != 3) {
+ // invalid args/size
+ PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+ angle = PyFloat_AsDouble(PyTuple_GET_ITEM(args, 0));
+
+ if (angle==-1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+ } else { // argument was not a sequence
+ PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+ }
+ } else if (size == 0) { //returns a new empty quat
+ return newQuaternionObject(NULL, Py_NEW, NULL);
+ } else {
+ listObject = args;
+ }
+
+ if (size == 3) { // invalid quat size
+ if(PySequence_Length(args) != 2){
+ PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+ }else{
+ if(size != 4){
+ PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+ }
+
+ for (i=0; i<size; i++) { //parse
+ q = PySequence_GetItem(listObject, i);
+ if (q == NULL) { // Failed to read sequence
+ PyErr_SetString(PyExc_RuntimeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+
+ quat[i] = PyFloat_AsDouble(q);
+ Py_DECREF(q);
+
+ if (quat[i]==-1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
+ return NULL;
+ }
+ }
+
+ if(size == 3) //calculate the quat based on axis/angle
+#ifdef USE_MATHUTILS_DEG
+ axis_angle_to_quat(quat, quat, angle * (Py_PI / 180));
+#else
+ axis_angle_to_quat(quat, quat, angle);
+#endif
+
+ return newQuaternionObject(quat, Py_NEW, NULL);
+}
+
+
+//-----------------------METHOD DEFINITIONS ----------------------
+static struct PyMethodDef Quaternion_methods[] = {
+ {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc},
+ {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc},
+ {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc},
+ {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc},
+ {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc},
+ {"to_euler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc},
+ {"to_matrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc},
+ {"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc},
+ {"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc},
+ {"difference", (PyCFunction) Quaternion_Difference, METH_O, Quaternion_Difference_doc},
+ {"slerp", (PyCFunction) Quaternion_Slerp, METH_VARARGS, Quaternion_Slerp_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[] = {
- {"w",
- (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
- "Quaternion W value",
- (void *)0},
- {"x",
- (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
- "Quaternion X axis",
- (void *)1},
- {"y",
- (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
- "Quaternion Y axis",
- (void *)2},
- {"z",
- (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
- "Quaternion Z axis",
- (void *)3},
- {"magnitude",
- (getter)Quaternion_getMagnitude, (setter)NULL,
- "Size of the quaternion",
- NULL},
- {"angle",
- (getter)Quaternion_getAngle, (setter)NULL,
- "angle of the quaternion",
- NULL},
- {"axis",
- (getter)Quaternion_getAxisVec, (setter)NULL,
- "quaternion axis as a vector",
- NULL},
- {"wrapped",
- (getter)BaseMathObject_getWrapped, (setter)NULL,
- "True when this wraps blenders internal data",
- NULL},
- {"_owner",
- (getter)BaseMathObject_getOwner, (setter)NULL,
- "Read only owner for vectors that depend on another object",
- NULL},
-
+ {"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion W value", (void *)0},
+ {"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion X axis", (void *)1},
+ {"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Y axis", (void *)2},
+ {"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Z axis", (void *)3},
+ {"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, "Size of the quaternion", NULL},
+ {"angle", (getter)Quaternion_getAngle, (setter)NULL, "angle of the quaternion", NULL},
+ {"axis",(getter)Quaternion_getAxisVec, (setter)NULL, "quaternion axis as a vector", NULL},
+ {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
+ {"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
-
//------------------PY_OBECT DEFINITION--------------------------
PyTypeObject quaternion_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -843,3 +954,4 @@ PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
return (PyObject *)self;
}
+
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c
index 862b7338ac0..558e4aac9c9 100644
--- a/source/blender/python/generic/vector.c
+++ b/source/blender/python/generic/vector.c
@@ -41,37 +41,6 @@
static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */
-/*-----------------------METHOD DEFINITIONS ----------------------*/
-static PyObject *Vector_Zero( VectorObject * self );
-static PyObject *Vector_Normalize( VectorObject * self );
-static PyObject *Vector_Negate( VectorObject * self );
-static PyObject *Vector_Resize2D( VectorObject * self );
-static PyObject *Vector_Resize3D( VectorObject * self );
-static PyObject *Vector_Resize4D( VectorObject * self );
-static PyObject *Vector_ToTuple( VectorObject * self, PyObject *value );
-static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args );
-static PyObject *Vector_Reflect( VectorObject *self, VectorObject *value );
-static PyObject *Vector_Cross( VectorObject * self, VectorObject * value );
-static PyObject *Vector_Dot( VectorObject * self, VectorObject * value );
-static PyObject *Vector_copy( VectorObject * self );
-
-static struct PyMethodDef Vector_methods[] = {
- {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, NULL},
- {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, NULL},
- {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, NULL},
- {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, NULL},
- {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, NULL},
- {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, NULL},
- {"toTuple", (PyCFunction) Vector_ToTuple, METH_O, NULL},
- {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, NULL},
- {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, NULL},
- {"cross", ( PyCFunction ) Vector_Cross, METH_O, NULL},
- {"dot", ( PyCFunction ) Vector_Dot, METH_O, NULL},
- {"copy", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
- {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
//----------------------------------Mathutils.Vector() ------------------
// Supports 2D, 3D, and 4D vector objects both int and float values
// accepted. Mixed float and int values accepted. Ints are parsed to float
@@ -124,8 +93,13 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
/*-----------------------------METHODS---------------------------- */
-/*----------------------------Vector.zero() ----------------------
- set the vector data to 0,0,0 */
+static char Vector_Zero_doc[] =
+".. method:: zero()\n"
+"\n"
+" Set all values to zero.\n"
+" :return: an instance of itself\n"
+" :rtype: vector\n";
+
static PyObject *Vector_Zero(VectorObject * self)
{
int i;
@@ -137,8 +111,18 @@ static PyObject *Vector_Zero(VectorObject * self)
Py_INCREF(self);
return (PyObject*)self;
}
-/*----------------------------Vector.normalize() -----------------
- normalize the vector data to a unit vector */
+/*----------------------------Vector.normalize() ----------------- */
+static char Vector_Normalize_doc[] =
+".. method:: normalize()\n"
+"\n"
+" Normalize the vector, making the length of the vector always 1.0.\n"
+" :return: an instance of itself\n"
+" :rtype: vector\n"
+"\n"
+" .. warning:: Normalizing a vector where all values are zero results in all axis having a nan value (not a number).\n"
+"\n"
+" .. note:: Normalize works for vectors of all sizes, however 4D Vectors w axis is left untouched.\n";
+
static PyObject *Vector_Normalize(VectorObject * self)
{
int i;
@@ -161,8 +145,14 @@ static PyObject *Vector_Normalize(VectorObject * self)
}
-/*----------------------------Vector.resize2D() ------------------
- resize the vector to x,y */
+/*----------------------------Vector.resize2D() ------------------ */
+static char Vector_Resize2D_doc[] =
+".. method:: resize2D()\n"
+"\n"
+" Resize the vector to 2D (x, y).\n"
+" :return: an instance of itself\n"
+" :rtype: vector\n";
+
static PyObject *Vector_Resize2D(VectorObject * self)
{
if(self->wrapped==Py_WRAP) {
@@ -184,8 +174,14 @@ static PyObject *Vector_Resize2D(VectorObject * self)
Py_INCREF(self);
return (PyObject*)self;
}
-/*----------------------------Vector.resize3D() ------------------
- resize the vector to x,y,z */
+/*----------------------------Vector.resize3D() ------------------ */
+static char Vector_Resize3D_doc[] =
+".. method:: resize3D()\n"
+"\n"
+" Resize the vector to 3D (x, y, z).\n"
+" :return: an instance of itself\n"
+" :rtype: vector\n";
+
static PyObject *Vector_Resize3D(VectorObject * self)
{
if (self->wrapped==Py_WRAP) {
@@ -210,8 +206,14 @@ static PyObject *Vector_Resize3D(VectorObject * self)
Py_INCREF(self);
return (PyObject*)self;
}
-/*----------------------------Vector.resize4D() ------------------
- resize the vector to x,y,z,w */
+/*----------------------------Vector.resize4D() ------------------ */
+static char Vector_Resize4D_doc[] =
+".. method:: resize4D()\n"
+"\n"
+" Resize the vector to 4D (x, y, z, w).\n"
+" :return: an instance of itself\n"
+" :rtype: vector\n";
+
static PyObject *Vector_Resize4D(VectorObject * self)
{
if(self->wrapped==Py_WRAP) {
@@ -239,8 +241,17 @@ static PyObject *Vector_Resize4D(VectorObject * self)
return (PyObject*)self;
}
-/*----------------------------Vector.resize4D() ------------------
- resize the vector to x,y,z,w */
+/*----------------------------Vector.toTuple() ------------------ */
+static char Vector_ToTuple_doc[] =
+".. method:: to_tuple(precision)\n"
+"\n"
+" Return this vector as a tuple with.\n"
+"\n"
+" :arg precision: The number to round the value to in [0, 21].\n"
+" :type precision: int\n"
+" :return: the values of the vector rounded by *precision*\n"
+" :rtype: tuple\n";
+
static PyObject *Vector_ToTuple(VectorObject * self, PyObject *value)
{
int ndigits= PyLong_AsSsize_t(value);
@@ -265,8 +276,19 @@ static PyObject *Vector_ToTuple(VectorObject * self, PyObject *value)
return ret;
}
-/*----------------------------Vector.toTrackQuat(track, up) ----------------------
- extract a quaternion from the vector and the track and up axis */
+/*----------------------------Vector.toTrackQuat(track, up) ---------------------- */
+static char Vector_ToTrackQuat_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."
+" :rtype: Quaternion\n";
+
static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
{
float vec[3], quat[4];
@@ -290,14 +312,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
if (strack[0] == '-') {
switch(strack[1]) {
case 'X':
- case 'x':
track = 3;
break;
case 'Y':
- case 'y':
track = 4;
break;
- case 'z':
case 'Z':
track = 5;
break;
@@ -315,14 +334,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
switch(strack[0]) {
case '-':
case 'X':
- case 'x':
track = 0;
break;
case 'Y':
- case 'y':
track = 1;
break;
- case 'z':
case 'Z':
track = 2;
break;
@@ -341,14 +357,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
if (strlen(sup) == 1) {
switch(*sup) {
case 'X':
- case 'x':
up = 0;
break;
- case 'Y':
case 'y':
up = 1;
break;
- case 'z':
case 'Z':
up = 2;
break;
@@ -385,6 +398,16 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
return a reflected vector on the mirror normal
vec - ((2 * DotVecs(vec, mirror)) * mirror)
*/
+static char 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: vector\n"
+" :return: The reflected vector.\n"
+" :rtype: Vector object matching the size of this vector.\n";
+
static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
{
float mirror[3], vec[3];
@@ -414,6 +437,18 @@ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
return newVectorObject(reflect, self->size, Py_NEW, NULL);
}
+static char 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: vector\n"
+" :return: The cross product.\n"
+" :rtype: Vector\n"
+"\n"
+" .. note:: both vectors must be 3D\n";
+
static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
{
VectorObject *vecCross = NULL;
@@ -436,6 +471,16 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
return (PyObject *)vecCross;
}
+static char 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: vector\n"
+" :return: The dot product.\n"
+" :rtype: Vector\n";
+
static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
{
double dot = 0.0;
@@ -460,8 +505,156 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
return PyFloat_FromDouble(dot);
}
-/*----------------------------Vector.copy() --------------------------------------
- return a copy of the vector */
+static char Vector_Angle_doc[] =
+".. function:: angle(other)\n"
+"\n"
+" Return the angle between two vectors.\n"
+"\n"
+" :type other: vector\n"
+" :return angle: angle in radians\n"
+" :rtype: float\n"
+"\n"
+" .. note:: Zero length vectors raise an :exc:`AttributeError`.\n";
+static PyObject *Vector_Angle(VectorObject * self, VectorObject * value)
+{
+ double dot = 0.0f, angleRads, test_v1 = 0.0f, test_v2 = 0.0f;
+ int x, size;
+
+ if (!VectorObject_Check(value)) {
+ PyErr_SetString( PyExc_TypeError, "vec.angle(value): expected a vector argument" );
+ return NULL;
+ }
+
+ if(self->size != value->size) {
+ PyErr_SetString(PyExc_AttributeError, "vec.angle(value): expects both vectors to have the same size\n");
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
+ return NULL;
+
+ //since size is the same....
+ size = self->size;
+
+ for(x = 0; x < size; x++) {
+ test_v1 += self->vec[x] * self->vec[x];
+ test_v2 += value->vec[x] * value->vec[x];
+ }
+ if (!test_v1 || !test_v2){
+ PyErr_SetString(PyExc_AttributeError, "vector.angle(other): zero length vectors are not acceptable arguments\n");
+ return NULL;
+ }
+
+ //dot product
+ for(x = 0; x < size; x++) {
+ dot += self->vec[x] * value->vec[x];
+ }
+ dot /= (sqrt(test_v1) * sqrt(test_v2));
+
+ angleRads = (double)saacos(dot);
+
+#ifdef USE_MATHUTILS_DEG
+ return PyFloat_FromDouble(angleRads * (180/ Py_PI));
+#else
+ return PyFloat_FromDouble(angleRads);
+#endif
+}
+
+static char Vector_Project_doc[] =
+".. function:: project(other)\n"
+"\n"
+" Return the projection of this vector onto the *other*.\n"
+"\n"
+" :type other: vector\n"
+" :return projection: the parallel projection vector\n"
+" :rtype: vector\n";
+
+static PyObject *Vector_Project(VectorObject * self, VectorObject * value)
+{
+ float vec[4];
+ double dot = 0.0f, dot2 = 0.0f;
+ int x, size;
+
+ if (!VectorObject_Check(value)) {
+ PyErr_SetString( PyExc_TypeError, "vec.project(value): expected a vector argument" );
+ return NULL;
+ }
+
+ if(self->size != value->size) {
+ PyErr_SetString(PyExc_AttributeError, "vec.project(value): expects both vectors to have the same size\n");
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
+ return NULL;
+
+
+ //since they are the same size...
+ size = self->size;
+
+ //get dot products
+ for(x = 0; x < size; x++) {
+ dot += self->vec[x] * value->vec[x];
+ dot2 += value->vec[x] * value->vec[x];
+ }
+ //projection
+ dot /= dot2;
+ for(x = 0; x < size; x++) {
+ vec[x] = (float)(dot * value->vec[x]);
+ }
+ return newVectorObject(vec, size, Py_NEW, NULL);
+}
+
+//----------------------------------Mathutils.MidpointVecs() -------------
+static char 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: Vector\n"
+" :arg factor: The interpolation value in [0.0, 1.0].\n"
+" :type factor: float\n"
+" :return: The interpolated rotation.\n"
+" :rtype: Vector\n";
+
+static PyObject *Vector_Lerp(VectorObject * self, PyObject * args)
+{
+ VectorObject *vec2 = NULL;
+ float fac, ifac, vec[4];
+ int x;
+
+ if(!PyArg_ParseTuple(args, "O!f", &vector_Type, &vec2, &fac)) {
+ PyErr_SetString(PyExc_TypeError, "vector.lerp(): expects a vector of the same size and float");
+ return NULL;
+ }
+ if(self->size != vec2->size) {
+ PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size");
+ return NULL;
+ }
+
+ if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(vec2))
+ return NULL;
+
+ ifac= 1.0 - fac;
+
+ for(x = 0; x < self->size; x++) {
+ vec[x] = (ifac * self->vec[x]) + (fac * vec2->vec[x]);
+ }
+ return newVectorObject(vec, self->size, Py_NEW, NULL);
+}
+
+/*----------------------------Vector.copy() -------------------------------------- */
+static char Vector_copy_doc[] =
+".. function:: copy()\n"
+"\n"
+" Returns a copy of this vector.\n"
+"\n"
+" :return: A copy of the vector.\n"
+" :rtype: Vector\n"
+"\n"
+" .. note:: use this to get a copy of a wrapped vector with no reference to the original data.\n";
+
static PyObject *Vector_copy(VectorObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -1808,7 +2001,87 @@ if len(unique) != len(items):
*/
+//-----------------row_vector_multiplication (internal)-----------
+//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 PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
+{
+ float vecNew[4], vecCopy[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_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
+ return NULL;
+ }else{
+ vecCopy[3] = 1.0f;
+ }
+ }
+
+ if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat))
+ return NULL;
+
+ for(x = 0; x < vec_size; x++){
+ vecCopy[x] = vec->vec[x];
+ }
+ vecNew[3] = 1.0f;
+ //muliplication
+ for(x = 0; x < mat->rowSize; x++) {
+ for(y = 0; y < mat->colSize; y++) {
+ dot += mat->matrix[x][y] * vecCopy[y];
+ }
+ vecNew[z++] = (float)dot;
+ dot = 0.0f;
+ }
+ return newVectorObject(vecNew, vec_size, Py_NEW, NULL);
+}
+
+/*----------------------------Vector.negate() -------------------- */
+static char Vector_Negate_doc[] =
+".. method:: negate()\n"
+"\n"
+" Set all values to their negative.\n"
+" :return: an instance of itself\n"
+" :rtype: vector\n";
+static PyObject *Vector_Negate(VectorObject * self)
+{
+ int i;
+ if(!BaseMath_ReadCallback(self))
+ return NULL;
+
+ for(i = 0; i < self->size; i++)
+ self->vec[i] = -(self->vec[i]);
+
+ BaseMath_WriteCallback(self); // alredy checked for error
+
+ Py_INCREF(self);
+ return (PyObject*)self;
+}
+
+static struct PyMethodDef Vector_methods[] = {
+ {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc},
+ {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc},
+ {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc},
+ {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc},
+ {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize3D_doc},
+ {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize4D_doc},
+ {"to_tuple", (PyCFunction) Vector_ToTuple, METH_O, Vector_ToTuple_doc},
+ {"to_track_quat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc},
+ {"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_O, Vector_Angle_doc},
+ {"project", ( PyCFunction ) Vector_Project, METH_O, Vector_Project_doc},
+ {"lerp", ( PyCFunction ) Vector_Lerp, METH_VARARGS, Vector_Lerp_doc},
+ {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
+ {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
+ {NULL, NULL, 0, NULL}
+};
/* Note
@@ -1817,6 +2090,8 @@ if len(unique) != len(items):
vec*mat and mat*vec both get sent to Vector_mul and it neesd to sort out the order
*/
+static char vector_doc[] = "This object gives access to Vectors in Blender.";
+
PyTypeObject vector_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
@@ -1852,7 +2127,7 @@ PyTypeObject vector_Type = {
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- NULL, /* char *tp_doc; Documentation string */
+ vector_doc, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
@@ -1897,7 +2172,6 @@ PyTypeObject vector_Type = {
NULL
};
-
/*------------------------newVectorObject (internal)-------------
creates a new vector object
pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
@@ -1956,59 +2230,3 @@ PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_su
return (PyObject *)self;
}
-
-//-----------------row_vector_multiplication (internal)-----------
-//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 PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
-{
- float vecNew[4], vecCopy[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_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
- return NULL;
- }else{
- vecCopy[3] = 1.0f;
- }
- }
-
- if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat))
- return NULL;
-
- for(x = 0; x < vec_size; x++){
- vecCopy[x] = vec->vec[x];
- }
- vecNew[3] = 1.0f;
- //muliplication
- for(x = 0; x < mat->rowSize; x++) {
- for(y = 0; y < mat->colSize; y++) {
- dot += mat->matrix[x][y] * vecCopy[y];
- }
- vecNew[z++] = (float)dot;
- dot = 0.0f;
- }
- return newVectorObject(vecNew, vec_size, Py_NEW, NULL);
-}
-
-/*----------------------------Vector.negate() --------------------
- set the vector to it's negative -x, -y, -z */
-static PyObject *Vector_Negate(VectorObject * self)
-{
- int i;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- for(i = 0; i < self->size; i++)
- self->vec[i] = -(self->vec[i]);
-
- BaseMath_WriteCallback(self); // alredy checked for error
-
- Py_INCREF(self);
- return (PyObject*)self;
-}