ImportExport Example

This example code demonstrates how to programmatically import a CAD model using HOOPS Exchange and convert it to another format. This is one of the best places to start with HOOPS Exchange.

In addition to this document, the File-to-File Translation tutorial provides you with ways to play along with the import and export parameters to discover HOOPS Exchange I/O capabilities.

ImportExport is available in HOOPS Exchange package, as part of the samples project. See Building Code Examples for more information about how to build and run the example code.

What is the ImportExport Sample

This sample reads an input CAD file and converts it to any of our export formats, according to the file extension passed in parameter. Once completed, the ImportExport generates a new CAD file and a log file in the same folder as the input file.

When invoked, it accepts up to 3 arguments, each having a default value:

Name Default
input _Aquo Bottle.CATProduct
output {input}.prc
log {output}_Log.txt

Use the --help option to get the full list of available parameters.

Note

Experimental USD export

Since HOOPS Exchange 2025.4.0, we support exporting to USD as an experimental feature. The Import Export sample can be extended to provide this functionality. For more information, see Extending the Import Export Sample.

The Code

The sample consists of a single source file, ImportExport.cpp.

Header Files

The most important header is A3DSDKInclude.h that declares the entire HOOPS Exchange API. The other headers facilitate writing example code.

Throughout the code, you will encounter helper functions such as AssertSuccess(), Assert(), and Sample:: namespaced utilities. These are part of the SampleTools library and are not specific to HOOPS Exchange.

Load/Unload HOOPS Exchange

Initializing and terminating HOOPS Exchange follows the usual pattern. For more information, see Initializing HOOPS Exchange.

48static void initialize_exchange(void) {
49    const A3DBool loaded = A3DSDKLoadLibraryA(HOOPS_BINARY_DIRECTORY);
50    REQUIRE(loaded);
51
52    A3DStatus status = A3DLicPutUnifiedLicense(HOOPS_LICENSE);
53    REQUIRE(status == A3D_SUCCESS);
54
55    status = A3DDllInitialize(A3D_DLL_MAJORVERSION, A3D_DLL_MINORVERSION);
56    REQUIRE(status == A3D_SUCCESS);
57
58    status = A3DDllSetCallbacksReport(Sample::PrintMessage, Sample::PrintWarning, Sample::PrintError);
59    REQUIRE(status == A3D_SUCCESS);
60}
259static void terminate_exchange(void) {
260    A3DStatus status = A3DDllTerminate();
261    REQUIRE(status == A3D_SUCCESS);
262
263    A3DSDKUnloadLibrary();
264}

Importing a CAD File

Importing a CAD file is done using the A3DAsmModelFileLoadFromFile() function. This function reads an input file path, and internally creates an entity called a model file.

The first thing we need to create is a location for storing the entity identifier. We also need to set the load parameters. HOOPS Exchange provides you with lots of ways to customize loading, and all parameters are set in the A3DRWParamsLoadData structure:

A3DAsmModelFile* model_file = A3D_NULL_HANDLE;
A3DRWParamsLoadData read_params = A3D_MAKE_DATA(A3DRWParamsLoadData);
// Customize parameters...

The following function takes a single file path string, and returns the created entity ID. Note the call to A3DAsmModelFileLoadFromFile():

 74static A3DAsmModelFile* import_cad_file(const std::string& file_path) {
 75    A3DAsmModelFile* model_file = A3D_NULL_HANDLE;
 76
 77    // Configure import parameters
 78    A3DRWParamsLoadData read_params                          = A3D_MAKE_DATA(A3DRWParamsLoadData);
 79    read_params.m_sGeneral.m_bReadSolids                     = A3D_TRUE;
 80    read_params.m_sGeneral.m_bReadSurfaces                   = A3D_TRUE;
 81    read_params.m_sGeneral.m_bReadWireframes                 = A3D_TRUE;
 82    read_params.m_sGeneral.m_bReadPmis                       = A3D_TRUE;
 83    read_params.m_sGeneral.m_bReadAttributes                 = A3D_TRUE;
 84    read_params.m_sGeneral.m_bReadHiddenObjects              = A3D_TRUE;
 85    read_params.m_sGeneral.m_bReadConstructionAndReferences  = A3D_FALSE;
 86    read_params.m_sGeneral.m_bReadActiveFilter               = A3D_TRUE;
 87    read_params.m_sGeneral.m_eReadingMode2D3D                = kA3DRead_3D;
 88    read_params.m_sGeneral.m_eReadGeomTessMode               = kA3DReadGeomAndTess;
 89    read_params.m_sGeneral.m_eDefaultUnit                    = kA3DUnitUnknown;
 90    read_params.m_sGeneral.m_dLongWireframeThreshold         = 24690.0;
 91    read_params.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
 92    read_params.m_sAssembly.m_bUseRootDirectory              = A3D_TRUE;
 93    read_params.m_sMultiEntries.m_bLoadDefault               = A3D_TRUE;
 94    read_params.m_sPmi.m_bAlwaysSubstituteFont               = A3D_FALSE;
 95    read_params.m_sPmi.m_pcSubstitutionFont                  = const_cast<char*>("Myriad CAD");
 96
 97    // Load the file
 98    const A3DStatus status = A3DAsmModelFileLoadFromFile(
 99        file_path.c_str(),
100        &read_params,
101        &model_file
102    );
103
104    REQUIRE_ANY_OF(status, A3D_SUCCESS, A3D_LOAD_MISSING_COMPONENTS);
105
106    return model_file;
107}

The model file entity returned by A3DAsmModelFileLoadFromFile() must be freed once you don’t need it, using A3DAsmModelFileDelete(). This is done later in the main() function:

Exporting a CAD File

HOOPS Exchange doesn’t provide a centralized export function, like A3DAsmModelFileLoadFromFile().

Instead, each format has its own specific function and parameter structure type. For example, to export a file to STL, use A3DAsmModelFileExportToStlFile() along with the A3DRWParamsExportStlData structure:

A3DStatus export_status                  = A3D_SUCCESS;
A3DRWParamsExportStlData export_data     = A3D_MAKE_DATA(A3DRWParamsExportStlData);
export_data.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
export_status = A3DAsmModelFileExportToStlFile(model_file, &export_data, c_file_path);
AssertSuccess(export_status);

In order to determine which pair of function and structure to call, the example code includes a function that returns the type enumeration, according to a file path, based on the file extensions:

////////////////////////////////////////////////////////////////////////////////
/// Map file extension to A3DEModellerType
static A3DEModellerType get_file_format(const std::string& filepath);

The implementation of the function is not in the scope of this document, but you have access to it directly from within the example code source. get_file_format() takes a file path in parameter, and returns the A3DEModellerType value corresponding to the file format.

The export_cad_file() function uses this value to select which function to call:

123static void export_cad_file(A3DAsmModelFile* model_file, const std::string& file_path) {
124    A3DStatus export_status       = A3D_SUCCESS;
125    const char* const c_file_path = file_path.c_str();
126    const A3DEModellerType type   = get_file_format(file_path);
127
128    // Each format has its own export params and function
129    switch (type) {
130
131        case kA3DModellerIges: {
132            A3DRWParamsExportIgesData export_data = A3D_MAKE_DATA(A3DRWParamsExportIgesData);
133            export_status = A3DAsmModelFileExportToIgesFile(model_file, &export_data, c_file_path);
134            break;
135        }
136
137        case kA3DModellerStep: {
138            A3DRWParamsExportStepData export_data = A3D_MAKE_DATA(A3DRWParamsExportStepData);
139            export_status = A3DAsmModelFileExportToStepFile(model_file, &export_data, c_file_path);
140            break;
141        }
142
143        case kA3DModellerJt: {
144            A3DRWParamsExportJTData export_data = A3D_MAKE_DATA(A3DRWParamsExportJTData);
145            export_data.m_eWriteGeomTessMode    = kA3DWriteGeomAndTess;
146            export_data.m_bWritePMI             = A3D_TRUE;
147            export_status = A3DAsmModelFileExportToJTFile(model_file, &export_data, c_file_path);
148            break;
149        }
150
151        case kA3DModellerWrl: {
152            export_status = A3DAsmModelFileExportToVrmlFile(model_file, c_file_path);
153            break;
154        }
155
156        case kA3DModellerXML: {
157            A3DRWParamsExportXMLData export_data            = A3D_MAKE_DATA(A3DRWParamsExportXMLData);
158            export_data.m_bExportMetadata                   = A3D_TRUE;
159            export_data.m_bExportTransformations            = A3D_TRUE;
160            export_data.m_bExportColorMaterial              = A3D_TRUE;
161            export_data.m_bExportProductInformationByFormat = A3D_FALSE;
162            export_status = A3DAsmModelFileExportToXMLFile(model_file, &export_data, c_file_path,NULL,NULL,NULL);
163            break;
164        }
165
166        case kA3DModeller3mf: {
167            A3DRWParamsExport3mfData export_data = A3D_MAKE_DATA(A3DRWParamsExport3mfData);
168            export_status = A3DAsmModelFileExportTo3mfFile(model_file, &export_data, c_file_path);
169            break;
170        }
171
172        case kA3DModellerU3D: {
173            A3DRWParamsExportU3DData export_data = A3D_MAKE_DATA(A3DRWParamsExportU3DData);
174            export_data.m_eU3DVersion            = kA3DECMA3;
175            export_status = A3DAsmModelFileExportToU3DFile(model_file, &export_data, c_file_path);
176            break;
177        }
178
179        case kA3DModellerPrc: {
180            A3DRWParamsExportPrcData export_data = A3D_MAKE_DATA(A3DRWParamsExportPrcData);
181            export_data.m_eCompressBrepType      = kA3DCompressionMedium;
182            export_status = A3DAsmModelFileExportToPrcFile(model_file, &export_data, c_file_path,NULL);
183            break;
184        }
185
186        case kA3DModellerOBJ: {
187            A3DRWParamsExportObjData export_data = A3D_MAKE_DATA(A3DRWParamsExportObjData);
188            export_status = A3DAsmModelFileExportToObjFile(model_file, &export_data, c_file_path);
189            break;
190        }
191
192        case kA3DModellerFBX: {
193            A3DRWParamsExportFbxData export_data = A3D_MAKE_DATA(A3DRWParamsExportFbxData);
194            export_status = A3DAsmModelFileExportToFbxFile(model_file, &export_data, c_file_path);
195            break;
196        }
197
198        case kA3DModellerGltf: {
199            A3DRWParamsExportGltfData export_data = A3D_MAKE_DATA(A3DRWParamsExportGltfData);
200            export_status = A3DAsmModelFileExportToGltfFile(model_file, &export_data, c_file_path);
201            break;
202        }
203#if defined HOOPS_EXCHANGE
204        case kA3DModellerParasolid: {
205            A3DRWParamsExportParasolidData export_data = A3D_MAKE_DATA(A3DRWParamsExportParasolidData);
206            export_status = A3DAsmModelFileExportToParasolidFile(model_file, &export_data, c_file_path);
207            break;
208        }
209
210        case kA3DModellerAcis: {
211            A3DRWParamsExportAcisData export_data = A3D_MAKE_DATA(A3DRWParamsExportAcisData);
212            export_status = A3DAsmModelFileExportToAcisFile(model_file, &export_data, c_file_path);
213            break;
214        }
215#endif
216
217#if defined _MSC_VER || defined __linux__
218#ifndef TS_PUBLISH_DISABLED
219        case kA3DModeller3dHtml: {
220            A3DRWParamsExportHtmlData export_data        = A3D_MAKE_DATA(A3DRWParamsExportHtmlData);
221            export_data.m_bIncludeMeasurementInformation = A3D_TRUE;
222            export_status = A3DAsmModelFileExportToHTMLFile(model_file, &export_data, c_file_path);
223            break;
224        }
225#endif
226#endif
227
228        case kA3DModellerStl: {
229            A3DRWParamsExportStlData export_data     = A3D_MAKE_DATA(A3DRWParamsExportStlData);
230            export_data.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
231            export_status = A3DAsmModelFileExportToStlFile(model_file, &export_data, c_file_path);
232            break;
233        }
234
235#if defined (A3DAPI_EXPERIMENTAL) || defined (A3DAPI_EXPERIMENTAL_WITHOUT_WARNING)
236        case experimental_kA3DModellerUSD: {
237            A3DRWParamsExportUSDData export_data = A3D_MAKE_DATA(A3DRWParamsExportUSDData);
238            export_status = A3DAsmModelFileExportToUSDFile(model_file, &export_data, c_file_path);
239            break;
240        }
241#endif
242
243        default : {
244            export_status = A3D_WRITE_WRITER_NOT_IMPLEMENTED;
245            break;
246        }
247    }
248
249    REQUIRE(export_status == A3D_SUCCESS);
250}

The Main function

In the main() function, we parse arguments, then call our above functions in order:

  1. Initialize HOOPS Exchange
  2. Load input file
  3. Write output file
  4. Delete loaded model file
  5. Terminate HOOPS Exchange
{
    Sample::Arguments args;

    if(!Sample::ParseArguments(argc, argv, args)) {
        return EXIT_FAILURE;
    }

    Sample::StartLogger(args.verbose, args.log_path);

    initialize_exchange();

    A3DAsmModelFile* model_file = import_cad_file(args.input_path);
    export_cad_file(model_file, args.output_path);

    const A3DStatus model_file_deleted = A3DAsmModelFileDelete(model_file);
    REQUIRE(model_file_deleted == A3D_SUCCESS);

    terminate_exchange();

    return EXIT_SUCCESS;
}