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;
}
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 need to get references to our canvas and window objects. In this case our canvas is referenced by the _canvas
variable and the window object is referenced by window
, but your application may define them differently. If you are using one of the Sandbox applications, you can get a reference to them using GetCanvas()
and GetCanvas().GetWindowKey()
, respectively.
Attach the newly imported model to the front view of our canvas. Then, we’ll define the model 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();
// 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;
}
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 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.
The Resource Monitor
Here’s how to load it into the scene:
window.GetDebuggingControl().SetResourceMonitor(true);
window.GetDebuggingControl().SetResourceMonitor(true);
6.5 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;
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).
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;
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]
//! [import_file]
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
}
//! [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 = 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;
}
//! [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(out updateInfo))
// This should still be 0.
static_models_created = (int)updateInfo.statics_created_count;
//! [first_update]
//! [second_update]
window.UpdateWithNotifier(Window.UpdateType.Default).Wait();
if (windowInfo.ShowLastUpdateInfo(out updateInfo))
// This should now be 1.
static_models_created = (int)updateInfo.statics_created_count;
//! [second_update]