Multiple Views

With CEETRON Envision, you can operate on multiple models and multiple views at the same time. This is a powerful feature that enables the user get a better overview of the analysis by, for instance:

  • Analyze and compare multiple models at the same time

  • Compare different simulation runs/time steps side by side

  • View multiple versions of the same model file with different feature extractions or results visualization

  • Look at the same model from different point of views a the same time

The views can have synchronized navigation or operate independently. If you have the same model in multiple views, all result visualization and feature extractions will apply to all the views the model is presented in.

../../_images/multiple_views.png

To have multiple views, you need one viewer per view. Read more on how to setup a viewer on UI Toolkit Integrations.

Creating Multiple Views

Below is example code on creating multiple views (using the Qt toolkit). This creates two views and puts the same model in both views. An info box and an axis cross is also added to each view.

MainWindow::MainWindow(cee::vis::OpenGLContextGroup* contextGroup)
:   m_openGLContextGroup(contextGroup)
{
    QFrame* mainFrame = new QFrame;
    QGridLayout* frameLayout = new QGridLayout;
    mainFrame->setLayout(frameLayout);
    setCentralWidget(mainFrame);

    std::vector<cee::qt::ViewerOpenGLWidgetDemo*> viewers;
    std::vector<cee::PtrRef<cee::vis::View> > views;

    // Create multiple views
    size_t numViewers = 2;
    for (size_t i = 0; i < numViewers; i++)
    {
        viewers.push_back(new cee::qt::ViewerOpenGLWidgetDemo(contextGroup, mainFrame));
        frameLayout->addWidget(viewers[i], 0, static_cast<int>(i));

        cee::PtrRef<cee::vis::View> view = new cee::vis::View;
        views.push_back(view);
        viewers[i]->setView(view.get());

        view->overlay().addItem(new cee::vis::OverlayAxisCross(&view->camera(),
            cee::vis::Font::createNormalFont().get()),
            cee::vis::OverlayItem::BOTTOM_LEFT, cee::vis::OverlayItem::HORIZONTAL);

        cee::vis::OverlayTextBox* textBox = new cee::vis::OverlayTextBox(cee::vis::Font::createNormalFont().get());
        textBox->setText(cee::qt::UtilsCore::toStr(QString("View %1").arg(i + 1)));
        textBox->setSizeToFitText();
        view->overlay().addItem(textBox, cee::vis::OverlayItem::TOP_LEFT, cee::vis::OverlayItem::HORIZONTAL);
    }

    // Create one model and add it to all views
    cee::PtrRef<cee::geo::GeometryModel> theModel = new cee::geo::GeometryModel;
    views[0]->addModel(theModel.get()); // Model musts be added to a view before parts can be added

    cee::geo::Part* part = new cee::geo::Part(cee::geo::DataGenerator::createBox(cee::Vec3d(0, 0, 0), cee::Vec3d(1, 0.75f, 0.5)).get());
    part->settings().addEffect(new cee::geo::EffectColor(cee::Color3f(0.00f, 0.53f, 0.58f)));
    theModel->addPart(part);

    for (size_t i = 0; i < numViewers; i++)
    {
        if (i > 0) // Model already added to first view
        {
            views[i]->addModel(theModel.get());
        }

        cee::BoundingBox bb = views[i]->boundingBox();
        views[i]->camera().fitView(bb, cee::Vec3d(0, 0, -1), cee::Vec3d(0, 1, 0));
    }
}

Synchronizing Multiple Views

If you want to synchronize the navigation between the views, create functionality to get the current camera setup from the view you’ve changed, and apply this to the views you want to synchronize. Then piggy back on the viewers events and call this function. For instance in mouseMoveEvent() and mouseWheelEvent().

void MainWindow::updateNavigationInSyncedViews(cee::vis::View* masterView)
{
    const cee::vis::Camera& masterCamera = masterView->camera();
    cee::Vec3d eye, vrp, up;
    masterCamera.toLookAt(&eye, &vrp, &up);

    cee::vis::Camera::ProjectionType projection = masterCamera.projection();
    const double frustumHeight = masterCamera.frontPlaneFrustumHeight();
    const double nearPlane = masterCamera.nearPlane();
    const double farPlane = masterCamera.farPlane();
    const double pi = 3.14159265358979323846;

    for (size_t i = 0; i < views.size(); i++)
    {
        if (masterView == views[i])
        {
            continue;
        }

        views[i]->camera().setFromLookAt(eye, vrp, up);

        if (projection == cee::vis::Camera::PERSPECTIVE)
        {
            double fovY = 2 * atan((frustumHeight / 2) / nearPlane);
            if (fovY > 0)
            {
                views[i]->camera().setProjectionAsPerspective(fovY * 180.0 / pi, nearPlane, farPlane);
            }
        }
        else if (projection == cee::vis::Camera::ORTHO)
        {
            if (frustumHeight > 0)
            {
                views[i]->camera().setProjectionAsOrtho(frustumHeight, nearPlane, farPlane);
            }
        }
        views[i]->requestRedraw();
    }
}
void ViewerOpenGLWidgetDemo::mouseMoveEvent(QMouseEvent* event)
{

    ...

    MainWindow::instance()->updateNavigationInSyncedViews(view());
}
../../_images/multiple_views_example.png

Example

QtMultiView

img_multi

Location: Examples/Qt/QtMultiView
There’s a small Qt example showing multiple views included in the
Envision Desktop distribution.