Static Model

Using a static model can dramatically reduce rendering time, especially for large models. In this tutorial, we’ll walk you through the basics of setting up your scene to work with a static model. For a top-level overview of the performance benefits of using a static model, please see the Performance Considerations section of the Programming Guide.

6.1 Importing a Model File

We’ll start off by importing an HSF file using an HPS::Stream::ImportOptionsKit. (For more information on importing files, please see this section.)

    HPS::Model myModel = Factory::CreateModel();

    SegmentKey modelSegment = myModel.GetSegmentKey();

    HPS::Stream::ImportNotifier importNotifier;
    try {
        HPS::Stream::ImportOptionsKit myImportOptionsKit;
        myImportOptionsKit.SetSegment(modelSegment); // set destination segment

        importNotifier = HPS::Stream::File::Import(filename, myImportOptionsKit);

        // Pauses this thread until the HSF is finished loading.
        importNotifier.Wait();
    }

    catch (HPS::IOException ioe) {
        // handle exception
        throw;
    }

6.2 Setting the Static Model

Next we’ll attach the newly imported model to the front view of our canvas. Then, we’ll define this segment as a static model:

    // Attach the model to the front View of the Canvas.
    _canvas.GetFrontView().AttachModel(myModel);

    modelSegment.GetPerformanceControl().SetStaticModel(Performance::StaticModel::Attribute);

    // An Exhaustive update after an initial file load will build a static model.
    window.UpdateWithNotifier(Window::UpdateType::Exhaustive).Wait();

6.3 Collecting Performance Diagnostics

In order to see diagnostic information about our static model, we’ll use the HPS::WindowInfoControl to populate an HPS::UpdateInfo object:

    WindowInfoControl windowInfo = window.GetWindowInfoControl();
    UpdateInfo updateInfo;
    size_t static_models_created = 0;

    if (windowInfo.ShowLastUpdateInfo(updateInfo)) {
        // This should be 1.
        static_models_created = updateInfo.statics_created_count;
    }

6.4 Changing the Static Model

For illustration purposes, we’re going to change the modelling matrix by doubling the scale of the model; this change will invalidate the static model and will require an update:

    // Changing the modelling matrix will invalidate the current static model.
    _canvas.GetFrontView().GetAttachedModel().GetSegmentKey().GetModellingMatrixControl().Scale(2.0f, 2.0f, 2.0f);

6.5 Using the Resource Monitor

A component of the HPS::DebuggingControl class, the Resource Monitor displays a variety of helpful statistics, including the number of static models generated in the most recent update. It’s a useful tool for debugging and for testing which changes will trigger regeneration of the static model.

../_images/ResourceMonitor.png

The Resource Monitor

Here’s how to load it into the scene:

    window.GetDebuggingControl().SetResourceMonitor(true);

6.6 Update Types

For performance reasons, when a window is updated with the Default UpdateType, the static model is not regenerated during an update immediately following any changes that have been made to the scene that invalidated the static model subtree. Instead, the static model will be regenerated on the next update as long as no further changes have occurred that would have invalidated the static model subtree. In other words, Visualize waits until it’s reasonably sure that all of the invalidating changes have been made before performing an update to the static model. This is a performance optimization to avoid generating a static model unnecessarily. (To force a static model regeneration, however, you would simply use the HPS::Window::UpdateType::Exhaustive update type.) The first non-Exhaustive and non-CompileOnly update after a modification will not build a static model.

    window.UpdateWithNotifier(Window::UpdateType::Default).Wait();
    if (windowInfo.ShowLastUpdateInfo(updateInfo))
        // This should still be 0.
        static_models_created = updateInfo.statics_created_count;

The second non-Exhaustive and non-CompileOnly update after a modification <em>will</em> build a static model (assuming no additional static-breaking changes are made, which would delay the update).

    window.UpdateWithNotifier(Window::UpdateType::Default).Wait();
    if (windowInfo.ShowLastUpdateInfo(updateInfo))
        // This should now be 1.
        static_models_created = updateInfo.statics_created_count;

Appendix

Full source code:

    //! [import_file]
    HPS::Model myModel = Factory::CreateModel();

    SegmentKey modelSegment = myModel.GetSegmentKey();

    HPS::Stream::ImportNotifier importNotifier;
    try {
        HPS::Stream::ImportOptionsKit myImportOptionsKit;
        myImportOptionsKit.SetSegment(modelSegment); // set destination segment

        importNotifier = HPS::Stream::File::Import(filename, myImportOptionsKit);

        // Pauses this thread until the HSF is finished loading.
        importNotifier.Wait();
    }

    catch (HPS::IOException ioe) {
        // handle exception
        throw;
    }
    //! [import_file]

    //! [set_static_model]
    // Attach the model to the front View of the Canvas.
    _canvas.GetFrontView().AttachModel(myModel);

    modelSegment.GetPerformanceControl().SetStaticModel(Performance::StaticModel::Attribute);

    // An Exhaustive update after an initial file load will build a static model.
    window.UpdateWithNotifier(Window::UpdateType::Exhaustive).Wait();
    //! [set_static_model]

    //! [update_info_sample]
    WindowInfoControl windowInfo = window.GetWindowInfoControl();
    UpdateInfo updateInfo;
    size_t static_models_created = 0;

    if (windowInfo.ShowLastUpdateInfo(updateInfo)) {
        // This should be 1.
        static_models_created = updateInfo.statics_created_count;
    }
    //! [update_info_sample]

    //! [static_model_change]

    // Changing the modelling matrix will invalidate the current static model.
    _canvas.GetFrontView().GetAttachedModel().GetSegmentKey().GetModellingMatrixControl().Scale(2.0f, 2.0f, 2.0f);

    //! [static_model_change]

    //! [set_resource_monitor]
    window.GetDebuggingControl().SetResourceMonitor(true);
    //! [set_resource_monitor]

    //! [first_update]
    window.UpdateWithNotifier(Window::UpdateType::Default).Wait();
    if (windowInfo.ShowLastUpdateInfo(updateInfo))
        // This should still be 0.
        static_models_created = updateInfo.statics_created_count;
    //! [first_update]

    //! [second_update]
    window.UpdateWithNotifier(Window::UpdateType::Default).Wait();
    if (windowInfo.ShowLastUpdateInfo(updateInfo))
        // This should now be 1.
        static_models_created = updateInfo.statics_created_count;
    //! [second_update]