Manifold Geometry // Многообразная Геометрия

Визуализация

Подписаться на эту рубрику по RSS

Визуализация в OpenCascade

«Although there are facilities for displaying graphics in Open CASCADE, the real function of the library is to do the math. There are dozens of graphics libraries (if not hundreds), but there are very few solid modeling libraries, and Open CASCADE is the only open source solid modeler» (взято с официального форума OCCT).

Сегодня мы отвлечемся от геометрического моделирования и поговорим о его «младшей сестре» — компьютерной графике. Мы знаем, что средствами OpenCascade можно создать CAD-модель, и, строго говоря, именно этому и посвящены наши заметки. Однако заниматься моделированием без визуализации невозможно. Поэтому обычно геометрические ядра перебрасывают некий мост между точным описанием формы и ее полигональными представлением для отображения на экране. Чаще всего ядро венчается алгоритмом построения треугольной сетки, которая переводит точную криволинейную модель в дискретную. Эта последняя используется, прежде всего, для визуализации, и требования к качеству сетки здесь минимальны. Иногда подобные сетки, годящиеся только для нужд визуализации, называют фасетами (англ. facet), а алгоритмы их построения — генераторами фасетов (англ. facet builder). В ядре OpenCascade генератор фасетов реализован в пакете BRepMesh. Типичная сетка, производимая этим генератором представлена на рис. 1.

Рис. 1. Фасетная подложка фрагмента модели ANC101 (Open CASCADE Technology).

Имея фасетное представление модели, мы можем визуализировать ее любым доступным способом, например, средствами OpenGL. Неплохой библиотекой для научной визуализации является VTK от компании Kitware. Это открытая библиотека, такая же демократичная как OpenCascade, поэтому их союз выглядит натурально. Еще один способ, лежащий на поверхности, — это визуализация средствами самой библиотеки OpenCascade. В обзоре базовых модулей мы уже отмечали эту возможность, снабдив повествование симпатичными картинками в режиме трассировки лучей. Важно четко усвоить, что моделирование и визуализация — это два независимых модуля библиотеки. Моделирование стоит на плечах вычислительной геометрии и алгебры, тогда как визуализация адресует, прежде всего, к технике и оптике. Водораздел между двумя дисциплинами не всегда четок, но он есть, и его надо научиться видеть.

Встроенные средства визуализации OpenCascade

Отметим сразу, что эти средства без преувеличений хороши. Однако, с точки зрения новичка, истинные преимущества встроенной подсистемы визуализации, скажем так, неочевидны. На момент написания этой заметки в моих руках находилась бета версия OpenCascade 7.0. Документация по поводу визуализации в ней, не будем скрывать, бессмысленна и беспощадна. Приведенные примеры кода не компилируются и не дают точных инструкций аля «делай так», предлагая пользователю самостоятельно разгадать кусочки ребуса вроде

Handle(V3d_Viewer) aViewer = ...; // Многоточие должен разгадать пользователь

Уверен, что со временем качество документации изменится к лучшему, и за тоннами текста начнет проглядывать жемчужина смысла. Однако сегодня чтение официальной документации может принести пользу только продвинутым пользователям, а новичкам остается посоветовать обратиться к демонстрационным приложениям, поставляемым вместе с библиотекой. Еще один замечательный способ получить представление о встроенных возможностях визуализации состоит в том, чтобы прогнать стандартные нерегрессионные тесты библиотеки и внимательно полистать итоговый HTML-отчет. Вы увидите множество картинок, относящихся к тестированию визуализационной подсистемы OpenCascade, из которых можно составить первое впечатление.

Можно ограничиться запуском тестов из групп v3d и 3rdparty. Например, тесты из группы 3rdparty дадут представление о том, как можно отрисовать текст в OpenGL-сцене, содержащей вашу CAD-модель.

Рис. 2. Пример модели.

Важнейшим достоинством встроенной визуализации OpenCascade является ее производительность. Производительность визуализации в VTK оказалась хуже, причем те модели, которые использовались для тестирования, нельзя назвать экстремально сложными (пример на рис. 2). Кроме того, встроенный визуализатор OpenCascade умеет рисовать каркасные модели, модели с невидимыми линиями, а также предоставляет механизм интерактивной селекции по наведению курсора мыши.

Рис. 3. Модель, отображенная средствами Open CASCADE Technology (красным цветом изображены «свободные» ребра).

В OpenCascade для визуализации геометрии CAD-модели используется вспомогательный класс: AIS_Shape (AIS = Application Interactive Services). Переход от точного B-Rep представления к полигональному осуществляется в его методе Compute(), который зовется при первой отрисовке автоматически. Понятно, что из одной мастер-модели (точной B-Rep модели) можно получить сколько угодно каких угодно полигональных представлений. Скажем, визуализировать точную геометрию можно перейдя к треугольникам, покрывающим поверхность модели, но можно ограничиться и только ребрами, вычерчивая таким образом проволочное представление геометрии. Вы можете изобрести и свой оригинальный способ отрисовки, уложив его в архитектуру OpenCascade.

Итак, одной модели могут отвечать несколько графических представлений. Архитектурно это выражается в том, что с одним экземпляром AIS_Shape связываются несколько экземпляров типа Prs3d_Presentation, которые содержат полигональные данные и заполняются в методе AIS_Shape::Compute().

Изучим подробнее механику перехода от точной модели к полигональной. Идея метода AIS_Shape::Compute(), который делает почти всю полезную работу, состоит в том, чтобы заполнить фасетными данными объект-представление Prs3d_Presentation. Последний принимается в качестве аргумента вместе с желаемым режимом отображения (display mode). Стандартными режимами отображения в OpenCascade являются затененный (shaded) и проволочный (wireframe), а также иногда режим невидимых линий (hidden lines removal). Каждому типу визуализации отвечает тот или иной конвертер, например, StdPrs_WFShape для проволочного представления, и StdPrs_ShadedShape для затененного. Конвертер заполняет объект-представление Prs3d_Presentation графическими примитивами, отвечающими тому или иному режиму.

Классический режим затененного отображения (shading) хорош для инженера, но не всегда для геометра. Иногда мы хотим видеть структуру фасетной подложки вместо сглаженного представления, формируемого видеокартой. Иными словами, часто в задачах вычислительной геометрии нам нужна триангуляция, а не оптическая иллюзия, делающая ее похожей на гладкую модель. Для работы с триангуляцией «живьем» мы могли бы использовать VTK, либо пакет MeshVS библиотеки OpenCascade. Последний заточен под визуализацию полигональных данных, отвязанных от точного B-Rep представления. Однако мы хотели бы сохранить привязку фасетов к оригинальному граничному представлению, учитывая, что эта привязка соблюдается фасетным генератором BRepMesh.

Рис. 4. Ассоциативность один-к-одному между криволинейными гранями и фасетными гранями.

Для каждой грани TopoDS_TFace мы можем получить ее полигональную подложку Poly_Triangulation, а для каждого ребра — соответствующий полигон Poly_PolygonOnTriangulation. Иными словами, фасетный генератор соблюдает соответствие между точной и дискретной геометриями, причем это соответствие взаимно однозначно (рис. 4). Замечательное свойство. Действительно, в компьютерной графике мы много работаем с полигональными моделями, в которых напрочь отсутствует (или утеряна) топологическая информация. В области же CAD мы хотим эту топологическую информацию сохранить, так как в ней закодирован конструктивный замысел: границы фасок и скруглений, острые края, зенковки и вообще все то, что принято называть «feature» («фичер»). Ни VTK, ни пакет MeshVS библиотеки OpenCascade ничего не знают о топологии вашей модели, то есть в них не отражается конструктивный замысел.

Допустим, что нам нужно представление, работающее в точности как shading, но дополненное границами треугольников (как на рис. 1). Сделать это можно легко, не расширяя стандартных средств библиотеки. Визуализация OpenCascade предоставляет некоторые возможности по настройке видимых элементов сцены при помощи объекта Drawer. Этот объект дает доступ к свойствам (т.н. «аспектам») полигональных примитивов.

//-------------------------------------------------------
// myAISContext предполагается уже созданным где-то выше
//-------------------------------------------------------
  
  Handle(Prs3d_Drawer) drawer = myAISContext->DefaultDrawer();
  //
  drawer->SetFaceBoundaryDraw(1);
  drawer->FaceBoundaryAspect()->SetWidth(3);
  drawer->FaceBoundaryAspect()->SetColor(Quantity_NOC_DARKGREEN);
  drawer->FaceBoundaryAspect()->SetTypeOfLine(Aspect_TOL_SOLID);
  //
  const Handle(Prs3d_ShadingAspect)& shadingAspect = drawer->ShadingAspect();
  shadingAspect->SetColor(Quantity_NOC_LIMEGREEN);
  //
  Handle(Graphic3d_AspectFillArea3d) fillingAspect = shadingAspect->Aspect();
  fillingAspect->SetEdgeOn();
  fillingAspect->SetEdgeColor(Quantity_NOC_DARKGREEN);

Код, приведенный выше, включает отрисовку ребер в shading-режиме, настраивает цвета и включает визуализацию границ треугольников при помощи метода SetEdgeOn(), выполненного на соответствующем «аспекте». Теперь мы можем насладиться видом реальной триангуляции с привязкой к исходной топологии CAD.

Рис. 5. Фасеты (очерчены тонкими линиями) с топологической привязкой (жирные линии) на примере модели ANC101.

Рис. 6. Фасеты (очерчены тонкими линиями) с топологической привязкой (жирные линии) на примере модели шарикоподшипника.

Так мы получаем «честную» полигональную визуализацию на той дискретизации, которая реально хранится в B-Rep модели. Отметим еще раз, что речь не идет о визуализации точной модели. Точная модель не рисуется никогда, поскольку она, грубо говоря, хранится в виде математических формул в оперативной памяти и требует предварительной полигонализации перед отправкой на видеокарту. Сравните две полигональные визуализации на одной и той же точной модели:

Рис. 7. Дискретизация MBB Gehause Rohteil, полученная с разной точностью. Слева включена визуализация ребер, справа — нет.

OpenCascade и VTK

Если вы предпочитаете VTK или рендеринг собственного изготовления, то OpenCascade для вас заканчивается генератором фасетов. Имея полигональную модель, вы отправляете ее на видеокарту тем или иным способом. Мы поговорим о визуализации при помощи VTK, поскольку от OpenCascade к VTK переброшен небольшой мостик. Речь идет о пакете IVtk, который предоставляет два сервиса: подготовку полигональных данных в виде адаптированном для VTK, а также утилиту для интерактивной селекции (пикер, от англ. picker). Чтобы понять как правильно использовать IVtk, нужно иметь представление об архитектуре собственно VTK.

В принципе неплохая документация по данной компоненте доступна на официальном сайте. Обратите внимание на то, что пакет IVtk там именуется VIS (VTK Integration Services).

VTK — это библиотека многоцелевой научной визуализации, которая не имеет прямого отношения к САПР. Вы, как программист, отвечаете за то, чтобы привести данные вашего приложения к одной из презентабельных форм, после чего эти данные могут быть обработаны множеством разнообразных специализированных алгоритмов — фильтров. Подчеркнем, что для VTK нет разницы, с геометрией вы работаете или, скажем, с сейсмологическими данными: ее инструментарий годится для любых целей. Грубо говоря, если вы знаете как перевести свои данные в полигональную (но не только) форму, то VTK знает, что делать дальше. И ни слова об OpenGL.

Архитектура VTK строится вокруг понятия конвейера (pipeline). Визуализация — это последовательный, конвейерный процесс, при котором полигональные данные «фильтруются» серией алгоритмов, прежде чем будут отправлены на отрисовку. Непосредственно стадия отрисовки отдается на откуп VTK, а программист фокусируется на том, чтобы построить нужный конвейер из подходящих алгоритмов. Если подходящих алгоритмов не оказалось, то пишутся свои.

Говоря о VTK, полезно отделить понятие визуализации от понятия отрисовки. Под отрисовкой понимаются непосредственные команды рендеринга («черчения»), тогда как визуализация — это наукоемкий процесс подготовки данных, настройки сцены и проч. Так, например, сейсмологические данные нельзя отрисовать, но можно визуализировать.

Рис. 8. Конвейер VTK.

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

Пакет IVtk — это готовые к использованию элементы конвейера, которые вы можете включить (или нет) в свое приложение. Кроме того, в состав пакета входит пикер (picker), работающий по тому же принципу, что родная интерактивная селекция OpenCascade. В идеале, визуализация построенная при помощи связки OpenCascade + IVtk + VTK, должна быть функционально эквивалентна встроенной визуализации OpenCascade. На деле же ситуация с VTK обстоит несколько хуже. Прежде всего, производительность визуализации в VTK 6.1 ниже производительности встроенной визуализации.

Замечу, что первые эксперименты с новым VTK 7.0 показывают, что производительность стала существенно лучше.

Рис. 9. Модель ANC101, представленная структурами OpenCascade и отрисованная при помощи VTK.

Кроме того, замечено, что страдает скорость интерактивной селекции — в случае с VTK интерактивная подсветка работает медленнее. Судить о том, насколько в этом виновата сама библиотека VTK, непросто, так как конструирование эффективного конвейера лежит полностью на совести программиста (т.е. легко ошибиться). Заметим также, что IVtk содержит специальный фильтр для двух режимов визуализации: shading и wireframe. Комбинированный режим, а также разнообразную «экзотику» вроде режима удаления скрытых линий (hidden lines removal), придется программировать самостоятельно.

Что выбрать?

В целом, CAD-визуализация посредством VTK + IVtk неплохо работает для небольших моделей. Однако в случае крупных сборок стандартные механизмы визуализации OpenCascade начинают серьезно выигрывать. Но следует иметь в виду, что выбирая VTK, вы получаете огромное количество готовых к использованию фильтров, которые могут понадобиться, например, на стыке CAD и CAE. С другой стороны, выбирая встроенные средства OpenCascade, вы получаете быструю и гибкую визуализацию, адаптированную непосредственно под нужны САПР.

Рис. 10. Полигональная подложка передней части самолета Блерио.

Приложение 1: инициализируем вьювер OpenCascade

Код справедлив для версии OCCT 7.0.

//-------------------------------------------------------
// OpenCascade viewer initialization
//-------------------------------------------------------
  
  static Handle(OpenGl_GraphicDriver) aGraphicDriver;
  //
  if ( aGraphicDriver.IsNull() )
  {
    Handle(Aspect_DisplayConnection) aDisplayConnection;
#if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
    aDisplayConnection = new Aspect_DisplayConnection( qgetenv("DISPLAY").constData() );
#endif
    aGraphicDriver = new OpenGl_GraphicDriver(aDisplayConnection);
  }
  
  // Create OpenCascade viewer
  TCollection_ExtendedString a3DName("Visu3D");
  Handle(V3d_Viewer) viewer = new V3d_Viewer(aGraphicDriver,
                                             a3DName.ToExtString(),
                                             "",
                                             1000.0,
                                             V3d_XposYnegZpos,
                                             Quantity_NOC_GRAY30,
                                             V3d_ZBUFFER,
                                             V3d_GOURAUD,
                                             V3d_WAIT,
                                             1,
                                             1,
                                             V3d_TEX_NONE);
  viewer->SetDefaultLights();
  viewer->SetLightOn();
  //
  Handle(AIS_InteractiveContext) context = new AIS_InteractiveContext(viewer);
  
  // Create OpenCascade viewer. NOTICE: this is you, who implement the
  // window here. Refer to OCCT visualization sample for details
  m_widgets.wViewer = new gui_my_viewer(context);

Заметим, что при создании вьювера, мы указываем режим затенения по Гуро (V3d_GOURAUD).

Приложение 2: антиалиасинг (antialiasing) в OpenCascade

Код справедлив для версии OCCT 7.0.

//-------------------------------------------------------
// OpenCascade viewer is already initialized here
//-------------------------------------------------------
  
  // Configure rendering parameters
  Graphic3d_RenderingParams& RenderParams = m_widgets.wViewer->GetView()->ChangeRenderingParams();
  RenderParams.NbMsaaSamples = 4; // Anti-aliasing by multi-sampling (4 times)