diff --git a/IO/Import/vtkGLTFImporter.cxx b/IO/Import/vtkGLTFImporter.cxx index f5197e6ba6988e94f49b7a6057e012143f331f99..43cd4fb94280fa0cf13d3bea871b8c32d3a57c44 100644 --- a/IO/Import/vtkGLTFImporter.cxx +++ b/IO/Import/vtkGLTFImporter.cxx @@ -403,9 +403,9 @@ void vtkGLTFImporter::InitializeLoader() int vtkGLTFImporter::ImportBegin() { // Make sure we have a file to read. - if (!this->FileName) + if (!this->Stream && !this->FileName) { - vtkErrorMacro("A FileName must be specified."); + vtkErrorMacro("Neither FileName nor Stream has been specified."); return 0; } @@ -422,21 +422,44 @@ int vtkGLTFImporter::ImportBegin() // Check extension std::vector<char> glbBuffer; - std::string extension = vtksys::SystemTools::GetFilenameLastExtension(this->FileName); - if (extension == ".glb") + if (this->Stream != nullptr) { - if (!this->Loader->LoadFileBuffer(this->FileName, glbBuffer)) + // this->Stream is defined. + if (this->StreamIsBinary) { - vtkErrorMacro("Error loading binary data"); + if (!this->Loader->LoadStreamBuffer(this->Stream, glbBuffer)) + { + vtkErrorMacro("Error loading binary data"); + return 0; + } + } + + if (!this->Loader->LoadModelMetaDataFromStream(this->Stream, this->StreamURILoader)) + { + vtkErrorMacro("Error loading model metadata"); return 0; } } - - if (!this->Loader->LoadModelMetaDataFromFile(this->FileName)) + else { - vtkErrorMacro("Error loading model metadata"); - return 0; + // this->FileName is defined. + std::string extension = vtksys::SystemTools::GetFilenameLastExtension(this->FileName); + if (extension == ".glb") + { + if (!this->Loader->LoadFileBuffer(this->FileName, glbBuffer)) + { + vtkErrorMacro("Error loading binary data"); + return 0; + } + } + + if (!this->Loader->LoadModelMetaDataFromFile(this->FileName)) + { + vtkErrorMacro("Error loading model metadata"); + return 0; + } } + if (!this->Loader->LoadModelData(glbBuffer)) { vtkErrorMacro("Error loading model data"); @@ -1037,7 +1060,16 @@ bool vtkGLTFImporter::GetTemporalInformation(vtkIdType animationIndex, double fr void vtkGLTFImporter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); - os << indent << "File Name: " << (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent; + if (this->Stream != nullptr) + { + os << "Stream (" << (this->StreamIsBinary ? "binary" : "ascii") << ")"; + } + else + { + os << "File Name: " << (this->FileName ? this->FileName : "(none)"); + } + os << "\n"; } //------------------------------------------------------------------------------ diff --git a/IO/Import/vtkGLTFImporter.h b/IO/Import/vtkGLTFImporter.h index 239d1d7fb75aa01a2a609d2144dbb2e387543cc4..c242f2a6f6a4facc8ebbb7fcb439994b8318fddd 100644 --- a/IO/Import/vtkGLTFImporter.h +++ b/IO/Import/vtkGLTFImporter.h @@ -51,16 +51,22 @@ #include "vtkIOImportModule.h" // For export macro #include "vtkImporter.h" -#include "vtkSmartPointer.h" // For SmartPointer +#include "vtkResourceStream.h" // For Stream +#include "vtkSmartPointer.h" // For SmartPointer +#include "vtkURILoader.h" // For URILoader #include <map> // For map #include <vector> // For vector VTK_ABI_NAMESPACE_BEGIN + +// Forward declarations class vtkActor; class vtkCamera; class vtkGLTFDocumentLoader; +class vtkResourceStream; class vtkTexture; +class vtkURILoader; class VTKIOIMPORT_EXPORT vtkGLTFImporter : public vtkImporter { @@ -78,6 +84,40 @@ public: vtkGetFilePathMacro(FileName); ///@} + ///@{ + /** + * Specify the glTF source stream to read from. When selecting the input method, `Stream` has a + * higher priority than `FileName` i.e. if a stream is provided, the filename is ignored. + * + * \note If the stream contains non-data URIs, specifying a custom uri loader is crucial. + * \sa SetStreamURILoader() + * + * \sa SetStreamIsBinary() + */ + vtkSetSmartPointerMacro(Stream, vtkResourceStream); + vtkGetSmartPointerMacro(Stream, vtkResourceStream); + ///@} + + ///@{ + /** + * Specify a custom URI loader for non-data URIs in the input stream. + * \sa SetStream(), SetStreamIsBinary() + */ + vtkSetSmartPointerMacro(StreamURILoader, vtkURILoader); + vtkGetSmartPointerMacro(StreamURILoader, vtkURILoader); + ///@} + + ///@{ + /** + * Set/Get whether the input stream is binary + * + * \sa SetStream() + */ + vtkSetMacro(StreamIsBinary, bool); + vtkGetMacro(StreamIsBinary, bool); + vtkBooleanMacro(StreamIsBinary, bool); + ///@} + /** * glTF defines multiple camera objects, but no default behavior for which camera should be * used. The importer will by default apply the asset's first camera. This accessor lets you use @@ -167,6 +207,9 @@ protected: virtual void ApplyArmatureProperties(vtkActor* actor); char* FileName = nullptr; + vtkSmartPointer<vtkResourceStream> Stream; + vtkSmartPointer<vtkURILoader> StreamURILoader; + bool StreamIsBinary = false; std::map<int, vtkSmartPointer<vtkCamera>> Cameras; std::map<int, vtkSmartPointer<vtkTexture>> Textures;