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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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, ¶m)) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user