Files
Hoops_Exchange/exchange/exchangesource/Shattered/Shattered.cpp
2025-12-15 23:22:33 +08:00

274 lines
10 KiB
C++

/***********************************************************************************************************************
*
* 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 <libgen.h> // for dirname
# define MAX_PATH 512
#endif
#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>
#include <hoops_license.h>
#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();
}