Drivers: add an Average Scale option to the Transform Channel driver vars.
Unlike location and rotation, there is a meaningful definition of overall/average scaling via the total change in the volume. This adds an option to retrieve that via a single driver variable, instead of having to use three and an expression. Using the determinant to compute the volume scaling also allows detecting flipping due to negative scale - this is impossible to do via the three variable approach. The volume_scale functions are added purely for code readability: 'volume scale factor' is easier to understand than determinant. Differential Revision: https://developer.blender.org/D4803
This commit is contained in:
@@ -1707,6 +1707,11 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
|
||||
/* not valid channel */
|
||||
return 0.0f;
|
||||
}
|
||||
else if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) {
|
||||
/* Cubic root of the change in volume, equal to the geometric mean
|
||||
* of scale over all three axes unless the matrix includes shear. */
|
||||
return cbrtf(mat4_to_volume_scale(mat));
|
||||
}
|
||||
else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) {
|
||||
/* Extract scale, and choose the right axis,
|
||||
* inline 'mat4_to_size'. */
|
||||
|
||||
@@ -260,6 +260,7 @@ float determinant_m2(float a, float b, float c, float d);
|
||||
float determinant_m3(
|
||||
float a, float b, float c, float d, float e, float f, float g, float h, float i);
|
||||
float determinant_m3_array(const float m[3][3]);
|
||||
float determinant_m4_mat3_array(const float m[4][4]);
|
||||
float determinant_m4(const float A[4][4]);
|
||||
|
||||
#define PSEUDOINVERSE_EPSILON 1e-8f
|
||||
@@ -277,6 +278,9 @@ void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]);
|
||||
void scale_m3_fl(float R[3][3], float scale);
|
||||
void scale_m4_fl(float R[4][4], float scale);
|
||||
|
||||
float mat3_to_volume_scale(const float M[3][3]);
|
||||
float mat4_to_volume_scale(const float M[4][4]);
|
||||
|
||||
float mat3_to_scale(const float M[3][3]);
|
||||
float mat4_to_scale(const float M[4][4]);
|
||||
float mat4_to_xy_scale(const float M[4][4]);
|
||||
|
||||
@@ -931,6 +931,13 @@ float determinant_m3_array(const float m[3][3])
|
||||
m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
|
||||
}
|
||||
|
||||
float determinant_m4_mat3_array(const float m[4][4])
|
||||
{
|
||||
return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
|
||||
m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
|
||||
m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
|
||||
}
|
||||
|
||||
bool invert_m3_ex(float m[3][3], const float epsilon)
|
||||
{
|
||||
float tmp[3][3];
|
||||
@@ -1641,6 +1648,19 @@ void mat4_to_size(float size[3], const float mat[4][4])
|
||||
size[2] = len_v3(mat[2]);
|
||||
}
|
||||
|
||||
/* This computes the overall volume scale factor of a transformation matrix.
|
||||
* For an orthogonal matrix, it is the product of all three scale values.
|
||||
* Returns a negative value if the transform is flipped by negative scale. */
|
||||
float mat3_to_volume_scale(const float mat[3][3])
|
||||
{
|
||||
return determinant_m3_array(mat);
|
||||
}
|
||||
|
||||
float mat4_to_volume_scale(const float mat[4][4])
|
||||
{
|
||||
return determinant_m4_mat3_array(mat);
|
||||
}
|
||||
|
||||
/* this gets the average scale of a matrix, only use when your scaling
|
||||
* data that has no idea of scale axis, examples are bone-envelope-radius
|
||||
* and curve radius */
|
||||
|
||||
@@ -357,6 +357,7 @@ typedef enum eDriverTarget_TransformChannels {
|
||||
DTAR_TRANSCHAN_SCALEX,
|
||||
DTAR_TRANSCHAN_SCALEY,
|
||||
DTAR_TRANSCHAN_SCALEZ,
|
||||
DTAR_TRANSCHAN_SCALE_AVG,
|
||||
|
||||
MAX_DTAR_TRANSCHAN_TYPES,
|
||||
} eDriverTarget_TransformChannels;
|
||||
|
||||
@@ -1645,6 +1645,7 @@ static void rna_def_drivertarget(BlenderRNA *brna)
|
||||
{DTAR_TRANSCHAN_SCALEX, "SCALE_X", 0, "X Scale", ""},
|
||||
{DTAR_TRANSCHAN_SCALEY, "SCALE_Y", 0, "Y Scale", ""},
|
||||
{DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""},
|
||||
{DTAR_TRANSCHAN_SCALE_AVG, "SCALE_AVG", 0, "Average Scale", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user