0032107: Data Exchange, RWGltf_CafReader - reading glTF document back loses sharing
[occt.git] / src / RWGltf / RWGltf_CafWriter.hxx
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.
53   const RWMesh_CoordinateSystemConverter& CoordinateSystemConverter() const { return myCSTrsf; }
54
55   //! Return transformation from OCCT to glTF coordinate system.
56   RWMesh_CoordinateSystemConverter& ChangeCoordinateSystemConverter() { return myCSTrsf; }
57
58   //! Set transformation from OCCT to glTF coordinate system.
59   void SetCoordinateSystemConverter (const RWMesh_CoordinateSystemConverter& theConverter) { myCSTrsf = theConverter; }
60
61   //! Return flag to write into binary glTF format (.glb), specified within class constructor.
62   bool IsBinary() const { return myIsBinary; }
63
64   //! Return preferred transformation format for writing into glTF file; RWGltf_WriterTrsfFormat_Compact by default.
65   RWGltf_WriterTrsfFormat TransformationFormat() const { return myTrsfFormat; }
66
67   //! Set preferred transformation format for writing into glTF file.
68   void SetTransformationFormat (RWGltf_WriterTrsfFormat theFormat) { myTrsfFormat = theFormat; }
69
70   //! Return name format for exporting Nodes; RWMesh_NameFormat_InstanceOrProduct by default.
71   RWMesh_NameFormat NodeNameFormat() const { return myNodeNameFormat; }
72
73   //! Set name format for exporting Nodes.
74   void SetNodeNameFormat (RWMesh_NameFormat theFormat) { myNodeNameFormat = theFormat; }
75
76   //! Return name format for exporting Meshes; RWMesh_NameFormat_Product by default.
77   RWMesh_NameFormat MeshNameFormat() const { return myMeshNameFormat; }
78
79   //! Set name format for exporting Meshes.
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.
83   bool IsForcedUVExport() const { return myIsForcedUVExport; }
84
85   //! Set flag to export UV coordinates even if there are no mapped texture; FALSE by default.
86   void SetForcedUVExport (bool theToForce) { myIsForcedUVExport = theToForce; }
87
88   //! Return default material definition to be used for nodes with only color defined.
89   const XCAFPrs_Style& DefaultStyle() const { return myDefaultStyle; }
90
91   //! Set default material definition to be used for nodes with only color defined.
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.
97   Standard_Boolean ToEmbedTexturesInGlb() { return myToEmbedTexturesInGlb; }
98
99   //! Set flag to write image textures into GLB file (binary gltf export).
100   void SetToEmbedTexturesInGlb (Standard_Boolean theToEmbedTexturesInGlb) { myToEmbedTexturesInGlb = theToEmbedTexturesInGlb; }
101
102   //! Return flag to merge faces within a single part; FALSE by default.
103   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.
107   void SetMergeFaces (bool theToMerge) { myToMergeFaces = theToMerge; }
108
109   //! Return flag to prefer keeping 16-bit indexes while merging face; FALSE by default.
110   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.
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
327     RWGltf_StyledShape() {}
328     explicit RWGltf_StyledShape (const TopoDS_Shape& theShape) : Shape (theShape) {}
329     explicit RWGltf_StyledShape (const TopoDS_Shape&  theShape,
330                                  const XCAFPrs_Style& theStyle) : Shape (theShape), Style (theStyle) {}
331   public:
332     //! Computes a hash code.
333     static Standard_Integer HashCode (const RWGltf_StyledShape& theShape, Standard_Integer theUpperBound)
334     {
335       return theShape.Shape.HashCode (theUpperBound);
336     }
337     //! Equality comparison.
338     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