利用者:Migius/orientation matrix
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.
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.
new method
new method apply_matrix():
- relies on functions: matrix_to_scale() and matrix_to_euler()
- algorithmus:
- input: orientation-matrix
- analyze matrix if LeftHand-Matrix
- extract scaleVector from matrix
- if LeftHand-Matrix: convert scaleVector-(X,Y,Z) to (X,Y,-Z)
- extract XYZ-euler from matrix
- if scaleVector[Z] is negative: recalculate XYZ-euler in LeftHand-system
- 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
- transcoding: Python to C
- check, if replacement in source code will brake existing functionality
- documentation, description
- report to bug-tracker
- report to patch-tracker
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.
(*) 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.