连续触发光线投射测试

2024-01-29

下列的这个答案 https://stackoverflow.com/a/54901850/3405291,我正在进行连续的光线投射:

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

我有这些插槽要处理whether and when应进行下一次连续光线投射测试:

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启用/禁用逻辑。我稍微查看了它的源代码,我想知道源代码的哪一部分可以帮助我弄清楚。


只是想分享我的观察:

我通过仅保留两个信号槽连接来简化代码:

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);});

    ...
}

但是,如果我不使用延迟时间,在某些时候,光线投射器会意外停止,不会发送任何包含命中结果的信号,并且光线投射器会保持不变enabled永远。看起来光线投射器卡住了:

void RayCastHandler::triggerTest( ... )
{
    ...
    // No delay
    rayCaster->trigger(origin, direction, length);

    ...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

连续触发光线投射测试 的相关文章

随机推荐