ndof trackball works... somehow
This commit is contained in:
@@ -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));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user