diff --git a/Include/API/lib3mf_meshobject.hpp b/Include/API/lib3mf_meshobject.hpp index ff6ec9a33..c2d4c4b6f 100644 --- a/Include/API/lib3mf_meshobject.hpp +++ b/Include/API/lib3mf_meshobject.hpp @@ -63,6 +63,7 @@ class CMeshObject : public virtual IMeshObject, public virtual CObject { NMR::CMeshInformation_Properties* getMeshInformationProperties(); + protected: /** diff --git a/Include/Common/Mesh/NMR_Mesh.h b/Include/Common/Mesh/NMR_Mesh.h index adef011c6..1297bff2e 100644 --- a/Include/Common/Mesh/NMR_Mesh.h +++ b/Include/Common/Mesh/NMR_Mesh.h @@ -57,6 +57,8 @@ namespace NMR { MESHFACES m_Faces; CBeamLattice m_BeamLattice; + + PMeshInformationHandler m_pMeshInformationHandler; public: CMesh(); diff --git a/Include/Model/Classes/NMR_ModelConstants.h b/Include/Model/Classes/NMR_ModelConstants.h index 7778b9905..f4751287b 100644 --- a/Include/Model/Classes/NMR_ModelConstants.h +++ b/Include/Model/Classes/NMR_ModelConstants.h @@ -80,6 +80,7 @@ These are given by the 3MF Standard #define XML_3MF_NAMESPACE_MATERIALSPEC "http://schemas.microsoft.com/3dmanufacturing/material/2015/02" #define XML_3MF_NAMESPACE_PRODUCTIONSPEC "http://schemas.microsoft.com/3dmanufacturing/production/2015/06" #define XML_3MF_NAMESPACE_BEAMLATTICESPEC "http://schemas.microsoft.com/3dmanufacturing/beamlattice/2017/02" +#define XML_3MF_NAMESPACE_TRIANGLESETS "http://schemas.microsoft.com/3dmanufacturing/trianglesets/2021/07" #define XML_3MF_NAMESPACE_SLICESPEC "http://schemas.microsoft.com/3dmanufacturing/slice/2015/07" #define XML_3MF_NAMESPACE_SECURECONTENTSPEC "http://schemas.microsoft.com/3dmanufacturing/securecontent/2019/04" #define XML_3MF_NAMESPACE_DIGITALSIGNATURESPEC "http://www.w3.org/2000/09/xmldsig#" @@ -94,6 +95,7 @@ These are given by the 3MF Standard #define XML_3MF_NAMESPACEPREFIX_SECURECONTENT "sc" #define XML_3MF_NAMESPACEPREFIX_VOLUMETRIC "v" #define XML_3MF_NAMESPACEPREFIX_IMPLICIT "i" +#define XML_3MF_NAMESPACEPREFIX_TRIANGLESETS "t" #define XML_3MF_ATTRIBUTE_XMLNS "xmlns" #define XML_3MF_ATTRIBUTE_PREFIX_XML "xml" @@ -149,6 +151,8 @@ These are given by the 3MF Standard #define XML_3MF_ELEMENT_BEAMSET "beamset" #define XML_3MF_ELEMENT_REF "ref" #define XML_3MF_ELEMENT_BALLREF "ballref" +#define XML_3MF_ELEMENT_TRIANGLESETS "trianglesets" +#define XML_3MF_ELEMENT_TRIANGLESET "triangleset" // Triangle element. #define XML_3MF_ELEMENT_TRIANGLE "triangle" @@ -188,6 +192,8 @@ These are given by the 3MF Standard // deprecated (has been used in draft version of the specification): #define XML_3MF_ATTRIBUTE_BEAMLATTICE_ACCURACY "accuracy" #define XML_3MF_ATTRIBUTE_BEAMLATTICE_PRECISION "precision" +#define XML_3MF_ATTRIBUTE_TRIANGLESET_IDENTIFIER "identifier" +#define XML_3MF_ATTRIBUTE_TRIANGLESET_NAME "name" // Vertex element. #define XML_3MF_ELEMENT_VERTEX "vertex" diff --git a/Include/Model/Classes/NMR_ModelTriangleSet.h b/Include/Model/Classes/NMR_ModelTriangleSet.h index 659cdf18f..111a56a48 100644 --- a/Include/Model/Classes/NMR_ModelTriangleSet.h +++ b/Include/Model/Classes/NMR_ModelTriangleSet.h @@ -73,6 +73,8 @@ namespace NMR { PModelTriangleSet duplicate(const std::string & sIdentifier); void merge (PModelTriangleSet pTriangleSet); + std::set & getTriangles (); + }; } diff --git a/Include/Model/Writer/v100/NMR_ModelWriterNode100_Mesh.h b/Include/Model/Writer/v100/NMR_ModelWriterNode100_Mesh.h index 94715edcd..072de84c3 100644 --- a/Include/Model/Writer/v100/NMR_ModelWriterNode100_Mesh.h +++ b/Include/Model/Writer/v100/NMR_ModelWriterNode100_Mesh.h @@ -56,6 +56,8 @@ This is the class for exporting the 3mf mesh node. #define MODELWRITERMESH100_BEAMLATTICE_REFSTARTLENGTH 14 #define MODELWRITERMESH100_BEAMLATTICE_BALLREFLINESTART " m_VertexLine; @@ -77,12 +80,14 @@ namespace NMR { std::array m_BallLine; std::array m_BeamRefLine; std::array m_BallRefLine; + std::array m_TriangleSetRefLine; nfUint32 m_nVertexBufferPos; nfUint32 m_nTriangleBufferPos; nfUint32 m_nBeamBufferPos; nfUint32 m_nBallBufferPos; nfUint32 m_nBeamRefBufferPos; nfUint32 m_nBallRefBufferPos; + nfUint32 m_nTriangleSetRefBufferPos; private: const int m_nPosAfterDecPoint; const nfInt64 m_nPutDoubleFactor; @@ -110,6 +115,9 @@ namespace NMR { __NMR_INLINE void putBallRefString(_In_ const nfChar * pszString); __NMR_INLINE void putBallRefUInt32(_In_ const nfUint32 nValue); + __NMR_INLINE void putTriangleSetRefString(_In_ const nfChar* pszString); + __NMR_INLINE void putTriangleSetRefUInt32(_In_ const nfUint32 nValue); + __NMR_INLINE void writeVertexData(_In_ MESHNODE * pNode); __NMR_INLINE void writeFaceData_Plain(_In_ MESHFACE * pFace, _In_opt_ const nfChar * pszAdditionalString); __NMR_INLINE void writeFaceData_OneProperty(_In_ MESHFACE * pFace, _In_ const ModelResourceID nPropertyID, _In_ const ModelResourceIndex nPropertyIndex, _In_opt_ const nfChar * pszAdditionalString); @@ -118,11 +126,12 @@ namespace NMR { __NMR_INLINE void writeBallData(_In_ MESHBALL * pBall, _In_ eModelBeamLatticeBallMode eBallMode, _In_ nfDouble dRadius); __NMR_INLINE void writeRefData(_In_ INT nRefID); __NMR_INLINE void writeBallRefData(_In_ INT nRefID); + __NMR_INLINE void writeTriangleSetRefData(_In_ INT nRefID); public: CModelWriterNode100_Mesh() = delete; CModelWriterNode100_Mesh(_In_ CModelMeshObject * pModelMeshObject, _In_ CXmlWriter * pXMLWriter, _In_ PProgressMonitor pProgressMonitor, _In_ PMeshInformation_PropertyIndexMapping pPropertyIndexMapping, _In_ int nPosAfterDecPoint, _In_ nfBool bWriteMaterialExtension, _In_ nfBool m_bWriteBeamLatticeExtension, - _In_ nfBool bWriteVolumetricExtension); + _In_ nfBool bWriteVolumetricExtension, _In_ nfBool bWriteTriangleSetExtension); virtual void writeToXML(); }; diff --git a/Include/Model/Writer/v100/NMR_ModelWriterNode100_Model.h b/Include/Model/Writer/v100/NMR_ModelWriterNode100_Model.h index d4eecb5de..6d6689714 100644 --- a/Include/Model/Writer/v100/NMR_ModelWriterNode100_Model.h +++ b/Include/Model/Writer/v100/NMR_ModelWriterNode100_Model.h @@ -54,6 +54,7 @@ namespace NMR { nfBool m_bWriteMaterialExtension; nfBool m_bWriteProductionExtension; nfBool m_bWriteBeamLatticeExtension; + nfBool m_bWriteTriangleSetExtension; nfBool m_bWriteNurbsExtension; nfBool m_bWriteSliceExtension; nfBool m_bWriteSecureContentExtension; diff --git a/Source/Model/Classes/NMR_ModelTriangleSet.cpp b/Source/Model/Classes/NMR_ModelTriangleSet.cpp index 43f0ccafc..b28b90b24 100644 --- a/Source/Model/Classes/NMR_ModelTriangleSet.cpp +++ b/Source/Model/Classes/NMR_ModelTriangleSet.cpp @@ -103,5 +103,9 @@ namespace NMR { } + std::set& CModelTriangleSet::getTriangles() + { + return m_sTriangles; + } } diff --git a/Source/Model/Writer/v100/NMR_ModelWriterNode100_Mesh.cpp b/Source/Model/Writer/v100/NMR_ModelWriterNode100_Mesh.cpp index 0cdeb444a..6894fd12e 100644 --- a/Source/Model/Writer/v100/NMR_ModelWriterNode100_Mesh.cpp +++ b/Source/Model/Writer/v100/NMR_ModelWriterNode100_Mesh.cpp @@ -51,7 +51,7 @@ This is the class for exporting the 3mf mesh node. namespace NMR { CModelWriterNode100_Mesh::CModelWriterNode100_Mesh(_In_ CModelMeshObject * pModelMeshObject, _In_ CXmlWriter * pXMLWriter, _In_ PProgressMonitor pProgressMonitor, - _In_ PMeshInformation_PropertyIndexMapping pPropertyIndexMapping, _In_ int nPosAfterDecPoint, _In_ nfBool bWriteMaterialExtension, _In_ nfBool bWriteBeamLatticeExtension, _In_ nfBool bWriteVolumetricExtension) + _In_ PMeshInformation_PropertyIndexMapping pPropertyIndexMapping, _In_ int nPosAfterDecPoint, _In_ nfBool bWriteMaterialExtension, _In_ nfBool bWriteBeamLatticeExtension, _In_ nfBool bWriteVolumetricExtension, _In_ nfBool bWriteTriangleSetExtension) :CModelWriterNode_ModelBase(pModelMeshObject->getModel(), pXMLWriter, pProgressMonitor), m_nPosAfterDecPoint(nPosAfterDecPoint), m_nPutDoubleFactor((nfInt64)(pow(10, CModelWriterNode100_Mesh::m_nPosAfterDecPoint))) { __NMRASSERT(pModelMeshObject != nullptr); @@ -61,6 +61,7 @@ namespace NMR { m_bWriteMaterialExtension = bWriteMaterialExtension; m_bWriteBeamLatticeExtension = bWriteBeamLatticeExtension; m_bWriteVolumetricExtension = bWriteVolumetricExtension; + m_bWriteTriangleSetExtension = bWriteTriangleSetExtension; m_pModelMeshObject = pModelMeshObject; m_pPropertyIndexMapping = pPropertyIndexMapping; @@ -72,12 +73,14 @@ namespace NMR { m_nBallBufferPos = 0; m_nBeamRefBufferPos = 0; m_nBallRefBufferPos = 0; + m_nTriangleSetRefBufferPos = 0; putVertexString(MODELWRITERMESH100_VERTEXLINESTART); putTriangleString(MODELWRITERMESH100_TRIANGLELINESTART); putBeamString(MODELWRITERMESH100_BEAMLATTICE_BEAMLINESTART); putBallString(MODELWRITERMESH100_BEAMLATTICE_BALLLINESTART); putBeamRefString(MODELWRITERMESH100_BEAMLATTICE_REFLINESTART); putBallRefString(MODELWRITERMESH100_BEAMLATTICE_BALLREFLINESTART); + putTriangleSetRefString(MODELWRITERMESH100_TRIANGLESETS_REFLINESTART); } bool stringRepresentationsDiffer(double a, double b, nfInt64 putFactor) { @@ -262,6 +265,32 @@ namespace NMR { } writeFullEndElement(); + + if (m_bWriteTriangleSetExtension) { + uint32_t nTriangleSetCount = m_pModelMeshObject->getTriangleSetCount(); + + if (nTriangleSetCount > 0) { + writeStartElementWithPrefix(XML_3MF_ELEMENT_TRIANGLESETS, XML_3MF_NAMESPACEPREFIX_TRIANGLESETS); + + for (uint32_t nTriangleSetIndex = 0; nTriangleSetIndex < nTriangleSetCount; nTriangleSetIndex++) { + auto pTriangleSet = m_pModelMeshObject->getTriangleSet(nTriangleSetIndex); + writeStartElementWithPrefix(XML_3MF_ELEMENT_TRIANGLESET, XML_3MF_NAMESPACEPREFIX_TRIANGLESETS); + writeStringAttribute(XML_3MF_ATTRIBUTE_TRIANGLESET_IDENTIFIER, pTriangleSet->getIdentifier ()); + writeStringAttribute(XML_3MF_ATTRIBUTE_TRIANGLESET_NAME, pTriangleSet->getName()); + + auto triangleRefs = pTriangleSet->getTriangles(); + for (auto triangleRef : triangleRefs) { + writeTriangleSetRefData (triangleRef); + } + + writeFullEndElement(); + } + + writeFullEndElement(); + } + } + + if (bMeshHasAProperty && !(nObjectLevelPropertyID != 0)) { throw CNMRException(NMR_ERROR_MISSINGOBJECTLEVELPID); } @@ -610,6 +639,34 @@ namespace NMR { m_nBeamRefBufferPos += nCount; } + void CModelWriterNode100_Mesh::putTriangleSetRefString(_In_ const nfChar* pszString) + { + __NMRASSERT(pszString); + const nfChar* pChar = pszString; + nfChar* pTarget = &m_TriangleSetRefLine[m_nTriangleSetRefBufferPos]; + + while (*pChar != 0) { + *pTarget = *pChar; + pTarget++; + pChar++; + m_nTriangleSetRefBufferPos++; + } + } + + void CModelWriterNode100_Mesh::putTriangleSetRefUInt32(_In_ const nfUint32 nValue) + { +#ifdef __GNUC__ + int nCount = sprintf(&m_TriangleSetRefLine[m_nTriangleSetRefBufferPos], "%d", nValue); +#else + int nCount = sprintf_s(&m_TriangleSetRefLine[m_nTriangleSetRefBufferPos], MODELWRITERMESH100_LINEBUFFERSIZE - m_nTriangleSetRefBufferPos, "%d", nValue); +#endif // __GNUC__ + + if (nCount < 1) + throw CNMRException(NMR_ERROR_COULDNOTCONVERTNUMBER); + m_nTriangleSetRefBufferPos += nCount; + } + + void CModelWriterNode100_Mesh::putBallRefString(_In_ const nfChar* pszString) { __NMRASSERT(pszString); @@ -792,4 +849,12 @@ namespace NMR { m_pXMLWriter->WriteRawLine(&m_BallRefLine[0], m_nBallRefBufferPos); } + __NMR_INLINE void CModelWriterNode100_Mesh::writeTriangleSetRefData(_In_ INT nRefID) + { + m_nTriangleSetRefBufferPos = MODELWRITERMESH100_TRIANGLESETS_REFSTARTLENGTH; + putTriangleSetRefUInt32(nRefID); + putTriangleSetRefString("\"/>"); + m_pXMLWriter->WriteRawLine(&m_TriangleSetRefLine[0], m_nTriangleSetRefBufferPos); + } + } diff --git a/Source/Model/Writer/v100/NMR_ModelWriterNode100_Model.cpp b/Source/Model/Writer/v100/NMR_ModelWriterNode100_Model.cpp index 35b9965de..8b719cbc5 100644 --- a/Source/Model/Writer/v100/NMR_ModelWriterNode100_Model.cpp +++ b/Source/Model/Writer/v100/NMR_ModelWriterNode100_Model.cpp @@ -80,6 +80,7 @@ namespace NMR { m_bWriteBeamLatticeExtension = true; m_bWriteSliceExtension = true; m_bWriteSecureContentExtension = true; + m_bWriteTriangleSetExtension = true; m_bWriteBaseMaterials = true; m_bWriteObjects = true; m_bWriteVolumetricExtension = true; @@ -166,6 +167,15 @@ namespace NMR { } } + if (m_bWriteTriangleSetExtension) { + writeConstPrefixedStringAttribute(XML_3MF_ATTRIBUTE_XMLNS, XML_3MF_NAMESPACEPREFIX_SLICE, XML_3MF_NAMESPACE_TRIANGLESETS); + if (m_pModel->RequireExtension(XML_3MF_NAMESPACE_TRIANGLESETS)) { + if (sRequiredExtensions.size() > 0) + sRequiredExtensions = sRequiredExtensions + " "; + sRequiredExtensions = sRequiredExtensions + XML_3MF_NAMESPACEPREFIX_TRIANGLESETS; + } + } + if (m_bWriteSecureContentExtension) { writeConstPrefixedStringAttribute(XML_3MF_ATTRIBUTE_XMLNS, XML_3MF_NAMESPACEPREFIX_SECURECONTENT, XML_3MF_NAMESPACE_SECURECONTENTSPEC); if (m_pModel->RequireExtension(XML_3MF_NAMESPACE_SECURECONTENTSPEC)) { @@ -603,7 +613,7 @@ namespace NMR { pMeshObject, m_pXMLWriter, m_pProgressMonitor, m_pPropertyIndexMapping, m_nDecimalPrecision, m_bWriteMaterialExtension, m_bWriteBeamLatticeExtension, - m_bWriteVolumetricExtension); + m_bWriteVolumetricExtension, m_bWriteTriangleSetExtension); ModelWriter_Mesh.writeToXML(); }