如何使用 Coin3d/OpenInventor 添加任意数量的引擎输出
How to add an arbitrary number of engine outputs using Coin3d/OpenInventor
我正在编写一个使用 Coin3d 库(基于与 OpenInventor 相同的代码库)可视化大型数据集的应用程序。这个问题我纠结了一段时间,一直没有找到满意的解决方案。
数据以可变数量 'strips' 的形式出现,我创建了一个 SoEngine
来收集要可视化的数据,将其发送到多个输出,然后连接到 SoQuadMesh
用于渲染的每个条带。
我在这里使用引擎的原因是数据是从数据源获取的,并且随着用户在它周围导航而更新可视化。也就是说,随着用户放大和缩小,图像的分辨率会发生变化(根据 google 地图)。数据在后台线程中检索(需要一两秒),然后用于更新引擎输出。
问题是似乎没有办法创建任意数量的 SoEngineOutput
s - 它们都必须在添加到引擎之前在 class 定义中声明SO_ENGINE_ADD_OUTPUT
宏。
通过分析 Coin 源代码,我试图通过稍微修改形式实现 SO_ENGINE_ADD_OUTPUT
宏背后的代码来解决这个问题,但最终我失败了(或者失去了勇气),因为 SoEngine::outputdata
是一个静态字段,应该只创建一次;我不想冒险 re-initialising 它的后果,不知道整个实施的细节 under-the-hood.
我现在的解决方案是将所有输出声明为可能的最大值,如 header:
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
这可行,但是当引擎 class 在 MAX_NUM_SAMPLE_SETS
设置为 100 时实例化大约 20 秒时性能会受到影响 - 这意味着声明 600 SoEngineOutputs
. MAX_NUM_SAMPLE_SETS = 100
是最大的可能 - 大多数可视化需要比这少得多(小于 10),所以我希望能够确定 run-time.
处的输出数量
所以我的问题是:
- 有没有办法在运行时在 Coin3d 中添加任意数量的
SoEngineOutput
s?
- 为什么 `SoEngineOutput 的声明次数如此之多会导致性能下降? (这可能是一个一般的 C++ 问题,我将为其创建一个单独的问题,或者它是 Coin3d 的问题)
- 有没有更好的方法来解决这个问题?
如果我有 50 的声誉可以发表评论,我会问你为什么要为此使用 SoEngine
。 SoEngine
s 的目的是启用场景图中各种元素之间的计算和构建依赖关系,这些元素在遍历期间必须处于活动状态,即动态地,并且可以写入 .iv
文件。
我的印象是,当您在演示之前加载数据时,您所做的事情需要完成一次。在这种情况下,您可以构建场景图并直接根据数据集填充节点,而无需通过 SoEngine
.
进行路由。
请注意,即使您在运行时有一个数据流,其可视化必须动态更新,您仍然可以在使用场景图时随意更改它,前提是您注意不要删除或添加遍历时的节点。有多种方法可以实现这一点,但这可能是另一个问题。
编辑:另一个问题:为什么,如果您以条带形式获取数据,您会首先将其转换为 SoIndexedFaceSet
而不是 SoTriangleStripSet
吗?
我正在编写一个使用 Coin3d 库(基于与 OpenInventor 相同的代码库)可视化大型数据集的应用程序。这个问题我纠结了一段时间,一直没有找到满意的解决方案。
数据以可变数量 'strips' 的形式出现,我创建了一个 SoEngine
来收集要可视化的数据,将其发送到多个输出,然后连接到 SoQuadMesh
用于渲染的每个条带。
我在这里使用引擎的原因是数据是从数据源获取的,并且随着用户在它周围导航而更新可视化。也就是说,随着用户放大和缩小,图像的分辨率会发生变化(根据 google 地图)。数据在后台线程中检索(需要一两秒),然后用于更新引擎输出。
问题是似乎没有办法创建任意数量的 SoEngineOutput
s - 它们都必须在添加到引擎之前在 class 定义中声明SO_ENGINE_ADD_OUTPUT
宏。
通过分析 Coin 源代码,我试图通过稍微修改形式实现 SO_ENGINE_ADD_OUTPUT
宏背后的代码来解决这个问题,但最终我失败了(或者失去了勇气),因为 SoEngine::outputdata
是一个静态字段,应该只创建一次;我不想冒险 re-initialising 它的后果,不知道整个实施的细节 under-the-hood.
我现在的解决方案是将所有输出声明为可能的最大值,如 header:
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
这可行,但是当引擎 class 在 MAX_NUM_SAMPLE_SETS
设置为 100 时实例化大约 20 秒时性能会受到影响 - 这意味着声明 600 SoEngineOutputs
. MAX_NUM_SAMPLE_SETS = 100
是最大的可能 - 大多数可视化需要比这少得多(小于 10),所以我希望能够确定 run-time.
所以我的问题是:
- 有没有办法在运行时在 Coin3d 中添加任意数量的
SoEngineOutput
s? - 为什么 `SoEngineOutput 的声明次数如此之多会导致性能下降? (这可能是一个一般的 C++ 问题,我将为其创建一个单独的问题,或者它是 Coin3d 的问题)
- 有没有更好的方法来解决这个问题?
如果我有 50 的声誉可以发表评论,我会问你为什么要为此使用 SoEngine
。 SoEngine
s 的目的是启用场景图中各种元素之间的计算和构建依赖关系,这些元素在遍历期间必须处于活动状态,即动态地,并且可以写入 .iv
文件。
我的印象是,当您在演示之前加载数据时,您所做的事情需要完成一次。在这种情况下,您可以构建场景图并直接根据数据集填充节点,而无需通过 SoEngine
.
请注意,即使您在运行时有一个数据流,其可视化必须动态更新,您仍然可以在使用场景图时随意更改它,前提是您注意不要删除或添加遍历时的节点。有多种方法可以实现这一点,但这可能是另一个问题。
编辑:另一个问题:为什么,如果您以条带形式获取数据,您会首先将其转换为 SoIndexedFaceSet
而不是 SoTriangleStripSet
吗?