连续触发射线检测测试

3

参考这个答案,我正在进行连续的射线投射:

m_rayCaster = new Qt3DRender::QRayCaster(m_scene->rootEntity());
m_rayCaster->setRunMode(Qt3DRender::QAbstractRayCaster::SingleShot);
m_scene->rootEntity()->addComponent(m_rayCaster);

我有这些插槽来处理下一个连续光线投射测试的是否何时进行:

QObject::connect(m_rayCaster, &Qt3DRender::QRayCaster::hitsChanged, this, &RayCastHandler::handleRayCasterHits);
QObject::connect(m_rayCaster, &Qt3DCore::QNode::enabledChanged, this, &RayCastHandler::handleRayCasterEnabledChange);
QObject::connect(this, &RayCastHandler::isPreviousTestDoneChanged, this, &RayCastHandler::handleIsPreviousTestDoneChange);
QObject::connect(this, &RayCastHandler::isNextTestRequiredChanged, this, &RayCastHandler::handleIsNextTestRequiredChange);

插槽设置条件并对其进行检查:
void RayCastHandler::handleRayCasterHits(const Qt3DRender::QAbstractRayCaster::Hits hits)
{
    analyzeHits(hits);
    bool required = isNextTestRequired(/* according to m_testCounter, m_testsTotal, ... */);
    emit isNextTestRequiredChanged(required);
    emit isPreviousTestDoneChanged(true);
    return;
}

void RayCastHandler::handleRayCasterEnabledChange(const bool enabled)
{
    m_isRayCasterEnabled = enabled;
    triggerNextTestIfAllConditionsAreTrue();
    return;
}

void RayCastHandler::handleIsPreviousTestDoneChange(const bool done)
{
    m_isPreviousTestDone = done;
    triggerNextTestIfAllConditionsAreTrue();
    return;
}

void RayCastHandler::handleIsNextTestRequiredChange(const bool required)
{
    m_isNextTestRequired = required;
    if (!m_isNextTestRequired)
        emit rayCastResultsChanged(m_collisions);
    triggerNextTestIfAllConditionsAreTrue();
    return;
}

检查下一个射线投射测试是否需要的代码:
bool RayCastHandler::isNextTestRequired(int &testCounter, const int &testsTotal)
{
    testCounter++;
    if (testCounter >= testsTotal) {
        return false;
    }
    return true;
}

最后,检查所有条件以触发下一个光线投射测试的函数如下:
bool RayCastHandler::triggerNextTestIfAllConditionsAreTrue()
{
    if (m_isPreviousTestDone && m_isNextTestRequired && m_isRayCasterEnabled) {
        triggerTest(/* Will trigger next ray cast test */);
        m_isPreviousTestDone = false;
        m_isNextTestRequired = false;
        m_isRayCasterEnabled = false;
    }
}

代码运行良好,但连续投射几个光线后就停止了。
通过记录日志信息,我发现m_rayCaster看起来会随机启用/禁用。我的意思是有时在完成一次射线测试之后,它会自动禁用,而有时它则会自动启用!我想知道是否有人可以介绍一下Qt3DRender :: QRayCaster的启用/禁用逻辑的参考文献。我稍微看了一下它的源代码,不知道哪部分源代码可以帮助我解决这个问题。
1个回答

1

我想分享一下我的观察:

我简化了代码,只保留了两个信号槽连接:

QObject::connect(m_rayCaster, &Qt3DRender::QRayCaster::hitsChanged, this, &RayCastHandler::handleRayCasterHits);
QObject::connect(m_rayCaster, &Qt3DCore::QNode::enabledChanged, this, &RayCastHandler::handleRayCasterEnabledChange);

一个插槽分析光线投射的命中情况:
void RayCastHandler::handleRayCasterHits(const Qt3DRender::QAbstractRayCaster::Hits hits)
{
    analyzeHits( ... , hits);
    return;
}

另一个插槽运行下一个连续的光线投射测试,如果光线投射器已被禁用:
void RayCastHandler::handleRayCasterEnabledChange(const bool enabled)
{
    // When the component disables itself, it is ready for the next ray-cast test
    if (!enabled) {
        bool required = isNextTestRequired( ... );
        if (required)
            triggerTest( ... );
        else
            // Send final ray-cast results by a signal, if next test is NOT needed
            emit rayCastResultsChanged( ... );
    }
    return;
}

上述代码只有在我使用时间延迟触发光线投射测试时才能正常工作。有时我不得不增加上述延迟时间才能使其正常工作。但至少它可以工作。虽然这很痛苦,因为它不是可靠的:

void RayCastHandler::triggerTest( ... )
{
    ...
    // 1 millisecond delay time
    QTimer::singleShot(1, [rayCaster, origin, direction, length](){rayCaster->trigger(origin, direction, length);});

    ...
}

然而,如果我不使用延迟时间,在某个时刻,光线投射器会突然停止,没有发送任何包含命中结果的信号,并且光线投射器将永久保持启用状态。看起来光线投射器被卡住了:
void RayCastHandler::triggerTest( ... )
{
    ...
    // No delay
    rayCaster->trigger(origin, direction, length);

    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接