Exporting


HOOPS Visualize can export a few different types of file formats. Regardless of the file type, a similar pattern is employed. For this section of the Programming Guide, we'll cover HSF file export (the native file format for HOOPS Visualize) as well as export to HTML. See the Programming Guide sections on Exchange integration and Parasolid integration for information on exporting via HOOPS Exchange and Parasolid, respectively.

HSF Export

When exporting data, HSFs can be written from any arbitrary segment. This means that the entire scene can be saved by writing from the window segment. Alternatively, a portion of the scene can be written if only a piece of a model needs to be saved. Note that when saving partial scenes, attributes inherited by the branch root are not saved with the HSF. If you wish to save attributes into the HSF, they must be explicitly set within the branch you are exporting.

The basic method for exporting a model to HSF is shown below:

try
{
exportOptionsKit.SetColorCompression(true, 16);
HPS::Stream::File::Export(filename, mySegmentKey, exportOptionsKit).Wait();
}
catch (IOException ioe)
{
// handle exception
throw;
}
try
{
HPS.Stream.ExportOptionsKit exportOptionsKit = new HPS.Stream.ExportOptionsKit();
exportOptionsKit.SetColorCompression(true, 16); // color compression ranges from 0 to 72
HPS.Stream.File.Export(filename, mySegmentKey, exportOptionsKit).Wait();
}
catch (HPS.IOException ioe)
{
// handle exception
}



The HPS::Stream::ExportOptionsKit has a variety of lossy compression options. Color compression is enabled in the snippet above as an example of how to specify compression.

IMPORTANT: All file exports are done synchronously, except for HSF stream files. Do not try to export on a separate thread while the scene graph can be modified, because the scene graph must be in a write-locked state during the export.

For HSF files, the HPS::Stream export operation will happen on a separate thread. Do not modify the subtree while the export is occurring. When exporting stream files, you should use a HPS::Stream::ExportNotifier to control the export operation. For example, you can call:

  • Status(), to receive the current export status and check the progress.
  • Wait(), to block the current thread until the export operation is finished.
  • Cancel(), to cancel the export operation.

If you cancel a file export, you are responsible for cleaning up the partially exported file on disk.

Exporting to a buffer

In addition to saving to an HSF, the HPS::Stream class supports exporting HSF data to a buffer. This is implemented as an overload to HPS::Stream::File::Export.

try
{
// write to a series of buffers
HPS::Stream::ExportNotifier exportNotifier = HPS::Stream::File::Export(mySegmentKey, exportOptionsKit, buffers);
// pauses this thread until the HSF is finished exporting
exportNotifier.Wait();
}
catch (HPS::IOException ioe)
{
// handle exception
throw;
}
byte[][] buffers;
try
{
HPS.Stream.ExportOptionsKit exportOptionsKit = new HPS.Stream.ExportOptionsKit();
// write to a series of buffers
HPS.Stream.ExportNotifier exportNotifier = HPS.Stream.File.Export(mySegmentKey, exportOptionsKit, out buffers);
exportNotifier.Wait();
}
catch (HPS.IOException ioe)
{
// handle exception
throw;
}



Export events

When writing an HSF file, Visualize can notify you of its progress through the use of HPS::Stream::SegmentExportEvent and HPS::Stream::GeometryExportEvent. You receive these events by setting an HPS::Stream::ExportEventHandler for the HPS::Stream::ExportEvent type (from HPS::Object::ClassID) on your HPS::Stream::ExportOptionsKit. The HPS::Stream::ExportEventHandler class has a virtual function, Handle, that Visualize will call with the HPS::Stream::ExportEvent data when it is about to write the provided data. You should override the Handle function to inspect the data to suit your needs.

The following code sample defines a custom ExportEventHandler class, which will export some non-db user data if a specific segment-name is encountered in the HSF file:

class SpecialExportEvent : public HPS::Stream::ExportEventHandler
{
public:
{
if (e != nullptr)
{
HPS::UTF8 name = seg_event->segment_key.Name();
if (name == "My_Special_Segment")
{
const char * str = "HOOPS! HOOPS!";
seg_event->non_db_user_data.assign(str, str+strlen(str));
}
}
}
};
class SpecialExportEvent : HPS.Stream.ExportEventHandler
{
public override void Handle(HPS.Stream.ExportEvent e)
{
HPS.Stream.SegmentExportEvent seg_event = (HPS.Stream.SegmentExportEvent)e;
string name = seg_event.segment_key.Name();
if (name == "My_Special_Segment")
{
string str = "HOOPS Visualize!";
seg_event.non_db_user_data = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, seg_event.non_db_user_data, 0, seg_event.non_db_user_data.Length);
}
}
};



We then set the custom handler on the HPS::Stream::ExportOptionsKit for the segment-export event, prior to exporting the HSF File:

SpecialExportEvent special_export_event;
export_options.SetEventHandler(special_export_event, HPS::Object::ClassID<HPS::Stream::SegmentExportEvent>());
SpecialExportEvent special_export_event = new SpecialExportEvent();
HPS.Stream.ExportOptionsKit export_options = new HPS.Stream.ExportOptionsKit();
export_options.SetEventHandler(special_export_event, HPS.Object.ClassID<HPS.Stream.SegmentExportEvent>());



User data

User data can be exported to an HSF file in 2 different ways. One form is user data that is specified within the database and is associated with a segment or geometry (See User Data), and will be automatically exported along with the database. The second form is user-data that is not associated with the database and can be exported by utilizing the HPS::Stream::ExportEvent::non_db_user_data, where you may copy arbitrary data.

HTML Export

Please note, HTML Export is only available for 64-bit Windows applications.

To export your model to HTML, first import it into Visualize and construct a SprocketPath object using your Canvas, Layout, Model, and View objects:

SprocketPath sPath(canvas, layout, view, model);
try
{
HTML::File::Export(sPath.GetKeyPath(), exportedHTMLFilePath, htmlTemplateFilePath);
}
catch (IOException const &)
{
// something went wrong with the HTML export
}
SprocketPath sPath = new SprocketPath(canvas, layout, view, model);
try
{
HTML.File.Export(sPath.GetKeyPath(), exportedHTMLFilePath, htmlTemplateFilePath);
}
catch (IOException)
{
// something went wrong with the HTML export
}



Call HTML::File::Export() with the following parameters: the keypath of your SprocketPath, the output file path for your HTML file, and the HTML template file into which the exported model will be embedded.

For your convenience, there are two template files in the Visualize package, both of which are based on HOOPS Communicator's StreamCache technology: HOOPSCommunicatorTemplate.html and HOOPSCommunicatorMinimalTemplate.html. The standard template includes advanced UI features, whereas the minimal template only includes the basic functionality for viewing a model.

For simplicity, we'll discuss how to modify the minimal HTML template below.

Modifying the HTML Template

The HTML export creates a totally self-contained HTML file for viewing a model. This means that all the markup, styling, javascript, images, and model data are contained in a single file which works out of the box in any modern browser with no internet connection required.

About the HOOPS Communicator Template File

The template file is a pre-processed HTML file with all dependencies inlined. Binary dependencies such as images and model data are base64 encoded into the file as well. All this preprocessing is done when the HOOPS Communicator package is built. Browsers can automatically base64 decode binary files such as images. Additional javascript code must be used to base64 decode the model data. This code is included in the standard template and can be leveraged by customers if needed.

Creating a Custom Template File

Aside from ensuring that the contents of hoops_web_viewer.js are included in the page, there are four required steps to create a custom template file. (To see a sample template, please go to the bottom of this page.)

Step 1: Insert the data replacement string

Include the replacement string in the file:

<!– SC_MODEL_DATA –>

The system searches the template file for this string and replaces it with base64 binary encoded data. Ideally this string should be saved in a variable. E.g.:

var SC_MODEL_DATA = "<!-- SC_MODEL_DATA -->";
Step 2: Add a container div

There must be a container div in the template in which the viewer will be created:

<div id="viewerContainer" style="width:100%; height:100%;"></div>

Feel free to add your own styling.

Step 3: Decode the base64-encoded data to a Uint8 buffer

Sample code to do this is provided in the minimal template. The _base64ToUint8Array method is a small helper function provided by HOOPS Communicator team:

var binaryModelData = _base64ToUint8Array(SC_MODEL_DATA)
Step 4: Create and start a WebViewer object

Specify your binary decoded data to the web viewer:

var viewer= new Communicator.WebViewer({ containerId: "viewerContainer", buffer: binaryModelData, });

Look, Feel & Functionality

Aside from the required elements enumerated above, users are free to add in their own HTML / JS / CSS code to the template. HOOPS Communicator customers may use the entirety of the Communicator API to create their own customized pages.

There are some restrictions for non-Communicator customers. The following classes aren't available to non-Communicator customers:

Communicator.MeshData
Communicator.MeshInstanceData

The following functions aren't available to non-Communicator customers:

Communicator.Model.createMesh
Communicator.Model.createMeshInstance

Helpful Hints

It can be challenging to work only in a single template file, especially given the size of the required javascript for the HOOPS WebViewer. There are a number of tools which can take a website and convert it to a self contained file. It would be helpful to design your template using normal separation of HTML, JS, CSS and employ a tool to combine all of it into your final template. We have had good luck using the webpage2html python module.

Sample HTML Template

The sample below shows the minimal HTML Export template; this file is available in the package in the samples->data directory. It will decode the plaintext data and start the viewer:

 Click to see HTML sample file

OBJ Export

To export your scene to an OBJ file, create a SprocketPath using your canvas, model, layout, and view. Then simply pass the SprocketPath as a keypath to the Export() function along with your file path:

SprocketPath path(canvas, canvas.GetAttachedLayout(), view, model);
UTF8 output_file = my_export_directory + "/obj_export_1.obj";
OBJ::ExportNotifier export_notifier = OBJ::File::Export(output_file, path.GetKeyPath());
SprocketPath path = new SprocketPath(canvas, canvas.GetAttachedLayout(), view, model);
string output_file = my_export_directory + "/obj_export_1.obj";
OBJ.ExportNotifier export_notifier = OBJ.File.Export(output_file, path.GetKeyPath());


In addition to an OBJ file, a file with an MTL extension will also be created in the output directory for most OBJ exports. This MTL file contains color and texture information. An image file will also be created for each texture used in the exported model.

For limitations of OBJ export, please see Supported File Formats.