1 // Copyright (c) 2017-2019 OPEN CASCADE SAS 2 // 3 // This file is part of Open CASCADE Technology software library. 4 // 5 // This library is free software; you can redistribute it and/or modify it under 6 // the terms of the GNU Lesser General Public License version 2.1 as published 7 // by the Free Software Foundation, with special exception defined in the file 8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT 9 // distribution for complete text of the license and disclaimer of any warranty. 10 // 11 // Alternatively, this file may be used under the terms of Open CASCADE 12 // commercial license or contractual agreement. 13 14 #ifndef _RWGltf_CafWriter_HeaderFiler 15 #define _RWGltf_CafWriter_HeaderFiler 16 17 #include <TColStd_IndexedDataMapOfStringString.hxx> 18 #include <TColStd_MapOfAsciiString.hxx> 19 #include <TDF_LabelSequence.hxx> 20 #include <TopTools_ShapeMapHasher.hxx> 21 #include <RWGltf_GltfBufferView.hxx> 22 #include <RWGltf_GltfFace.hxx> 23 #include <RWGltf_WriterTrsfFormat.hxx> 24 #include <RWMesh_CoordinateSystemConverter.hxx> 25 #include <RWMesh_NameFormat.hxx> 26 #include <XCAFPrs_Style.hxx> 27 28 #include <memory> 29 30 class Message_ProgressRange; 31 class RWMesh_FaceIterator; 32 class RWGltf_GltfOStreamWriter; 33 class RWGltf_GltfMaterialMap; 34 class RWGltf_GltfSceneNodeMap; 35 class TDocStd_Document; 36 37 //! glTF writer context from XCAF document. 38 class RWGltf_CafWriter : public Standard_Transient 39 { 40 DEFINE_STANDARD_RTTIEXT(RWGltf_CafWriter, Standard_Transient) 41 public: 42 43 //! Main constructor. 44 //! @param theFile [in] path to output glTF file 45 //! @param theIsBinary [in] flag to write into binary glTF format (.glb) 46 Standard_EXPORT RWGltf_CafWriter (const TCollection_AsciiString& theFile, 47 Standard_Boolean theIsBinary); 48 49 //! Destructor. 50 Standard_EXPORT virtual ~RWGltf_CafWriter(); 51 52 //! Return transformation from OCCT to glTF coordinate system. CoordinateSystemConverter() const53 const RWMesh_CoordinateSystemConverter& CoordinateSystemConverter() const { return myCSTrsf; } 54 55 //! Return transformation from OCCT to glTF coordinate system. ChangeCoordinateSystemConverter()56 RWMesh_CoordinateSystemConverter& ChangeCoordinateSystemConverter() { return myCSTrsf; } 57 58 //! Set transformation from OCCT to glTF coordinate system. SetCoordinateSystemConverter(const RWMesh_CoordinateSystemConverter & theConverter)59 void SetCoordinateSystemConverter (const RWMesh_CoordinateSystemConverter& theConverter) { myCSTrsf = theConverter; } 60 61 //! Return flag to write into binary glTF format (.glb), specified within class constructor. IsBinary() const62 bool IsBinary() const { return myIsBinary; } 63 64 //! Return preferred transformation format for writing into glTF file; RWGltf_WriterTrsfFormat_Compact by default. TransformationFormat() const65 RWGltf_WriterTrsfFormat TransformationFormat() const { return myTrsfFormat; } 66 67 //! Set preferred transformation format for writing into glTF file. SetTransformationFormat(RWGltf_WriterTrsfFormat theFormat)68 void SetTransformationFormat (RWGltf_WriterTrsfFormat theFormat) { myTrsfFormat = theFormat; } 69 70 //! Return name format for exporting Nodes; RWMesh_NameFormat_InstanceOrProduct by default. NodeNameFormat() const71 RWMesh_NameFormat NodeNameFormat() const { return myNodeNameFormat; } 72 73 //! Set name format for exporting Nodes. SetNodeNameFormat(RWMesh_NameFormat theFormat)74 void SetNodeNameFormat (RWMesh_NameFormat theFormat) { myNodeNameFormat = theFormat; } 75 76 //! Return name format for exporting Meshes; RWMesh_NameFormat_Product by default. MeshNameFormat() const77 RWMesh_NameFormat MeshNameFormat() const { return myMeshNameFormat; } 78 79 //! Set name format for exporting Meshes. SetMeshNameFormat(RWMesh_NameFormat theFormat)80 void SetMeshNameFormat (RWMesh_NameFormat theFormat) { myMeshNameFormat = theFormat; } 81 82 //! Return TRUE to export UV coordinates even if there are no mapped texture; FALSE by default. IsForcedUVExport() const83 bool IsForcedUVExport() const { return myIsForcedUVExport; } 84 85 //! Set flag to export UV coordinates even if there are no mapped texture; FALSE by default. SetForcedUVExport(bool theToForce)86 void SetForcedUVExport (bool theToForce) { myIsForcedUVExport = theToForce; } 87 88 //! Return default material definition to be used for nodes with only color defined. DefaultStyle() const89 const XCAFPrs_Style& DefaultStyle() const { return myDefaultStyle; } 90 91 //! Set default material definition to be used for nodes with only color defined. SetDefaultStyle(const XCAFPrs_Style & theStyle)92 void SetDefaultStyle (const XCAFPrs_Style& theStyle) { myDefaultStyle = theStyle; } 93 94 //! Return flag to write image textures into GLB file (binary gltf export); TRUE by default. 95 //! When set to FALSE, texture images will be written as separate files. 96 //! Has no effect on writing into non-binary format. ToEmbedTexturesInGlb()97 Standard_Boolean ToEmbedTexturesInGlb() { return myToEmbedTexturesInGlb; } 98 99 //! Set flag to write image textures into GLB file (binary gltf export). SetToEmbedTexturesInGlb(Standard_Boolean theToEmbedTexturesInGlb)100 void SetToEmbedTexturesInGlb (Standard_Boolean theToEmbedTexturesInGlb) { myToEmbedTexturesInGlb = theToEmbedTexturesInGlb; } 101 102 //! Return flag to merge faces within a single part; FALSE by default. ToMergeFaces() const103 bool ToMergeFaces() const { return myToMergeFaces; } 104 105 //! Set flag to merge faces within a single part. 106 //! May reduce JSON size thanks to smaller number of primitive arrays. SetMergeFaces(bool theToMerge)107 void SetMergeFaces (bool theToMerge) { myToMergeFaces = theToMerge; } 108 109 //! Return flag to prefer keeping 16-bit indexes while merging face; FALSE by default. ToSplitIndices16() const110 bool ToSplitIndices16() const { return myToSplitIndices16; } 111 112 //! Set flag to prefer keeping 16-bit indexes while merging face. 113 //! Has effect only with ToMergeFaces() option turned ON. 114 //! May reduce binary data size thanks to smaller triangle indexes. SetSplitIndices16(bool theToSplit)115 void SetSplitIndices16 (bool theToSplit) { myToSplitIndices16 = theToSplit; } 116 117 //! Write glTF file and associated binary file. 118 //! Triangulation data should be precomputed within shapes! 119 //! @param theDocument [in] input document 120 //! @param theRootLabels [in] list of root shapes to export 121 //! @param theLabelFilter [in] optional filter with document nodes to export, 122 //! with keys defined by XCAFPrs_DocumentExplorer::DefineChildId() and filled recursively 123 //! (leaves and parent assembly nodes at all levels); 124 //! when not NULL, all nodes not included into the map will be ignored 125 //! @param theFileInfo [in] map with file metadata to put into glTF header section 126 //! @param theProgress [in] optional progress indicator 127 //! @return FALSE on file writing failure 128 Standard_EXPORT virtual bool Perform (const Handle(TDocStd_Document)& theDocument, 129 const TDF_LabelSequence& theRootLabels, 130 const TColStd_MapOfAsciiString* theLabelFilter, 131 const TColStd_IndexedDataMapOfStringString& theFileInfo, 132 const Message_ProgressRange& theProgress); 133 134 //! Write glTF file and associated binary file. 135 //! Triangulation data should be precomputed within shapes! 136 //! @param theDocument [in] input document 137 //! @param theFileInfo [in] map with file metadata to put into glTF header section 138 //! @param theProgress [in] optional progress indicator 139 //! @return FALSE on file writing failure 140 Standard_EXPORT virtual bool Perform (const Handle(TDocStd_Document)& theDocument, 141 const TColStd_IndexedDataMapOfStringString& theFileInfo, 142 const Message_ProgressRange& theProgress); 143 144 protected: 145 146 //! Write binary data file with triangulation data. 147 //! Triangulation data should be precomputed within shapes! 148 //! @param theDocument [in] input document 149 //! @param theRootLabels [in] list of root shapes to export 150 //! @param theLabelFilter [in] optional filter with document nodes to export 151 //! @param theProgress [in] optional progress indicator 152 //! @return FALSE on file writing failure 153 Standard_EXPORT virtual bool writeBinData (const Handle(TDocStd_Document)& theDocument, 154 const TDF_LabelSequence& theRootLabels, 155 const TColStd_MapOfAsciiString* theLabelFilter, 156 const Message_ProgressRange& theProgress); 157 158 //! Write JSON file with glTF structure (should be called after writeBinData()). 159 //! @param theDocument [in] input document 160 //! @param theRootLabels [in] list of root shapes to export 161 //! @param theLabelFilter [in] optional filter with document nodes to export 162 //! @param theFileInfo [in] map with file metadata to put into glTF header section 163 //! @param theProgress [in] optional progress indicator 164 //! @return FALSE on file writing failure 165 Standard_EXPORT virtual bool writeJson (const Handle(TDocStd_Document)& theDocument, 166 const TDF_LabelSequence& theRootLabels, 167 const TColStd_MapOfAsciiString* theLabelFilter, 168 const TColStd_IndexedDataMapOfStringString& theFileInfo, 169 const Message_ProgressRange& theProgress); 170 171 protected: 172 173 //! Return TRUE if face mesh should be skipped (e.g. because it is invalid or empty). 174 Standard_EXPORT virtual Standard_Boolean toSkipFaceMesh (const RWMesh_FaceIterator& theFaceIter); 175 176 //! Generate name for specified labels. 177 //! @param[in] theFormat name format to apply 178 //! @param[in] theLabel instance label 179 //! @param[in] theRefLabel product label 180 Standard_EXPORT virtual TCollection_AsciiString formatName (RWMesh_NameFormat theFormat, 181 const TDF_Label& theLabel, 182 const TDF_Label& theRefLabel) const; 183 184 //! Write mesh nodes into binary file. 185 //! @param theGltfFace [out] glTF face definition 186 //! @param theBinFile [out] output file to write into 187 //! @param theFaceIter [in] current face to write 188 //! @param theAccessorNb [in] [out] last accessor index 189 Standard_EXPORT virtual void saveNodes (RWGltf_GltfFace& theGltfFace, 190 std::ostream& theBinFile, 191 const RWMesh_FaceIterator& theFaceIter, 192 Standard_Integer& theAccessorNb) const; 193 194 //! Write mesh normals into binary file. 195 //! @param theGltfFace [out] glTF face definition 196 //! @param theBinFile [out] output file to write into 197 //! @param theFaceIter [in] current face to write 198 //! @param theAccessorNb [in] [out] last accessor index 199 Standard_EXPORT virtual void saveNormals (RWGltf_GltfFace& theGltfFace, 200 std::ostream& theBinFile, 201 RWMesh_FaceIterator& theFaceIter, 202 Standard_Integer& theAccessorNb) const; 203 204 //! Write mesh texture UV coordinates into binary file. 205 //! @param theGltfFace [out] glTF face definition 206 //! @param theBinFile [out] output file to write into 207 //! @param theFaceIter [in] current face to write 208 //! @param theAccessorNb [in] [out] last accessor index 209 Standard_EXPORT virtual void saveTextCoords (RWGltf_GltfFace& theGltfFace, 210 std::ostream& theBinFile, 211 const RWMesh_FaceIterator& theFaceIter, 212 Standard_Integer& theAccessorNb) const; 213 214 //! Write mesh indexes into binary file. 215 //! @param theGltfFace [out] glTF face definition 216 //! @param theBinFile [out] output file to write into 217 //! @param theFaceIter [in] current face to write 218 //! @param theAccessorNb [in] [out] last accessor index 219 Standard_EXPORT virtual void saveIndices (RWGltf_GltfFace& theGltfFace, 220 std::ostream& theBinFile, 221 const RWMesh_FaceIterator& theFaceIter, 222 Standard_Integer& theAccessorNb); 223 224 protected: 225 226 //! Write bufferView for vertex positions within RWGltf_GltfRootElement_Accessors section 227 //! @param theGltfFace [in] face definition to write 228 Standard_EXPORT virtual void writePositions (const RWGltf_GltfFace& theGltfFace); 229 230 //! Write bufferView for vertex normals within RWGltf_GltfRootElement_Accessors section 231 //! @param theGltfFace [in] face definition to write 232 Standard_EXPORT virtual void writeNormals (const RWGltf_GltfFace& theGltfFace); 233 234 //! Write bufferView for vertex texture coordinates within RWGltf_GltfRootElement_Accessors section 235 //! @param theGltfFace [in] face definition to write 236 Standard_EXPORT virtual void writeTextCoords (const RWGltf_GltfFace& theGltfFace); 237 238 //! Write bufferView for triangle indexes within RWGltf_GltfRootElement_Accessors section. 239 //! @param theGltfFace [in] face definition to write 240 Standard_EXPORT virtual void writeIndices (const RWGltf_GltfFace& theGltfFace); 241 242 protected: 243 244 //! Write RWGltf_GltfRootElement_Accessors section. 245 //! @param theSceneNodeMap [in] ordered map of scene nodes 246 Standard_EXPORT virtual void writeAccessors (const RWGltf_GltfSceneNodeMap& theSceneNodeMap); 247 248 //! Write RWGltf_GltfRootElement_Animations section (reserved). 249 Standard_EXPORT virtual void writeAnimations(); 250 251 //! Write RWGltf_GltfRootElement_Asset section. 252 //! @param theFileInfo [in] optional metadata to write into file header 253 Standard_EXPORT virtual void writeAsset (const TColStd_IndexedDataMapOfStringString& theFileInfo); 254 255 //! Write RWGltf_GltfRootElement_BufferViews section. 256 //! @param theBinDataBufferId [in] index of binary buffer with vertex data 257 Standard_EXPORT virtual void writeBufferViews (const Standard_Integer theBinDataBufferId); 258 259 //! Write RWGltf_GltfRootElement_Buffers section. 260 Standard_EXPORT virtual void writeBuffers(); 261 262 //! Write RWGltf_GltfRootElement_ExtensionsUsed/RWGltf_GltfRootElement_ExtensionsRequired sections (reserved). 263 Standard_EXPORT virtual void writeExtensions(); 264 265 //! Write RWGltf_GltfRootElement_Images section. 266 //! @param theSceneNodeMap [in] ordered map of scene nodes 267 //! @param theMaterialMap [out] map of materials, filled with image files used by textures 268 Standard_EXPORT virtual void writeImages (const RWGltf_GltfSceneNodeMap& theSceneNodeMap); 269 270 //! Write RWGltf_GltfRootElement_Materials section. 271 //! @param theSceneNodeMap [in] ordered map of scene nodes 272 //! @param theMaterialMap [out] map of materials, filled with materials 273 Standard_EXPORT virtual void writeMaterials (const RWGltf_GltfSceneNodeMap& theSceneNodeMap); 274 275 //! Write RWGltf_GltfRootElement_Meshes section. 276 //! @param theSceneNodeMap [in] ordered map of scene nodes 277 //! @param theMaterialMap [in] map of materials 278 Standard_EXPORT virtual void writeMeshes (const RWGltf_GltfSceneNodeMap& theSceneNodeMap); 279 280 //! Write a primitive array to RWGltf_GltfRootElement_Meshes section. 281 //! @param[in] theGltfFace face to write 282 //! @param[in] theName primitive array name 283 //! @param[in,out] theToStartPrims flag indicating that primitive array has been started 284 Standard_EXPORT virtual void writePrimArray (const RWGltf_GltfFace& theGltfFace, 285 const TCollection_AsciiString& theName, 286 bool& theToStartPrims); 287 288 //! Write RWGltf_GltfRootElement_Nodes section. 289 //! @param theDocument [in] input document 290 //! @param theRootLabels [in] list of root shapes to export 291 //! @param theLabelFilter [in] optional filter with document nodes to export 292 //! @param theSceneNodeMap [in] ordered map of scene nodes 293 //! @param theSceneRootNodeInds [out] sequence of scene nodes pointing to root shapes (to be used for writeScenes()) 294 Standard_EXPORT virtual void writeNodes (const Handle(TDocStd_Document)& theDocument, 295 const TDF_LabelSequence& theRootLabels, 296 const TColStd_MapOfAsciiString* theLabelFilter, 297 const RWGltf_GltfSceneNodeMap& theSceneNodeMap, 298 NCollection_Sequence<Standard_Integer>& theSceneRootNodeInds); 299 300 //! Write RWGltf_GltfRootElement_Samplers section. 301 Standard_EXPORT virtual void writeSamplers(); 302 303 //! Write RWGltf_GltfRootElement_Scene section. 304 //! @param theDefSceneId [in] index of default scene (0) 305 Standard_EXPORT virtual void writeScene (const Standard_Integer theDefSceneId); 306 307 //! Write RWGltf_GltfRootElement_Scenes section. 308 //! @param theSceneRootNodeInds [in] sequence of scene nodes pointing to root shapes 309 Standard_EXPORT virtual void writeScenes (const NCollection_Sequence<Standard_Integer>& theSceneRootNodeInds); 310 311 //! Write RWGltf_GltfRootElement_Skins section (reserved). 312 Standard_EXPORT virtual void writeSkins(); 313 314 //! Write RWGltf_GltfRootElement_Textures section. 315 //! @param theSceneNodeMap [in] ordered map of scene nodes 316 //! @param theMaterialMap [out] map of materials, filled with textures 317 Standard_EXPORT virtual void writeTextures (const RWGltf_GltfSceneNodeMap& theSceneNodeMap); 318 319 protected: 320 321 //! Shape + Style pair. 322 struct RWGltf_StyledShape 323 { 324 TopoDS_Shape Shape; 325 XCAFPrs_Style Style; 326 RWGltf_StyledShapeRWGltf_CafWriter::RWGltf_StyledShape327 RWGltf_StyledShape() {} RWGltf_StyledShapeRWGltf_CafWriter::RWGltf_StyledShape328 explicit RWGltf_StyledShape (const TopoDS_Shape& theShape) : Shape (theShape) {} RWGltf_StyledShapeRWGltf_CafWriter::RWGltf_StyledShape329 explicit RWGltf_StyledShape (const TopoDS_Shape& theShape, 330 const XCAFPrs_Style& theStyle) : Shape (theShape), Style (theStyle) {} 331 public: 332 //! Computes a hash code. HashCodeRWGltf_CafWriter::RWGltf_StyledShape333 static Standard_Integer HashCode (const RWGltf_StyledShape& theShape, Standard_Integer theUpperBound) 334 { 335 return theShape.Shape.HashCode (theUpperBound); 336 } 337 //! Equality comparison. IsEqualRWGltf_CafWriter::RWGltf_StyledShape338 static Standard_Boolean IsEqual (const RWGltf_StyledShape& theS1, const RWGltf_StyledShape& theS2) 339 { 340 return theS1.Shape.IsSame (theS2.Shape) 341 && theS1.Style.IsEqual(theS2.Style); 342 } 343 }; 344 345 typedef NCollection_IndexedDataMap<RWGltf_StyledShape, Handle(RWGltf_GltfFaceList), RWGltf_StyledShape> ShapeToGltfFaceMap; 346 347 protected: 348 349 TCollection_AsciiString myFile; //!< output glTF file 350 TCollection_AsciiString myBinFileNameFull; //!< output file with binary data (full path) 351 TCollection_AsciiString myBinFileNameShort; //!< output file with binary data (short path) 352 RWGltf_WriterTrsfFormat myTrsfFormat; //!< transformation format to write into glTF file 353 RWMesh_NameFormat myNodeNameFormat; //!< name format for exporting Nodes 354 RWMesh_NameFormat myMeshNameFormat; //!< name format for exporting Meshes 355 Standard_Boolean myIsBinary; //!< flag to write into binary glTF format (.glb) 356 Standard_Boolean myIsForcedUVExport; //!< export UV coordinates even if there are no mapped texture 357 Standard_Boolean myToEmbedTexturesInGlb; //!< flag to write image textures into GLB file 358 Standard_Boolean myToMergeFaces; //!< flag to merge faces within a single part 359 Standard_Boolean myToSplitIndices16; //!< flag to prefer keeping 16-bit indexes while merging face 360 RWMesh_CoordinateSystemConverter myCSTrsf; //!< transformation from OCCT to glTF coordinate system 361 XCAFPrs_Style myDefaultStyle; //!< default material definition to be used for nodes with only color defined 362 363 opencascade::std::shared_ptr<RWGltf_GltfOStreamWriter> 364 myWriter; //!< JSON writer 365 Handle(RWGltf_GltfMaterialMap) myMaterialMap; //!< map of defined materials 366 RWGltf_GltfBufferView myBuffViewPos; //!< current buffer view with nodes positions 367 RWGltf_GltfBufferView myBuffViewNorm; //!< current buffer view with nodes normals 368 RWGltf_GltfBufferView myBuffViewTextCoord; //!< current buffer view with nodes UV coordinates 369 RWGltf_GltfBufferView myBuffViewInd; //!< current buffer view with triangulation indexes 370 ShapeToGltfFaceMap myBinDataMap; //!< map for TopoDS_Face to glTF face (merging duplicates) 371 int64_t myBinDataLen64; //!< length of binary file 372 373 }; 374 375 #endif // _RWGltf_CafWriter_HeaderFiler 376