Showing the changes to interface/src/Application.cpp (1 of 1 file). Show all
Unified · Split
| @@ -144,7 +144,7 @@ · 143 unmodified lines | |||
| 144 | #include "ui/AddressBarDialog.h" | 144 | #include "ui/AddressBarDialog.h" |
| 145 | #include "ui/UpdateDialog.h" | 145 | #include "ui/UpdateDialog.h" |
| 146 | 146 | ||
| 147 | #include <qopenglcontext.h> | 147 | //#include <qopenglcontext.h> |
| 148 | 148 | ||
| 149 | // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU | 149 | // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU |
| 150 | #if defined(Q_OS_WIN) | 150 | #if defined(Q_OS_WIN) |
| @@ -2281,7 +2281,7 @@ void Application::updateMouseRay() { · 2130 unmodified lines | |||
| 2281 | PerformanceWarning warn(showWarnings, "Application::updateMouseRay()"); | 2281 | PerformanceWarning warn(showWarnings, "Application::updateMouseRay()"); |
| 2282 | 2282 | ||
| 2283 | // make sure the frustum is up-to-date | 2283 | // make sure the frustum is up-to-date |
| 2284 | _myCamera.loadViewFrustum(_viewFrustum); | 2284 | loadViewFrustum(_myCamera, _viewFrustum); |
| 2285 | 2285 | ||
| 2286 | PickRay pickRay = computePickRay(getTrueMouseX(), getTrueMouseY()); | 2286 | PickRay pickRay = computePickRay(getTrueMouseX(), getTrueMouseY()); |
| 2287 | _mouseRayOrigin = pickRay.origin; | 2287 | _mouseRayOrigin = pickRay.origin; |
| @@ -2665,7 +2665,7 @@ void Application::update(float deltaTime) { · 377 unmodified lines | |||
| 2665 | // to the server. | 2665 | // to the server. |
| 2666 | { | 2666 | { |
| 2667 | PerformanceTimer perfTimer("loadViewFrustum"); | 2667 | PerformanceTimer perfTimer("loadViewFrustum"); |
| 2668 | _myCamera.loadViewFrustum(_viewFrustum); | 2668 | loadViewFrustum(_myCamera, _viewFrustum); |
| 2669 | } | 2669 | } |
| 2670 | 2670 | ||
| 2671 | quint64 now = usecTimestampNow(); | 2671 | quint64 now = usecTimestampNow(); |
| @@ -2713,192 +2713,6 @@ void Application::update(float deltaTime) { · 41 unmodified lines | |||
| 2713 | _myAvatar->updateSensorToWorldMatrix(); | 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 | int Application::sendNackPackets() { | 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 | // loadViewFrustum() | 2984 | // loadViewFrustum() |
| 3142 | // | 2985 | // |
| 3143 | // Description: this will load the view frustum bounds for EITHER the head | 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 | viewFrustum.calculate(); | 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 | glm::vec3 Application::getSunDirection() { | 3002 | glm::vec3 Application::getSunDirection() { |
| 3168 | // Sun direction is in fact just the location of the sun relative to the origin | 3003 | // Sun direction is in fact just the location of the sun relative to the origin |
| 3169 | auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage(); | 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 | renderArgs->_viewport = viewport; | 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 | // render rear mirror view | 3431 | // render rear mirror view |
| 3618 | displaySide(renderArgs, _mirrorCamera, true, billboard); | 3432 | displaySide(renderArgs, _mirrorCamera, true, billboard); |
| 3619 | 3433 | ||
| @@ -3625,7 +3439,11 @@ void Application::resetSensors() { · 5 unmodified lines | |||
| 3625 | DependencyManager::get<DdeFaceTracker>()->reset(); | 3439 | DependencyManager::get<DdeFaceTracker>()->reset(); |
| 3626 | 3440 | ||
| 3627 | getActiveDisplayPlugin()->resetSensors(); | 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 | _myAvatar->reset(); | 3448 | _myAvatar->reset(); |
| 3631 | 3449 | ||
| @@ -4383,7 +4201,7 @@ void Application::setPreviousScriptLocation(const QString& previousScriptLocatio · 751 unmodified lines | |||
| 4383 | 4201 | ||
| 4384 | void Application::loadDialog() { | 4202 | void Application::loadDialog() { |
| 4385 | 4203 | ||
| 4386 | QString fileNameString = QFileDialog::getOpenFileName(desktop(), | 4204 | QString fileNameString = QFileDialog::getOpenFileName(_glWidget, |
| 4387 | tr("Open Script"), | 4205 | tr("Open Script"), |
| 4388 | getPreviousScriptLocation(), | 4206 | getPreviousScriptLocation(), |
| 4389 | tr("JavaScript Files (*.js)")); | 4207 | tr("JavaScript Files (*.js)")); |
| @@ -4424,7 +4242,7 @@ void Application::setScriptsLocation(const QString& scriptsLocation) { · 34 unmodified lines | |||
| 4424 | 4242 | ||
| 4425 | void Application::toggleLogDialog() { | 4243 | void Application::toggleLogDialog() { |
| 4426 | if (! _logDialog) { | 4244 | if (! _logDialog) { |
| 4427 | _logDialog = new LogDialog(desktop(), getLogger()); | 4245 | _logDialog = new LogDialog(_glWidget, getLogger()); |
| 4428 | } | 4246 | } |
| 4429 | 4247 | ||
| 4430 | if (_logDialog->isVisible()) { | 4248 | if (_logDialog->isVisible()) { |
| @@ -4435,7 +4253,6 @@ void Application::toggleLogDialog() { · 4 unmodified lines | |||
| 4435 | } | 4253 | } |
| 4436 | 4254 | ||
| 4437 | void Application::takeSnapshot() { | 4255 | void Application::takeSnapshot() { |
| 4438 | #if 0 | ||
| 4439 | QMediaPlayer* player = new QMediaPlayer(); | 4256 | QMediaPlayer* player = new QMediaPlayer(); |
| 4440 | QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); | 4257 | QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); |
| 4441 | player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); | 4258 | player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); |
| @@ -4449,10 +4266,9 @@ void Application::takeSnapshot() { · 7 unmodified lines | |||
| 4449 | } | 4266 | } |
| 4450 | 4267 | ||
| 4451 | if (!_snapshotShareDialog) { | 4268 | if (!_snapshotShareDialog) { |
| 4452 | _snapshotShareDialog = new SnapshotShareDialog(fileName, desktop()); | 4269 | _snapshotShareDialog = new SnapshotShareDialog(fileName, _glWidget); |
| 4453 | } | 4270 | } |
| 4454 | _snapshotShareDialog->show(); | 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 | updateDisplayMode(); | 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 | } | ||