Showing the changes to interface/src/Application.cpp (1 of 1 file). Show all
Unified · Split
| @@ -144,7 +144,7 @@ · 143 unmodified lines | ||
| 144 | 144 | #include "ui/AddressBarDialog.h" |
| 145 | 145 | #include "ui/UpdateDialog.h" |
| 146 | 146 | |
| 147 | −#include <qopenglcontext.h> | |
| 147 | +//#include <qopenglcontext.h> | |
| 148 | 148 | |
| 149 | 149 | // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU |
| 150 | 150 | #if defined(Q_OS_WIN) |
| @@ -2281,7 +2281,7 @@ void Application::updateMouseRay() { · 2130 unmodified lines | ||
| 2281 | 2281 | PerformanceWarning warn(showWarnings, "Application::updateMouseRay()"); |
| 2282 | 2282 | |
| 2283 | 2283 | // make sure the frustum is up-to-date |
| 2284 | − _myCamera.loadViewFrustum(_viewFrustum); | |
| 2284 | + loadViewFrustum(_myCamera, _viewFrustum); | |
| 2285 | 2285 | |
| 2286 | 2286 | PickRay pickRay = computePickRay(getTrueMouseX(), getTrueMouseY()); |
| 2287 | 2287 | _mouseRayOrigin = pickRay.origin; |
| @@ -2665,7 +2665,7 @@ void Application::update(float deltaTime) { · 377 unmodified lines | ||
| 2665 | 2665 | // to the server. |
| 2666 | 2666 | { |
| 2667 | 2667 | PerformanceTimer perfTimer("loadViewFrustum"); |
| 2668 | − _myCamera.loadViewFrustum(_viewFrustum); | |
| 2668 | + loadViewFrustum(_myCamera, _viewFrustum); | |
| 2669 | 2669 | } |
| 2670 | 2670 | |
| 2671 | 2671 | quint64 now = usecTimestampNow(); |
| @@ -2713,192 +2713,6 @@ void Application::update(float deltaTime) { · 41 unmodified lines | ||
| 2713 | 2713 | _myAvatar->updateSensorToWorldMatrix(); |
| 2714 | 2714 | } |
| 2715 | 2715 | |
| 2716 | −void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index) { | |
| 2717 | − PalmData* palm; | |
| 2718 | − bool foundHand = false; | |
| 2719 | − for (size_t j = 0; j < hand->getNumPalms(); j++) { | |
| 2720 | − if (hand->getPalms()[j].getSixenseID() == index) { | |
| 2721 | − palm = &(hand->getPalms()[j]); | |
| 2722 | − foundHand = true; | |
| 2723 | − break; | |
| 2724 | − } | |
| 2725 | − } | |
| 2726 | − if (!foundHand) { | |
| 2727 | − PalmData newPalm(hand); | |
| 2728 | − hand->getPalms().push_back(newPalm); | |
| 2729 | − palm = &(hand->getPalms()[hand->getNumPalms() - 1]); | |
| 2730 | − palm->setSixenseID(index); | |
| 2731 | − } | |
| 2732 | − | |
| 2733 | − palm->setActive(pose.isValid()); | |
| 2734 | − | |
| 2735 | − // transform from sensor space, to world space, to avatar model space. | |
| 2736 | − glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation()); | |
| 2737 | − glm::mat4 sensorToWorldMat = _myAvatar->getSensorToWorldMatrix(); | |
| 2738 | − glm::mat4 modelMat = createMatFromQuatAndPos(_myAvatar->getOrientation(), _myAvatar->getPosition()); | |
| 2739 | − glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat; | |
| 2740 | − | |
| 2741 | − glm::vec3 position = extractTranslation(objectPose); | |
| 2742 | − glm::quat rotation = glm::quat_cast(objectPose); | |
| 2743 | − | |
| 2744 | − // Compute current velocity from position change | |
| 2745 | − glm::vec3 rawVelocity; | |
| 2746 | − if (deltaTime > 0.0f) { | |
| 2747 | − rawVelocity = (position - palm->getRawPosition()) / deltaTime; | |
| 2748 | − } else { | |
| 2749 | − rawVelocity = glm::vec3(0.0f); | |
| 2750 | − } | |
| 2751 | − palm->setRawVelocity(rawVelocity); // meters/sec | |
| 2752 | − | |
| 2753 | − // Angular Velocity of Palm | |
| 2754 | − glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); | |
| 2755 | − glm::vec3 angularVelocity(0.0f); | |
| 2756 | − float rotationAngle = glm::angle(deltaRotation); | |
| 2757 | − if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { | |
| 2758 | − angularVelocity = glm::normalize(glm::axis(deltaRotation)); | |
| 2759 | − angularVelocity *= (rotationAngle / deltaTime); | |
| 2760 | − palm->setRawAngularVelocity(angularVelocity); | |
| 2761 | − } else { | |
| 2762 | − palm->setRawAngularVelocity(glm::vec3(0.0f)); | |
| 2763 | − } | |
| 2764 | − | |
| 2765 | − if (InputDevice::getLowVelocityFilter()) { | |
| 2766 | − // Use a velocity sensitive filter to damp small motions and preserve large ones with | |
| 2767 | − // no latency. | |
| 2768 | − float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); | |
| 2769 | − position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); | |
| 2770 | − rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter); | |
| 2771 | − } | |
| 2772 | − palm->setRawPosition(position); | |
| 2773 | − palm->setRawRotation(rotation); | |
| 2774 | − | |
| 2775 | − // Store the one fingertip in the palm structure so we can track velocity | |
| 2776 | − const float FINGER_LENGTH = 0.3f; // meters | |
| 2777 | − const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); | |
| 2778 | − const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; | |
| 2779 | − glm::vec3 oldTipPosition = palm->getTipRawPosition(); | |
| 2780 | − if (deltaTime > 0.0f) { | |
| 2781 | − palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); | |
| 2782 | − } else { | |
| 2783 | − palm->setTipVelocity(glm::vec3(0.0f)); | |
| 2784 | − } | |
| 2785 | − palm->setTipPosition(newTipPosition); | |
| 2786 | −} | |
| 2787 | − | |
| 2788 | −void Application::emulateMouse(Hand* hand, float click, float shift, int index) { | |
| 2789 | − // Locate the palm, if it exists and is active | |
| 2790 | − PalmData* palm; | |
| 2791 | − bool foundHand = false; | |
| 2792 | − for (size_t j = 0; j < hand->getNumPalms(); j++) { | |
| 2793 | − if (hand->getPalms()[j].getSixenseID() == index) { | |
| 2794 | − palm = &(hand->getPalms()[j]); | |
| 2795 | − foundHand = true; | |
| 2796 | − break; | |
| 2797 | − } | |
| 2798 | − } | |
| 2799 | − if (!foundHand || !palm->isActive()) { | |
| 2800 | − return; | |
| 2801 | − } | |
| 2802 | − | |
| 2803 | − // Process the mouse events | |
| 2804 | − QPoint pos; | |
| 2805 | − | |
| 2806 | − unsigned int deviceID = index == 0 ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT; | |
| 2807 | − | |
| 2808 | − if (qApp->isHMDMode()) { | |
| 2809 | − pos = qApp->getApplicationCompositor().getPalmClickLocation(palm); | |
| 2810 | − } | |
| 2811 | − else { | |
| 2812 | − // Get directon relative to avatar orientation | |
| 2813 | − glm::vec3 direction = glm::inverse(_myAvatar->getOrientation()) * palm->getFingerDirection(); | |
| 2814 | − | |
| 2815 | − // Get the angles, scaled between (-0.5,0.5) | |
| 2816 | − float xAngle = (atan2(direction.z, direction.x) + M_PI_2); | |
| 2817 | − float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)M_PI_2)); | |
| 2818 | − auto canvasSize = qApp->getCanvasSize(); | |
| 2819 | − // Get the pixel range over which the xAngle and yAngle are scaled | |
| 2820 | − float cursorRange = canvasSize.x * InputDevice::getCursorPixelRangeMult(); | |
| 2821 | − | |
| 2822 | − pos.setX(canvasSize.x / 2.0f + cursorRange * xAngle); | |
| 2823 | − pos.setY(canvasSize.y / 2.0f + cursorRange * yAngle); | |
| 2824 | − | |
| 2825 | − } | |
| 2826 | − | |
| 2827 | − //If we are off screen then we should stop processing, and if a trigger or bumper is pressed, | |
| 2828 | − //we should unpress them. | |
| 2829 | − if (pos.x() == INT_MAX) { | |
| 2830 | − if (_oldHandLeftClick[index]) { | |
| 2831 | − QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0); | |
| 2832 | − | |
| 2833 | − qApp->mouseReleaseEvent(&mouseEvent, deviceID); | |
| 2834 | − | |
| 2835 | − _oldHandLeftClick[index] = false; | |
| 2836 | − } | |
| 2837 | − if (_oldHandRightClick[index]) { | |
| 2838 | − QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0); | |
| 2839 | − | |
| 2840 | − qApp->mouseReleaseEvent(&mouseEvent, deviceID); | |
| 2841 | − | |
| 2842 | − _oldHandRightClick[index] = false; | |
| 2843 | − } | |
| 2844 | − return; | |
| 2845 | − } | |
| 2846 | − | |
| 2847 | − //If position has changed, emit a mouse move to the application | |
| 2848 | − if (pos.x() != _oldHandMouseX[index] || pos.y() != _oldHandMouseY[index]) { | |
| 2849 | − QMouseEvent mouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton, 0); | |
| 2850 | − | |
| 2851 | − // Only send the mouse event if the opposite left button isnt held down. | |
| 2852 | − // Is this check necessary? | |
| 2853 | − if (!_oldHandLeftClick[(int)(!index)]) { | |
| 2854 | − qApp->mouseMoveEvent(&mouseEvent, deviceID); | |
| 2855 | − } | |
| 2856 | − } | |
| 2857 | − _oldHandMouseX[index] = pos.x(); | |
| 2858 | − _oldHandMouseY[index] = pos.y(); | |
| 2859 | − | |
| 2860 | − //We need separate coordinates for clicks, since we need to check if | |
| 2861 | − //a magnification window was clicked on | |
| 2862 | − int clickX = pos.x(); | |
| 2863 | − int clickY = pos.y(); | |
| 2864 | − //Set pos to the new click location, which may be the same if no magnification window is open | |
| 2865 | − pos.setX(clickX); | |
| 2866 | − pos.setY(clickY); | |
| 2867 | − | |
| 2868 | − // Right click | |
| 2869 | − if (shift == 1.0f && click == 1.0f) { | |
| 2870 | − if (!_oldHandRightClick[index]) { | |
| 2871 | − _oldHandRightClick[index] = true; | |
| 2872 | − | |
| 2873 | − QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, Qt::RightButton, Qt::RightButton, 0); | |
| 2874 | − | |
| 2875 | − qApp->mousePressEvent(&mouseEvent, deviceID); | |
| 2876 | − } | |
| 2877 | − } else if (_oldHandRightClick[index]) { | |
| 2878 | − QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0); | |
| 2879 | − | |
| 2880 | − qApp->mouseReleaseEvent(&mouseEvent, deviceID); | |
| 2881 | − | |
| 2882 | − _oldHandRightClick[index] = false; | |
| 2883 | − } | |
| 2884 | − | |
| 2885 | − // Left click | |
| 2886 | − if (shift != 1.0f && click == 1.0f) { | |
| 2887 | − if (!_oldHandLeftClick[index]) { | |
| 2888 | − _oldHandLeftClick[index] = true; | |
| 2889 | − | |
| 2890 | − QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, 0); | |
| 2891 | − | |
| 2892 | − qApp->mousePressEvent(&mouseEvent, deviceID); | |
| 2893 | − } | |
| 2894 | − } else if (_oldHandLeftClick[index]) { | |
| 2895 | − QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0); | |
| 2896 | − | |
| 2897 | − qApp->mouseReleaseEvent(&mouseEvent, deviceID); | |
| 2898 | − | |
| 2899 | − _oldHandLeftClick[index] = false; | |
| 2900 | − } | |
| 2901 | −} | |
| 2902 | 2716 | |
| 2903 | 2717 | int Application::sendNackPackets() { |
| 2904 | 2718 | |
| @@ -3138,6 +2952,35 @@ void Application::queryOctree(NodeType_t serverType, PacketType::Value packetTyp · 233 unmodified lines | ||
| 3138 | 2952 | }); |
| 3139 | 2953 | } |
| 3140 | 2954 | |
| 2955 | + | |
| 2956 | +bool Application::isHMDMode() const { | |
| 2957 | + return getActiveDisplayPlugin()->isHmd(); | |
| 2958 | +} | |
| 2959 | + | |
| 2960 | +QRect Application::getDesirableApplicationGeometry() { | |
| 2961 | + QRect applicationGeometry = getWindow()->geometry(); | |
| 2962 | + | |
| 2963 | + // If our parent window is on the HMD, then don't use its geometry, instead use | |
| 2964 | + // the "main screen" geometry. | |
| 2965 | + HMDToolsDialog* hmdTools = DependencyManager::get<DialogsManager>()->getHMDToolsDialog(); | |
| 2966 | + if (hmdTools && hmdTools->hasHMDScreen()) { | |
| 2967 | + QScreen* hmdScreen = hmdTools->getHMDScreen(); | |
| 2968 | + QWindow* appWindow = getWindow()->windowHandle(); | |
| 2969 | + QScreen* appScreen = appWindow->screen(); | |
| 2970 | + | |
| 2971 | + // if our app's screen is the hmd screen, we don't want to place the | |
| 2972 | + // running scripts widget on it. So we need to pick a better screen. | |
| 2973 | + // we will use the screen for the HMDTools since it's a guarenteed | |
| 2974 | + // better screen. | |
| 2975 | + if (appScreen == hmdScreen) { | |
| 2976 | + QScreen* betterScreen = hmdTools->windowHandle()->screen(); | |
| 2977 | + applicationGeometry = betterScreen->geometry(); | |
| 2978 | + } | |
| 2979 | + } | |
| 2980 | + return applicationGeometry; | |
| 2981 | +} | |
| 2982 | + | |
| 2983 | +///////////////////////////////////////////////////////////////////////////////////// | |
| 3141 | 2984 | // loadViewFrustum() |
| 3142 | 2985 | // |
| 3143 | 2986 | // Description: this will load the view frustum bounds for EITHER the head |
| @@ -3156,14 +2999,6 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { · 12 unmodified lines | ||
| 3156 | 2999 | viewFrustum.calculate(); |
| 3157 | 3000 | } |
| 3158 | 3001 | |
| 3159 | −bool Application::isHMDMode() const { | |
| 3160 | − return getActiveDisplayPlugin()->isHmd(); | |
| 3161 | −} | |
| 3162 | − | |
| 3163 | −QRect Application::getDesirableApplicationGeometry() { | |
| 3164 | − return getWindow()->geometry(); | |
| 3165 | −} | |
| 3166 | − | |
| 3167 | 3002 | glm::vec3 Application::getSunDirection() { |
| 3168 | 3003 | // Sun direction is in fact just the location of the sun relative to the origin |
| 3169 | 3004 | auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage(); |
| @@ -3593,27 +3428,6 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi · 423 unmodified lines | ||
| 3593 | 3428 | } |
| 3594 | 3429 | renderArgs->_viewport = viewport; |
| 3595 | 3430 | |
| 3596 | −#if 0 | |
| 3597 | − auto origRenderMode = renderArgs->_renderMode; | |
| 3598 | − renderArgs->_renderMode = RenderArgs::MIRROR_RENDER_MODE; | |
| 3599 | − | |
| 3600 | − { | |
| 3601 | − gpu::Batch batch; | |
| 3602 | − batch.setViewportTransform(viewport); | |
| 3603 | − batch.setStateScissorRect(viewport); | |
| 3604 | − batch.clearFramebuffer( | |
| 3605 | − gpu::Framebuffer::BUFFER_COLOR0 | | |
| 3606 | − gpu::Framebuffer::BUFFER_COLOR1 | | |
| 3607 | − gpu::Framebuffer::BUFFER_COLOR2 | | |
| 3608 | − gpu::Framebuffer::BUFFER_DEPTH, | |
| 3609 | − vec4(vec3(0), 1), 1.0, 0.0, true); | |
| 3610 | − renderArgs->_context->render(batch); | |
| 3611 | − } | |
| 3612 | − | |
| 3613 | − bool updateViewFrustum = false; | |
| 3614 | − loadViewFrustum(_mirrorCamera, _viewFrustum); | |
| 3615 | −#endif | |
| 3616 | − | |
| 3617 | 3431 | // render rear mirror view |
| 3618 | 3432 | displaySide(renderArgs, _mirrorCamera, true, billboard); |
| 3619 | 3433 | |
| @@ -3625,7 +3439,11 @@ void Application::resetSensors() { · 5 unmodified lines | ||
| 3625 | 3439 | DependencyManager::get<DdeFaceTracker>()->reset(); |
| 3626 | 3440 | |
| 3627 | 3441 | getActiveDisplayPlugin()->resetSensors(); |
| 3628 | − //_leapmotion.reset(); | |
| 3442 | + | |
| 3443 | + QScreen* currentScreen = _window->windowHandle()->screen(); | |
| 3444 | + QWindow* mainWindow = _window->windowHandle(); | |
| 3445 | + QPoint windowCenter = mainWindow->geometry().center(); | |
| 3446 | + _glWidget->cursor().setPos(currentScreen, windowCenter); | |
| 3629 | 3447 | |
| 3630 | 3448 | _myAvatar->reset(); |
| 3631 | 3449 | |
| @@ -4383,7 +4201,7 @@ void Application::setPreviousScriptLocation(const QString& previousScriptLocatio · 751 unmodified lines | ||
| 4383 | 4201 | |
| 4384 | 4202 | void Application::loadDialog() { |
| 4385 | 4203 | |
| 4386 | − QString fileNameString = QFileDialog::getOpenFileName(desktop(), | |
| 4204 | + QString fileNameString = QFileDialog::getOpenFileName(_glWidget, | |
| 4387 | 4205 | tr("Open Script"), |
| 4388 | 4206 | getPreviousScriptLocation(), |
| 4389 | 4207 | tr("JavaScript Files (*.js)")); |
| @@ -4424,7 +4242,7 @@ void Application::setScriptsLocation(const QString& scriptsLocation) { · 34 unmodified lines | ||
| 4424 | 4242 | |
| 4425 | 4243 | void Application::toggleLogDialog() { |
| 4426 | 4244 | if (! _logDialog) { |
| 4427 | − _logDialog = new LogDialog(desktop(), getLogger()); | |
| 4245 | + _logDialog = new LogDialog(_glWidget, getLogger()); | |
| 4428 | 4246 | } |
| 4429 | 4247 | |
| 4430 | 4248 | if (_logDialog->isVisible()) { |
| @@ -4435,7 +4253,6 @@ void Application::toggleLogDialog() { · 4 unmodified lines | ||
| 4435 | 4253 | } |
| 4436 | 4254 | |
| 4437 | 4255 | void Application::takeSnapshot() { |
| 4438 | −#if 0 | |
| 4439 | 4256 | QMediaPlayer* player = new QMediaPlayer(); |
| 4440 | 4257 | QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); |
| 4441 | 4258 | player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); |
| @@ -4449,10 +4266,9 @@ void Application::takeSnapshot() { · 7 unmodified lines | ||
| 4449 | 4266 | } |
| 4450 | 4267 | |
| 4451 | 4268 | if (!_snapshotShareDialog) { |
| 4452 | − _snapshotShareDialog = new SnapshotShareDialog(fileName, desktop()); | |
| 4269 | + _snapshotShareDialog = new SnapshotShareDialog(fileName, _glWidget); | |
| 4453 | 4270 | } |
| 4454 | 4271 | _snapshotShareDialog->show(); |
| 4455 | −#endif | |
| 4456 | 4272 | |
| 4457 | 4273 | } |
| 4458 | 4274 | |
| @@ -4910,3 +4726,190 @@ void Application::setActiveDisplayPlugin(const QString& pluginName) { · 451 unmodified lines | ||
| 4910 | 4726 | } |
| 4911 | 4727 | updateDisplayMode(); |
| 4912 | 4728 | } |
| 4729 | + | |
| 4730 | +void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index) { | |
| 4731 | + PalmData* palm; | |
| 4732 | + bool foundHand = false; | |
| 4733 | + for (size_t j = 0; j < hand->getNumPalms(); j++) { | |
| 4734 | + if (hand->getPalms()[j].getSixenseID() == index) { | |
| 4735 | + palm = &(hand->getPalms()[j]); | |
| 4736 | + foundHand = true; | |
| 4737 | + break; | |
| 4738 | + } | |
| 4739 | + } | |
| 4740 | + if (!foundHand) { | |
| 4741 | + PalmData newPalm(hand); | |
| 4742 | + hand->getPalms().push_back(newPalm); | |
| 4743 | + palm = &(hand->getPalms()[hand->getNumPalms() - 1]); | |
| 4744 | + palm->setSixenseID(index); | |
| 4745 | + } | |
| 4746 | + | |
| 4747 | + palm->setActive(pose.isValid()); | |
| 4748 | + | |
| 4749 | + // transform from sensor space, to world space, to avatar model space. | |
| 4750 | + glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation()); | |
| 4751 | + glm::mat4 sensorToWorldMat = _myAvatar->getSensorToWorldMatrix(); | |
| 4752 | + glm::mat4 modelMat = createMatFromQuatAndPos(_myAvatar->getOrientation(), _myAvatar->getPosition()); | |
| 4753 | + glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat; | |
| 4754 | + | |
| 4755 | + glm::vec3 position = extractTranslation(objectPose); | |
| 4756 | + glm::quat rotation = glm::quat_cast(objectPose); | |
| 4757 | + | |
| 4758 | + // Compute current velocity from position change | |
| 4759 | + glm::vec3 rawVelocity; | |
| 4760 | + if (deltaTime > 0.0f) { | |
| 4761 | + rawVelocity = (position - palm->getRawPosition()) / deltaTime; | |
| 4762 | + } else { | |
| 4763 | + rawVelocity = glm::vec3(0.0f); | |
| 4764 | + } | |
| 4765 | + palm->setRawVelocity(rawVelocity); // meters/sec | |
| 4766 | + | |
| 4767 | + // Angular Velocity of Palm | |
| 4768 | + glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); | |
| 4769 | + glm::vec3 angularVelocity(0.0f); | |
| 4770 | + float rotationAngle = glm::angle(deltaRotation); | |
| 4771 | + if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { | |
| 4772 | + angularVelocity = glm::normalize(glm::axis(deltaRotation)); | |
| 4773 | + angularVelocity *= (rotationAngle / deltaTime); | |
| 4774 | + palm->setRawAngularVelocity(angularVelocity); | |
| 4775 | + } else { | |
| 4776 | + palm->setRawAngularVelocity(glm::vec3(0.0f)); | |
| 4777 | + } | |
| 4778 | + | |
| 4779 | + if (InputDevice::getLowVelocityFilter()) { | |
| 4780 | + // Use a velocity sensitive filter to damp small motions and preserve large ones with | |
| 4781 | + // no latency. | |
| 4782 | + float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); | |
| 4783 | + position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); | |
| 4784 | + rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter); | |
| 4785 | + } | |
| 4786 | + palm->setRawPosition(position); | |
| 4787 | + palm->setRawRotation(rotation); | |
| 4788 | + | |
| 4789 | + // Store the one fingertip in the palm structure so we can track velocity | |
| 4790 | + const float FINGER_LENGTH = 0.3f; // meters | |
| 4791 | + const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); | |
| 4792 | + const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; | |
| 4793 | + glm::vec3 oldTipPosition = palm->getTipRawPosition(); | |
| 4794 | + if (deltaTime > 0.0f) { | |
| 4795 | + palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); | |
| 4796 | + } else { | |
| 4797 | + palm->setTipVelocity(glm::vec3(0.0f)); | |
| 4798 | + } | |
| 4799 | + palm->setTipPosition(newTipPosition); | |
| 4800 | +} | |
| 4801 | + | |
| 4802 | +void Application::emulateMouse(Hand* hand, float click, float shift, int index) { | |
| 4803 | + // Locate the palm, if it exists and is active | |
| 4804 | + PalmData* palm; | |
| 4805 | + bool foundHand = false; | |
| 4806 | + for (size_t j = 0; j < hand->getNumPalms(); j++) { | |
| 4807 | + if (hand->getPalms()[j].getSixenseID() == index) { | |
| 4808 | + palm = &(hand->getPalms()[j]); | |
| 4809 | + foundHand = true; | |
| 4810 | + break; | |
| 4811 | + } | |
| 4812 | + } | |
| 4813 | + if (!foundHand || !palm->isActive()) { | |
| 4814 | + return; | |
| 4815 | + } | |
| 4816 | + | |
| 4817 | + // Process the mouse events | |
| 4818 | + QPoint pos; | |
| 4819 | + | |
| 4820 | + unsigned int deviceID = index == 0 ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT; | |
| 4821 | + | |
| 4822 | + if (qApp->isHMDMode()) { | |
| 4823 | + pos = qApp->getApplicationCompositor().getPalmClickLocation(palm); | |
| 4824 | + } | |
| 4825 | + else { | |
| 4826 | + // Get directon relative to avatar orientation | |
| 4827 | + glm::vec3 direction = glm::inverse(_myAvatar->getOrientation()) * palm->getFingerDirection(); | |
| 4828 | + | |
| 4829 | + // Get the angles, scaled between (-0.5,0.5) | |
| 4830 | + float xAngle = (atan2(direction.z, direction.x) + M_PI_2); | |
| 4831 | + float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)M_PI_2)); | |
| 4832 | + auto canvasSize = qApp->getCanvasSize(); | |
| 4833 | + // Get the pixel range over which the xAngle and yAngle are scaled | |
| 4834 | + float cursorRange = canvasSize.x * InputDevice::getCursorPixelRangeMult(); | |
| 4835 | + | |
| 4836 | + pos.setX(canvasSize.x / 2.0f + cursorRange * xAngle); | |
| 4837 | + pos.setY(canvasSize.y / 2.0f + cursorRange * yAngle); | |
| 4838 | + | |
| 4839 | + } | |
| 4840 | + | |
| 4841 | + //If we are off screen then we should stop processing, and if a trigger or bumper is pressed, | |
| 4842 | + //we should unpress them. | |
| 4843 | + if (pos.x() == INT_MAX) { | |
| 4844 | + if (_oldHandLeftClick[index]) { | |
| 4845 | + QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0); | |
| 4846 | + | |
| 4847 | + qApp->mouseReleaseEvent(&mouseEvent, deviceID); | |
| 4848 | + | |
| 4849 | + _oldHandLeftClick[index] = false; | |
| 4850 | + } | |
| 4851 | + if (_oldHandRightClick[index]) { | |
| 4852 | + QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0); | |
| 4853 | + | |
| 4854 | + qApp->mouseReleaseEvent(&mouseEvent, deviceID); | |
| 4855 | + | |
| 4856 | + _oldHandRightClick[index] = false; | |
| 4857 | + } | |
| 4858 | + return; | |
| 4859 | + } | |
| 4860 | + | |
| 4861 | + //If position has changed, emit a mouse move to the application | |
| 4862 | + if (pos.x() != _oldHandMouseX[index] || pos.y() != _oldHandMouseY[index]) { | |
| 4863 | + QMouseEvent mouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton, 0); | |
| 4864 | + | |
| 4865 | + // Only send the mouse event if the opposite left button isnt held down. | |
| 4866 | + // Is this check necessary? | |
| 4867 | + if (!_oldHandLeftClick[(int)(!index)]) { | |
| 4868 | + qApp->mouseMoveEvent(&mouseEvent, deviceID); | |
| 4869 | + } | |
| 4870 | + } | |
| 4871 | + _oldHandMouseX[index] = pos.x(); | |
| 4872 | + _oldHandMouseY[index] = pos.y(); | |
| 4873 | + | |
| 4874 | + //We need separate coordinates for clicks, since we need to check if | |
| 4875 | + //a magnification window was clicked on | |
| 4876 | + int clickX = pos.x(); | |
| 4877 | + int clickY = pos.y(); | |
| 4878 | + //Set pos to the new click location, which may be the same if no magnification window is open | |
| 4879 | + pos.setX(clickX); | |
| 4880 | + pos.setY(clickY); | |
| 4881 | + | |
| 4882 | + // Right click | |
| 4883 | + if (shift == 1.0f && click == 1.0f) { | |
| 4884 | + if (!_oldHandRightClick[index]) { | |
| 4885 | + _oldHandRightClick[index] = true; | |
| 4886 | + | |
| 4887 | + QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, Qt::RightButton, Qt::RightButton, 0); | |
| 4888 | + | |
| 4889 | + qApp->mousePressEvent(&mouseEvent, deviceID); | |
| 4890 | + } | |
| 4891 | + } else if (_oldHandRightClick[index]) { | |
| 4892 | + QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0); | |
| 4893 | + | |
| 4894 | + qApp->mouseReleaseEvent(&mouseEvent, deviceID); | |
| 4895 | + | |
| 4896 | + _oldHandRightClick[index] = false; | |
| 4897 | + } | |
| 4898 | + | |
| 4899 | + // Left click | |
| 4900 | + if (shift != 1.0f && click == 1.0f) { | |
| 4901 | + if (!_oldHandLeftClick[index]) { | |
| 4902 | + _oldHandLeftClick[index] = true; | |
| 4903 | + | |
| 4904 | + QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, 0); | |
| 4905 | + | |
| 4906 | + qApp->mousePressEvent(&mouseEvent, deviceID); | |
| 4907 | + } | |
| 4908 | + } else if (_oldHandLeftClick[index]) { | |
| 4909 | + QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0); | |
| 4910 | + | |
| 4911 | + qApp->mouseReleaseEvent(&mouseEvent, deviceID); | |
| 4912 | + | |
| 4913 | + _oldHandLeftClick[index] = false; | |
| 4914 | + } | |
| 4915 | +} | |