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()
This commit is contained in:
@@ -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... */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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},
|
||||
|
||||
Reference in New Issue
Block a user