/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// /* OdVisualizeAssemblyConsoleApp Converts files inside input folder into .VSFX and creates assembly from them. */ #include "OdaCommon.h" #include "Tv.h" #include "TvFactory.h" #include "TvDatabaseReceiver.h" #include "OdVisualizeAssemblyCommon.h" #include "RxInit.h" #include "ExPrintConsole.h" #include "OdPerfTimer.h" #include "OdModuleNames.h" #include "RxDynamicModule.h" #include "TvModuleNames.h" #include "TvCoreModulesNames.h" // Ifc #ifdef IFC_MODULES_ENABLED #include "Common/daiModuleNames.h" #include "Common/ModuleNames.h" #endif #ifndef _TOOLKIT_IN_DLL_ // Visualize API ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdRxCommonDataAccessModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvDbCoreModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvDbIOModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( TvISMModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( TvSCENEOEModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvTfModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvDbPartialViewingModuleImpl ); //Visualize device ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( VisualizeDeviceModule ); //Obj2Visualize ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvVisualizeObjFilerModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdObjToolkitModuleImpl ); //Raster images ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdRasterProcessingServicesImpl ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( ExRasterModule ); //Device ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTrGL2RenderModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( GLES2Module ); //DWG #ifdef DWG_MODULES_ENABLED ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvVisualizeDwgFilerModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvVisualize2DwgFilerModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdDbIOModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( ISMModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( SCENEOEModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( ModelerModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdDbEntitiesModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdRecomputeDimBlockModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( TD_DynBlocksModule ); #endif // DWG_MODULES_ENABLED ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdRxThreadPoolImpl ); // IFC #ifdef IFC_MODULES_ENABLED ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvVisualizeIfcFilerModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdSDAIModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdIfcCoreModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdIfc2x3Module ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdIfc4Module ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdIfcGeomModuleImpl ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdIfcFacetModelerModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdIfcBrepBuilderModule ); #endif // IFC_MODULES_ENABLED //TvCore ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvCoreDatabaseModule ); ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvCoreDatabaseIOModule ); //Vsf2Visualize ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT( OdTvVisualizeVsfFilerModule ); ODRX_BEGIN_STATIC_MODULE_MAP() ODRX_DEFINE_STATIC_APPMODULE( OdTvModuleName, OdTvModule ) ODRX_DEFINE_STATIC_APPMODULE( RxCommonDataAccessModuleName, OdRxCommonDataAccessModule ) ODRX_DEFINE_STATIC_APPMODULE( OdTvDbCoreModuleName, OdTvDbCoreModule ) ODRX_DEFINE_STATIC_APPMODULE( L"TV_SCENEOE", TvSCENEOEModule ) ODRX_DEFINE_STATIC_APPMODULE( OdTvDbIOAppName, OdTvDbIOModule ) ODRX_DEFINE_STATIC_APPMODULE( L"TV_ISM", TvISMModule ) ODRX_DEFINE_STATIC_APPMODULE( OdTvTfModuleName, OdTvTfModule ) ODRX_DEFINE_STATIC_APPMODULE( OdTvPartialViewingModuleName, OdTvDbPartialViewingModuleImpl ) ODRX_DEFINE_STATIC_APPMODULE( OdTvVisualizeDeviceModuleName, VisualizeDeviceModule ) ODRX_DEFINE_STATIC_APPMODULE( OdTvObj2VisualizeModuleName, OdTvVisualizeObjFilerModule ) ODRX_DEFINE_STATIC_APPMODULE( OdObjToolkitModuleName, OdObjToolkitModuleImpl ) ODRX_DEFINE_STATIC_APPMODULE( OdRasterProcessorModuleName, OdRasterProcessingServicesImpl ) ODRX_DEFINE_STATIC_APPMODULE( RX_RASTER_SERVICES_APPNAME, ExRasterModule ) ODRX_DEFINE_STATIC_APPMODULE( OdTrGL2ModuleName, OdTrGL2RenderModule ) ODRX_DEFINE_STATIC_APPMODULE( OdWinGLES2ModuleName, GLES2Module ) //DWG #ifdef DWG_MODULES_ENABLED ODRX_DEFINE_STATIC_APPMODULE( OdTvDwg2VisualizeModuleName, OdTvVisualizeDwgFilerModule ) ODRX_DEFINE_STATIC_APPMODULE( OdTvVisualize2DwgModuleName, OdTvVisualize2DwgFilerModule ) ODRX_DEFINE_STATIC_APPMODULE( OdDbIOAppName, OdDbIOModule ) ODRX_DEFINE_STATIC_APPMODULE( L"ISM", ISMModule ) ODRX_DEFINE_STATIC_APPMODULE( L"SCENEOE", SCENEOEModule ) ODRX_DEFINE_STATIC_APPLICATION( OdModelerGeometryModuleName, ModelerModule ) ODRX_DEFINE_STATIC_APPMODULE( OdDbEntitiesAppName, OdDbEntitiesModule ) ODRX_DEFINE_STATIC_APPLICATION( OdRecomputeDimBlockModuleName, OdRecomputeDimBlockModule ) ODRX_DEFINE_STATIC_APPMODULE( OdDynBlocksModuleName, TD_DynBlocksModule ) #endif // DWG_MODULES_ENABLED // IFC #ifdef IFC_MODULES_ENABLED ODRX_DEFINE_STATIC_APPMODULE( OdTvIfc2VisualizeModuleName, OdTvVisualizeIfcFilerModule ) ODRX_DEFINE_STATIC_APPMODULE( OdSDAIModuleName, OdSDAIModule ) ODRX_DEFINE_STATIC_APPMODULE( OdIfcCoreModuleName, OdIfcCoreModule ) ODRX_DEFINE_STATIC_APPMODULE( OdIfc2x3ModuleName, OdIfc2x3Module ) ODRX_DEFINE_STATIC_APPMODULE( OdIfc4ModuleName, OdIfc4Module ) ODRX_DEFINE_STATIC_APPMODULE( OdIfcGeomModuleName, OdIfcGeomModuleImpl ) ODRX_DEFINE_STATIC_APPMODULE( OdIfcFacetModelerModuleName, OdIfcFacetModelerModule ) ODRX_DEFINE_STATIC_APPMODULE( OdIfcBrepBuilderModuleName, OdIfcBrepBuilderModule ) #endif //TvCore ODRX_DEFINE_STATIC_APPMODULE( OdTvCoreDatabaseModuleName, OdTvCoreDatabaseModule ) ODRX_DEFINE_STATIC_APPMODULE( OdTvCoreDatabaseIOModuleName, OdTvCoreDatabaseIOModule ) //Vsf2Visualize ODRX_DEFINE_STATIC_APPMODULE( OdTvVsf2VisualizeModuleName, OdTvVisualizeVsfFilerModule ) ODRX_DEFINE_STATIC_APPMODULE( OdThreadPoolModuleName, OdRxThreadPoolImpl ) // uncomment for multicore/multicpu support in statically linked version ODRX_END_STATIC_MODULE_MAP() #endif void ODASdkActivate() { static const char* ActInfo[] = { #ifdef TEIGHA_TRIAL "", "" #else //"UserInfo", "UserSignature" // Before compiling, a ODA SDK activation file should be placed in a location that a compiler can access, // otherwise you get a compiler error such as "Kernel/Extensions/ExServices/ExSystemServices.h:43:10: fatal error: 'OdActivationInfo' file not found". // To learn about ODA SDK activation, see the activation guide at https://docs.opendesign.com/tkernel/oda_activation.html #include "OdActivationInfo" #endif }; odActivate(ActInfo[0], ActInfo[1]); } void ODASdkDeactivate() { odCleanUpStaticData(); } int main( int argc, char* argv[] ) { #ifndef _TOOLKIT_IN_DLL_ ODRX_INIT_STATIC_MODULE_MAP(); #endif // Verify the argument count and display an error message as required if( argc < 2 ) { odPrintConsoleString( L"usage: OdVisualizeAssemblyConsoleApp -id [-od ] [-r path, if output is not specified.\n" ); return 1; } //Parse arguments list enum class SupportedFormat { kVSFX = 1 << 0, kDWG = 1 << 1, kIFC = 1 << 2, kNWD = 1 << 3, kRVT = 1 << 4 }; int nArg = 1; OdString inputPath, outputPath; bool bRecursive = false; OdUInt8 formats = 0; bool bExtPI = false; OdString tmpPath = OdString::kEmpty; while( nArg < argc ) { OdString arg = argv[ nArg ]; if( arg == OD_T( "-id" ) ) { inputPath = argv[ ++nArg ]; if( outputPath.isEmpty() ) outputPath = inputPath; } else if( arg == OD_T( "-od" ) ) { outputPath = argv[ ++nArg ]; } else if( arg == OD_T( "-r" ) ) { bRecursive = true; } else if( arg == OD_T( "-VSFX" ) ) { SETBIT_1( formats, (OdUInt8)( SupportedFormat::kVSFX ) ); } else if( arg == OD_T( "-DWG" ) ) { SETBIT_1( formats, (OdUInt8)( SupportedFormat::kDWG ) ); } else if( arg == OD_T( "-IFC" ) ) { SETBIT_1( formats, (OdUInt8)( SupportedFormat::kIFC ) ); } else if( arg == OD_T( "-NWD" ) ) { SETBIT_1( formats, (OdUInt8)( SupportedFormat::kNWD ) ); } else if( arg == OD_T( "-RVT" ) ) { SETBIT_1( formats, (OdUInt8)( SupportedFormat::kRVT ) ); } else if( arg == OD_T( "-piext" ) ) { bExtPI = true; } else if( arg == OD_T( "-stream" ) ) { tmpPath = argv[ ++nArg ]; } else { ODA_FAIL(); odPrintConsoleString( OD_T( "Invalid input parameter ") + arg + OD_T( "\n" ) ); return 1; } nArg++; } // Activate ODA SDK ODASdkActivate(); // Initialize factory odTvInitialize(); OdTvFileServices coll; if( outputPath[ outputPath.getLength() - 1 ] != coll.folderDelimeter() ) { outputPath += coll.folderDelimeter(); } //Setup files collector if( formats == 0 ) { coll.addSupportedExt( OD_T( "VSFX" ) ); coll.addSupportedExt( OD_T( "RVT" ) ); coll.addSupportedExt( OD_T( "IFC" ) ); coll.addSupportedExt( OD_T( "NWD" ) ); coll.addSupportedExt( OD_T( "DWG" ) ); } else { if( GETBIT( formats, (OdUInt8)( SupportedFormat::kVSFX ) ) ) coll.addSupportedExt( OD_T( "VSFX" ) ); if( GETBIT( formats, (OdUInt8)( SupportedFormat::kDWG ) ) ) coll.addSupportedExt( OD_T( "DWG" ) ); if( GETBIT( formats, (OdUInt8)( SupportedFormat::kIFC ) ) ) coll.addSupportedExt( OD_T( "IFC" ) ); if( GETBIT( formats, (OdUInt8)( SupportedFormat::kNWD ) ) ) coll.addSupportedExt( OD_T( "NWD" ) ); if( GETBIT( formats, (OdUInt8)( SupportedFormat::kRVT ) ) ) coll.addSupportedExt( OD_T( "RVT" ) ); } OdTvFactoryId factId = odTvGetFactory(); odPrintConsoleString( OD_T( "OdVisualizeAssemblyConsoleApp developed by ODA\n" ) ); //Collect input files OdStringArray files = coll.collectFiles( inputPath, bRecursive ); if( files.isEmpty() ) { odPrintConsoleString( OD_T( "No files found\n" ) ); odTvUninitialize(); ODASdkDeactivate(); return 0; } if( !OdTvFileServices::createDirectoryIfNotExist( outputPath ) ) { odPrintConsoleString( OD_T( "Error: can not create output directory\n" ) ); odTvUninitialize(); ODASdkDeactivate(); return 1; } //Convert all non-VFSX files into VSFX odPrintConsoleString( OD_T( "\nConversion phase\n" ) ); OdTvFileConverter converter; OdString outFileName = OdString::kEmpty; for( unsigned int i = 0; i < files.size(); ++i ) { if( OdTvFileServices::getFileExt( files[ i ] ) != OD_T( "VSFX" ) ) { OdString fileName = coll.getFileName( files[ i ] ); if( !tmpPath.isEmpty() ) { outFileName = outputPath + fileName + OD_T( ".vsfx" ); fileName = tmpPath; } else { outFileName = OdString::kEmpty; fileName = outputPath + fileName + OD_T( ".vsfx" ); } odPrintConsoleString( OD_T( "Converting " ) + files[ i ] + " -> " + fileName + OD_T( "... " ) ); OdTvFileConverter::Statistic stat; if( converter.convertFile( files[ i ], fileName, &stat, bExtPI ) == tvOk ) { if( !outFileName.isEmpty() ) { odPrintConsoleString( OD_T( "DONE\nMaking streaming compatible " ) + fileName + " -> " + outFileName + OD_T( "... " ) ); OdTvDatabaseReceiver::makeStreamingCompatible( fileName, outFileName ); fileName = outFileName; } files[ i ] = fileName; odPrintConsoleString( OD_T( "DONE" ) ); OdString statStr; statStr.format( OD_T( "( %.3f secs, %.3f MB )\n" ), (float)( stat.conversionTime ) / 1000.f, (float)( stat.fileSize ) / ( 1024.f * 1024.f ) ); odPrintConsoleString( statStr ); } else { files[ i ] = OdString::kEmpty; odPrintConsoleString( OD_T( "FAILED\n" ) ); } } } //Create assembly odPrintConsoleString( OD_T( "\nReferencing phase\n" ) ); OdPerfTimerWrapper refTimer; refTimer.getTimer()->start(); //Create database, device and view OdTvDatabaseId dbId = odTvGetFactory().createDatabase(); OdTvDatabasePtr pDb = dbId.openObject( OdTv::kForWrite ); OdTvGsDeviceId devId = pDb->createDevice( OD_T( "AssemblyDevice" ) ); OdTvGsViewId viewId = devId.openObject( OdTv::kForWrite )->createView( OD_T( "AssemblyView" ) ); OdTvGsViewPtr pView = viewId.openObject( OdTv::kForWrite ); devId.openObject( OdTv::kForWrite )->addView( viewId ); bool bCopyViewParams = true; for( unsigned int i = 0; i < files.size(); ++i ) { if( files[ i ].isEmpty() ) continue; //Prevent self-referencing if( coll.getFileName( files[ i ] ) == OD_T( "assembly.vsfx" ) ) { odPrintConsoleString( OD_T( "Skipped " ) + files[ i ] + OD_T( "\n" ) ); continue; } OdString modelName = OdString::kEmpty; odPrintConsoleString( OD_T( "Referencing " ) + files[ i ] + OD_T( "... " ) ); //Find model to be referenced - first model in the database OdTvDatabaseId refDbId = odTvGetFactory().readVSFX( files[ i ], false, true ); if( refDbId.isNull() ) { odPrintConsoleString( OD_T( "FAILED, can not load database\n" ) ); continue; } { OdTvDatabasePtr pRefDb = refDbId.openObject(); OdTvModelId modelId = pRefDb->getModelsIterator()->getModel(); if( modelId.isNull() ) { odPrintConsoleString( OD_T( "FAILED, can not find model\n" ) ); continue; } modelName = modelId.openObject()->getName(); //Copy view parameters if need if( bCopyViewParams ) { OdTvDevicesIteratorPtr pDevs = pRefDb->getDevicesIterator(); for( ; !pDevs->done(); pDevs->step() ) { OdTvGsDeviceId dId = pDevs->getDevice(); OdTvGsDevicePtr pD = dId.openObject(); if( pD->getActive() ) { OdTvGsViewId vId = pD->getActiveView(); if( !vId.isNull() ) { OdTvGsViewPtr pV = vId.openObject(); //Copy view params pView->setView( pV->position(), pV->target(), pV->upVector(), pV->fieldWidth(), pV->fieldHeight(), pV->isPerspective() ? OdTvGsView::kPerspective : OdTvGsView::kParallel ); //Copy visual style OdTvVisualStyleId stId = pV->getVisualStyle(); if( !stId.isNull() ) { OdTvVisualStyleId styleId = pDb->createVisualStyle( OD_T( "AssemblyVisualStyle" ) ); styleId.openObject( OdTv::kForWrite )->copyFrom( stId ); pView->setVisualStyle( styleId ); } bCopyViewParams = false; } } } } } odTvGetFactory().removeDatabase( refDbId ); //Create model reference OdTvModelId modelrefId = pDb->createModelReference( coll.getFileName( files[ i ] ), /*files[i]*/coll.getFileName( files[ i ] ), modelName, OdTvModel::kMain, true); if( modelrefId.isNull() ) { odPrintConsoleString( OD_T( "FAILED, can not reffer model\n" ) ); continue; } else { //Add model to the view pView->addModel( modelrefId ); odPrintConsoleString( OD_T( "DONE\n" ) ); } } //Save assembly file OdTvVSFExportOptions opts; opts.compression = OdTvVSFExportOptions::kInt16; opts.normalsCompression = OdTvVSFExportOptions::kTwoFloats; opts.m_IgnoreFaceNormals = true; if( tmpPath.isEmpty() ) { pDb->addPartialViewIndexes( true, bExtPI ); pDb->writeVSFX( outputPath + OD_T( "assembly.vsfx" ), &opts ); } else { pDb->addPartialViewIndexes( true, bExtPI ); pDb->writeVSFX( tmpPath, &opts ); odPrintConsoleString( OD_T( "Making streaming-compatible assembly...\n " ) ); OdTvDatabaseReceiver::makeStreamingCompatible( tmpPath, outputPath + OD_T( "assembly.vsfx" ) ); } refTimer.getTimer()->stop(); OdString statStr; statStr.format( OD_T( "Assembly created in %.3f secs\n" ), (float)( refTimer.getTimer()->countedSec() ) ); odPrintConsoleString( statStr ); odPrintConsoleString( OD_T( "Assembly saved as " ) + outputPath + OD_T( "assembly.vsfx\n" ) ); //Release pointers, remove database pView.release(); pDb.release(); odTvGetFactory().removeDatabase( dbId ); // Uninitialize factory odTvUninitialize(); // Deactivate ODA SDK ODASdkDeactivate(); return 0; }