如何使用Coin3d / OpenInventor添加任意数量的引擎输出

时间:2016-06-23 10:33:54

标签: c++ openinventor coin3d

我正在编写一个应用程序,它使用Coin3d库(基于与OpenInventor相同的代码库)可视化大型数据集。我一直在努力解决这个问题,但我从未找到过令人满意的解决方案。

数据来自可变数量的条带'我创建了一个SoEngine来收集要显示的数据,将其发送到多个输出,然后连接到每个条带的SoQuadMesh进行渲染。

我在这里使用引擎的原因是数据从数据源获取,并且当用户在其周围导航时更新可视化。也就是说,当用户放大和缩小时,图像的分辨率会发生变化(根据谷歌地图)。数据在后台线程中检索(需要一两秒钟),然后用于更新引擎输出。

问题是似乎没有办法创建任意数量的SoEngineOutput - 在使用SO_ENGINE_ADD_OUTPUT添加到引擎之前,它们都必须在类定义中声明宏。

通过分析Coin源代码,我试图通过以稍微修改的形式实现SO_ENGINE_ADD_OUTPUT宏背后的代码来解决这个问题,但最终我失败了(或者失去了我的神经)因为{{1}是一个静态字段,应该只创建一次;我不想冒险重新初始化它的后果,而不知道整个实现的细节。

我现在使用的解决方案是将所有输出声明为可能的最大值,如标题中所示:

SoEngine::outputdata

然后在Engine构造函数中,将每个输出添加到引擎输出列表:

class Engine : public SoEngine
{
    SO_ENGINE_HEADER(Engine);

public:

    // The output: vector of points, edges, colours and indices
    // A set of these is needed for each strip in the visualisation
    SoEngineOutputList dataPoints;
    SoEngineOutputList edgePoints;
    SoEngineOutputList dataColours;
    SoEngineOutputList edgeColours;
    SoEngineOutputList numSamples;
    SoEngineOutputList numDepths;

// Macro to simplify and shorten the code for adding multiple engine outputs
#define ENGINE_DECLARE_OUTPUTS(N) \
    SoEngineOutput dataPoints_##N;  /*SoMFVec3f*/ \
    SoEngineOutput edgePoints_##N;  /*SoMFVec3f*/ \
    SoEngineOutput dataColours_##N; /*SoMFColor*/ \
    SoEngineOutput edgeColours_##N; /*SoMFColor*/ \
    SoEngineOutput numSamples_##N;  /*SoSFInt32 */ \
    SoEngineOutput numDepths_##N;   /*SoSFInt32 */

    // Declare all the outputs from the engine. Note that they have to be added
    // individually because it uses the macro above.
    ENGINE_DECLARE_OUTPUTS(0);
    ENGINE_DECLARE_OUTPUTS(1);
    ENGINE_DECLARE_OUTPUTS(2);
    ENGINE_DECLARE_OUTPUTS(3);
    // etc. all the way to a constant MAX_NUM_SAMPLE_SETS

这样可行,但当#define ENGINE_ADD_OUTPUTS(N) \ SO_ENGINE_ADD_OUTPUT(dataPoints_##N, SoMFVec3f); \ SO_ENGINE_ADD_OUTPUT(edgePoints_##N, SoMFVec3f); \ SO_ENGINE_ADD_OUTPUT(dataColours_##N, SoMFColor); \ SO_ENGINE_ADD_OUTPUT(edgeColours_##N, SoMFColor); \ SO_ENGINE_ADD_OUTPUT(numSamples_##N, SoSFInt32); \ SO_ENGINE_ADD_OUTPUT(numDepths_##N, SoSFInt32); \ dataPoints.append(&dataPoints_##N); \ edgePoints.append(&edgePoints_##N); \ dataColours.append(&dataColours_##N); \ edgeColours.append(&edgeColours_##N); \ numSamples.append(&numSamples_##N); \ numDepths.append(&numDepths_##N); // Add all the outputs from the engine. Note that they have to be added // individually because it uses the macro above. The number added should match // the number defined in MAX_NUM_SAMPLE_SETS ENGINE_ADD_OUTPUTS(0); ENGINE_ADD_OUTPUTS(1); ENGINE_ADD_OUTPUTS(2); ENGINE_ADD_OUTPUTS(3); // etc. all the way to a constant MAX_NUM_SAMPLE_SETS 设置为100时,实例化大约20秒时Engine类会受到性能影响 - 这意味着声明为600 MAX_NUM_SAMPLE_SETSSoEngineOutputs是最大的可能 - 大多数可视化需要比这少(少于10),所以我希望能够在运行时确定输出的数量。

所以我的问题是:

  1. 有没有办法在运行时在Coin3d中添加任意数量的MAX_NUM_SAMPLE_SETS = 100
  2. 为什么在SoEngineOutput的声明数量上会出现这样的性能影响? (这可能是一个普通的C ++问题,我将为此创建一个单独的问题,或者这是Coin3d的一个问题)
  3. 有更好的方法为此实施解决方案吗?

1 个答案:

答案 0 :(得分:1)

如果我有50个可以让我发表评论的声誉,我会问你为什么要使用SoEngineSoEngine的目的是启用计算并构建场景图中各种元素之间的依赖关系,这些元素必须在遍历期间是活动的,即动态的,并且可以写入.iv文件。 / p>

我得到的印象是,在演示之前加载数据时,您需要做的一次。在这种情况下,您可以构建场景图并直接根据数据集填充节点,而无需通过SoEngine进行路由。

请注意,即使您在运行时有动态更新可视化的数据流,您仍然可以在使用时更改场景图,如果您注意不要删除或添加节点它正在被遍历。有多种方法可以实现这一目标,但这可能是另一个问题。

修改:另一个问题:为什么,如果您获取条带数据,首先会将其转换为SoIndexedFaceSet而不是SoTriangleStripSet