Example #1
0
// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose.
// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward
// such that it lies on the surface of the kdop.
bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut) {

    // transform point into local space of jointShape.
    glm::vec3 localPoint = shapePose.inverse().xformPoint(point);

    // Only works for 14-dop shape infos.
    if (shapeInfo.dots.size() != DOP14_COUNT) {
        return false;
    }

    glm::vec3 minDisplacement(FLT_MAX);
    float minDisplacementLen = FLT_MAX;
    glm::vec3 p = localPoint - shapeInfo.avgPoint;
    float pLen = glm::length(p);
    if (pLen > 0.0f) {
        int slabCount = 0;
        for (int i = 0; i < DOP14_COUNT; i++) {
            float dot = glm::dot(p, DOP14_NORMALS[i]);
            if (dot > 0.0f && dot < shapeInfo.dots[i]) {
                slabCount++;
                float distToPlane = pLen * (shapeInfo.dots[i] / dot);
                float displacementLen = distToPlane - pLen;

                // keep track of the smallest displacement
                if (displacementLen < minDisplacementLen) {
                    minDisplacementLen = displacementLen;
                    minDisplacement = (p / pLen) * displacementLen;
                }
            }
        }
        if (slabCount == (DOP14_COUNT / 2) && minDisplacementLen != FLT_MAX) {
            // we are within the k-dop so push the point along the minimum displacement found
            displacementOut = shapePose.xformVectorFast(minDisplacement);
            return true;
        } else {
            // point is outside of kdop
            return false;
        }
    } else {
        // point is directly on top of shapeInfo.avgPoint.
        // push the point out along the x axis.
        displacementOut = shapePose.xformVectorFast(shapeInfo.points[0]);
        return true;
    }
}
void SwipeGestureRecognizer::onTouchMoved(const Touch *touch)
{
    if (numTouches() < numTouchesRequired()) {
        return;
    }

    uint64_t deltaTime = touch->timestamp() - m_startTime;
    if (deltaTime == 0) {
        return;
    }

    if (state() != State::Possible) {
        return;
    }

    float prevCentralX = centralX();
    float prevCentralY = centralY();
    updateCentralPoint();
    float deltaX = centralX()  - prevCentralX;
    float deltaY = centralY()  - prevCentralY;
    m_cumulativeDeltaX += deltaX;
    m_cumulativeDeltaY += deltaY;
    float avrgVelocityX = m_cumulativeDeltaX / deltaTime;
    float avrgVelocityY = m_cumulativeDeltaY / deltaTime;
    float cumulativeDeltaSquared = SQUARED_PYTHAGOREAN(m_cumulativeDeltaY, m_cumulativeDeltaX);
    float avrgVelocitySquared = SQUARED_PYTHAGOREAN(avrgVelocityY, avrgVelocityX);
    float thresholdSquared = SQUARED(recognitionThreshold());
    float minDisplacementSquared = SQUARED(minDisplacement());
    float minVelocitySquared = SQUARED(m_minVelocity);
    // qDebug() << m_minVelocity << " " << minDisplacement() << " " << maxDuration();
    // qDebug() << sqrtf(avrgVelocitySquared) << " " << sqrtf(cumulativeDeltaSquared) << " " << deltaTime;

    if (m_noDirection) {
        if (cumulativeDeltaSquared >= thresholdSquared
                && avrgVelocitySquared >= minVelocitySquared
                && cumulativeDeltaSquared >= minDisplacementSquared) {
            setState(State::Recognized);
        }
    } else {
        float absVelocityX  = fabsf(avrgVelocityX);
        float absVelocityY  = fabsf(avrgVelocityY);
        if (absVelocityX > absVelocityY) {
            float absCumulativeDeltaX  = fabsf(m_cumulativeDeltaX);
            if (absCumulativeDeltaX > recognitionThreshold()) {
                if ((deltaX < 0.0f && (m_direction & Left) == 0)
                        || ((deltaX > 0.0f) && (m_direction & Right) == 0)
                        || fabsf(atanf(m_cumulativeDeltaY /m_cumulativeDeltaX)) >= m_maxAngle) {
                    setState(State::Failed);
                } else if (absVelocityX >= m_minVelocity
                           && absCumulativeDeltaX >= minDisplacement()) {
                    setState(State::Recognized);
                }
            }
        } else if (absVelocityY > absVelocityX) {
            float absCumulativeDeltaY  = fabsf(m_cumulativeDeltaY);
            if (absCumulativeDeltaY > recognitionThreshold()) {
                if ((deltaY < 0.0f && (m_direction & Up) == 0)
                        || ((deltaY > 0.0f) && (m_direction & Down) == 0)
                        || fabsf(atanf(m_cumulativeDeltaX / m_cumulativeDeltaY)) >= m_maxAngle) {
                    setState(State::Failed);
                } else if (absVelocityY >= m_minVelocity
                           && absCumulativeDeltaY >= minDisplacement()) {
                    setState(State::Recognized);
                }
            }
        } else if (cumulativeDeltaSquared > thresholdSquared) {
            setState(State::Failed);
        }
    }
}