From BlenderWiki

Jump to: navigation, search

Mathutils API Update

Recently a patch was submitted [#25747], which highlights some problems with the mathutils API which I have also noticed from my use of mathutils for testing tools and import/exporters.

I ran these changes by Uncle_Entity, dougal2 & z0r on IRC before writing up the proposal for initial feedback and have now written down the proposed changes in detail.

--Ideasman42 10:51, 3 February 2011 (UTC)

Coerce Method Arguments

At the moment passing fixed values to a function is annoying because you must use mathutils constructors, or assign a value beforehand for reuse.

>>> myvec.cross(Vector((0, 0, 1)))

... but we could also accept

>>> myvec.cross((0, 0, 1))

Same with vec.angle(other), quat.difference((...))

This will NOT extend to operators

>>> Vector(...) + (1,2,3)
>>> Vector(...) + Euler(...)

Seems convenient but introduces ambiguity as to what is the return type, and confuses which operators have special behavior such as Vector() * Matrix().

It also means the first value:

>>> (x, y, z, x) * Matrix()

Could be treated as a 4d vector or a quaternion.

Separate Modify In-Place Methods

Clear separation between methods which modify in-place and ones which return new values.

At the moment this backfires in common cases when modifying wrapped data is not intended:

>>> imat = obj.matrix_world.invert() * othermat # edits object.
>>> imat = obj.matrix_world.copy().invert() * othermat # ok.

mathutils wrapped types are used in the GameEngine and for many RNA types so I think its worth avoiding confusion here.

I propose to have 2 methods in cases such as this.

>>> matrix.invert()  # Inverts in-place, returns None
>>> matrix.inverted()  # Returns a new, inverted matrix.

Same with normalize / normalized, transpose / transposed... etc.


Rename Methods

  • matrix/euler.to_quat() --> to_quaternion()
    This abbreviation isnt used anywhere else in mathutils.
  • matrix.rotation_part() --> matrix.to_3x3()
    rotation_part() also contains scale which is misleading.
  • matrix.translation_part() --> to_translation()
  • scale_part() --> to_scale()
    At the moment we have matrix methods rotation_part() / scale_part() / translation_part().
    The method naming implies that together they will decompose the matrix, but as noted above this is not the case.
    Since these methods were written I have added...
>>> loc, rot, scale = matrix.decompose()

So I'm proposing to drop the *_part() suffix and have this in keeping with: matrix.to_euler(), to_quat(), to_3x3()

  • matrix.resize3x3 --> resize_3x3(), better matches to_3x3().

Consistent Matrix Constructor Argument order

At the moment Matrix constructor order is mixed.

>>> mathutils.Matrix.Rotation(angle, matrix_size, axis)
>>> mathutils.Matrix.Scale(factor, matrix_size, axis)
>>> mathutils.Matrix.Shear(plane, factor, matrix_size)  # <-- Odd one out
>>> mathutils.Matrix.OrthoProjection(plane, matrix_size, axis)
>>> mathutils.Matrix.Translation(vector)