Esempio n. 1
0
double CanvasGL::getDepthValueAtCoord(ivec2 coord, const LayerRAM* depthLayerRAM) const{
    const LayerRAM* dlr = depthLayerRAM;
    if (!dlr)
        dlr = getDepthLayerRAM();

    if (dlr) {
        auto screenDims(getScreenDimensions());
        auto depthDims = dlr->getDimensions();
        coord = glm::max(coord, ivec2(0));

        double depthScreenRatioX = static_cast<double>(depthDims.x) / static_cast<double>(screenDims.x);
        double depthScreenRatioY = static_cast<double>(depthDims.y) / static_cast<double>(screenDims.y);
        size2_t coordDepth;
        coordDepth.x = static_cast<size_t>(depthScreenRatioX*static_cast<double>(coord.x));
        coordDepth.y = static_cast<size_t>(depthScreenRatioY*static_cast<double>(coord.y));
        depthDims -= 1;
        coordDepth = glm::min(coordDepth, depthDims);

        double depthValue = dlr->getValueAsSingleDouble(coordDepth);

        // Convert to normalized device coordinates
        return 2.0*depthValue - 1.0;
    }
    else
        return 1.0;
}
Esempio n. 2
0
void CanvasQt::touchEvent(QTouchEvent* touch) {
    size_t nTouchPoints = touch->touchPoints().size();
    if (nTouchPoints < 1) {
        return;
    }

    QTouchEvent::TouchPoint firstPoint = touch->touchPoints()[0];
    
    switch (firstPoint.state())
    {
    case Qt::TouchPointPressed:
        gestureMode_ = nTouchPoints > 1; // Treat single touch point as mouse event
        break;
    case Qt::TouchPointMoved:
        gestureMode_ = nTouchPoints > 1; // Treat single touch point as mouse event
        break;
    case Qt::TouchPointStationary:
        gestureMode_ = nTouchPoints > 1; // Treat single touch point as mouse event
        break;
    case Qt::TouchPointReleased:
        gestureMode_ = false;
        break;
    default:
        gestureMode_ = false;
    }
    // Copy touch points
    std::vector<TouchPoint> touchPoints;
    touchPoints.reserve(touch->touchPoints().size());
    // Fetch layer before loop (optimization)
    const LayerRAM* depthLayerRAM = getDepthLayerRAM();
    vec2 screenSize(getScreenDimensions());

    std::vector<int> endedTouchIds;

    for (auto& touchPoint : touch->touchPoints()) {
        vec2 screenTouchPos(touchPoint.pos().x(), touchPoint.pos().y());
        vec2 prevScreenTouchPos(touchPoint.lastPos().x(), touchPoint.lastPos().y());
        TouchPoint::TouchState touchState;
        switch (touchPoint.state())
        {
        case Qt::TouchPointPressed:
            touchState = TouchPoint::TOUCH_STATE_STARTED;
            break;
        case Qt::TouchPointMoved:
            touchState = TouchPoint::TOUCH_STATE_UPDATED;
            break;
        case Qt::TouchPointStationary:
            touchState = TouchPoint::TOUCH_STATE_STATIONARY;
            break;
        case Qt::TouchPointReleased:
            touchState = TouchPoint::TOUCH_STATE_ENDED;
            break;
        default:
            touchState = TouchPoint::TOUCH_STATE_NONE;
        }

        ivec2 pixelCoord = ivec2(static_cast<int>(screenTouchPos.x),
            screenSize.y - 1 - static_cast<int>(screenTouchPos.y));
        
        // Note that screenTouchPos/prevScreenTouchPos are in [0 screenDim] and does not need to be 
        // adjusted to become centered in the pixel (+0.5)
        
        // Saving id order to preserve order of touch points at next touch event
        
        const auto lastIdIdx = std::find(lastTouchIds_.begin(), lastTouchIds_.end(), touchPoint.id());

        if (lastIdIdx != lastTouchIds_.end()) {
            if (touchState == TouchPoint::TOUCH_STATE_ENDED){
                endedTouchIds.push_back(touchPoint.id());
            }
        }
        else{
            lastTouchIds_.push_back(touchPoint.id());


        }
        touchPoints.emplace_back(touchPoint.id(), screenTouchPos,
            (screenTouchPos) / screenSize,
            prevScreenTouchPos,
            (prevScreenTouchPos) / screenSize,
            touchState, getDepthValueAtCoord(pixelCoord, depthLayerRAM));
    }
    // Ensure that the order to the touch points are the same as last touch event.
    // Note that the ID of a touch point is always the same but the order in which
    // they are given can vary.
    // Example
    // lastTouchIds_    touchPoints
    //     0                 0
    //     3                 1 
    //     2                 2
    //     4
    // Will result in:
    //                  touchPoints
    //                       0 (no swap)
    //                       2 (2 will swap with 1)
    //                       1

    auto touchIndex = 0; // Index to first unsorted element in touchPoints array
    for (const auto& lastTouchPointId : lastTouchIds_) {
        const auto touchPointIt = std::find_if(touchPoints.begin(), touchPoints.end(), [lastTouchPointId](const TouchPoint& p) { return p.getId() == lastTouchPointId; });
        // Swap current location in the container with the location it was in last touch event.
        if (touchPointIt != touchPoints.end() && std::distance(touchPoints.begin(), touchPointIt) != touchIndex) {
            std::swap(*(touchPoints.begin() + touchIndex), *touchPointIt);
            ++touchIndex;
        }
    }

    for (auto& endedId : endedTouchIds) {
        std::vector<int>::iterator foundIdx = std::find(lastTouchIds_.begin(), lastTouchIds_.end(), endedId);
        if (foundIdx != lastTouchIds_.end())
            lastTouchIds_.erase(foundIdx);
    }

    TouchEvent touchEvent(touchPoints, getScreenDimensions());
    touch->accept();

    // We need to send out touch event all the time to support one -> two finger touch switch
    Canvas::touchEvent(&touchEvent);

    // Mouse events will be triggered for touch events by Qt4 and Qt >= 5.3.0
    // https://bugreports.qt.io/browse/QTBUG-40038
#if defined(USING_QT5) && (QT_VERSION < QT_VERSION_CHECK(5, 3, 0))
    if(touch->touchPoints().size() == 1 && lastNumFingers_ < 2){
        MouseEvent* mouseEvent = nullptr;
        ivec2 pos = ivec2(static_cast<int>(firstPoint.pos().x()), static_cast<int>(firstPoint.pos().y()));
        uvec2 screenPosInvY(static_cast<unsigned int>(pos.x), static_cast<unsigned int>(getScreenDimensions().y-1-pos.y));
        double depth = getDepthValueAtCoord(screenPosInvY);
        switch (touchPoints.front().state())
        {
        case TouchPoint::TOUCH_STATE_STARTED:
            mouseEvent = new MouseEvent(pos, MouseEvent::MOUSE_BUTTON_LEFT, MouseEvent::MOUSE_STATE_PRESS, 
                EventConverterQt::getModifier(touch), getScreenDimensions(), depth);
            Canvas::mousePressEvent(mouseEvent);
            break;
        case TouchPoint::TOUCH_STATE_UPDATED:
            mouseEvent = new MouseEvent(pos, MouseEvent::MOUSE_BUTTON_LEFT, MouseEvent::MOUSE_STATE_MOVE, 
                EventConverterQt::getModifier(touch), getScreenDimensions(), depth);
            Canvas::mouseMoveEvent(mouseEvent);
            break;
        case TouchPoint::TOUCH_STATE_STATIONARY:
            break; // Do not fire event while standing still.
        case TouchPoint::TOUCH_STATE_ENDED:
            mouseEvent = new MouseEvent(pos, MouseEvent::MOUSE_BUTTON_LEFT, MouseEvent::MOUSE_STATE_RELEASE, 
                EventConverterQt::getModifier(touch), getScreenDimensions(), depth);
            Canvas::mouseReleaseEvent(mouseEvent);
            break;
        default:
            break;
        }
        delete mouseEvent;
    }
#endif

    lastNumFingers_ = static_cast<int>(touch->touchPoints().size());
    screenPositionNormalized_ = touchEvent.getCenterPointNormalized();
}