From BlenderWiki

Jump to: navigation, search
Note: This is an archived version of the Blender Developer Wiki. The current and active wiki is available on wiki.blender.org.

this page is dedicated to solve some issues in orientation-matrix in Blender <2.50

2009.09.16: WIP

Intro

Current implementation of orientation-matrix system in Blender is not reliable: there are limitations / some nasty problems with mirrored/non-uniform-scaled geometry in Blender

Perhaps, it is not a bug, but a system design side-effect: insufficient/incomplete representation method of object orientation data with "all-in-one loc/rot/scale-matrix".

Orientation System

Blender orientation-matrix is an orthogonal_matrix. Applying non-orthogonal-matrix (e.g. shear-matrix) doesn't work - it is on-the-fly transformed into orthogonal-matrix, so some information is lost or corrupted.

RGB-boxes represent matrix (its XYZ-vectors)

get_matrix()

WIP: implemented in PyAPI: getMatrix(object), object.matrixLocal(), object.matrixWorld()

apply_matrix

current implementation

  • used in: PyAPI.object.setMatrix(matrix), clear_parent(), apply_obmat()
  • involved functions: matrix_to_euler() and matrix_to_scale()
  • current implementation, issues:
    • incorrect resulting object-orientation and/or object-scale, if given matrix is left-hand-oriented (mirrored objects = uneven number of negative scale factors)
    • no support for shear-matrix
  • tests: "old" is produced with current apply_method, "new" with new method prototyped in python.
non-uniform scale + Z-rotation: correct.
negative scale + Z-rotation: correct.
non-uniform scale + XYZ-rotation: correct.
negative scale + XYZ-rotation: old_method fails.


new method

new method apply_matrix():

  • relies on functions: matrix_to_scale() and matrix_to_euler()
  • algorithmus:
    1. input: orientation-matrix
    2. analyze matrix if LeftHand-Matrix
    3. extract scaleVector from matrix
    4. if LeftHand-Matrix: convert scaleVector-(X,Y,Z) to (X,Y,-Z)
    5. extract XYZ-euler from matrix
    6. if scaleVector[Z] is negative: recalculate XYZ-euler in LeftHand-system
    7. output: scaleVector and XYZ-euler

matrix_to_scale()

implemented in arithb_c: Mat3ToSize(), Mat4ToSize()

used in: matrix.getScale() WIP: existing method: matrix.scalePart()

The new method respects negative scale-factors:

calculate scale values from lengths of axis vectors
if uneven number of negative scale factors given, that means left-hand-matrix,
   then set scaleZ negative *)

todo: *) it is not a perfect solution yet. We need a method to estimate proper euler_angles relation to negative scaling (=mirrored orientation-axes).

--------------- Dependances:

Mat3ToSize() : Referenced by:

apply_targetless_ik(),
ElementBoneSize(),
ElementResize(),
Mat3BlendMat3(),
PoseBone_setLocalMatrix().

Mat4ToSize() : Referenced by:

actcon_get_tarmat(),
apply_objects_visual_tx(),
childof_evaluate(),
constraintSizeLim(),
do_strip_modifiers(),
do_viewbuts(),
followpath_evaluate(),
generateSkeletonFromReebGraph(),
Mat4BlendMat4(),
Mat4ToDQuat(),
pose_copy_menu(),
PoseBone_setLocalMatrix(),
PoseBone_setPoseMatrix(),
posechannel_get_local_transform(),
rotlike_evaluate(),
rotlimit_evaluate(),
sizelike_evaluate(),
sizelimit_evaluate(),
stretchto_evaluate(),
trackto_evaluate(),
transform_evaluate(),
view3d_panel_object().

matrix_to_euler()

implemented in arithb_c: Mat3ToEul(), mat3_to_eul2()

The new method recognize mirrored matrices:

get rotationPart from the matrix
left-hand-matrix detection (if negative scaleZ-factor there)
if right-hand-matrix, then standard calculation of euler_angles
if left-hand-matrix, then alternative calculation

---------------- Dependences:

Mat3ToEul() : Referenced by:

apply_armature_pose2bones(),
apply_obmat(),
euler_rot(),
Mat4ToEul(),
Matrix_scalePart(),
Matrix_toEuler(),
Object_GetEuler(),
Object_getSize(),
QuatToEul(),
read_videoscape_nurbs(),
KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo(),
KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo()

Mat4ToEul() : Referenced by:

actcon_get_tarmat(),
apply_objects_visual_tx(),
childof_evaluate(),
constraintRotLim(),
do_strip_modifiers(),
generateSkeletonFromReebGraph(),
posechannel_get_local_transform(),
KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo(),
rotlike_evaluate(),
rotlimit_evaluate(),
transform_evaluate(),
visualkey_get_value().
used in: matrix.getEuler()

euler_rot : Referenced by:

Euler_Rotate(),
rotlike_evaluate().

Patch

  • arithb_c.patch (2009.03.25) - the patch for 2.48a svn rev.19305. Tested successfully on winXP32+scons+minGW

Todo

  • prototyping and testing in python 100%.png
  • transcoding: Python to C 100%.png
  • check, if replacement in source code will brake existing functionality 50%.png
  • documentation, description 50%.png
  • report to bug-tracker 100%.png
  • report to patch-tracker 00%.png

inverse_matrix

current implementation

  • needed in Blender in many places, intern and by PyAPI
  • current implementation: matrix.inverse()
    • mathematically correct, e.g. matrix.inverse().inverse() gives back the same matrix
    • but geometrically not feasible in Blender, because resulting inverse_matrix is sometimes non-conform to Blender-orientation-system
    • especially: if given matrix has rotation and non-uniform-scaling, final matrix become shear (non-orthogonal-matrix). Blender cant handle it correctly.
    • tests: "old" is produced with current inverse_method, "new" with new method prototyped in python.
if no_rotation: all perfect.
if rotation: errors, old_method produces shear-matrix!
negative_scale* + no_rotation: all perfect.
negative_scale* + rotation: errors, shear-matrix!

(*) tests made with new apply_matrix method, so negative_scale errors not appeared

new method (proposal)*

(*) Very early stage, WIP. I am not quite sure, if we even need this sort of functionality with inverse matrices. With current implementation i suspect some issues with non-uniform-scaled rotated objects in parent-trees, but it needs more investigation.

New method should solve some limitations / problems with mirrored/non-uniform-scaled parented geometry in Blender.

Idea

  • new paradigm for handle with orientation_matrices: not mathematical, but geometrical oriented method
  • the system must preserve critical orientation parameters like object's scale and orientation-angles, during entire transforming process, regardless of number and type of transformations

Goals

bug-free, lossless, unambiguous and reversible transforming procedures, like:

  • converting representation e.g. from "matrix" to "euler/scale"-form
  • transforming orientation_matrix
  • converting orientation_matrix to any level in parent-hierarchies, (= preserving orientation-data)

Pros

more stable and reliable work with:

  • (?) armatures
  • (?) parenting-systems
  • (?) import/export routines
  • (?) animation (IPO-curves continuity in sizeXYZ, rotXYZ)

inverse_matrix()

The new method is a geometrical equivalent of mathematical matrix.inverse() method:

  • more visually comprehensible / more intuitive
  • direct usable as object_matrix in Blender
matrix split to two components: scale_vector and eulers
inverse_scale_vector = 1 / (scale_vector)
[1, 4, -2] -> [1, 0.25, -0.5]
[1, 0.5, -2] -> [1, 2, -0.5]
inverse_eulers = (eulers)* -1
[30,0,0] -> [-30,0,0]
[30,-20,0] -> [-30,20,0]
for 4x4_matrix: inverse_location_vector = (loc_vector)* -1
[1, 4, -2] -> [-1, -4, 2]
re-generate inverted_matrix on basis of inverse_(loc/rot/scale)_vectors

Patch

Although python prototype evaluated successfully, writing a patch in C will take a while, cause it needs a deeper analyze of dependencies in source code. Probably inverseMatrix calculation is not exclusively used for object orientation purposes.

Todo

  • prototyping and testing in python 100%.png
  • transcoding: Python to C 00%.png
  • check, if replacement in source code will brake existing functionality 25%.png
  • documentation, description 50%.png
  • report to bug-tracker 00%.png
  • report to patch-tracker 00%.png