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
This commit is contained in:
2010-01-25 09:44:04 +00:00
parent eed13d859b
commit 0a0f4c9d81
26 changed files with 1540 additions and 1714 deletions

View File

@@ -10,6 +10,83 @@ Geometry
This new module provides access to a geometry function.
"""
def Intersect(vec1, vec2, vec3, ray, orig, clip=1):
"""
Return the intersection between a ray and a triangle, if possible, return None otherwise.
@type vec1: Vector object.
@param vec1: A 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 3d vector, one corner of the triangle.
@type ray: Vector object.
@param ray: A 3d vector, the orientation of the ray. the length of the ray is not used, only the direction.
@type orig: Vector object.
@param orig: A 3d vector, the origin of the ray.
@type clip: integer
@param clip: if 0, don't restrict the intersection to the area of the triangle, use the infinite plane defined by the triangle.
@rtype: Vector object
@return: The intersection between a ray and a triangle, if possible, None otherwise.
"""
def TriangleArea(vec1, vec2, vec3):
"""
Return the area size of the 2D or 3D triangle defined.
@type vec1: Vector object.
@param vec1: A 2d or 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 2d or 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 2d or 3d vector, one corner of the triangle.
@rtype: float
@return: The area size of the 2D or 3D triangle defined.
"""
def TriangleNormal(vec1, vec2, vec3):
"""
Return the normal of the 3D triangle defined.
@type vec1: Vector object.
@param vec1: A 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 3d vector, one corner of the triangle.
@rtype: float
@return: The normal of the 3D triangle defined.
"""
def QuadNormal(vec1, vec2, vec3, vec4):
"""
Return the normal of the 3D quad defined.
@type vec1: Vector object.
@param vec1: A 3d vector, the first vertex of the quad.
@type vec2: Vector object.
@param vec2: A 3d vector, the second vertex of the quad.
@type vec3: Vector object.
@param vec3: A 3d vector, the third vertex of the quad.
@type vec4: Vector object.
@param vec4: A 3d vector, the fourth vertex of the quad.
@rtype: float
@return: The normal of the 3D quad defined.
"""
def LineIntersect(vec1, vec2, vec3, vec4):
"""
Return a tuple with the points on each line respectively closest to the other
(when both lines intersect, both vector hold the same value).
The lines are evaluated as infinite lines in space, the values returned may not be between the 2 points given for each line.
@type vec1: Vector object.
@param vec1: A 3d vector, one point on the first line.
@type vec2: Vector object.
@param vec2: A 3d vector, another point on the first line.
@type vec3: Vector object.
@param vec3: A 3d vector, one point on the second line.
@type vec4: Vector object.
@param vec4: A 3d vector, another point on the second line.
@rtype: (Vector object, Vector object)
@return: A tuple with the points on each line respectively closest to the other.
"""
def PolyFill(polylines):
"""
Takes a list of polylines and calculates triangles that would fill in the polylines.

View File

@@ -22,242 +22,13 @@ Example::
matTotal.invert()
mat3 = matTotal.rotationPart
quat1 = mat.toQuat()
quat2 = mat3.toQuat()
quat1 = mat.to_quat()
quat2 = mat3.to_quat()
angle = DifferenceQuats(quat1, quat2)
print angle
"""
def Rand (low=0.0, high = 1.0):
"""
Return a random number within a range.
low and high represent are optional parameters which represent the range
from which the random number must return its result.
@type low: float
@param low: The lower range.
@type high: float
@param high: The upper range.
"""
def Intersect(vec1, vec2, vec3, ray, orig, clip=1):
"""
Return the intersection between a ray and a triangle, if possible, return None otherwise.
@type vec1: Vector object.
@param vec1: A 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 3d vector, one corner of the triangle.
@type ray: Vector object.
@param ray: A 3d vector, the orientation of the ray. the length of the ray is not used, only the direction.
@type orig: Vector object.
@param orig: A 3d vector, the origin of the ray.
@type clip: integer
@param clip: if 0, don't restrict the intersection to the area of the triangle, use the infinite plane defined by the triangle.
@rtype: Vector object
@return: The intersection between a ray and a triangle, if possible, None otherwise.
"""
def TriangleArea(vec1, vec2, vec3):
"""
Return the area size of the 2D or 3D triangle defined.
@type vec1: Vector object.
@param vec1: A 2d or 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 2d or 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 2d or 3d vector, one corner of the triangle.
@rtype: float
@return: The area size of the 2D or 3D triangle defined.
"""
def TriangleNormal(vec1, vec2, vec3):
"""
Return the normal of the 3D triangle defined.
@type vec1: Vector object.
@param vec1: A 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 3d vector, one corner of the triangle.
@rtype: float
@return: The normal of the 3D triangle defined.
"""
def QuadNormal(vec1, vec2, vec3, vec4):
"""
Return the normal of the 3D quad defined.
@type vec1: Vector object.
@param vec1: A 3d vector, the first vertex of the quad.
@type vec2: Vector object.
@param vec2: A 3d vector, the second vertex of the quad.
@type vec3: Vector object.
@param vec3: A 3d vector, the third vertex of the quad.
@type vec4: Vector object.
@param vec4: A 3d vector, the fourth vertex of the quad.
@rtype: float
@return: The normal of the 3D quad defined.
"""
def LineIntersect(vec1, vec2, vec3, vec4):
"""
Return a tuple with the points on each line respectively closest to the other
(when both lines intersect, both vector hold the same value).
The lines are evaluated as infinite lines in space, the values returned may not be between the 2 points given for each line.
@type vec1: Vector object.
@param vec1: A 3d vector, one point on the first line.
@type vec2: Vector object.
@param vec2: A 3d vector, another point on the first line.
@type vec3: Vector object.
@param vec3: A 3d vector, one point on the second line.
@type vec4: Vector object.
@param vec4: A 3d vector, another point on the second line.
@rtype: (Vector object, Vector object)
@return: A tuple with the points on each line respectively closest to the other.
"""
def AngleBetweenVecs(vec1, vec2):
"""
Return the angle between two vectors. Zero length vectors raise an error.
@type vec1: Vector object.
@param vec1: A 2d or 3d vector.
@type vec2: Vector object.
@param vec2: A 2d or 3d vector.
@rtype: float
@return: The angle between the vectors in degrees.
@raise AttributeError: When there is a zero-length vector as an argument.
"""
def MidpointVecs(vec1, vec2):
"""
Return a vector to the midpoint between two vectors.
@type vec1: Vector object.
@param vec1: A 2d,3d or 4d vector.
@type vec2: Vector object.
@param vec2: A 2d,3d or 4d vector.
@rtype: Vector object
@return: The vector to the midpoint.
"""
def ProjectVecs(vec1, vec2):
"""
Return the projection of vec1 onto vec2.
@type vec1: Vector object.
@param vec1: A 2d,3d or 4d vector.
@type vec2: Vector object.
@param vec2: A 2d,3d or 4d vector.
@rtype: Vector object
@return: The parallel projection vector.
"""
def RotationMatrix(angle, matSize, axisFlag, axis):
"""
Create a matrix representing a rotation.
@type angle: float
@param angle: The angle of rotation desired.
@type matSize: int
@param matSize: The size of the rotation matrix to construct.
Can be 2d, 3d, or 4d.
@type axisFlag: string (optional)
@param axisFlag: Possible values:
- "x - x-axis rotation"
- "y - y-axis rotation"
- "z - z-axis rotation"
- "r - arbitrary rotation around vector"
@type axis: Vector object. (optional)
@param axis: The arbitrary axis of rotation used with "R"
@rtype: Matrix object.
@return: A new rotation matrix.
"""
def TranslationMatrix(vector):
"""
Create a matrix representing a translation
@type vector: Vector object
@param vector: The translation vector
@rtype: Matrix object.
@return: An identity matrix with a translation.
"""
def ScaleMatrix(factor, matSize, axis):
"""
Create a matrix representing a scaling.
@type factor: float
@param factor: The factor of scaling to apply.
@type matSize: int
@param matSize: The size of the scale matrix to construct.
Can be 2d, 3d, or 4d.
@type axis: Vector object. (optional)
@param axis: Direction to influence scale.
@rtype: Matrix object.
@return: A new scale matrix.
"""
def OrthoProjectionMatrix(plane, matSize, axis):
"""
Create a matrix to represent an orthographic projection
@type plane: string
@param plane: Can be any of the following:
- "x - x projection (2D)"
- "y - y projection (2D)"
- "xy - xy projection"
- "xz - xz projection"
- "yz - yz projection"
- "r - arbitrary projection plane"
@type matSize: int
@param matSize: The size of the projection matrix to construct.
Can be 2d, 3d, or 4d.
@type axis: Vector object. (optional)
@param axis: Arbitrary perpendicular plane vector.
@rtype: Matrix object.
@return: A new projeciton matrix.
"""
def ShearMatrix(plane, factor, matSize):
"""
Create a matrix to represent an orthographic projection
@type plane: string
@param plane: Can be any of the following:
- "x - x shear (2D)"
- "y - y shear (2D)"
- "xy - xy shear"
- "xz - xz shear"
- "yz - yz shear"
@type factor: float
@param factor: The factor of shear to apply.
@type matSize: int
@param matSize: The size of the projection matrix to construct.
Can be 2d, 3d, or 4d.
@rtype: Matrix object.
@return: A new shear matrix.
"""
def DifferenceQuats(quat1, quat2):
"""
Returns a quaternion represting the rotational difference.
@type quat1: Quaternion object.
@param quat1: Quaternion.
@type quat2: Quaternion object.
@param quat2: Quaternion.
@rtype: Quaternion object
@return: Return a quaternion which which represents the rotational
difference between the two quat rotations.
"""
def Slerp(quat1, quat2, factor):
"""
Returns the interpolation of two quaternions.
@type quat1: Quaternion object.
@param quat1: Quaternion.
@type quat2: Quaternion object.
@param quat2: Quaternion.
@type factor: float
@param factor: The interpolation value
@rtype: Quaternion object
@return: The interpolated rotation.
"""
class Vector:
"""
The Vector object
@@ -330,100 +101,6 @@ class Vector:
- (): An empty 3 dimensional vector.
"""
def copy():
"""
Returns a copy of this vector
@return: a copy of itself
"""
def zero():
"""
Set all values to zero.
@return: an instance of itself
"""
def normalize():
"""
Normalize the vector, making the length of the vector always 1.0
@note: Normalize works for vectors of all sizes, however 4D Vectors w axis is left untouched.
@note: Normalizing a vector where all values are zero results in all axis having a nan value (not a number).
@return: an instance of itself
"""
def negate():
"""
Set all values to their negative.
@return: an instance of its self
"""
def resize2D():
"""
Resize the vector to 2d.
@return: an instance of itself
"""
def resize3D():
"""
Resize the vector to 3d. New axis will be 0.0.
@return: an instance of itself
"""
def resize4D():
"""
Resize the vector to 4d. New axis will be 0.0.
The last component will be 1.0, to make multiplying 3d vectors by 4x4 matrices easier.
@return: an instance of itself
"""
def toTrackQuat(track, up):
"""
Return a quaternion rotation from the vector and the track and up axis.
@type track: String.
@param track: Possible values:
- "x - x-axis up"
- "y - y-axis up"
- "z - z-axis up"
- "-x - negative x-axis up"
- "-y - negative y-axis up"
- "-z - negative z-axis up"
@type up: String.
@param up: Possible values:
- "x - x-axis up"
- "y - y-axis up"
- "z - z-axis up"
@rtype: Quaternion
@return: Return a quaternion rotation from the vector and the track and up axis.
"""
def reflect(mirror):
"""
Return the reflection vector from the mirror vector argument.
@type mirror: Vector object
@param mirror: This vector could be a normal from the reflecting surface.
@rtype: Vector object matching the size of this vector.
@return: The reflected vector.
"""
def cross(other):
"""
Return the cross product of this vector and another.
@note: both vectors must be 3D.
@type other: Vector object
@param other: The other vector to perform the cross product with.
@rtype: Vector
@return: The cross product.
"""
def dot(other):
"""
Return the dot product of this vector and another.
@note: both vectors must be the same size.
@type other: Vector object
@param other: The other vector to perform the dot product with.
@rtype: float
@return: The dot product.
"""
class Euler:
"""
The Euler object
@@ -470,43 +147,6 @@ class Euler:
@note: Values are in degrees.
"""
def zero():
"""
Set all values to zero.
@return: an instance of itself
"""
def copy():
"""
@return: a copy of this euler.
"""
def unique():
"""
Calculate a unique rotation for this euler. Avoids gimble lock.
@return: an instance of itself
"""
def toMatrix():
"""
Return a matrix representation of the euler.
@rtype: Matrix object
@return: A 3x3 roation matrix representation of the euler.
"""
def toQuat():
"""
Return a quaternion representation of the euler.
@rtype: Quaternion object
@return: Quaternion representation of the euler.
"""
def makeCompatible(eul_compat):
"""
Make this euler compatible with another, so interpolating between them works as expected.
@rtype: Euler object
@return: an instance of itself
"""
class Quaternion:
"""
The Quaternion object
@@ -571,76 +211,6 @@ class Quaternion:
- (): An identity 4 dimensional quaternion.
"""
def identity():
"""
Set the quaternion to the identity quaternion.
@return: an instance of itself
"""
def copy():
"""
make a copy of the quaternion.
@return: a copy of itself
"""
def negate():
"""
Set the quaternion to its negative.
@return: an instance of itself
"""
def conjugate():
"""
Set the quaternion to its conjugate.
@return: an instance of itself
"""
def inverse():
"""
Set the quaternion to its inverse
@return: an instance of itself
"""
def normalize():
"""
Normalize the quaternion.
@return: an instance of itself
"""
def toEuler(eul_compat):
"""
Return Euler representation of the quaternion.
@type eul_compat: L{Euler}
@param eul_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.
@rtype: Euler object
@return: Euler representation of the quaternion.
"""
def toMatrix():
"""
Return a matrix representation of the quaternion.
@rtype: Matrix object
@return: A 3x3 rotation matrix representation of the quaternion.
"""
def cross(other):
"""
Return the cross product of this quaternion and another.
@type other: Quaterion object
@param other: The other quaternion to perform the cross product with.
@rtype: Vector
@return: The cross product.
"""
def dot(other):
"""
Return the dot product of this quaternion and another.
@type other: Quaterion object
@param other: The other quaternion to perform the dot product with.
@rtype: float
@return: The dot product.
"""
class Matrix:
"""
The Matrix Object
@@ -699,99 +269,3 @@ class Matrix:
- (list1, etc.): Matrix object initialized with the given values;
- (): An empty 3 dimensional matrix.
"""
def zero():
"""
Set all matrix values to 0.
@return: an instance of itself
"""
def copy():
"""
Returns a copy of this matrix
@return: a copy of itself
"""
def identity():
"""
Set the matrix to the identity matrix.
An object with zero location and rotation, a scale of 1, will have an identity matrix.
See U{http://en.wikipedia.org/wiki/Identity_matrix}
@return: an instance of itself
"""
def transpose():
"""
Set the matrix to its transpose.
See U{http://en.wikipedia.org/wiki/Transpose}
@return: None
"""
def determinant():
"""
Return the determinant of a matrix.
See U{http://en.wikipedia.org/wiki/Determinant}
@rtype: float
@return: Return a the determinant of a matrix.
"""
def invert():
"""
Set the matrix to its inverse.
See U{http://en.wikipedia.org/wiki/Inverse_matrix}
@return: an instance of itself.
@raise ValueError: When matrix is singular.
"""
def rotationPart():
"""
Return the 3d submatrix corresponding to the linear term of the
embedded affine transformation in 3d. This matrix represents rotation
and scale. Note that the (4,4) element of a matrix can be used for uniform
scaling, too.
@rtype: Matrix object.
@return: Return the 3d matrix for rotation and scale.
"""
def translationPart():
"""
Return a the translation part of a 4 row matrix.
@rtype: Vector object.
@return: Return a the translation of a matrix.
"""
def scalePart():
"""
Return a the scale part of a 3x3 or 4x4 matrix.
@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.
@rtype: Vector object.
@return: Return a the scale of a matrix.
"""
def resize4x4():
"""
Resize the matrix to by 4x4
@return: an instance of itself.
"""
def toEuler(eul_compat):
"""
Return an Euler representation of the rotation matrix (3x3 or 4x4 matrix only).
@type eul_compat: L{Euler}
@param eul_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.
@rtype: Euler object
@return: Euler representation of the rotation matrix.
"""
def toQuat():
"""
Return a quaternion representation of the rotation matrix
@rtype: Quaternion object
@return: Quaternion representation of the rotation matrix
"""

View File

@@ -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 */
};
/*----------------------------MODULE INIT-------------------------*/
PyObject *Geometry_Init(void)
//---------------------------------INTERSECTION FUNCTIONS--------------------
//----------------------------------Mathutils.Intersect() -------------------
static PyObject *M_Geometry_Intersect( 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);
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_Geometry_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_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);
}

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -29,6 +29,7 @@ Generate html docs by running...
sphinx-build source/blender/python/doc/sphinx-in source/blender/python/doc/sphinx-out
'''
import os
import inspect
import bpy
@@ -121,6 +122,10 @@ def pyprop2sphinx(ident, fw, identifier, py_prop):
def pymodule2sphinx(BASEPATH, module_name, module, title):
import types
# lame, python wont give some access
MethodDescriptorType = type(dict.get)
GetSetDescriptorType = type(int.real)
filepath = os.path.join(BASEPATH, module_name + ".rst")
@@ -138,21 +143,45 @@ def pymodule2sphinx(BASEPATH, module_name, module, title):
# Note, may contain sphinx syntax, dont mangle!
fw(module.__doc__.strip())
fw("\n\n")
classes = []
for attribute in dir(module):
if not attribute.startswith("_"):
value = getattr(module, attribute)
value_type = type(value)
print(attribute, value_type)
if value_type == types.FunctionType:
pyfunc2sphinx("", fw, attribute, value, is_class=False)
elif value_type in (types.BuiltinMethodType, types.BuiltinFunctionType): # both the same at the moment but to be future proof
# note: can't get args from these, so dump the string as is
# this means any module used like this must have fully formatted docstrings.
py_c_func2sphinx("", fw, attribute, value, is_class=False)
elif value_type == type:
classes.append((attribute, value))
# TODO, more types...
# write collected classes now
for (attribute, value) in classes:
# May need to be its own function
fw(".. class:: %s\n\n" % attribute)
if value.__doc__:
for l in value.__doc__.split("\n"):
fw(" %s\n" % l)
fw("\n")
for key, descr in value.__dict__.items():
if key.startswith("__"):
continue
descr_type = type(descr)
if descr_type in (MethodDescriptorType, ): # GetSetDescriptorType, GetSetDescriptorType's are not documented yet
if descr.__doc__:
for l in descr.__doc__.split("\n"):
fw(" %s\n" % l)
fw("\n")
fw("\n\n")
file.close()
@@ -186,8 +215,8 @@ def rna2sphinx(BASEPATH):
fw("\n")
fw(".. toctree::\n")
fw(" :glob:\n\n")
fw(" bpy.ops.*\n\n")
fw(" bpy.types.*\n\n")
#fw(" bpy.ops.*\n\n")
#fw(" bpy.types.*\n\n")
# py modules
fw(" bpy.utils\n\n")
@@ -196,6 +225,8 @@ def rna2sphinx(BASEPATH):
# C modules
fw(" bpy.props\n\n")
fw(" Mathutils\n\n")
file.close()
# python modules
@@ -206,6 +237,9 @@ def rna2sphinx(BASEPATH):
from bpy import props as module
pymodule2sphinx(BASEPATH, "bpy.props", module, "Blender Python Property Definitions")
import Mathutils as module
pymodule2sphinx(BASEPATH, "Mathutils", module, "Module Mathutils")
del module