diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-10-26 16:48:07 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-10-26 16:48:07 +0400 |
commit | f8ec6b8654962cd2fc77b9941f35c8127d37fc90 (patch) | |
tree | be28affb99be07434be6301d7b91f458b688ae4d /source | |
parent | 30b4fa2aa839e7dba72d6d913fd0bff5cc816e43 (diff) |
move matrix decomposition out of object.c into BLI_math_matrix function: mat4_to_loc_rot_size(), use this now for pchan_apply_mat4() to support negative scale, visual keying now uses compatible eulers.
also added access to this in python's mathutils.Matrix()
loc, quat, scale = matrix.decompose()
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_armature.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 40 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 51 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_matrix.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_matrix.c | 42 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature.c | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_pose.c | 2 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_matrix.c | 37 |
8 files changed, 115 insertions, 64 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 466b5d9a845..06e24431df4 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -105,7 +105,8 @@ void armature_mat_pose_to_bone(struct bPoseChannel *pchan, float inmat[][4], flo void armature_loc_pose_to_bone(struct bPoseChannel *pchan, float *inloc, float *outloc); void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4]); -void pchan_apply_mat4(struct bPoseChannel *pchan, float mat[][4]); +void pchan_mat3_to_rot(struct bPoseChannel *pchan, float mat[][3], short use_compat); +void pchan_apply_mat4(struct bPoseChannel *pchan, float mat[][4], short use_comat); void pchan_to_mat4(struct bPoseChannel *pchan, float chan_mat[4][4]); /* Rotation Mode Conversions - Used for PoseChannels + Objects... */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 029b3c2e141..b44bf751a8a 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1177,32 +1177,30 @@ void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc) VECCOPY(outloc, nLocMat[3]); } +/* same as object_mat3_to_rot() */ +void pchan_mat3_to_rot(bPoseChannel *pchan, float mat[][3], short use_compat) +{ + switch(pchan->rotmode) { + case ROT_MODE_QUAT: + mat3_to_quat(pchan->quat, mat); + break; + case ROT_MODE_AXISANGLE: + mat3_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, mat); + break; + default: /* euler */ + if(use_compat) mat3_to_compatible_eulO(pchan->eul, pchan->eul, pchan->rotmode, mat); + else mat3_to_eulO(pchan->eul, pchan->rotmode, mat); + } +} /* Apply a 4x4 matrix to the pose bone, * similar to object_apply_mat4() */ -void pchan_apply_mat4(bPoseChannel *pchan, float mat[][4]) +void pchan_apply_mat4(bPoseChannel *pchan, float mat[][4], short use_compat) { - /* location */ - copy_v3_v3(pchan->loc, mat[3]); - - /* scale */ - mat4_to_size(pchan->size, mat); - - /* rotation */ - if (pchan->rotmode == ROT_MODE_AXISANGLE) { - float tmp_quat[4]; - - /* need to convert to quat first (in temp var)... */ - mat4_to_quat(tmp_quat, mat); - quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, tmp_quat); - } - else if (pchan->rotmode == ROT_MODE_QUAT) { - mat4_to_quat(pchan->quat, mat); - } - else { - mat4_to_eulO(pchan->eul, pchan->rotmode, mat); - } + float rot[3][3]; + mat4_to_loc_rot_size(pchan->loc, rot, pchan->size, mat); + pchan_mat3_to_rot(pchan, rot, use_compat); } /* Remove rest-position effects from pose-transform for obtaining diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 9d93fac8ad0..5ade08478a2 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1680,54 +1680,25 @@ void object_rot_to_mat3(Object *ob, float mat[][3]) void object_mat3_to_rot(Object *ob, float mat[][3], short use_compat) { - if (ob->rotmode == ROT_MODE_QUAT) + switch(ob->rotmode) { + case ROT_MODE_QUAT: mat3_to_quat(ob->quat, mat); - else if (ob->rotmode == ROT_MODE_AXISANGLE) + break; + case ROT_MODE_AXISANGLE: mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat); - else { - if(use_compat) { - float eul[3]; - VECCOPY(eul, ob->rot); - mat3_to_compatible_eulO(ob->rot, eul, ob->rotmode, mat); - } - else - mat3_to_eulO(ob->rot, ob->rotmode, mat); + break; + default: /* euler */ + if(use_compat) mat3_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, mat); + else mat3_to_eulO(ob->rot, ob->rotmode, mat); } } /* see pchan_apply_mat4() for the equivalent 'pchan' function */ void object_apply_mat4(Object *ob, float mat[][4], short use_compat) { - float mat3[3][3]; /* obmat -> 3x3 */ - float mat3_n[3][3]; /* obmat -> normalized, 3x3 */ - float imat3_n[3][3]; /* obmat -> normalized & inverted, 3x3 */ - - /* location */ - copy_v3_v3(ob->loc, mat[3]); - - /* rotation & scale are linked, we need to create the mat's - * for these together since they are related. */ - copy_m3_m4(mat3, mat); - /* so scale doesnt interfear with rotation [#24291] */ - /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */ - normalize_m3_m3(mat3_n, (const float(*)[3])mat3); - if(is_negative_m3(mat3_n)) { - negate_v3(mat3_n[0]); - negate_v3(mat3_n[1]); - negate_v3(mat3_n[2]); - } - - /* rotation */ - object_mat3_to_rot(ob, mat3_n, use_compat); - - /* scale */ - /* note: mat4_to_size(ob->size, mat) fails for negative scale */ - invert_m3_m3(imat3_n, mat3_n); - mul_m3_m3m3(mat3, imat3_n, mat3); - - ob->size[0]= mat3[0][0]; - ob->size[1]= mat3[1][1]; - ob->size[2]= mat3[2][2]; + float rot[3][3]; + mat4_to_loc_rot_size(ob->loc, rot, ob->size, mat); + object_mat3_to_rot(ob, rot, use_compat); } void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index d25707d480c..76de8f827be 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -144,6 +144,8 @@ void mat4_to_size(float r[3], float M[4][4]); void translate_m4(float mat[4][4], float tx, float ty, float tz); void rotate_m4(float mat[4][4], const char axis, const float angle); +void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[][4]); + void loc_eul_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3]); void loc_eulO_size_to_mat4(float R[4][4], diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 86eee4c2202..80d7709f3a9 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -952,6 +952,48 @@ float mat4_to_scale(float mat[][4]) return mat3_to_scale(tmat); } +void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[][4]) +{ + float mat3[3][3]; /* wmat -> 3x3 */ + float mat3_n[3][3]; /* wmat -> normalized, 3x3 */ + float imat3_n[3][3]; /* wmat -> normalized & inverted, 3x3 */ + short is_neg; + /* location */ + copy_v3_v3(loc, wmat[3]); + + /* rotation & scale are linked, we need to create the mat's + * for these together since they are related. */ + copy_m3_m4(mat3, wmat); + /* so scale doesnt interfear with rotation [#24291] */ + /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */ + is_neg= is_negative_m3(mat3); + normalize_m3_m3(mat3_n, (const float(*)[3])mat3); + if(is_neg) { + negate_v3(mat3_n[0]); + negate_v3(mat3_n[1]); + negate_v3(mat3_n[2]); + } + + /* rotation */ + /* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */ + copy_m3_m3(rot, mat3_n); + + /* scale */ + /* note: mat4_to_size(ob->size, mat) fails for negative scale */ + invert_m3_m3(imat3_n, mat3_n); + mul_m3_m3m3(mat3, imat3_n, mat3); + + size[0]= mat3[0][0]; + size[1]= mat3[1][1]; + size[2]= mat3[2][2]; + + /* with a negative matrix, all scaled will be negative + * flipping isnt needed but nicer to result in a positive scale */ + if(is_neg) { + negate_v3(size); + } +} + void scale_m3_fl(float m[][3], float scale) { m[0][0]= m[1][1]= m[2][2]= scale; diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 28165c0e018..fd747cc32aa 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -681,7 +681,7 @@ static int pose_visual_transform_apply_exec (bContext *C, wmOperator *UNUSED(op) invert_m4_m4(imat, pchan->pose_mat); mul_m4_m4m4(delta_mat, mat, imat); - pchan_apply_mat4(pchan, delta_mat); + pchan_apply_mat4(pchan, delta_mat, TRUE); where_is_pose_bone(scene, ob, pchan, CFRA, 1); } diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index e4a3be023ca..b4a132dd1ec 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -550,7 +550,7 @@ static void rna_PoseChannel_matrix_local_get(PointerRNA *ptr, float *values) static void rna_PoseChannel_matrix_local_set(PointerRNA *ptr, const float *values) { bPoseChannel *pchan= (bPoseChannel*)ptr->data; - pchan_apply_mat4(pchan, (float (*)[4])values); + pchan_apply_mat4(pchan, (float (*)[4])values, FALSE); /* no compat for pradictable result */ } #else diff --git a/source/blender/python/generic/mathutils_matrix.c b/source/blender/python/generic/mathutils_matrix.c index 36a9bf8b55d..c74ec3536e5 100644 --- a/source/blender/python/generic/mathutils_matrix.c +++ b/source/blender/python/generic/mathutils_matrix.c @@ -942,6 +942,7 @@ PyObject *Matrix_scalePart(MatrixObject * self) scale[2]= tmat[2][2]; return newVectorObject(scale, 3, Py_NEW, NULL); } + /*---------------------------Matrix.invert() ---------------------*/ static char Matrix_Invert_doc[] = ".. method:: invert()\n" @@ -1009,6 +1010,41 @@ PyObject *Matrix_Invert(MatrixObject * self) return (PyObject *)self; } +/*---------------------------Matrix.decompose() ---------------------*/ +static char Matrix_decompose_doc[] = +".. method:: decompose()\n" +"\n" +" Return the location, rotaion and scale components of this matrix.\n" +"\n" +" :return: loc, rot, scale triple.\n" +" :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)"; +static PyObject *Matrix_decompose(MatrixObject * self) +{ + PyObject *ret; + float loc[3]; + float rot[3][3]; + float quat[4]; + float size[3]; + + if(self->colSize != 4 || self->rowSize != 4) { + PyErr_SetString(PyExc_AttributeError, "Matrix.decompose(): inappropriate matrix size - expects 4x4 matrix\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(self)) + return NULL; + + mat4_to_loc_rot_size(loc, rot, size, (float (*)[4])self->contigPtr); + mat3_to_quat(quat, rot); + + ret= PyTuple_New(3); + PyTuple_SET_ITEM(ret, 0, newVectorObject(loc, 3, Py_NEW, NULL)); + PyTuple_SET_ITEM(ret, 1, newQuaternionObject(quat, Py_NEW, NULL)); + PyTuple_SET_ITEM(ret, 2, newVectorObject(size, 3, Py_NEW, NULL)); + + return ret; +} + /*---------------------------Matrix.determinant() ----------------*/ static char Matrix_Determinant_doc[] = @@ -1755,6 +1791,7 @@ static struct PyMethodDef Matrix_methods[] = { {"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}, + {"decompose", (PyCFunction) Matrix_decompose, METH_NOARGS, Matrix_decompose_doc}, {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc}, {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc}, {"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc}, |