/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2016 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ //#define USE_OLD_INTERACTIONHANDLER #ifdef USE_OLD_INTERACTIONHANDLER #include #include #include #include namespace openspace { namespace interaction { MouseController::MouseController() : _lastTrackballPos(0.f) , _isMouseBeingPressedAndHeld(false) {} glm::vec3 MouseController::mapToTrackball(glm::vec2 mousePos) { const float RADIUS = 0.5; // Sphere radius glm::vec3 out = glm::vec3(mousePos.x - 0.5, -1.0*(mousePos.y - 0.5), 0); // Mapping according to Holroyds trackball // Piece-wise sphere + hyperbolic sheet if (out.x*out.x + out.y*out.y <= RADIUS*RADIUS / 2.0) { //Spherical Region out.z = RADIUS*RADIUS - (out.x*out.x + out.y*out.y); out.z = out.z > 0.0f ? sqrtf(out.z) : 0.0f; } else { //Hyperbolic Region - for smooth z values out.z = (RADIUS*RADIUS) / (2.0f*sqrt(out.x*out.x + out.y*out.y)); } return glm::normalize(out); } glm::vec3 MouseController::mapToCamera(glm::vec3 trackballPos) { //Get x,y,z axis vectors of current camera view glm::vec3 currentViewYaxis = glm::normalize(_handler->camera()->lookUpVectorCameraSpace()); psc viewDir = _handler->camera()->position() - _handler->focusNode()->worldPosition(); glm::vec3 currentViewZaxis = glm::normalize(viewDir.vec3()); glm::vec3 currentViewXaxis = glm::normalize(glm::cross(currentViewYaxis, currentViewZaxis)); //mapping to camera co-ordinate currentViewXaxis *= trackballPos.x; currentViewYaxis *= trackballPos.y; currentViewZaxis *= trackballPos.z; return (currentViewXaxis + currentViewYaxis + currentViewZaxis); } void MouseController::trackballRotate(int x, int y) { // Normalize mouse coordinates to [0,1] glm::vec2 res = OsEng.windowWrapper().currentWindowSize(); glm::vec2 mousePos = glm::vec2((float)x / res.x, (float)y / res.y); mousePos = glm::clamp(mousePos, -0.5f, 1.5f); // Ugly fix #1: Camera position becomes NaN on mouse values outside [-0.5, 1.5] //mousePos[1] = 0.5; // Ugly fix #2: Tempoarily only allow rotation around y glm::vec3 curTrackballPos = mapToTrackball(mousePos); // LDEBUG(mousePos.x << ", " << mousePos.y << " = " << curTrackballPos.x << ", " << curTrackballPos.y << ", " << curTrackballPos.z); // Disable movement on the first click for extra smoothness if (!_isMouseBeingPressedAndHeld) { _lastTrackballPos = curTrackballPos; _isMouseBeingPressedAndHeld = true; } if (curTrackballPos != _lastTrackballPos) { // calculate rotation angle (in radians) float rotationAngle = glm::angle(curTrackballPos, _lastTrackballPos); //rotationAngle *= static_cast(_handler->deltaTime()) * 100.0f; // Map trackballpos to camera // glm::vec3 trackballMappedToCamera = mapToCamera(_lastTrackballPos - curTrackballPos); // psc currentCamPos = camera_->getPosition(); // glm::vec3 nextCamPos = currentCamPos.getVec3f() + trackballMappedToCamera; // glm::vec3 rotationAxis = glm::cross(currentCamPos.getVec3f(), nextCamPos); glm::vec3 rotationAxis = glm::cross(_lastTrackballPos, curTrackballPos); rotationAxis = glm::normalize(rotationAxis); glm::quat quaternion = glm::angleAxis(rotationAngle, rotationAxis); // Apply quaternion to camera //_handler->orbitDelta(quaternion); _lastTrackballPos = curTrackballPos; } } TrackballMouseController::TrackballMouseController() : MouseController() , _leftMouseButtonDown(false) {} void TrackballMouseController::button(MouseButton button, MouseAction action) { if (button == MouseButton::Left && action == MouseAction::Press) _leftMouseButtonDown = true; else if (button == MouseButton::Left && action == MouseAction::Release) { _leftMouseButtonDown = false; _isMouseBeingPressedAndHeld = false; } } void TrackballMouseController::move(float x, float y) { if (_leftMouseButtonDown) trackballRotate(static_cast(x), static_cast(y)); } void TrackballMouseController::scrollWheel(int pos) { /* const float speed = 4.75f; const float dt = static_cast(_handler->deltaTime()); if (pos < 0) { PowerScaledScalar dist(speed * dt, 0.0f); _handler->distanceDelta(dist); } else if (pos > 0) { PowerScaledScalar dist(-speed * dt, 0.0f); _handler->distanceDelta(dist); } */ } void TrackballMouseController::update(const double& dt){ } OrbitalMouseController::OrbitalMouseController() : MouseController() , _leftMouseButtonDown(false) , _rightMouseButtonDown(false) , _middleMouseButtonDown(false) , _currentCursorPos(0) , _rotationSpeed(10.f) , _navigationSpeed(3.f) { for (int n = 0; n < 3; ++n){ _previousCursorPos[n] = glm::vec2(0); } } void OrbitalMouseController::button(MouseButton button, MouseAction action) { if (button == MouseButton::Left){ if (action == MouseAction::Press){ _leftMouseButtonDown = true; _previousCursorPos[MouseButtons::ButtonLeft] = OsEng.windowWrapper().mousePosition(); } else if (action == MouseAction::Release) { _leftMouseButtonDown = false; _currentCursorDiff[MouseButtons::ButtonLeft] = glm::vec2(0); } } else if (button == MouseButton::Right){ if (action == MouseAction::Press){ _rightMouseButtonDown = true; _previousCursorPos[MouseButtons::ButtonRight] = OsEng.windowWrapper().mousePosition(); } else if (action == MouseAction::Release) { _rightMouseButtonDown = false; _currentCursorDiff[MouseButtons::ButtonRight] = glm::vec2(0); } } else if (button == MouseButton::Middle){ if (action == MouseAction::Press){ _middleMouseButtonDown = true; _previousCursorPos[MouseButtons::ButtonMiddle] = OsEng.windowWrapper().mousePosition(); } else if (action == MouseAction::Release) { _middleMouseButtonDown = false; _currentCursorDiff[MouseButtons::ButtonMiddle] = glm::vec2(0); } } } void OrbitalMouseController::move(float x, float y) { _currentCursorPos = OsEng.windowWrapper().mousePosition(); if (_leftMouseButtonDown) { glm::vec2 diff = _currentCursorPos - _previousCursorPos[MouseButtons::ButtonLeft]; glm::vec2 res = OsEng.windowWrapper().currentWindowSize(); _currentCursorDiff[MouseButtons::ButtonLeft] = diff / res; } if (_rightMouseButtonDown) { glm::vec2 diff = _currentCursorPos - _previousCursorPos[MouseButtons::ButtonRight]; glm::vec2 res = OsEng.windowWrapper().currentWindowSize(); _currentCursorDiff[MouseButtons::ButtonRight] = diff / res; } if (_middleMouseButtonDown) { glm::vec2 diff = _currentCursorPos - _previousCursorPos[MouseButtons::ButtonMiddle]; glm::vec2 res = OsEng.windowWrapper().currentWindowSize(); _currentCursorDiff[MouseButtons::ButtonMiddle] = diff / res; } } void OrbitalMouseController::scrollWheel(int pos) { } void OrbitalMouseController::update(const double& dt){ /* const float interactionSpeed = OsEng.interactionHandler().interactionSensitivity(); const bool rotationInvert = OsEng.interactionHandler().invertRotation(); const bool rollInvert = OsEng.interactionHandler().invertRoll(); //if (_leftMouseButtonDown || _rightMouseButtonDown || _middleMouseButtonDown){ _handler->orbit( static_cast(_leftMouseButtonDown) * static_cast(dt) * _currentCursorDiff[MouseButtons::ButtonLeft].x * interactionSpeed * (rotationInvert ? -1.f : 1.f), static_cast(_leftMouseButtonDown) * static_cast(dt) * _currentCursorDiff[MouseButtons::ButtonLeft].y * interactionSpeed * (rotationInvert ? -1.f : 1.f), static_cast(_middleMouseButtonDown) * static_cast(dt) * _currentCursorDiff[MouseButtons::ButtonMiddle].x * interactionSpeed * (rollInvert ? -1.f : 1.f), static_cast(_rightMouseButtonDown) * static_cast(dt) * _currentCursorDiff[MouseButtons::ButtonRight].y * _navigationSpeed); //} */ // if (_leftMouseButtonDown){ // _handler->orbit(static_cast(dt)* _currentCursorDiff[MouseButtons::ButtonLeft].x * _rotationSpeed, static_cast(dt)* _currentCursorDiff[MouseButtons::ButtonLeft].y * _rotationSpeed, 0.f); // } // if (_middleMouseButtonDown){ // _handler->orbit(0.f, 0.f, static_cast(dt)* _currentCursorDiff[MouseButtons::ButtonMiddle].x * _rotationSpeed); // } // if (_rightMouseButtonDown){ // _handler->distance(static_cast(dt)* _currentCursorDiff[MouseButtons::ButtonRight].y * _navigationSpeed); // } } } // namespace interaction } // namespace openspace #endif // USE_OLD_INTERACTIONHANDLER