Как добавить произвольное количество выходов двигателя, используя Coin3d / OpenInventor

Я пишу приложение, которое визуализирует большой набор данных, используя библиотеку Coin3d (которая основана на той же кодовой базе, что и OpenInventor). Я боролся с этой проблемой некоторое время, и я никогда не находил удовлетворительного решения.

Данные поступают в переменное количество «полос», и я создал SoEngine который собирает данные для визуализации, отправляет их на несколько выходов, которые затем подключаются к SoQuadMesh для каждой полосы для рендеринга.

Причина, по которой я использую движок, заключается в том, что данные извлекаются из источника данных, а визуализация обновляется по мере того, как пользователь перемещается по нему. То есть, когда пользователь увеличивает и уменьшает масштаб изображения, его разрешение изменяется (согласно картам Google). Данные извлекаются в фоновом потоке (это занимает секунду или две), а затем используются для обновления выходных данных двигателя.

Проблема в том, что не существует способа создать произвольное число SoEngineOutputs — все они должны быть объявлены в определении класса перед добавлением в движок с SO_ENGINE_ADD_OUTPUT макро.

Анализируя исходный код Coin, я попытался обойти это путем реализации кода, стоящего за SO_ENGINE_ADD_OUTPUT макрос в слегка измененной форме, но в конечном итоге я потерпел неудачу (или потерял самообладание), потому что SoEngine::outputdata статическое поле, которое должно быть создано только один раз; Я не хотел рисковать последствиями его повторной инициализации, не зная деталей всей внутренней реализации.

Решение, которое я сейчас работаю, состоит в том, чтобы объявить все выходные данные до возможного максимального значения, как в заголовке:

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

Затем в конструкторе Engine добавьте каждый вывод в списки вывода engine:

#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

Это работает, но производительность падает, когда класс Engine создается примерно 20 секунд, когда MAX_NUM_SAMPLE_SETS установлен на 100 — что означает объявление 600 SoEngineOutputs, MAX_NUM_SAMPLE_SETS = 100 является наибольшим из возможных — для большинства визуализаций требуется намного меньше (менее 10), поэтому я хочу иметь возможность определять количество выходных данных во время выполнения.

Итак, мои вопросы:

  1. Есть ли способ добавить произвольное количество SoEngineOutputв Coin3d во время выполнения?
  2. Почему производительность падает с таким количеством объявлений SoEngineOutput? (Возможно, это общий вопрос C ++, для которого я создам отдельный вопрос, или это проблема с Coin3d)
  3. Есть ли лучший способ реализовать решение для этого?

0

Решение

Если бы у меня была 50 репутация, которая позволила бы мне комментировать, я бы спросил, почему вы хотите использовать SoEngine за это. Цель SoEngines состоит в том, чтобы включить вычисления и построить зависимости между различными элементами в графе сцены, которые должны быть активными во время обхода, то есть динамически, и которые могут быть записаны в .iv файл.

У меня складывается впечатление, что то, что вы делаете, нужно сделать один раз, когда вы загружаете свои данные до презентации. В этом случае вы можете построить свой граф сцены и заполнить свои узлы непосредственно на основе набора данных, не направляя его через SoEngine,

Обратите внимание, что даже если у вас есть поток данных во время выполнения, для которого визуализация должна обновляться динамически, вы все равно можете изменять график сцены, пока он используется, если вы позаботитесь о том, чтобы не удалять или добавлять узлы во время его работы. пройден. Есть разные способы сделать это, но это, вероятно, другой вопрос.

Изменить: Другой вопрос: почему, если вы получите данные в полосах, вы бы преобразовать их в SoIndexedFaceSet и не SoTriangleStripSet на первом месте?

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]