/*********************************************************************************************************************** * * Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc. * The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret * as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event * of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized * employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the * scope and manner of such use. * ***********************************************************************************************************************/ /** \file Shattered.cpp PRC Can be used as a multi-file format using our shattered mode. This sample demonstrates how to load a CAD file independently from each other. Then it creates one PRC per file. Finally the full model is reloaded in memory from these multiple files. ***********************************************************************************************************************/ #ifndef _MSC_VER # include // for dirname # define MAX_PATH 512 #endif #define INITIALIZE_A3D_API #include #include #include "../common.hpp" //###################################################################################################################### #ifndef _MSC_VER void SplitPathLinux( const char *pcPath, /* I: Path to split */ char pcDir[MAX_PATH], /* O: Extracted dir */ char pcFile[MAX_PATH], /* O: Extracted file name */ char pcExt[8]) /* O: Extracted file extension */ { char acBuf[MAX_PATH*3]; char *pcDirName, *pcFileName, *pcCur; int iLen, iLenExt; strcpy(acBuf, pcPath); pcDirName = dirname(acBuf ); strcpy(pcDir, pcDirName); strcpy(acBuf, pcPath); pcFileName = basename(acBuf); if(*pcFileName == '/') pcFileName++; iLen = strlen(pcFileName); pcCur = pcFileName+iLen-1; iLenExt = 0; while(pcCur >= pcFileName) { if(*pcCur == '.') break; pcCur--; iLenExt++; } if(iLenExt == iLen) { strcpy(pcFile, pcFileName); *pcExt = '\0'; } else if(iLenExt) { strncpy(pcFile, pcFileName, pcCur-pcFileName); pcFile[pcCur-pcFileName] = '\0'; strncpy(pcExt, pcCur+1, iLenExt); pcExt[iLenExt] = '\0'; } else { strncpy(pcFile, pcFileName, iLen-1); pcFile[iLen] = '\0'; *pcExt = '\0'; } } #endif static MY_CHAR acSrcFileName[_MAX_PATH * 2]; static MY_CHAR acDstPathName[_MAX_PATH * 2]; static MY_CHAR acLogFileName[_MAX_PATH * 2]; //###################################################################################################################### // Main function #ifdef _MSC_VER int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv) #else int main(A3DInt32 iArgc, A3DUTF8Char** ppcArgv) #endif { // // ### COMMAND LINE ARGUMENTS // if (iArgc > 4) { MY_PRINTF2("Usage:\n %s [input CAD file] [output PRC directory] [output LOG file]\n", ppcArgv[0]); MY_PRINTF(" Default output PRC directory is 'CURRENT_DIR'\n"); MY_PRINTF(" Default output LOG file is [input CAD file]_Log.txt\n\n"); return A3D_ERROR; } if (iArgc > 1) MY_STRCPY(acSrcFileName, ppcArgv[1]); else MY_STRCPY(acSrcFileName, DEFAULT_INPUT_CAD); if (iArgc > 2) MY_STRCPY(acDstPathName, ppcArgv[2]); else MY_STRCPY(acDstPathName, _T(SAMPLES_DEFAULT_OUTPUT_PATH)); if (iArgc > 3) MY_STRCPY(acLogFileName, ppcArgv[3]); else MY_SPRINTF(acLogFileName, "%s_Log.txt", acSrcFileName); GetLogFile(acLogFileName); // Initialize log file // // ### INITIALIZE HOOPS EXCHANGE // A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(_T(HOOPS_BINARY_DIRECTORY), HOOPS_LICENSE); CHECK_RET(sHoopsExchangeLoader.m_eSDKStatus); // Initialize callbacks CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree)); CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError)); // // ### PROCESS SAMPLE CODE // A3DImport sImport(acSrcFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parameters A3DStatus iRet = sHoopsExchangeLoader.Import(sImport); if (iRet != A3D_SUCCESS && iRet != A3D_LOAD_MISSING_COMPONENTS) CHECK_RET(iRet); //Extract all dependencies from a CAD file - This step is not necessary when the assemblies dependencies are known A3DUTF8Char** ppPart, ** ppAssembly, ** ppMissing; A3DUns32 uNbPart, uNbAssembly, uNbMissing; A3DAsmGetFilesPathFromModelFile(sHoopsExchangeLoader.m_psModelFile, &uNbPart, &ppPart, &uNbAssembly, &ppAssembly, &uNbMissing, &ppMissing); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Load and convert Each CAD to a PRC. // Each part is managed independently because sImport.m_sLoadData.m_sIncremental.m_bLoadNoDependencies is set to true // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// A3DUniChar acDrive[8]; A3DUniChar acDir[_MAX_PATH]; A3DUniChar acName[_MAX_PATH]; A3DUniChar acExt[_MAX_PATH]; A3DUniChar acPrcFileName[_MAX_PATH * 3]; A3DUTF8Char** acPrcFilePath = (A3DUTF8Char**)malloc(sizeof(A3DUTF8Char*) * (uNbPart + uNbAssembly + 1)); memset(acPrcFilePath, 0, sizeof(A3DUTF8Char*) * (uNbPart + uNbAssembly + 1)); const MemoryGuard sGuardPrcFilePath(acPrcFilePath); A3DUTF8Char** acCADFilePath = (A3DUTF8Char**)malloc(sizeof(A3DUTF8Char*) * (uNbPart + uNbAssembly + 1)); memset(acCADFilePath, 0, sizeof(A3DUTF8Char*) * (uNbPart + uNbAssembly + 1)); const MemoryGuard sGuardCADFilePath(acCADFilePath); for (unsigned int uI = 0; uI < uNbAssembly; ++uI) { if (sHoopsExchangeLoader.m_psModelFile) { A3DAsmModelFileDelete(sHoopsExchangeLoader.m_psModelFile); sHoopsExchangeLoader.m_psModelFile = NULL; } // Determine PRc File Name + Unicode to UT8 conversions #ifdef _MSC_VER wchar_t* pucString = (wchar_t*)malloc(_MAX_PATH * 3 * sizeof(wchar_t)); A3DMiscUTF8ToUnicode(ppAssembly[uI], (A3DUTF8Char*)pucString); _wsplitpath(pucString, acDrive, acDir, acName, acExt); free(pucString); pucString = NULL; swprintf(&acPrcFileName[0], _MAX_PATH * 3, L"%s\\%s.prc", &acDstPathName[0], acName); acPrcFilePath[uI] = (A3DUTF8Char*)malloc(_MAX_PATH * 3 * sizeof(A3DUTF8Char)); A3DMiscUnicodeToUTF8((A3DUTF8Char*)&acPrcFileName[0], acPrcFilePath[uI]); #else SplitPathLinux(ppAssembly[uI], acDir, acName, acExt); acPrcFilePath[uI] = (A3DUTF8Char*)malloc(_MAX_PATH * 3 * sizeof(A3DUTF8Char)); sprintf(acPrcFilePath[uI], "%s/%s.prc", &acDstPathName[0], acName); #endif acCADFilePath[uI] = ppAssembly[uI]; //Convert assembly files to PRC A3DImport sSubImport(ppAssembly[uI]); // see A3DSDKInternalConvert.hxx for import and export detailed parameters sSubImport.m_sLoadData.m_sIncremental.m_bLoadNoDependencies = true; A3DExport sExport(acPrcFilePath[uI]); // see A3DSDKInternalConvert.hxx for import and export detailed parameters TEST_RET(sHoopsExchangeLoader.Convert(sSubImport, sExport)); } //Convert CAD part files to PRC for (unsigned int uI = 0; uI < uNbPart; ++uI) { if (sHoopsExchangeLoader.m_psModelFile) { A3DAsmModelFileDelete(sHoopsExchangeLoader.m_psModelFile); sHoopsExchangeLoader.m_psModelFile = NULL; } #ifdef _MSC_VER //Generate PRC filename; convert wchar_t path to UTF-8 wchar_t* pucString = (wchar_t*)malloc(_MAX_PATH * 3 * sizeof(wchar_t)); A3DMiscUTF8ToUnicode(ppPart[uI], (A3DUTF8Char*)pucString); _wsplitpath(pucString, acDrive, acDir, acName, acExt); free(pucString); pucString = NULL; swprintf(&acPrcFileName[0], _MAX_PATH * 3, L"%s\\%s.prc", &acDstPathName[0], acName); acPrcFilePath[uI + uNbAssembly] = (A3DUTF8Char*)malloc(_MAX_PATH * 3 * sizeof(A3DUTF8Char)); A3DMiscUnicodeToUTF8((A3DUTF8Char*)&acPrcFileName[0], acPrcFilePath[uI + uNbAssembly]); #else SplitPathLinux(ppPart[uI], acDir, acName, acExt); acPrcFilePath[uI + uNbAssembly] = (A3DUTF8Char*)malloc(_MAX_PATH * 3 * sizeof(A3DUTF8Char)); sprintf(acPrcFilePath[uI + uNbAssembly], "%s/%s.prc", &acDstPathName[0], acName); #endif acCADFilePath[uI + uNbAssembly] = ppPart[uI]; //Convert assembly files to PRC A3DImport sSubImport(ppPart[uI]); // see A3DSDKInternalConvert.hxx for import and export detailed parameters sSubImport.m_sLoadData.m_sIncremental.m_bLoadNoDependencies = true; A3DExport sExport(acPrcFilePath[uI + uNbAssembly]); // see A3DSDKInternalConvert.hxx for import and export detailed parameters TEST_RET(sHoopsExchangeLoader.Convert(sSubImport, sExport)); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Load the full Model from PRC. // A mapping between CAD filepath and PRC filepath needs to be maintained by customers to use this fuction. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (sHoopsExchangeLoader.m_psModelFile) { A3DAsmModelFileDelete(sHoopsExchangeLoader.m_psModelFile); sHoopsExchangeLoader.m_psModelFile = NULL; } A3DRWParamsLoadData sParamsLoadData; A3D_INITIALIZE_DATA(A3DRWParamsLoadData, sParamsLoadData); A3DUTF8Char acRootPrcFilePath[_MAX_PATH * 3]; #ifdef _MSC_VER _wsplitpath(iArgc > 1 ? ppcArgv[1] : DEFAULT_INPUT_CAD, acDrive, acDir, acName, acExt); swprintf(acPrcFileName, _MAX_PATH * 3, L"%s\\%s.prc", &acDstPathName[0], acName); A3DMiscUnicodeToUTF8((A3DUTF8Char*)&acPrcFileName[0], &acRootPrcFilePath[0]); #else SplitPathLinux(iArgc > 1 ? ppcArgv[1] : DEFAULT_INPUT_CAD, acDir, acName, acExt); sprintf(acRootPrcFilePath, "%s/%s.prc", &acDstPathName[0], acName); #endif CHECK_RET(A3DAsmModelFileLoadFromPRCFiles(&acRootPrcFilePath[0], uNbPart + uNbAssembly, (const A3DUTF8Char**)acPrcFilePath, (const A3DUTF8Char**)acCADFilePath, &sParamsLoadData, &(sHoopsExchangeLoader.m_psModelFile))); A3DAsmGetFilesPathFromModelFile(NULL, &uNbPart, &ppPart, &uNbAssembly, &ppAssembly, &uNbMissing, &ppMissing); for (unsigned int uI = 0; uI < uNbAssembly + uNbPart; ++uI) { free(acPrcFilePath[uI]); } // // ### TERMINATE HOOPS EXCHANGE // // Check memory allocations return (int)ListLeaks(); }