Ejemplo n.º 1
0
void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
    if (!_enabled) {
        return;
    }

    const auto frame = _controller.frame();
    const auto frameID = frame.id();
    if (_lastFrameID >= frameID) {
        // Leap Motion not connected or duplicate frame.
        return;
    }

    if (!_hasLeapMotionBeenConnected) {
        emit deviceConnected(getName());
        _hasLeapMotionBeenConnected = true;
    }

    processFrame(frame);  // Updates _joints.

    auto joints = _joints;

    auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
    userInputMapper->withLock([&, this]() {
        _inputDevice->update(deltaTime, inputCalibrationData, joints, _prevJoints);
    });

    _prevJoints = joints;

    _lastFrameID = frameID;
}
Ejemplo n.º 2
0
void FboCache::lockTexture(int texture) {
    withLock(_lock, [&] {
        Q_ASSERT(_fboMap.count(texture));
        if (!_fboLocks.count(texture)) {
            Q_ASSERT(_readyFboQueue.front()->texture() == (GLuint)texture);
            _readyFboQueue.pop_front();
            _fboLocks[texture] = 1;
        } else {
            _fboLocks[texture]++;
        }
    });
}
Ejemplo n.º 3
0
void LeapMotionPlugin::init() {
    loadSettings();

    auto preferences = DependencyManager::get<Preferences>();
    static const QString LEAPMOTION_PLUGIN { "Leap Motion" };
    {
        auto getter = [this]()->bool { return _enabled; };
        auto setter = [this](bool value) {
            _enabled = value;
            saveSettings();
            if (!_enabled) {
                auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
                userInputMapper->withLock([&, this]() {
                    _inputDevice->clearState();
                });
            }
        };
        auto preference = new CheckPreference(LEAPMOTION_PLUGIN, "Enabled", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = [this]()->QString { return _sensorLocation; };
        auto setter = [this](QString value) {
            _sensorLocation = value;
            saveSettings();
            applySensorLocation();
        };
        auto preference = new ComboBoxPreference(LEAPMOTION_PLUGIN, "Sensor location", getter, setter);
        QStringList list = { SENSOR_ON_DESKTOP, SENSOR_ON_HMD };
        preference->setItems(list);
        preferences->addPreference(preference);
    }
    {
        auto getter = [this]()->float { return _desktopHeightOffset; };
        auto setter = [this](float value) {
            _desktopHeightOffset = value;
            saveSettings();
            applyDesktopHeightOffset();
        };
        auto preference = new SpinnerPreference(LEAPMOTION_PLUGIN, "Desktop height for horizontal forearms", getter, setter);
        float MIN_VALUE = 0.0f;
        float MAX_VALUE = 1.0f;
        float DECIMALS = 2.0f;
        float STEP = 0.01f;
        preference->setMin(MIN_VALUE);
        preference->setMax(MAX_VALUE);
        preference->setDecimals(DECIMALS);
        preference->setStep(STEP);
        preferences->addPreference(preference);
    }
}
Ejemplo n.º 4
0
void NeuronPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
    std::vector<NeuronJoint> joints;
    {
        // lock and copy
        std::lock_guard<std::mutex> guard(_jointsMutex);
        joints = _joints;
    }

    auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
    userInputMapper->withLock([&, this]() {
        _inputDevice->update(deltaTime, inputCalibrationData, joints, _prevJoints);
    });

    _prevJoints = joints;
}
Ejemplo n.º 5
0
void KinectPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {

    if (!_enabled) {
        return;
    }

    updateBody(); // updates _joints

    std::vector<KinectJoint> joints = _joints;

    auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
    userInputMapper->withLock([&, this]() {
        _inputDevice->update(deltaTime, inputCalibrationData, joints, _prevJoints);
    });

    _prevJoints = joints;
}
Ejemplo n.º 6
0
QOpenGLFramebufferObject* FboCache::getReadyFbo() {
    QOpenGLFramebufferObject* result = nullptr;
    withLock(_lock, [&] {
        // Delete any FBOs queued for deletion
        _destroyFboQueue.clear();

        if (_readyFboQueue.empty()) {
            qDebug() << "Building new offscreen FBO number " << _fboMap.size() + 1;
            result = new QOpenGLFramebufferObject(_size, QOpenGLFramebufferObject::CombinedDepthStencil);
            _fboMap[result->texture()] = QSharedPointer<QOpenGLFramebufferObject>(result);
            _readyFboQueue.push_back(result);
        } else {
            result = _readyFboQueue.front();
        }
    });
    return result;
}
Ejemplo n.º 7
0
void FboCache::releaseTexture(int texture, GLsync readSync) {
    withLock(_lock, [&] {
        Q_ASSERT(_fboMap.count(texture));
        Q_ASSERT(_fboLocks.count(texture));
        int newLockCount = --_fboLocks[texture];
        if (!newLockCount) {
            auto fbo = _fboMap[texture].data();
            if (fbo->size() != _size) {
                // Move the old FBO to the destruction queue.
                // We can't destroy the FBO here because we might 
                // not be on the right thread or have the context active
                _destroyFboQueue.push_back(_fboMap[texture]);
                _fboMap.remove(texture);
            } else {
                _readyFboQueue.push_back(fbo);
            }
            _fboLocks.remove(texture);
        }
    });
}
  void runOvrThread() {
    // Make the shared context current
    glfwMakeContextCurrent(renderWindow);
    // Each thread requires it's own glewInit call.
    glewInit();

    // Synchronization to determine when a given eye's render commands have completed
    GLsync eyeFences[2]{0, 0};
    // The index of the current rendering target framebuffer.  
    int backBuffers[2]{0, 0};
    // The pose for each rendered framebuffer
    ovrPosef backPoses[2];

    // Offscreen rendering targets.  two for each eye.
    // One is used for rendering while the other is used for distortion
    gl::FrameBufferWrapper frameBuffers[2][2];
    for_each_eye([&](ovrEyeType eye) {
      glm::uvec2 frameBufferSize = Rift::fromOvr(eyeTextures[0].Header.TextureSize);
      for (int i = 0; i < 2; ++i) {
        frameBuffers[i][eye].init(frameBufferSize);
      }
    });

    while (running) {
      for (int i = 0; i < 2; ++i) {
        for_each_eye([&](ovrEyeType eye) {
          if (0 != eyeFences[eye]) {
            GLenum result = glClientWaitSync(eyeFences[eye], GL_SYNC_FLUSH_COMMANDS_BIT, 0);
            switch (result) {
            case GL_ALREADY_SIGNALED:
            case GL_CONDITION_SATISFIED:
              withLock(ovrLock, [&]{
                eyeFences[eye] = 0;
                int bufferIndex = backBuffers[eye];
                textureIds[eye] = frameBuffers[bufferIndex][eye].color->texture;
                backBuffers[eye] = (bufferIndex + 1) % 2;
                eyePoses[eye] = backPoses[eye];
              });
              break;
            }
          }
        });


        ovrEyeType eye = hmd->EyeRenderOrder[i];
        if (0 != eyeFences[eye]) {
          continue;
        }

        gl::MatrixStack & mv = gl::Stacks::modelview();
        gl::Stacks::projection().top() = projections[eye];
        gl::Stacks::with_push(mv, [&]{
          const ovrEyeRenderDesc & erd = eyeRenderDescs[eye];

          // We can only acquire an eye pose between beginframe and endframe.
          // So we've arranged for the lock to be only open at those points.  
          // The main thread will spend most of it's time in the wait.
          ::withLock(ovrLock, [&]{
            if (running) {
              backPoses[eye] = ovrHmd_GetEyePose(hmd, eye);
            }
          });

          {
            // Apply the head pose
            glm::mat4 m = Rift::fromOvr(backPoses[eye]);
            mv.preMultiply(glm::inverse(m));
            // Apply the per-eye offset
            glm::vec3 eyeOffset = Rift::fromOvr(erd.ViewAdjust);
            mv.preMultiply(glm::translate(glm::mat4(), eyeOffset));
          }

          int bufferIndex = backBuffers[eye];
          gl::FrameBufferWrapper & frameBuffer = frameBuffers[bufferIndex][eye];
          // Render the scene to an offscreen buffer
          frameBuffer.activate();
          renderScene();
          frameBuffer.deactivate();
          eyeFences[eye] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
        });
      }
    }
  }
Ejemplo n.º 9
0
void RenderableWebEntityItem::render(RenderArgs* args) {
    QOpenGLContext * currentContext = QOpenGLContext::currentContext();
    QSurface * currentSurface = currentContext->surface();
    if (!_webSurface) {
        _webSurface = new OffscreenQmlSurface();
        _webSurface->create(currentContext);
        _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
        _webSurface->load("WebEntity.qml");
        _webSurface->resume();
        _webSurface->getRootItem()->setProperty("url", _sourceUrl);
        _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) {
            _webSurface->lockTexture(textureId);
            assert(!glGetError());
            // TODO change to atomic<GLuint>?
            withLock(_textureLock, [&] {
                std::swap(_texture, textureId);
            });
            if (textureId) {
                _webSurface->releaseTexture(textureId);
            }
            if (_texture) {
                _webSurface->makeCurrent();
                glBindTexture(GL_TEXTURE_2D, _texture);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glBindTexture(GL_TEXTURE_2D, 0);
                _webSurface->doneCurrent();
            }
        });

        auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) {
            // Ignore mouse interaction if we're locked
            if (this->getLocked()) {
                return;
            }

            if (event->button() == Qt::MouseButton::RightButton) {
                if (event->type() == QEvent::MouseButtonPress) {
                    const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event);
                    _lastPress = toGlm(mouseEvent->pos());
                }
            }

            if (intersection.entityID == getID()) {
                if (event->button() == Qt::MouseButton::RightButton) {
                    if (event->type() == QEvent::MouseButtonRelease) {
                        const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event);
                        ivec2 dist = glm::abs(toGlm(mouseEvent->pos()) - _lastPress);
                        if (!glm::any(glm::greaterThan(dist, ivec2(1)))) {
                            AbstractViewStateInterface::instance()->postLambdaEvent([this] {
                                QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack");
                            });
                        }
                        _lastPress = ivec2(INT_MIN);
                    }
                    return;
                }

                // FIXME doesn't work... double click events not received
                if (event->type() == QEvent::MouseButtonDblClick) {
                    AbstractViewStateInterface::instance()->postLambdaEvent([this] {
                        _webSurface->getRootItem()->setProperty("url", _sourceUrl);
                    });
                }

                if (event->button() == Qt::MouseButton::MiddleButton) {
                    if (event->type() == QEvent::MouseButtonRelease) {
                        AbstractViewStateInterface::instance()->postLambdaEvent([this] {
                            _webSurface->getRootItem()->setProperty("url", _sourceUrl);
                        });
                    }
                    return;
                }

                // Map the intersection point to an actual offscreen pixel
                glm::vec3 point = intersection.intersection;
                point -= getPosition();
                point = glm::inverse(getRotation()) * point;
                point /= getDimensions();
                point += 0.5f;
                point.y = 1.0f - point.y;
                point *= getDimensions() * METERS_TO_INCHES * DPI;
                // Forward the mouse event.  
                QMouseEvent mappedEvent(event->type(),
                    QPoint((int)point.x, (int)point.y),
                    event->screenPos(), event->button(),
                    event->buttons(), event->modifiers());
                QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent);
            }
        };

        EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer);
        QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent);
        QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent);
        QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent);
    }

    glm::vec2 dims = glm::vec2(getDimensions());
    dims *= METERS_TO_INCHES * DPI;
    // The offscreen surface is idempotent for resizes (bails early
    // if it's a no-op), so it's safe to just call resize every frame 
    // without worrying about excessive overhead.
    _webSurface->resize(QSize(dims.x, dims.y));
    currentContext->makeCurrent(currentSurface);

    PerformanceTimer perfTimer("RenderableWebEntityItem::render");
    Q_ASSERT(getType() == EntityTypes::Web);
    static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f);

    Q_ASSERT(args->_batch);
    gpu::Batch& batch = *args->_batch;
    batch.setModelTransform(getTransformToCenter());
    bool textured = false, culled = false, emissive = false;
    if (_texture) {
        batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture);
        textured = emissive = true;
    }
    
    DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, textured, culled, emissive);
    DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f));
}