Tutorial 6: Static Model Workflow

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 ImportOptionsKit. (For more information on importing files, please see this section.)

[snippet t.5.1.a]
HPS::Model myModel = Factory::CreateModel();
SegmentKey modelSegment = myModel.GetSegmentKey();
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;
}
HPS.Model myModel = Factory.CreateModel();
SegmentKey modelSegment = myModel.GetSegmentKey();
// Modify this path to point to your model file.
string filename = "C:\\myData\\bnc.hsf";
HPS.Stream.ImportNotifier importNotifier = new Stream.ImportNotifier();
try
{
HPS.Stream.ImportOptionsKit myImportOptionsKit = new Stream.ImportOptionsKit();
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)
{
// handle exception
}



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:

[snippet t.6.2.a]
// 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();
// 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 WindowInfoControl to populate an UpdateInfo object:

[snippet t.6.3.a]
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;
}
WindowInfoControl windowInfo = window.GetWindowInfoControl();
UpdateInfo updateInfo = new HPS.UpdateInfo();
int static_models_created = 0;
if (windowInfo.ShowLastUpdateInfo(out updateInfo))
{
// This should be 1.
static_models_created = (int)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:

[snippet t.6.4.a]
// Changing the modelling matrix will invalidate the current static model.
_canvas.GetFrontView().GetAttachedModel().GetSegmentKey().GetModellingMatrixControl().Scale(2.0f, 2.0f, 2.0f);
// 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.

[figure 6.1.a] The Resource Monitor

Here's how to load it into the scene:

[snippet t.6.5.a]
window.GetDebuggingControl().SetResourceMonitor(true);
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 Exhaustive UpdateType.)

The first non-Exhaustive and non-CompileOnly update after a modification will not build a static model.

[snippet t.6.6.a]
window.UpdateWithNotifier(Window::UpdateType::Default).Wait();
if (windowInfo.ShowLastUpdateInfo(updateInfo))
// This should still be 0.
static_models_created = updateInfo.statics_created_count;
window.UpdateWithNotifier(Window.UpdateType.Default).Wait();
if (windowInfo.ShowLastUpdateInfo(out updateInfo))
// This should still be 0.
static_models_created = (int)updateInfo.statics_created_count;

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

[snippet t.6.6.b]
window.UpdateWithNotifier(Window::UpdateType::Default).Wait();
if (windowInfo.ShowLastUpdateInfo(updateInfo))
// This should now be 1.
static_models_created = updateInfo.statics_created_count;
window.UpdateWithNotifier(Window.UpdateType.Default).Wait();
if (windowInfo.ShowLastUpdateInfo(out updateInfo))
// This should now be 1.
static_models_created = (int)updateInfo.statics_created_count;

Appendices

Full source code:

[snippet t.6.7.a]
HPS::Model myModel = Factory::CreateModel();
SegmentKey modelSegment = myModel.GetSegmentKey();
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;
}
// 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();
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;
}
// Changing the modelling matrix will invalidate the current static model.
_canvas.GetFrontView().GetAttachedModel().GetSegmentKey().GetModellingMatrixControl().Scale(2.0f, 2.0f, 2.0f);
window.GetDebuggingControl().SetResourceMonitor(true);
window.UpdateWithNotifier(Window::UpdateType::Default).Wait();
if (windowInfo.ShowLastUpdateInfo(updateInfo))
// This should still be 0.
static_models_created = updateInfo.statics_created_count;
window.UpdateWithNotifier(Window::UpdateType::Default).Wait();
if (windowInfo.ShowLastUpdateInfo(updateInfo))
// This should now be 1.
static_models_created = updateInfo.statics_created_count;
HPS.Model myModel = Factory.CreateModel();
SegmentKey modelSegment = myModel.GetSegmentKey();
// Modify this path to point to your model file.
string filename = "C:\\myData\\bnc.hsf";
HPS.Stream.ImportNotifier importNotifier = new Stream.ImportNotifier();
try
{
HPS.Stream.ImportOptionsKit myImportOptionsKit = new Stream.ImportOptionsKit();
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)
{
// handle exception
}
// 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();
WindowInfoControl windowInfo = window.GetWindowInfoControl();
UpdateInfo updateInfo = new HPS.UpdateInfo();
int static_models_created = 0;
if (windowInfo.ShowLastUpdateInfo(out updateInfo))
{
// This should be 1.
static_models_created = (int)updateInfo.statics_created_count;
}
// Changing the modelling matrix will invalidate the current static model.
_canvas.GetFrontView().GetAttachedModel().GetSegmentKey().GetModellingMatrixControl().Scale(2.0f, 2.0f, 2.0f);
window.GetDebuggingControl().SetResourceMonitor(true);
window.UpdateWithNotifier(Window.UpdateType.Default).Wait();
if (windowInfo.ShowLastUpdateInfo(out updateInfo))
// This should still be 0.
static_models_created = (int)updateInfo.statics_created_count;
window.UpdateWithNotifier(Window.UpdateType.Default).Wait();
if (windowInfo.ShowLastUpdateInfo(out updateInfo))
// This should now be 1.
static_models_created = (int)updateInfo.statics_created_count;