diff --git a/modules/touch/ext/levmarq.cpp b/modules/touch/ext/levmarq.cpp index b0add0228a..a36a0605ca 100644 --- a/modules/touch/ext/levmarq.cpp +++ b/modules/touch/ext/levmarq.cpp @@ -33,8 +33,8 @@ void levmarq_init(LMstat *lmstat) { lmstat->verbose = 0; lmstat->max_it = 5000; lmstat->init_lambda = 1e-6; - lmstat->up_factor = 5; - lmstat->down_factor = 5; + lmstat->up_factor = 10; + lmstat->down_factor = 10; lmstat->target_derr = 1e-12; } diff --git a/modules/touch/include/TouchInteraction.h b/modules/touch/include/TouchInteraction.h index d1a0edf507..2d1a57d56a 100644 --- a/modules/touch/include/TouchInteraction.h +++ b/modules/touch/include/TouchInteraction.h @@ -144,6 +144,8 @@ class TouchInteraction : public properties::PropertyOwner LMstat _lmstat; glm::dvec3 _centroid; + glm::dquat _toSlerp; + double _time; VelocityStates _vel; ScaleFactor _friction; ScaleFactor _sensitivity; diff --git a/modules/touch/src/TouchInteraction.cpp b/modules/touch/src/TouchInteraction.cpp index bba7227341..41162e5f6f 100644 --- a/modules/touch/src/TouchInteraction.cpp +++ b/modules/touch/src/TouchInteraction.cpp @@ -65,6 +65,7 @@ TouchInteraction::TouchInteraction() _sensitivity{ 2.0, 0.1, 0.1, 0.1, 0.4 }, _projectionScaleFactor{ 1.000004 }, // calculated with two vectors with known diff in length, then projDiffLength/diffLength. _currentRadius{ 1.0 }, + _time{ 0.0 }, _directTouchMode{ false }, _tap{ false } { addProperty(_touchScreenSize); @@ -169,24 +170,26 @@ void TouchInteraction::manipulate(const std::vector& list) { return glm::length(ptr->screenPoints.at(x) - newScreenPoint); }; - // Gradient (finite derivative) of distToMinimize w.r.t par + // Gradient of distToMinimize w.r.t par (using central difference) auto gradient = [](double* g, double* par, int x, void* fdata) { FunctionData* ptr = reinterpret_cast(fdata); double f0 = ptr->distToMinimize(par, x, fdata); - double f1, der, minStep = 1e-11; + double f1, f2, der, minStep = 1e-11; glm::dvec3 camPos = ptr->camera->positionVec3(); glm::dvec3 selectedPoint = (ptr->node->rotationMatrix() * ptr->selectedPoints.at(x)) + ptr->node->worldPosition(); double h = minStep * glm::distance(camPos, selectedPoint); double* dPar = new double[ptr->nDOF]; + for (int i = 0; i < ptr->nDOF; ++i) { + dPar[i] = par[i]; + } for (int i = 0; i < ptr->nDOF; ++i) { - for (int j = 0; j < ptr->nDOF; ++j) { - dPar[j] = par[j]; - } h = (i == 2) ? 1e-4 : h; // the 'zoom'-DOF is so big a smaller step creates NAN dPar[i] += h; f1 = ptr->distToMinimize(dPar, x, fdata); + dPar[i] -= h; der = (f1 - f0) / h; + g[i] = (i > 1 && i < 4) ? der : der / abs(der); } delete[] dPar; @@ -357,14 +360,14 @@ void TouchInteraction::interpret(const std::vector& list, const std: _action.pick = false; } else { - if (std::abs(dist - lastDist)/list.at(0).getMotionSpeed() < 0.01 && list.size() == 2) { + if (std::abs(dist - lastDist)/list.at(0).getMotionSpeed() < 0.01 && list.size() == 3) { _action.rot = false; _action.pinch = false; _action.pan = true; _action.roll = false; _action.pick = false; } - else if (list.size() > 2 && std::abs(minDiff) < 0.0008) { + else if (list.size() > 1 && std::abs(minDiff) < 0.0008) { // if one finger is still and another moving, we have roll _action.rot = false; _action.pinch = false; _action.pan = false; @@ -428,33 +431,19 @@ void TouchInteraction::accelerate(const std::vector& list, const std if (_selected.size() == 1 && _selected.at(0).node != _focusNode) { _focusNode = _selected.at(0).node; // rotate camera to look at new focus OsEng.interactionHandler().setFocusNode(_focusNode); // cant do setFocusNode since TouchInteraction is not subclass of InteractionMode - glm::dvec3 camToFocus = glm::normalize(_focusNode->worldPosition() - _camera->positionVec3()); - glm::dvec3 camForward = glm::normalize(_camera->viewDirectionWorldSpace()); + glm::dvec3 camToFocus = _focusNode->worldPosition() - _camera->positionVec3(); glm::dvec3 camUp = glm::normalize(_camera->lookUpVectorWorldSpace()); - glm::dvec3 camRight = glm::normalize(glm::cross(camUp, camForward)); - - - glm::dvec2 angles = glm::dvec2(0.0); - - - glm::dvec3 directionToCenter = normalize(_focusNode->worldPosition() - _camera->positionVec3()); - glm::dvec3 lookUp = _camera->lookUpVectorWorldSpace(); - glm::dvec3 camDirection = _camera->viewDirectionWorldSpace(); - - // Make a representation of the rotation quaternion with local and global rotations - glm::dmat4 lookAtMat = lookAt( - glm::dvec3(0, 0, 0), - directionToCenter, - glm::normalize(camDirection + lookUp)); // To avoid problem with lookup in up direction - glm::dquat globalCamRot = normalize(quat_cast(inverse(lookAtMat))); - glm::dquat localCamRot = inverse(globalCamRot) * _camera->rotationQuaternion() * glm::dquat(glm::dvec3(angles.y, angles.x, 0.0)); - - _camera->setRotation(globalCamRot * localCamRot); - /// - + glm::dvec3 camForward = glm::normalize(_camera->viewDirectionWorldSpace()); + double angle = glm::angle(camForward, camToFocus); + glm::dvec3 axis = glm::normalize(glm::cross(camForward, camToFocus)); + _toSlerp.x = axis.x * sin(angle / 2.0); + _toSlerp.y = axis.y * sin(angle / 2.0); + _toSlerp.z = axis.z * sin(angle / 2.0); + _toSlerp.w = cos(angle / 2.0); + _time = 0.0; } - else { // should zoom in to current _selected.coordinates position + else { // should zoom in to current _selected.coordinates position but not further than _directTouchMode activation double dist = glm::distance(_camera->positionVec3(), _camera->focusPositionVec3()) - _focusNode->boundingSphere(); double startDecline = _focusNode->boundingSphere() / (0.15 * _projectionScaleFactor); double factor = 2.0; @@ -507,6 +496,12 @@ void TouchInteraction::step(double dt) { dvec3 eulerAngles(_vel.localRot.y*dt, _vel.localRot.x*dt, 0); dquat rotationDiff = dquat(eulerAngles); localCamRot = localCamRot * rotationDiff; + + // if we have chosen a new focus node + if (_time < 1) { + _time += 0.5 * dt; + localCamRot = slerp(localCamRot, _toSlerp, _time); + } } { // Orbit (global rotation) dvec3 eulerAngles(_vel.globalRot.y*dt, _vel.globalRot.x*dt, 0);