bugfix [#22836] Alt+MMB view alignment don't respect all axes directions

also moved rotation_between_quats_to_quat into BLI_math from python mathutils.
This commit is contained in:
Campbell Barton
2010-07-26 00:11:14 +00:00
parent cc061d075f
commit e4a7087982
4 changed files with 85 additions and 25 deletions

View File

@@ -40,10 +40,10 @@ extern "C" {
/* init */ /* init */
void unit_qt(float q[4]); void unit_qt(float q[4]);
void copy_qt_qt(float q[4], float a[4]); void copy_qt_qt(float q[4], const float a[4]);
/* arithmetic */ /* arithmetic */
void mul_qt_qtqt(float q[4], float a[4], float b[4]); void mul_qt_qtqt(float q[4], const float a[4], const float b[4]);
void mul_qt_v3(float q[4], float r[3]); void mul_qt_v3(float q[4], float r[3]);
void mul_qt_fl(float q[4], float f); void mul_qt_fl(float q[4], float f);
void mul_fac_qt_fl(float q[4], float f); void mul_fac_qt_fl(float q[4], float f);
@@ -51,6 +51,7 @@ void mul_fac_qt_fl(float q[4], float f);
void sub_qt_qtqt(float q[4], float a[4], float b[4]); void sub_qt_qtqt(float q[4], float a[4], float b[4]);
void invert_qt(float q[4]); void invert_qt(float q[4]);
void invert_qt_qt(float *q1, const float *q2);
void conjugate_qt(float q[4]); void conjugate_qt(float q[4]);
float dot_qtqt(float a[4], float b[4]); float dot_qtqt(float a[4], float b[4]);
void normalize_qt(float q[4]); void normalize_qt(float q[4]);
@@ -72,6 +73,7 @@ void tri_to_quat(float q[4], float a[3], float b[3], float c[3]);
void vec_to_quat(float q[4], float vec[3], short axis, short upflag); void vec_to_quat(float q[4], float vec[3], short axis, short upflag);
/* note: v1 and v2 must be normalized */ /* note: v1 and v2 must be normalized */
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]); void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]);
void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4]);
/* TODO: don't what this is, but it's not the same as mat3_to_quat */ /* TODO: don't what this is, but it's not the same as mat3_to_quat */
void mat3_to_quat_is_ok(float q[4], float mat[3][3]); void mat3_to_quat_is_ok(float q[4], float mat[3][3]);

View File

@@ -36,7 +36,7 @@ void unit_qt(float *q)
q[1]= q[2]= q[3]= 0.0f; q[1]= q[2]= q[3]= 0.0f;
} }
void copy_qt_qt(float *q1, float *q2) void copy_qt_qt(float *q1, const float *q2)
{ {
q1[0]= q2[0]; q1[0]= q2[0];
q1[1]= q2[1]; q1[1]= q2[1];
@@ -49,7 +49,7 @@ int is_zero_qt(float *q)
return (q[0] == 0 && q[1] == 0 && q[2] == 0 && q[3] == 0); return (q[0] == 0 && q[1] == 0 && q[2] == 0 && q[3] == 0);
} }
void mul_qt_qtqt(float *q, float *q1, float *q2) void mul_qt_qtqt(float *q, const float *q1, const float *q2)
{ {
float t0,t1,t2; float t0,t1,t2;
@@ -104,6 +104,12 @@ void invert_qt(float *q)
mul_qt_fl(q, 1.0f/f); mul_qt_fl(q, 1.0f/f);
} }
void invert_qt_qt(float *q1, const float *q2)
{
copy_qt_qt(q1, q2);
invert_qt(q1);
}
/* simple mult */ /* simple mult */
void mul_qt_fl(float *q, float f) void mul_qt_fl(float *q, float f)
{ {
@@ -336,6 +342,23 @@ void rotation_between_vecs_to_quat(float *q, const float v1[3], const float v2[3
axis_angle_to_quat(q, axis, angle); axis_angle_to_quat(q, axis, angle);
} }
void rotation_between_quats_to_quat(float *q, const float q1[4], const float q2[4])
{
float tquat[4];
double dot = 0.0f;
int x;
copy_qt_qt(tquat, q1);
conjugate_qt(tquat);
dot = 1.0f / dot_qtqt(tquat, tquat);
for(x = 0; x < 4; x++)
tquat[x] *= dot;
mul_qt_qtqt(q, tquat, q2);
}
void vec_to_quat(float *q,float *vec, short axis, short upflag) void vec_to_quat(float *q,float *vec, short axis, short upflag)
{ {
float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1; float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1;

View File

@@ -600,23 +600,66 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
/* check for view snap */ /* check for view snap */
if (vod->axis_snap){ if (vod->axis_snap){
int i; int i;
float viewmat[3][3]; float viewquat_inv[4];
float zaxis[3]={0,0,1};
invert_qt_qt(viewquat_inv, rv3d->viewquat);
mul_qt_v3(viewquat_inv, zaxis);
quat_to_mat3( viewmat,rv3d->viewquat);
for (i = 0 ; i < 39; i++){ for (i = 0 ; i < 39; i++){
float snapmat[3][3];
float view = (int)snapquats[i][4]; float view = (int)snapquats[i][4];
float viewquat_inv_test[4];
float zaxis_test[3]={0,0,1};
quat_to_mat3( snapmat,snapquats[i]); invert_qt_qt(viewquat_inv_test, snapquats[i]);
mul_qt_v3(viewquat_inv_test, zaxis_test);
if(angle_v3v3(zaxis_test, zaxis) < DEG2RAD(45/3)) {
/* find the best roll */
float quat_roll[4], quat_final[4], quat_best[4];
float viewquat_align[4]; /* viewquat aligned to zaxis_test */
float viewquat_align_inv[4]; /* viewquat aligned to zaxis_test */
float best_angle = FLT_MAX;
int j;
/* viewquat_align is the original viewquat aligned to the snapped axis
* for testing roll */
rotation_between_vecs_to_quat(viewquat_align, zaxis_test, zaxis);
normalize_qt(viewquat_align);
mul_qt_qtqt(viewquat_align, rv3d->viewquat, viewquat_align);
normalize_qt(viewquat_align);
invert_qt_qt(viewquat_align_inv, viewquat_align);
/* find best roll */
for(j= 0; j<8; j++) {
float angle;
float xaxis1[3]={1,0,0};
float xaxis2[3]={1,0,0};
float quat_final_inv[4];
axis_angle_to_quat(quat_roll, zaxis_test, j * DEG2RAD(45.0));
normalize_qt(quat_roll);
mul_qt_qtqt(quat_final, snapquats[i], quat_roll);
normalize_qt(quat_final);
/* compare 2 vector angles to find the least roll */
invert_qt_qt(quat_final_inv, quat_final);
mul_qt_v3(viewquat_align_inv, xaxis1);
mul_qt_v3(quat_final_inv, xaxis2);
angle= angle_v3v3(xaxis1, xaxis2);
if(angle <= best_angle) {
best_angle= angle;
copy_qt_qt(quat_best, quat_final);
if(j) view= 0; /* view grid assumes certain up axis */
}
}
copy_qt_qt(rv3d->viewquat, quat_best);
rv3d->view= view; /* if we snap to a rolled camera the grid is invalid */
if ((dot_v3v3(snapmat[0], viewmat[0]) > thres) &&
(dot_v3v3(snapmat[1], viewmat[1]) > thres) &&
(dot_v3v3(snapmat[2], viewmat[2]) > thres)
) {
copy_qt_qt(rv3d->viewquat, snapquats[i]);
rv3d->view= view;
break; break;
} }
} }

View File

@@ -190,9 +190,7 @@ static char Quaternion_Difference_doc[] =
static PyObject *Quaternion_Difference(QuaternionObject * self, QuaternionObject * value) static PyObject *Quaternion_Difference(QuaternionObject * self, QuaternionObject * value)
{ {
float quat[QUAT_SIZE], tempQuat[QUAT_SIZE]; float quat[QUAT_SIZE];
double dot = 0.0f;
int x;
if (!QuaternionObject_Check(value)) { if (!QuaternionObject_Check(value)) {
PyErr_SetString( PyExc_TypeError, "quat.difference(value): expected a quaternion argument" ); PyErr_SetString( PyExc_TypeError, "quat.difference(value): expected a quaternion argument" );
@@ -202,14 +200,8 @@ static PyObject *Quaternion_Difference(QuaternionObject * self, QuaternionObject
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL; return NULL;
copy_qt_qt(tempQuat, self->quat); rotation_between_quats_to_quat(quat, self->quat, value->quat);
conjugate_qt(tempQuat);
dot = sqrt(dot_qtqt(tempQuat, tempQuat));
for(x = 0; x < QUAT_SIZE; x++) {
tempQuat[x] /= (float)(dot * dot);
}
mul_qt_qtqt(quat, tempQuat, value->quat);
return newQuaternionObject(quat, Py_NEW, NULL); return newQuaternionObject(quat, Py_NEW, NULL);
} }