ndof trackball works... somehow

This commit is contained in:
2011-06-20 21:34:23 +00:00
parent 0faeffb8a5
commit 4030f82aad

View File

@@ -949,6 +949,25 @@ float ndof_to_angle_axis(const float ndof[3], float axis[3])
return angular_velocity; return angular_velocity;
} }
void ndof_to_quat(wmNDOFMotionData* ndof, float q[4])
{
const float x = ndof->rx;
const float y = ndof->ry;
const float z = ndof->rz;
float angular_velocity = sqrtf(x*x + y*y + z*z);
float angle = ndof->dt * angular_velocity;
// combined scaling factor -- normalize axis while converting to quaternion
float scale = sin(0.5f * angle) / angular_velocity;
// convert axis-angle to quaternion
q[0] = cos(0.5f * angle);
q[1] = scale * x;
q[2] = scale * y;
q[3] = scale * z;
}
// Mike's version // Mike's version
static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event)
{ {
@@ -964,7 +983,7 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event)
if (dt > 0.25f) if (dt > 0.25f)
/* this is probably the first event for this motion, so set dt to something reasonable */ /* this is probably the first event for this motion, so set dt to something reasonable */
/* TODO: replace such guesswork with a flag or field from the NDOF manager */ /* TODO: replace such guesswork with a flag or field from the NDOF manager */
dt = 0.0125f; ndof->dt = dt = 0.0125f;
if (has_rotation) if (has_rotation)
@@ -972,37 +991,29 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event)
if (has_rotation) { if (has_rotation) {
if (U.flag & USER_TRACKBALL) { if (U.flag & USER_TRACKBALL) {
/* TODO: write trackball code! */
float axis[3] = {ndof->rx, ndof->ry, ndof->rz}; float rot[4];
float angle = sensitivity * dt * ndof_to_angle_axis(axis, axis); float view_inv[4], view_inv_conj[4];
float rotation[4], rotationconj[4];
float view[4], viewconj[4];
// convert to quaternion ndof_to_quat(ndof, rot);
axis_angle_to_quat(rotation, axis, angle);
// extract rotation component of viewquat // swap y and z -- not sure why, but it works
copy_qt_qt(view, rv3d->viewquat); {
invert_qt(view); float temp = -rot[2]; // also invert device y
normalize_qt(view); rot[2] = rot[3];
copy_qt_qt(viewconj, view); rot[3] = temp;
conjugate_qt(viewconj); }
// transform device rotation into view's frame of reference invert_qt_qt(view_inv, rv3d->viewquat);
// rotation(view) = view * rotation(world) * viewconj copy_qt_qt(view_inv_conj, view_inv);
mul_qt_qtqt(rotation, rotation, viewconj); conjugate_qt(view_inv_conj);
mul_qt_qtqt(rotation, view, rotation);
// apply rotation to obtain new viewpoint // transform rotation from view to world coordinates
// copy_qt_qt(rotationconj, rotation); mul_qt_qtqt(rot, view_inv, rot);
// conjugate_qt(rotationconj); mul_qt_qtqt(rot, rot, view_inv_conj);
// mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotationconj);
// mul_qt_qtqt(rv3d->viewquat, rotation, rv3d->viewquat);
mul_qt_qtqt(rv3d->viewquat, rotation, rv3d->viewquat);
// this is *close* to trackball behavior // apply rotation
// rotation axis needs to remain fixed relative to viewpoint, not world coordinates mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
ED_region_tag_redraw(CTX_wm_region(C)); ED_region_tag_redraw(CTX_wm_region(C));