470 lines
16 KiB
C++
470 lines
16 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.
|
|
*
|
|
***********************************************************************************************************************/
|
|
|
|
#include <A3DSDKIncludes.h>
|
|
#include "PRC2XML.h"
|
|
|
|
#include <map>
|
|
|
|
//######################################################################################################################
|
|
#define READMAXBIGSTRING 65536
|
|
A3DUTF8Char gbigstring[READMAXBIGSTRING]; // 64 kB buffer is OK to store big strings like array of doubles
|
|
A3DUns32 gnAllocatedStrings = 0;
|
|
|
|
//######################################################################################################################
|
|
void setDoubleAttribute(_TiXmlElement* psElement, const char* name, double val)
|
|
{
|
|
// max size of one double: "%.15 " 13+1+15+1=30
|
|
A3DUTF8Char* pc = gbigstring;
|
|
size_t iwritten = sprintf_s(pc,sizeof(gbigstring)-1, "%.15f", val);
|
|
for(size_t i = iwritten - 1; i > 0; i--)
|
|
{
|
|
if((pc)[i] == '0')
|
|
(pc)[i] = 0;
|
|
else
|
|
break;
|
|
}
|
|
|
|
psElement->SetAttribute(name, pc);
|
|
}
|
|
|
|
//######################################################################################################################
|
|
const _TiXmlElement* _FirstChildByAttribute(_TiXmlElement* psElement, const A3DUTF8Char* pcAttribName, void* pValue)
|
|
{
|
|
A3DUTF8Char buffer[64];
|
|
sprintf_s(buffer,sizeof(buffer)-1, "%p", pValue);
|
|
|
|
const _TiXmlElement* child = psElement->FirstChildElement();
|
|
for(; child; child = child->NextSiblingElement())
|
|
{
|
|
const A3DUTF8Char* pcValue = child->Attribute(pcAttribName);
|
|
if(pcValue != NULL && strcmp(pcValue, buffer) == 0)
|
|
return child;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
unsigned int getPRC2XMLID(const A3DEntity* pElement)
|
|
{
|
|
static std::map<const A3DEntity*, unsigned> mapElementIds;
|
|
auto itFound = mapElementIds.find(pElement);
|
|
if (itFound == mapElementIds.end())
|
|
{
|
|
// Just use index in export as unique identifier within the xml
|
|
unsigned uiUniqueId = (unsigned)mapElementIds.size();
|
|
mapElementIds[pElement] = uiUniqueId;
|
|
return uiUniqueId;
|
|
}
|
|
else
|
|
return itFound->second;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
void setAttributePtr(const A3DUTF8Char* pcAttribName, const A3DEntity* pElement, _TiXmlElement* setting)
|
|
{
|
|
setting->SetAttribute(pcAttribName, getPRC2XMLID(pElement));
|
|
}
|
|
|
|
//######################################################################################################################
|
|
void setAttributePRC2XMLID(const A3DEntity* pElement, _TiXmlElement* setting)
|
|
{
|
|
setAttributePtr("uiPRC2XML_ID", pElement, setting);
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traversePRC2XMLIDs(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DEntity** pp, _TiXmlElement* setting)
|
|
{
|
|
if (uiSize > 0)
|
|
{
|
|
A3DUns32 ui = 0;
|
|
_TiXmlElement* uints = new _TiXmlElement(name);
|
|
uints->SetAttribute("size", (int)uiSize);
|
|
|
|
// max size of one uint: "%d " 14+1=15
|
|
A3DUns32 uiFormat = 15;
|
|
A3DUTF8Char* pc = NULL;
|
|
if (uiFormat * uiSize > READMAXBIGSTRING)
|
|
{
|
|
pc = (A3DUTF8Char*)malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
|
|
pc[0] = 0;
|
|
gnAllocatedStrings++;
|
|
}
|
|
else
|
|
pc = gbigstring;
|
|
|
|
size_t uiNext = 0;
|
|
for (ui = 0; ui < uiSize; ++ui)
|
|
{
|
|
int iwritten = sprintf(pc + uiNext, "%u ", getPRC2XMLID(pp[ui]));
|
|
uiNext += size_t(iwritten);
|
|
}
|
|
pc[uiNext] = 0;
|
|
|
|
uints->SetAttribute("data", pc);
|
|
setting->LinkEndChild(uints);
|
|
|
|
if (uiFormat * uiSize > READMAXBIGSTRING)
|
|
free(pc);
|
|
}
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseDoubles(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DDouble* pd, _TiXmlElement* setting)
|
|
{
|
|
if(uiSize > 0)
|
|
{
|
|
A3DUns32 ui = 0;
|
|
_TiXmlElement* doubles = new _TiXmlElement(name);
|
|
|
|
doubles->SetAttribute("size", (int)uiSize);
|
|
|
|
// max size of one double: "%.15 " 13+1+15+1=30
|
|
A3DUns32 uiFormat = 30;
|
|
A3DUTF8Char* pc = NULL;
|
|
if(uiFormat*uiSize > READMAXBIGSTRING)
|
|
{
|
|
pc = (A3DUTF8Char*) malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
|
|
pc[0] = 0;
|
|
gnAllocatedStrings++;
|
|
}
|
|
else
|
|
pc = gbigstring;
|
|
|
|
size_t uiNext = 0;
|
|
for(ui = 0; ui < uiSize; ++ui)
|
|
{
|
|
int iwritten = sprintf(pc+uiNext, "%.15f", pd[ui]);
|
|
size_t i = size_t(iwritten - 1);
|
|
for(; i > 0; i--)
|
|
{
|
|
if((pc+uiNext)[i] == '0')
|
|
(pc+uiNext)[i] = 0;
|
|
else
|
|
break;
|
|
}
|
|
(pc+uiNext)[i+1] = L' ';
|
|
uiNext += i+2;
|
|
}
|
|
pc[uiNext-1] = 0;
|
|
|
|
doubles->SetAttribute("data", pc);
|
|
setting->LinkEndChild(doubles);
|
|
|
|
if(uiFormat*uiSize > READMAXBIGSTRING)
|
|
free(pc);
|
|
}
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseUInts(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DUns32* pui, _TiXmlElement* setting)
|
|
{
|
|
if(uiSize > 0)
|
|
{
|
|
A3DUns32 ui = 0;
|
|
_TiXmlElement* uints = new _TiXmlElement(name);
|
|
uints->SetAttribute("size", (int)uiSize);
|
|
|
|
// max size of one uint: "%d " 14+1=15
|
|
A3DUns32 uiFormat = 15;
|
|
A3DUTF8Char* pc = NULL;
|
|
if(uiFormat*uiSize > READMAXBIGSTRING)
|
|
{
|
|
pc = (A3DUTF8Char*) malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
|
|
pc[0] = 0;
|
|
gnAllocatedStrings++;
|
|
}
|
|
else
|
|
pc = gbigstring;
|
|
|
|
size_t uiNext = 0;
|
|
for(ui = 0; ui < uiSize; ++ui)
|
|
{
|
|
int iwritten = sprintf(pc+uiNext, "%u ", pui[ui]);
|
|
uiNext += size_t(iwritten);
|
|
}
|
|
pc[uiNext] = 0;
|
|
|
|
uints->SetAttribute("data", pc);
|
|
setting->LinkEndChild(uints);
|
|
|
|
if(uiFormat*uiSize > READMAXBIGSTRING)
|
|
free(pc);
|
|
}
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseUChars(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DUns8* pui, _TiXmlElement* setting)
|
|
{
|
|
if(uiSize > 0)
|
|
{
|
|
A3DUns32 ui = 0;
|
|
_TiXmlElement* uints = new _TiXmlElement(name);
|
|
uints->SetAttribute("size", (int)uiSize);
|
|
|
|
// max size of one uchar: "%d ": 6
|
|
A3DUns32 uiFormat = 6;
|
|
A3DUTF8Char* pc = NULL;
|
|
if(uiFormat*uiSize > READMAXBIGSTRING)
|
|
{
|
|
pc = (A3DUTF8Char*) malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
|
|
pc[0] = 0;
|
|
gnAllocatedStrings++;
|
|
}
|
|
else
|
|
pc = gbigstring;
|
|
|
|
size_t uiNext = 0;
|
|
for(ui = 0; ui < uiSize; ++ui)
|
|
{
|
|
int iwritten = sprintf(pc+uiNext, "%u ", pui[ui]);
|
|
uiNext += size_t(iwritten);
|
|
}
|
|
pc[uiNext] = 0;
|
|
|
|
uints->SetAttribute("data", pc);
|
|
setting->LinkEndChild(uints);
|
|
|
|
if(uiFormat*uiSize > READMAXBIGSTRING)
|
|
free(pc);
|
|
}
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseBools(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DBool* pb, _TiXmlElement* setting)
|
|
{
|
|
if(uiSize > 0)
|
|
{
|
|
A3DUns32 ui = 0;
|
|
_TiXmlElement* bools = new _TiXmlElement(name);
|
|
bools->SetAttribute("size", (int) uiSize);
|
|
|
|
// max size of one bool: 2
|
|
A3DUns32 uiFormat = 2;
|
|
A3DUTF8Char* pc = NULL;
|
|
if(uiFormat*uiSize > READMAXBIGSTRING)
|
|
{
|
|
pc = (A3DUTF8Char*) malloc(size_t(uiSize * uiFormat) * sizeof(A3DUTF8Char));
|
|
pc[0] = 0;
|
|
gnAllocatedStrings++;
|
|
}
|
|
else
|
|
pc = gbigstring;
|
|
|
|
size_t uiNext = 0;
|
|
for(ui = 0; ui < uiSize; ++ui)
|
|
{
|
|
int iwritten = sprintf(pc+uiNext, "%u ", pb[ui] ? 1 : 0);
|
|
uiNext += size_t(iwritten);
|
|
}
|
|
pc[uiNext] = 0;
|
|
|
|
bools->SetAttribute("data", pc);
|
|
setting->LinkEndChild(bools);
|
|
|
|
if(uiFormat*uiSize > READMAXBIGSTRING)
|
|
free(pc);
|
|
}
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traversePoint(const A3DUTF8Char* name, const A3DVector3dData& sData, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* pt = new _TiXmlElement(name);
|
|
setDoubleAttribute(pt, "m_dX", sData.m_dX);
|
|
setDoubleAttribute(pt, "m_dY", sData.m_dY);
|
|
setDoubleAttribute(pt, "m_dZ", sData.m_dZ);
|
|
setting->LinkEndChild(pt);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traversePoint2d(const A3DUTF8Char* name, const A3DVector2dData& sData, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* pt = new _TiXmlElement(name);
|
|
setDoubleAttribute(pt, "m_dX", sData.m_dX);
|
|
setDoubleAttribute(pt, "m_dY", sData.m_dY);
|
|
setting->LinkEndChild(pt);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traversePoints(const A3DUTF8Char* name, const A3DUns32 uiSize, const A3DVector3dData* pv, _TiXmlElement* setting)
|
|
{
|
|
if(uiSize > 0)
|
|
{
|
|
A3DDouble* pd = (A3DDouble*) malloc(size_t(uiSize) * 3 * sizeof(A3DDouble));
|
|
if(pd == NULL)
|
|
return A3D_ALLOC_FATAL_ERROR;
|
|
|
|
for(A3DUns32 ui = 0; ui < uiSize; ++ui)
|
|
{
|
|
pd[3*ui] = pv[ui].m_dX;
|
|
pd[3*ui+1] = pv[ui].m_dY;
|
|
pd[3*ui+2] = pv[ui].m_dZ;
|
|
}
|
|
traverseDoubles(name, 3*uiSize, pd, setting);
|
|
free(pd);
|
|
}
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseInterval(const A3DIntervalData* pData, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* extent1d = new _TiXmlElement("A3DIntervalData");
|
|
setDoubleAttribute(extent1d, "m_dMin", pData->m_dMin);
|
|
setDoubleAttribute(extent1d, "m_dMax", pData->m_dMax);
|
|
setting->LinkEndChild(extent1d);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseDomain(const A3DDomainData* pData, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* extent2d = new _TiXmlElement("A3DDomainData");
|
|
setDoubleAttribute(extent2d, "m_sMin.m_dX", pData->m_sMin.m_dX);
|
|
setDoubleAttribute(extent2d, "m_sMin.m_dY", pData->m_sMin.m_dY);
|
|
setDoubleAttribute(extent2d, "m_sMax.m_dX", pData->m_sMax.m_dX);
|
|
setDoubleAttribute(extent2d, "m_sMax.m_dY", pData->m_sMax.m_dY);
|
|
setting->LinkEndChild(extent2d);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseBoundingBox(const A3DBoundingBoxData* pData, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* extent3d = new _TiXmlElement("A3DBoundingBoxData");
|
|
setDoubleAttribute(extent3d, "m_sMin.m_dX", pData->m_sMin.m_dX);
|
|
setDoubleAttribute(extent3d, "m_sMin.m_dY", pData->m_sMin.m_dY);
|
|
setDoubleAttribute(extent3d, "m_sMin.m_dZ", pData->m_sMin.m_dZ);
|
|
setDoubleAttribute(extent3d, "m_sMax.m_dX", pData->m_sMax.m_dX);
|
|
setDoubleAttribute(extent3d, "m_sMax.m_dY", pData->m_sMax.m_dY);
|
|
setDoubleAttribute(extent3d, "m_sMax.m_dZ", pData->m_sMax.m_dZ);
|
|
setting->LinkEndChild(extent3d);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseParam(const A3DParameterizationData* pData, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* param = new _TiXmlElement("A3DParameterizationData");
|
|
setDoubleAttribute(param, "m_sInterval.m_dMin", pData->m_sInterval.m_dMin);
|
|
setDoubleAttribute(param, "m_sInterval.m_dMax", pData->m_sInterval.m_dMax);
|
|
setDoubleAttribute(param, "m_dCoeffA", pData->m_dCoeffA);
|
|
setDoubleAttribute(param, "m_dCoeffB", pData->m_dCoeffB);
|
|
setting->LinkEndChild(param);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseUVParam(const A3DUVParameterizationData* pData, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* param = new _TiXmlElement("A3DUVParameterizationData");
|
|
traverseDomain(&pData->m_sUVDomain, param);
|
|
setDoubleAttribute(param, "m_dUCoeffA", pData->m_dUCoeffA);
|
|
setDoubleAttribute(param, "m_dUCoeffB", pData->m_dUCoeffB);
|
|
setDoubleAttribute(param, "m_dVCoeffA", pData->m_dVCoeffA);
|
|
setDoubleAttribute(param, "m_dVCoeffB", pData->m_dVCoeffB);
|
|
setDoubleAttribute(param, "m_bSwapUV", (int)pData->m_bSwapUV);
|
|
setting->LinkEndChild(param);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseCartesianTransformationData(const A3DMiscCartesianTransformationData& oTrsf, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* trsf = new _TiXmlElement("A3DMiscCartesianTransformationData");
|
|
trsf->SetAttribute("m_ucBehaviour", (int)(oTrsf.m_ucBehaviour));
|
|
traversePoint("m_sOrigin" , oTrsf.m_sOrigin , trsf);
|
|
traversePoint("m_sXVector", oTrsf.m_sXVector, trsf);
|
|
traversePoint("m_sYVector", oTrsf.m_sYVector, trsf);
|
|
traversePoint("m_sScale" , oTrsf.m_sScale , trsf);
|
|
setting->LinkEndChild(trsf);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseCartesianTransformation(const A3DMiscCartesianTransformation* pTrsf, _TiXmlElement* setting)
|
|
{
|
|
if (pTrsf)
|
|
{
|
|
A3DMiscCartesianTransformationData sData;
|
|
A3D_INITIALIZE_DATA(A3DMiscCartesianTransformationData, sData);
|
|
A3DStatus iRet = A3DMiscCartesianTransformationGet(pTrsf, &sData);
|
|
if (iRet == A3D_SUCCESS)
|
|
{
|
|
traverseCartesianTransformationData(sData, setting);
|
|
A3DMiscCartesianTransformationGet(NULL, &sData);
|
|
}
|
|
else
|
|
{
|
|
setting->SetAttribute("error", A3DMiscGetErrorMsg(iRet));
|
|
}
|
|
}
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseGeneralTransformation(const A3DMiscGeneralTransformation* pTrsf, _TiXmlElement* setting)
|
|
{
|
|
_TiXmlElement* trsf = new _TiXmlElement("A3DMiscGeneralTransformationData");
|
|
A3DMiscGeneralTransformationData sData;
|
|
A3D_INITIALIZE_DATA(A3DMiscGeneralTransformationData, sData);
|
|
A3DStatus iRet = A3DMiscGeneralTransformationGet(pTrsf, &sData);
|
|
if (iRet == A3D_SUCCESS)
|
|
{
|
|
traverseDoubles("m_adCoeff", 16, sData.m_adCoeff, trsf);
|
|
A3DMiscGeneralTransformationGet(NULL, &sData);
|
|
}
|
|
else
|
|
{
|
|
trsf->SetAttribute("error", A3DMiscGetErrorMsg(iRet));
|
|
}
|
|
setting->LinkEndChild(trsf);
|
|
return A3D_SUCCESS;
|
|
}
|
|
|
|
//######################################################################################################################
|
|
A3DStatus traverseTransformation(const A3DMiscTransformation* pTransfo3d, _TiXmlElement* setting)
|
|
{
|
|
if(pTransfo3d == NULL)
|
|
return A3D_SUCCESS;
|
|
|
|
A3DStatus iRet;
|
|
_TiXmlElement* trsf = new _TiXmlElement("A3DMiscTransformation");
|
|
traverseSource(pTransfo3d, trsf);
|
|
A3DEEntityType eType = kA3DTypeUnknown;
|
|
iRet = A3DEntityGetType(pTransfo3d, &eType);
|
|
if (eType == kA3DTypeMiscCartesianTransformation)
|
|
{
|
|
iRet = traverseCartesianTransformation(pTransfo3d, trsf);
|
|
}
|
|
else if (eType == kA3DTypeMiscGeneralTransformation)
|
|
{
|
|
iRet = traverseGeneralTransformation(pTransfo3d, trsf);
|
|
}
|
|
else
|
|
{
|
|
trsf->SetAttribute("error", A3DMiscGetErrorMsg(iRet));
|
|
}
|
|
|
|
setting->LinkEndChild(trsf);
|
|
return iRet;
|
|
}
|
|
|