信号与槽连接:在循环内迭代触发信号

3

设置光线投射

我将QRayCaster添加到我的根实体,并将其信号连接到一个插槽:

void MySceneClass::createRootEntity()
{
    // ...
    // Add ray caster to root entity
    m_rayCaster = new Qt3DRender::QRayCaster(m_rootEntity);
    m_rayCaster->setRunMode(Qt3DRender::QAbstractRayCaster::SingleShot);
    m_rootEntity->addComponent(m_rayCaster);

    // Set up signal to slot connection
    QObject::connect(m_rayCaster, &Qt3DRender::QRayCaster::hitsChanged,
                     this,        &MySceneClass::handleRayCasterHits);
    // ...
}

我通过插槽记录光线投射命中情况:

void MySceneClass::handleRayCasterHits(const Qt3DRender::QAbstractRayCaster::Hits hits)
{

    qDebug() << "Ray casting resulted in hits";

}

触发射线投射器

我在循环中迭代地触发射线投射器:

void MyOtherClass::triggerRayCaster()
{

    for (int i = 0; i < 100; ++i) {

        m_mySceneClass->castRay(QVector3D(i, i, 50.0f),       // origin
                                QVector3D(0.0f, 0.0f, -1.0f), // direction
                                -1                            // length (-1 means infinite)
                                );

    }

}

问题

问题在于,在所有测试中,只有 triggerRayCaster() 函数内最后一次循环产生的结果被 handleRayCasterHits() 函数捕获并记录。

我不明白,我是否漏掉了什么?

1个回答

3
为了理解这是如何发生的,你需要了解Qt3D的工作原理:
1. Qt3D在不同线程中执行所有操作。渲染、逻辑和其他操作都有自己的线程并且可以并行执行(除非你告诉它不要这么做)。 2. Qt3D有前端(你在代码中使用的部分)和后端。前端节点被转换为后端节点。例如,在渲染器的后端节点中查看。渲染线程收集全部渲染后端节点并在渲染阶段执行它们。所有其他线程也会对它们的后端节点进行相同的操作(逻辑、输入等)。每当前端节点发生变化时,它们会通知后端节点,以便它们可以相应地修改其内容或获取删除或创建的状态。
这意味着,在你的示例代码中,你快速设置光线投射器上想要投射的射线方向(因为for循环在微秒内执行) ,但这并没有立即进行光线投射。实际的光线投射是由处理与前端光线投射器节点相对应的后端节点的后端线程执行的。这永远无法在你的for循环需要执行的几微秒内完成。这就是为什么你需要一个回调函数来获取结果而不能在下一行代码中简单地进行光线投射的原因。
解决方案: 你需要做的是,要么在回调函数中连续发射下一个光线并存储索引,在某处告诉它何时停止发射新光线;要么使用一个定时器,例如100ms的间隔(足以让Qt3D的所有线程至少执行一次,因为它可能以30fps运行),触发光线投射。

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