Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:42

0001 // Author: Kirill Gavrilov
0002 // Copyright (c) 2016-2019 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014 
0015 #ifndef _RWGltf_GltfJsonParser_HeaderFile
0016 #define _RWGltf_GltfJsonParser_HeaderFile
0017 
0018 #include <Message_Gravity.hxx>
0019 #include <Message_ProgressScope.hxx>
0020 #include <RWGltf_GltfPrimArrayData.hxx>
0021 #include <RWGltf_GltfLatePrimitiveArray.hxx>
0022 #include <RWGltf_GltfBufferView.hxx>
0023 #include <RWGltf_GltfRootElement.hxx>
0024 #include <RWGltf_MaterialCommon.hxx>
0025 #include <RWGltf_MaterialMetallicRoughness.hxx>
0026 #include <RWMesh_CoordinateSystemConverter.hxx>
0027 #include <RWMesh_NodeAttributes.hxx>
0028 #include <TColStd_IndexedDataMapOfStringString.hxx>
0029 #include <TopoDS_Face.hxx>
0030 #include <TopTools_SequenceOfShape.hxx>
0031 
0032 // workaround name collisions with XLib
0033 #ifdef None
0034   #undef None
0035 #endif
0036 #ifdef Bool
0037   #undef Bool
0038 #endif
0039 
0040 #ifdef HAVE_RAPIDJSON
0041   //#define RAPIDJSON_ASSERT
0042   #include <Standard_WarningsDisable.hxx>
0043   #include <rapidjson/document.h>
0044   #include <rapidjson/prettywriter.h>
0045   #include <rapidjson/stringbuffer.h>
0046   #include <rapidjson/istreamwrapper.h>
0047   #include <rapidjson/ostreamwrapper.h>
0048   #include <Standard_WarningsRestore.hxx>
0049   
0050   typedef rapidjson::Document::ValueType RWGltf_JsonValue;
0051 #endif
0052 
0053 
0054 //! INTERNAL tool for parsing glTF document (JSON structure).
0055 class RWGltf_GltfJsonParser
0056 #ifdef HAVE_RAPIDJSON
0057 : public rapidjson::Document
0058 #endif
0059 {
0060 public:
0061 
0062 #ifdef HAVE_RAPIDJSON
0063   //! Auxiliary method for formatting error code.
0064   Standard_EXPORT static const char* FormatParseError (rapidjson::ParseErrorCode theCode);
0065 #endif
0066 
0067 public:
0068 
0069   //! Empty constructor.
0070   Standard_EXPORT RWGltf_GltfJsonParser (TopTools_SequenceOfShape& theRootShapes);
0071 
0072   //! Set file path.
0073   Standard_EXPORT void SetFilePath (const TCollection_AsciiString& theFilePath);
0074 
0075   //! Set flag for probing file without complete reading.
0076   void SetProbeHeader (bool theToProbe) { myToProbeHeader = theToProbe; }
0077 
0078   //! Return prefix for reporting issues.
0079   const TCollection_AsciiString& ErrorPrefix() const { return myErrorPrefix; }
0080 
0081   //! Set prefix for reporting issues.
0082   void SetErrorPrefix (const TCollection_AsciiString& theErrPrefix) { myErrorPrefix = theErrPrefix; }
0083 
0084   //! Set map for storing node attributes.
0085   void SetAttributeMap (RWMesh_NodeAttributeMap& theAttribMap) { myAttribMap = &theAttribMap; }
0086 
0087   //! Set list for storing external files.
0088   void SetExternalFiles (NCollection_IndexedMap<TCollection_AsciiString>& theExternalFiles) { myExternalFiles = &theExternalFiles; }
0089 
0090   //! Set metadata map.
0091   void SetMetadata (TColStd_IndexedDataMapOfStringString& theMetadata) { myMetadata = &theMetadata; }
0092 
0093   //! Set flag to translate asset.extras into metadata.
0094   void SetReadAssetExtras (bool theToRead) { myToReadAssetExtras = theToRead; }
0095 
0096   //! Return transformation from glTF to OCCT coordinate system.
0097   const RWMesh_CoordinateSystemConverter& CoordinateSystemConverter() const { return myCSTrsf; }
0098 
0099   //! Set transformation from glTF to OCCT coordinate system.
0100   void SetCoordinateSystemConverter (const RWMesh_CoordinateSystemConverter& theConverter) { myCSTrsf = theConverter; }
0101 
0102   //! Initialize binary format.
0103   void SetBinaryFormat (int64_t theBinBodyOffset,
0104                         int64_t theBinBodyLen)
0105   {
0106     myIsBinary      = true;
0107     myBinBodyOffset = theBinBodyOffset;
0108     myBinBodyLen    = theBinBodyLen;
0109   }
0110 
0111   //! Set flag to ignore nodes without Geometry, TRUE by default.
0112   void SetSkipEmptyNodes (bool theToSkip) { myToSkipEmptyNodes = theToSkip; }
0113 
0114   //! Set flag to flag to load all scenes in the document, FALSE by default which means only main (default) scene will be loaded.
0115   void SetLoadAllScenes (bool theToLoadAll) { myToLoadAllScenes = theToLoadAll; }
0116 
0117   //! Set flag to use Mesh name in case if Node name is empty, TRUE by default.
0118   void SetMeshNameAsFallback (bool theToFallback) { myUseMeshNameAsFallback = theToFallback; }
0119 
0120   //! Parse glTF document.
0121   Standard_EXPORT bool Parse (const Message_ProgressRange& theProgress);
0122 
0123   //! Return face list for loading triangulation.
0124   NCollection_Vector<TopoDS_Face>& FaceList() { return myFaceList; }
0125 
0126 protected:
0127 #ifdef HAVE_RAPIDJSON
0128   //! Search mandatory root elements in the document.
0129   //! Return FALSE if some mandatory element is missing.
0130   Standard_EXPORT bool gltfParseRoots();
0131 
0132   //! Parse default scene.
0133   Standard_EXPORT bool gltfParseScene (const Message_ProgressRange& theProgress);
0134 
0135   //! Parse document metadata.
0136   Standard_EXPORT void gltfParseAsset();
0137 
0138 protected:
0139 
0140   //! Parse materials defined in the document.
0141   Standard_EXPORT void gltfParseMaterials();
0142 
0143   //! Parse standard material.
0144   Standard_EXPORT bool gltfParseStdMaterial (Handle(RWGltf_MaterialCommon)& theMat,
0145                                              const RWGltf_JsonValue& theMatNode);
0146 
0147   //! Parse pbrMetallicRoughness material.
0148   Standard_EXPORT bool gltfParsePbrMaterial (Handle(RWGltf_MaterialMetallicRoughness)& theMat,
0149                                              const RWGltf_JsonValue& theMatNode);
0150 
0151   //! Parse common material (KHR_materials_common extension).
0152   Standard_EXPORT bool gltfParseCommonMaterial (Handle(RWGltf_MaterialCommon)& theMat,
0153                                                 const RWGltf_JsonValue& theMatNode);
0154 
0155   //! Parse texture definition.
0156   Standard_EXPORT bool gltfParseTexture (Handle(Image_Texture)& theTexture,
0157                                          const RWGltf_JsonValue* theTextureId);
0158 
0159   //! Parse texture definition in binary buffer of GLB file.
0160   Standard_EXPORT bool gltfParseTexturInGlbBuffer (Handle(Image_Texture)& theTexture,
0161                                                    const RWGltf_JsonValue& theBinVal,
0162                                                    const TCollection_AsciiString& theBufferViewId,
0163                                                    const RWGltf_JsonValue& theBufferViewName);
0164 
0165   //! Parse texture definition in binary buffer of glTF file.
0166   Standard_EXPORT bool gltfParseTextureInBufferView (Handle(Image_Texture)& theTexture,
0167                                                      const TCollection_AsciiString& theSourceId,
0168                                                      const TCollection_AsciiString& theBufferViewhId,
0169                                                      const RWGltf_JsonValue& theBufferView);
0170 
0171   //! Bind material definition to the map.
0172   Standard_EXPORT void gltfBindMaterial (const Handle(RWGltf_MaterialMetallicRoughness)& theMatPbr,
0173                                          const Handle(RWGltf_MaterialCommon)& theMatCommon);
0174 
0175 protected:
0176 
0177   //! Parse scene array of nodes recursively.
0178   Standard_EXPORT bool gltfParseSceneNodes (TopTools_SequenceOfShape& theShapeSeq,
0179                                             const RWGltf_JsonValue& theSceneNodes,
0180                                             const Message_ProgressRange& theProgress);
0181 
0182   //! Parse scene node recursively.
0183   Standard_EXPORT bool gltfParseSceneNode (TopoDS_Shape& theNodeShape,
0184                                            const TCollection_AsciiString& theSceneNodeId,
0185                                            const RWGltf_JsonValue& theSceneNode,
0186                                            const Message_ProgressRange& theProgress);
0187 
0188   //! Parse mesh element.
0189   Standard_EXPORT bool gltfParseMesh (TopoDS_Shape& theMeshShape,
0190                                       const TCollection_AsciiString& theMeshId,
0191                                       const RWGltf_JsonValue& theMesh);
0192 
0193   //! Parse primitive array.
0194   Standard_EXPORT bool gltfParsePrimArray (TopoDS_Shape& thePrimArrayShape,
0195                                            const TCollection_AsciiString& theMeshId,
0196                                            const TCollection_AsciiString& theMeshName,
0197                                            const RWGltf_JsonValue& thePrimArray);
0198 
0199   //! Parse accessor.
0200   Standard_EXPORT bool gltfParseAccessor (const Handle(RWGltf_GltfLatePrimitiveArray)& theMeshData,
0201                                           const TCollection_AsciiString& theName,
0202                                           const RWGltf_JsonValue& theAccessor,
0203                                           const RWGltf_GltfArrayType theType,
0204                                           const RWGltf_JsonValue* theCompBuffView);
0205 
0206   //! Parse buffer view.
0207   Standard_EXPORT bool gltfParseBufferView (const Handle(RWGltf_GltfLatePrimitiveArray)& theMeshData,
0208                                             const TCollection_AsciiString& theName,
0209                                             const RWGltf_JsonValue& theBufferView,
0210                                             const RWGltf_GltfAccessor& theAccessor,
0211                                             const RWGltf_GltfArrayType theType);
0212 
0213   //! Parse buffer.
0214   Standard_EXPORT bool gltfParseBuffer (const Handle(RWGltf_GltfLatePrimitiveArray)& theMeshData,
0215                                         const TCollection_AsciiString& theName,
0216                                         const RWGltf_JsonValue& theBuffer,
0217                                         const RWGltf_GltfAccessor&   theAccessor,
0218                                         const RWGltf_GltfBufferView& theView,
0219                                         const RWGltf_GltfArrayType   theType);
0220 
0221 protected:
0222 
0223   //! Read vec4 from specified item.
0224   static bool gltfReadVec4 (Graphic3d_Vec4d& theVec4,
0225                             const RWGltf_JsonValue* theVal)
0226   {
0227     if (theVal == NULL
0228     || !theVal->IsArray()
0229     ||  theVal->Size() != 4)
0230     {
0231       return false;
0232     }
0233 
0234     for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
0235     {
0236       const RWGltf_JsonValue& aGenVal = (*theVal)[aCompIter];
0237       if (!aGenVal.IsNumber())
0238       {
0239         return false;
0240       }
0241       theVec4[aCompIter] = aGenVal.GetDouble();
0242     }
0243     return true;
0244   }
0245 
0246   //! Validate color
0247   static bool validateColor4 (const Graphic3d_Vec4d& theVec)
0248   {
0249     return theVec.r() >= 0.0 && theVec.r() <= 1.0
0250         && theVec.g() >= 0.0 && theVec.g() <= 1.0
0251         && theVec.b() >= 0.0 && theVec.b() <= 1.0
0252         && theVec.a() >= 0.0 && theVec.a() <= 1.0;
0253   }
0254 
0255   //! Read vec3 from specified item.
0256   static bool gltfReadVec3 (Graphic3d_Vec3d& theVec3,
0257                             const RWGltf_JsonValue* theVal)
0258   {
0259     if (theVal == NULL
0260     || !theVal->IsArray()
0261     ||  theVal->Size() != 3)
0262     {
0263       return false;
0264     }
0265 
0266     for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
0267     {
0268       const RWGltf_JsonValue& aGenVal = (*theVal)[aCompIter];
0269       if (!aGenVal.IsNumber())
0270       {
0271         return false;
0272       }
0273       theVec3[aCompIter] = aGenVal.GetDouble();
0274     }
0275     return true;
0276   }
0277 
0278   //! Validate color
0279   static bool validateColor3 (const Graphic3d_Vec3d& theVec)
0280   {
0281     return theVec.r() >= 0.0 && theVec.r() <= 1.0
0282         && theVec.g() >= 0.0 && theVec.g() <= 1.0
0283         && theVec.b() >= 0.0 && theVec.b() <= 1.0;
0284   }
0285 
0286 protected:
0287 
0288   //! Groups for re-using shapes.
0289   enum ShapeMapGroup
0290   {
0291     ShapeMapGroup_Nodes,     //!< nodes
0292     ShapeMapGroup_Meshes,    //!< meshes
0293     ShapeMapGroup_PrimArray, //!< primitive array
0294   };
0295 
0296   //! Bind name attribute.
0297   void bindNodeShape (TopoDS_Shape& theShape,
0298                       const TopLoc_Location& theLoc,
0299                       const TCollection_AsciiString& theNodeId,
0300                       const RWGltf_JsonValue* theUserName)
0301   {
0302     bindNamedShape (theShape, ShapeMapGroup_Nodes, theLoc, theNodeId, theUserName);
0303   }
0304 
0305   //! Bind name attribute.
0306   void bindMeshShape (TopoDS_Shape& theShape,
0307                       const TCollection_AsciiString& theMeshId,
0308                       const RWGltf_JsonValue* theUserName)
0309   {
0310     bindNamedShape (theShape, ShapeMapGroup_Meshes, TopLoc_Location(), theMeshId, theUserName);
0311   }
0312 
0313   //! Find named shape.
0314   bool findNodeShape (TopoDS_Shape& theShape,
0315                       const TCollection_AsciiString& theNodeId) const
0316   {
0317     return findNamedShape (theShape, ShapeMapGroup_Nodes, theNodeId);
0318   }
0319 
0320   //! Find named shape.
0321   bool findMeshShape (TopoDS_Shape& theShape,
0322                       const TCollection_AsciiString& theMeshId) const
0323   {
0324     return findNamedShape (theShape, ShapeMapGroup_Meshes, theMeshId);
0325   }
0326 
0327   //! Bind name attribute.
0328   Standard_EXPORT void bindNamedShape (TopoDS_Shape& theShape,
0329                                        ShapeMapGroup theGroup,
0330                                        const TopLoc_Location& theLoc,
0331                                        const TCollection_AsciiString& theId,
0332                                        const RWGltf_JsonValue* theUserName);
0333 
0334   //! Find named shape.
0335   bool findNamedShape (TopoDS_Shape& theShape,
0336                        ShapeMapGroup theGroup,
0337                        const TCollection_AsciiString& theId) const
0338   {
0339     return myShapeMap[theGroup].Find (theId, theShape);
0340   }
0341 
0342   //! Return the string representation of the key.
0343   static TCollection_AsciiString getKeyString (const RWGltf_JsonValue& theValue)
0344   {
0345     if (theValue.IsString())
0346     {
0347       return TCollection_AsciiString (theValue.GetString());
0348     }
0349     else if (theValue.IsInt())
0350     {
0351       return TCollection_AsciiString (theValue.GetInt());
0352     }
0353     return TCollection_AsciiString();
0354   }
0355 
0356 protected:
0357 
0358   //! Auxiliary structure for fast look-up of document sub-nodes of specified node.
0359   class GltfElementMap
0360   {
0361   public:
0362 
0363     //! Empty constructor.
0364     GltfElementMap() : myRoot (NULL) {}
0365 
0366     //! Return TRUE if this element is NULL.
0367     bool IsNull() const { return myRoot == NULL; }
0368 
0369     //! Access this node.
0370     const RWGltf_JsonValue* Root() const { return myRoot; }
0371 
0372     //! Find the child node with specified key.
0373     const RWGltf_JsonValue* FindChild (const TCollection_AsciiString& theKey)
0374     {
0375       const RWGltf_JsonValue* aNode = NULL;
0376       return myChildren.Find (theKey, aNode)
0377            ? aNode
0378            : NULL;
0379     }
0380 
0381     //! Find the child node with specified key.
0382     const RWGltf_JsonValue* FindChild (const RWGltf_JsonValue& theKey)
0383     {
0384       const TCollection_AsciiString aKey = getKeyString (theKey);
0385       if (aKey.IsEmpty())
0386       {
0387         return NULL;
0388       }
0389 
0390       const RWGltf_JsonValue* aNode = NULL;
0391       return myChildren.Find (aKey, aNode)
0392            ? aNode
0393            : NULL;
0394     }
0395 
0396     //! Initialize the element.
0397     void Init (const TCollection_AsciiString& theRootName,
0398                const RWGltf_JsonValue* theRoot);
0399 
0400   private:
0401 
0402     NCollection_DataMap<TCollection_AsciiString, const RWGltf_JsonValue*> myChildren;
0403     const RWGltf_JsonValue* myRoot;
0404 
0405   };
0406 #endif
0407 protected:
0408 
0409   //! Print message about invalid glTF syntax.
0410   void reportGltfSyntaxProblem (const TCollection_AsciiString& theMsg, Message_Gravity theGravity);
0411 
0412 protected:
0413 
0414   TopTools_SequenceOfShape*        myRootShapes;    //!< sequence of result root shapes
0415   RWMesh_NodeAttributeMap*         myAttribMap;     //!< shape attributes
0416   NCollection_IndexedMap<TCollection_AsciiString>*
0417                                    myExternalFiles; //!< list of external file references
0418   RWMesh_CoordinateSystemConverter myCSTrsf;        //!< transformation from glTF to OCCT coordinate system
0419   TColStd_IndexedDataMapOfStringString* myMetadata; //!< file metadata
0420 
0421   NCollection_DataMap<TCollection_AsciiString, Handle(RWGltf_MaterialMetallicRoughness)> myMaterialsPbr;
0422   NCollection_DataMap<TCollection_AsciiString, Handle(RWGltf_MaterialCommon)> myMaterialsCommon;
0423   NCollection_DataMap<TCollection_AsciiString, Handle(XCAFDoc_VisMaterial)> myMaterials;
0424   NCollection_DataMap<TCollection_AsciiString, TopoDS_Shape> myShapeMap[3];
0425 
0426   NCollection_DataMap<TCollection_AsciiString, bool> myProbedFiles;
0427   NCollection_DataMap<TCollection_AsciiString, Handle(NCollection_Buffer)> myDecodedBuffers;
0428   NCollection_Vector<TopoDS_Face> myFaceList; //!< face list for loading triangulation
0429 
0430   TCollection_AsciiString   myFilePath;       //!< file path
0431   TCollection_AsciiString   myFolder;         //!< folder
0432   TCollection_AsciiString   myErrorPrefix;    //!< invalid syntax error prefix
0433   int64_t                   myBinBodyOffset;  //!< offset to binary body
0434   int64_t                   myBinBodyLen;     //!< binary body length
0435   bool                      myIsBinary;       //!< binary document
0436   bool                      myIsGltf1;        //!< obsolete glTF 1.0 version format
0437   bool                      myToSkipEmptyNodes; //!< ignore nodes without Geometry
0438   bool                      myToLoadAllScenes;  //!< flag to load all scenes in the document, FALSE by default
0439   bool                      myUseMeshNameAsFallback; //!< flag to use Mesh name in case if Node name is empty, TRUE by default
0440   bool                      myToProbeHeader;  //!< flag to probe header without full reading, FALSE by default
0441   bool                      myToReadAssetExtras; //!< flag to translate asset.extras into metadata, TRUE by default
0442 
0443 #ifdef HAVE_RAPIDJSON
0444   GltfElementMap myGltfRoots[RWGltf_GltfRootElement_NB]; //!< glTF format root elements
0445 #endif
0446 
0447 };
0448 
0449 #endif // _RWGltf_GltfJsonParser_HeaderFile