diff --git a/.gitignore b/.gitignore index fd49a43b7..723ddc52e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ CMakeSettings.json *.user .cache *.DS_Store +test.db diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ae672a72..4f0371166 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,6 +132,7 @@ add_subdirectory(CesiumGltfWriter) add_subdirectory(CesiumGltfReader) add_subdirectory(CesiumAsync) add_subdirectory(Cesium3DTiles) +add_subdirectory(Cesium3DTilesReader) add_subdirectory(Cesium3DTilesSelection) add_subdirectory(CesiumIonClient) diff --git a/Cesium3DTilesReader/CMakeLists.txt b/Cesium3DTilesReader/CMakeLists.txt new file mode 100644 index 000000000..00bb26e55 --- /dev/null +++ b/Cesium3DTilesReader/CMakeLists.txt @@ -0,0 +1,51 @@ +add_library(Cesium3DTilesReader "") +configure_cesium_library(Cesium3DTilesReader) + +cesium_glob_files(CESIUM_3DTILES_READER_SOURCES src/*.cpp generated/*.cpp) +cesium_glob_files(CESIUM_3DTILES_READER_HEADERS src/*.h src/*.hpp generated/*.h generated/*.hpp) +cesium_glob_files(CESIUM_3DTILES_READER_PUBLIC_HEADERS include/Cesium3DTiles/*.h) # Correct is Cesium3DTiles not Cesium3DTilesReader +cesium_glob_files(CESIUM_3DTILES_READER_TEST_SOURCES test/*.cpp) +cesium_glob_files(CESIUM_3DTILES_READER_TEST_HEADERS test/*.h) + +set_target_properties(Cesium3DTilesReader + PROPERTIES + TEST_SOURCES "${CESIUM_3DTILES_READER_TEST_SOURCES}" + TEST_HEADERS "${CESIUM_3DTILES_READER_TEST_HEADERS}" + TEST_DATA_DIR ${CMAKE_CURRENT_LIST_DIR}/test/data +) + +set_target_properties(Cesium3DTilesReader + PROPERTIES + PUBLIC_HEADER "${CESIUM_3DTILES_READER_PUBLIC_HEADERS}" +) + +target_sources( + Cesium3DTilesReader + PRIVATE + ${CESIUM_3DTILES_READER_SOURCES} + ${CESIUM_3DTILES_READER_HEADERS} + PUBLIC + ${CESIUM_3DTILES_READER_PUBLIC_HEADERS} +) + +target_include_directories( + Cesium3DTilesReader + SYSTEM PUBLIC + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_LIST_DIR}/include + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/src + ${CMAKE_CURRENT_LIST_DIR}/generated +) + +target_link_libraries(Cesium3DTilesReader + PUBLIC + Cesium3DTiles + CesiumJsonReader + GSL +) + +install(TARGETS Cesium3DTilesReader + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/Cesium3DTiles # Correct is Cesium3DTiles not Cesium3DTilesReader +) diff --git a/Cesium3DTilesReader/generated/AssetJsonHandler.h b/Cesium3DTilesReader/generated/AssetJsonHandler.h new file mode 100644 index 000000000..ac4dc4b16 --- /dev/null +++ b/Cesium3DTilesReader/generated/AssetJsonHandler.h @@ -0,0 +1,33 @@ +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Asset.h" +#include "Cesium3DTiles/ReaderContext.h" +#include "CesiumJsonReader/StringJsonHandler.h" +#include "ExtensibleObjectJsonHandler.h" + +namespace Cesium3DTiles { +struct ReaderContext; + +class AssetJsonHandler : public ExtensibleObjectJsonHandler { +public: + using ValueType = Asset; + + AssetJsonHandler(const ReaderContext& context) noexcept; + void reset(IJsonHandler* pParentHandler, Asset* pObject); + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +protected: + IJsonHandler* readObjectKeyAsset( + const std::string& objectType, + const std::string_view& str, + Asset& o); + +private: + Asset* _pObject = nullptr; + CesiumJsonReader::StringJsonHandler _version; + CesiumJsonReader::StringJsonHandler _tilesetVersion; +}; +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/generated/BoundingVolumeJsonHandler.h b/Cesium3DTilesReader/generated/BoundingVolumeJsonHandler.h new file mode 100644 index 000000000..12ac6a55f --- /dev/null +++ b/Cesium3DTilesReader/generated/BoundingVolumeJsonHandler.h @@ -0,0 +1,41 @@ +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/BoundingVolume.h" +#include "Cesium3DTiles/ReaderContext.h" +#include "CesiumJsonReader/ArrayJsonHandler.h" +#include "CesiumJsonReader/DoubleJsonHandler.h" +#include "ExtensibleObjectJsonHandler.h" + +namespace Cesium3DTiles { +struct ReaderContext; + +class BoundingVolumeJsonHandler : public ExtensibleObjectJsonHandler { +public: + using ValueType = BoundingVolume; + + BoundingVolumeJsonHandler(const ReaderContext& context) noexcept; + void reset(IJsonHandler* pParentHandler, BoundingVolume* pObject); + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +protected: + IJsonHandler* readObjectKeyBoundingVolume( + const std::string& objectType, + const std::string_view& str, + BoundingVolume& o); + +private: + BoundingVolume* _pObject = nullptr; + CesiumJsonReader:: + ArrayJsonHandler + _box; + CesiumJsonReader:: + ArrayJsonHandler + _region; + CesiumJsonReader:: + ArrayJsonHandler + _sphere; +}; +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/generated/ContentJsonHandler.h b/Cesium3DTilesReader/generated/ContentJsonHandler.h new file mode 100644 index 000000000..d7cb8bd89 --- /dev/null +++ b/Cesium3DTilesReader/generated/ContentJsonHandler.h @@ -0,0 +1,34 @@ +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "BoundingVolumeJsonHandler.h" +#include "Cesium3DTiles/Content.h" +#include "Cesium3DTiles/ReaderContext.h" +#include "CesiumJsonReader/StringJsonHandler.h" +#include "ExtensibleObjectJsonHandler.h" + +namespace Cesium3DTiles { +struct ReaderContext; + +class ContentJsonHandler : public ExtensibleObjectJsonHandler { +public: + using ValueType = Content; + + ContentJsonHandler(const ReaderContext& context) noexcept; + void reset(IJsonHandler* pParentHandler, Content* pObject); + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +protected: + IJsonHandler* readObjectKeyContent( + const std::string& objectType, + const std::string_view& str, + Content& o); + +private: + Content* _pObject = nullptr; + BoundingVolumeJsonHandler _boundingVolume; + CesiumJsonReader::StringJsonHandler _uri; +}; +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/generated/GeneratedJsonHandlers.cpp b/Cesium3DTilesReader/generated/GeneratedJsonHandlers.cpp new file mode 100644 index 000000000..0e699e79d --- /dev/null +++ b/Cesium3DTilesReader/generated/GeneratedJsonHandlers.cpp @@ -0,0 +1,282 @@ +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#include "Cesium3DTiles/Tileset.h" +#include "TilesetJsonHandler.h" + +#include +#include + +using namespace Cesium3DTiles; + +TilesetJsonHandler::TilesetJsonHandler(const ReaderContext& context) noexcept + : ExtensibleObjectJsonHandler(context), + _asset(context), + _properties(context), + _geometricError(), + _root(context), + _extensionsUsed(), + _extensionsRequired() {} + +void TilesetJsonHandler::reset( + CesiumJsonReader::IJsonHandler* pParentHandler, + Tileset* pObject) { + ExtensibleObjectJsonHandler::reset(pParentHandler, pObject); + this->_pObject = pObject; +} + +CesiumJsonReader::IJsonHandler* +TilesetJsonHandler::readObjectKey(const std::string_view& str) { + assert(this->_pObject); + return this->readObjectKeyTileset(Tileset::TypeName, str, *this->_pObject); +} + +CesiumJsonReader::IJsonHandler* TilesetJsonHandler::readObjectKeyTileset( + const std::string& objectType, + const std::string_view& str, + Tileset& o) { + using namespace std::string_literals; + + if ("asset"s == str) + return property("asset", this->_asset, o.asset); + if ("properties"s == str) + return property("properties", this->_properties, o.properties); + if ("geometricError"s == str) + return property("geometricError", this->_geometricError, o.geometricError); + if ("root"s == str) + return property("root", this->_root, o.root); + if ("extensionsUsed"s == str) + return property("extensionsUsed", this->_extensionsUsed, o.extensionsUsed); + if ("extensionsRequired"s == str) + return property( + "extensionsRequired", + this->_extensionsRequired, + o.extensionsRequired); + + return this->readObjectKeyExtensibleObject(objectType, str, *this->_pObject); +} +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#include "Cesium3DTiles/Tile.h" +#include "TileJsonHandler.h" + +#include +#include + +using namespace Cesium3DTiles; + +TileJsonHandler::TileJsonHandler(const ReaderContext& context) noexcept + : ExtensibleObjectJsonHandler(context), + _boundingVolume(context), + _viewerRequestVolume(context), + _geometricError(), + _refine(), + _transform(), + _content(context), + _children(context) {} + +void TileJsonHandler::reset( + CesiumJsonReader::IJsonHandler* pParentHandler, + Tile* pObject) { + ExtensibleObjectJsonHandler::reset(pParentHandler, pObject); + this->_pObject = pObject; +} + +CesiumJsonReader::IJsonHandler* +TileJsonHandler::readObjectKey(const std::string_view& str) { + assert(this->_pObject); + return this->readObjectKeyTile(Tile::TypeName, str, *this->_pObject); +} + +CesiumJsonReader::IJsonHandler* TileJsonHandler::readObjectKeyTile( + const std::string& objectType, + const std::string_view& str, + Tile& o) { + using namespace std::string_literals; + + if ("boundingVolume"s == str) + return property("boundingVolume", this->_boundingVolume, o.boundingVolume); + if ("viewerRequestVolume"s == str) + return property( + "viewerRequestVolume", + this->_viewerRequestVolume, + o.viewerRequestVolume); + if ("geometricError"s == str) + return property("geometricError", this->_geometricError, o.geometricError); + if ("refine"s == str) + return property("refine", this->_refine, o.refine); + if ("transform"s == str) + return property("transform", this->_transform, o.transform); + if ("content"s == str) + return property("content", this->_content, o.content); + if ("children"s == str) + return property("children", this->_children, o.children); + + return this->readObjectKeyExtensibleObject(objectType, str, *this->_pObject); +} +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#include "Cesium3DTiles/Content.h" +#include "ContentJsonHandler.h" + +#include +#include + +using namespace Cesium3DTiles; + +ContentJsonHandler::ContentJsonHandler(const ReaderContext& context) noexcept + : ExtensibleObjectJsonHandler(context), _boundingVolume(context), _uri() {} + +void ContentJsonHandler::reset( + CesiumJsonReader::IJsonHandler* pParentHandler, + Content* pObject) { + ExtensibleObjectJsonHandler::reset(pParentHandler, pObject); + this->_pObject = pObject; +} + +CesiumJsonReader::IJsonHandler* +ContentJsonHandler::readObjectKey(const std::string_view& str) { + assert(this->_pObject); + return this->readObjectKeyContent(Content::TypeName, str, *this->_pObject); +} + +CesiumJsonReader::IJsonHandler* ContentJsonHandler::readObjectKeyContent( + const std::string& objectType, + const std::string_view& str, + Content& o) { + using namespace std::string_literals; + + if ("boundingVolume"s == str) + return property("boundingVolume", this->_boundingVolume, o.boundingVolume); + if ("uri"s == str) + return property("uri", this->_uri, o.uri); + + return this->readObjectKeyExtensibleObject(objectType, str, *this->_pObject); +} +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#include "BoundingVolumeJsonHandler.h" +#include "Cesium3DTiles/BoundingVolume.h" + +#include +#include + +using namespace Cesium3DTiles; + +BoundingVolumeJsonHandler::BoundingVolumeJsonHandler( + const ReaderContext& context) noexcept + : ExtensibleObjectJsonHandler(context), _box(), _region(), _sphere() {} + +void BoundingVolumeJsonHandler::reset( + CesiumJsonReader::IJsonHandler* pParentHandler, + BoundingVolume* pObject) { + ExtensibleObjectJsonHandler::reset(pParentHandler, pObject); + this->_pObject = pObject; +} + +CesiumJsonReader::IJsonHandler* +BoundingVolumeJsonHandler::readObjectKey(const std::string_view& str) { + assert(this->_pObject); + return this->readObjectKeyBoundingVolume( + BoundingVolume::TypeName, + str, + *this->_pObject); +} + +CesiumJsonReader::IJsonHandler* +BoundingVolumeJsonHandler::readObjectKeyBoundingVolume( + const std::string& objectType, + const std::string_view& str, + BoundingVolume& o) { + using namespace std::string_literals; + + if ("box"s == str) + return property("box", this->_box, o.box); + if ("region"s == str) + return property("region", this->_region, o.region); + if ("sphere"s == str) + return property("sphere", this->_sphere, o.sphere); + + return this->readObjectKeyExtensibleObject(objectType, str, *this->_pObject); +} +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#include "Cesium3DTiles/Properties.h" +#include "PropertiesJsonHandler.h" + +#include +#include + +using namespace Cesium3DTiles; + +PropertiesJsonHandler::PropertiesJsonHandler( + const ReaderContext& context) noexcept + : ExtensibleObjectJsonHandler(context), _maximum(), _minimum() {} + +void PropertiesJsonHandler::reset( + CesiumJsonReader::IJsonHandler* pParentHandler, + Properties* pObject) { + ExtensibleObjectJsonHandler::reset(pParentHandler, pObject); + this->_pObject = pObject; +} + +CesiumJsonReader::IJsonHandler* +PropertiesJsonHandler::readObjectKey(const std::string_view& str) { + assert(this->_pObject); + return this->readObjectKeyProperties( + Properties::TypeName, + str, + *this->_pObject); +} + +CesiumJsonReader::IJsonHandler* PropertiesJsonHandler::readObjectKeyProperties( + const std::string& objectType, + const std::string_view& str, + Properties& o) { + using namespace std::string_literals; + + if ("maximum"s == str) + return property("maximum", this->_maximum, o.maximum); + if ("minimum"s == str) + return property("minimum", this->_minimum, o.minimum); + + return this->readObjectKeyExtensibleObject(objectType, str, *this->_pObject); +} +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#include "AssetJsonHandler.h" +#include "Cesium3DTiles/Asset.h" + +#include +#include + +using namespace Cesium3DTiles; + +AssetJsonHandler::AssetJsonHandler(const ReaderContext& context) noexcept + : ExtensibleObjectJsonHandler(context), _version(), _tilesetVersion() {} + +void AssetJsonHandler::reset( + CesiumJsonReader::IJsonHandler* pParentHandler, + Asset* pObject) { + ExtensibleObjectJsonHandler::reset(pParentHandler, pObject); + this->_pObject = pObject; +} + +CesiumJsonReader::IJsonHandler* +AssetJsonHandler::readObjectKey(const std::string_view& str) { + assert(this->_pObject); + return this->readObjectKeyAsset(Asset::TypeName, str, *this->_pObject); +} + +CesiumJsonReader::IJsonHandler* AssetJsonHandler::readObjectKeyAsset( + const std::string& objectType, + const std::string_view& str, + Asset& o) { + using namespace std::string_literals; + + if ("version"s == str) + return property("version", this->_version, o.version); + if ("tilesetVersion"s == str) + return property("tilesetVersion", this->_tilesetVersion, o.tilesetVersion); + + return this->readObjectKeyExtensibleObject(objectType, str, *this->_pObject); +} diff --git a/Cesium3DTilesReader/generated/PropertiesJsonHandler.h b/Cesium3DTilesReader/generated/PropertiesJsonHandler.h new file mode 100644 index 000000000..828825b23 --- /dev/null +++ b/Cesium3DTilesReader/generated/PropertiesJsonHandler.h @@ -0,0 +1,33 @@ +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Properties.h" +#include "Cesium3DTiles/ReaderContext.h" +#include "CesiumJsonReader/DoubleJsonHandler.h" +#include "ExtensibleObjectJsonHandler.h" + +namespace Cesium3DTiles { +struct ReaderContext; + +class PropertiesJsonHandler : public ExtensibleObjectJsonHandler { +public: + using ValueType = Properties; + + PropertiesJsonHandler(const ReaderContext& context) noexcept; + void reset(IJsonHandler* pParentHandler, Properties* pObject); + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +protected: + IJsonHandler* readObjectKeyProperties( + const std::string& objectType, + const std::string_view& str, + Properties& o); + +private: + Properties* _pObject = nullptr; + CesiumJsonReader::DoubleJsonHandler _maximum; + CesiumJsonReader::DoubleJsonHandler _minimum; +}; +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/generated/TileJsonHandler.h b/Cesium3DTilesReader/generated/TileJsonHandler.h new file mode 100644 index 000000000..fd45897de --- /dev/null +++ b/Cesium3DTilesReader/generated/TileJsonHandler.h @@ -0,0 +1,44 @@ +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "BoundingVolumeJsonHandler.h" +#include "Cesium3DTiles/ReaderContext.h" +#include "Cesium3DTiles/Tile.h" +#include "CesiumJsonReader/ArrayJsonHandler.h" +#include "CesiumJsonReader/DoubleJsonHandler.h" +#include "CesiumJsonReader/StringJsonHandler.h" +#include "ContentJsonHandler.h" +#include "ExtensibleObjectJsonHandler.h" + +namespace Cesium3DTiles { +struct ReaderContext; + +class TileJsonHandler : public ExtensibleObjectJsonHandler { +public: + using ValueType = Tile; + + TileJsonHandler(const ReaderContext& context) noexcept; + void reset(IJsonHandler* pParentHandler, Tile* pObject); + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +protected: + IJsonHandler* readObjectKeyTile( + const std::string& objectType, + const std::string_view& str, + Tile& o); + +private: + Tile* _pObject = nullptr; + BoundingVolumeJsonHandler _boundingVolume; + BoundingVolumeJsonHandler _viewerRequestVolume; + CesiumJsonReader::DoubleJsonHandler _geometricError; + CesiumJsonReader::StringJsonHandler _refine; + CesiumJsonReader:: + ArrayJsonHandler + _transform; + ContentJsonHandler _content; + CesiumJsonReader::ArrayJsonHandler _children; +}; +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/generated/TilesetJsonHandler.h b/Cesium3DTilesReader/generated/TilesetJsonHandler.h new file mode 100644 index 000000000..e9a27ecbb --- /dev/null +++ b/Cesium3DTilesReader/generated/TilesetJsonHandler.h @@ -0,0 +1,48 @@ +// This file was generated by generate-gltf-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "AssetJsonHandler.h" +#include "Cesium3DTiles/ReaderContext.h" +#include "Cesium3DTiles/Tileset.h" +#include "CesiumJsonReader/ArrayJsonHandler.h" +#include "CesiumJsonReader/DictionaryJsonHandler.h" +#include "CesiumJsonReader/DoubleJsonHandler.h" +#include "CesiumJsonReader/StringJsonHandler.h" +#include "ExtensibleObjectJsonHandler.h" +#include "PropertiesJsonHandler.h" +#include "TileJsonHandler.h" + +namespace Cesium3DTiles { +struct ReaderContext; + +class TilesetJsonHandler : public ExtensibleObjectJsonHandler { +public: + using ValueType = Tileset; + + TilesetJsonHandler(const ReaderContext& context) noexcept; + void reset(IJsonHandler* pParentHandler, Tileset* pObject); + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +protected: + IJsonHandler* readObjectKeyTileset( + const std::string& objectType, + const std::string_view& str, + Tileset& o); + +private: + Tileset* _pObject = nullptr; + AssetJsonHandler _asset; + CesiumJsonReader::DictionaryJsonHandler + _properties; + CesiumJsonReader::DoubleJsonHandler _geometricError; + TileJsonHandler _root; + CesiumJsonReader:: + ArrayJsonHandler + _extensionsUsed; + CesiumJsonReader:: + ArrayJsonHandler + _extensionsRequired; +}; +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/include/Cesium3DTiles/IExtensionJsonHandler.h b/Cesium3DTilesReader/include/Cesium3DTiles/IExtensionJsonHandler.h new file mode 100644 index 000000000..204c77e89 --- /dev/null +++ b/Cesium3DTilesReader/include/Cesium3DTiles/IExtensionJsonHandler.h @@ -0,0 +1,20 @@ +#pragma once + +#include "CesiumJsonReader/IJsonHandler.h" + +#include +#include + +namespace Cesium3DTiles { + +struct ExtensibleObject; + +class IExtensionJsonHandler : public CesiumJsonReader::IJsonHandler { +public: + virtual void reset( + IJsonHandler* pParentHandler, + ExtensibleObject& o, + const std::string_view& extensionName) = 0; +}; + +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/include/Cesium3DTiles/ReaderContext.h b/Cesium3DTilesReader/include/Cesium3DTiles/ReaderContext.h new file mode 100644 index 000000000..3b75efd26 --- /dev/null +++ b/Cesium3DTilesReader/include/Cesium3DTiles/ReaderContext.h @@ -0,0 +1,11 @@ +#pragma once + +namespace Cesium3DTiles { + +class TilesetReader; + +struct ReaderContext { + const TilesetReader& reader; +}; + +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/include/Cesium3DTiles/ReaderLibrary.h b/Cesium3DTilesReader/include/Cesium3DTiles/ReaderLibrary.h new file mode 100644 index 000000000..d8a0d4853 --- /dev/null +++ b/Cesium3DTilesReader/include/Cesium3DTiles/ReaderLibrary.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUM3DTILESREADER_BUILDING +#define CESIUM3DTILESREADER_API __declspec(dllexport) +#else +#define CESIUM3DTILESREADER_API __declspec(dllimport) +#endif +#else +#define CESIUM3DTILESREADER_API +#endif diff --git a/Cesium3DTilesReader/include/Cesium3DTiles/TilesetReader.h b/Cesium3DTilesReader/include/Cesium3DTiles/TilesetReader.h new file mode 100644 index 000000000..9e2d288c7 --- /dev/null +++ b/Cesium3DTilesReader/include/Cesium3DTiles/TilesetReader.h @@ -0,0 +1,178 @@ +#pragma once + +#include "Cesium3DTiles/IExtensionJsonHandler.h" +#include "Cesium3DTiles/ReaderLibrary.h" +#include "Cesium3DTiles/Tileset.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Cesium3DTiles { + +struct ReaderContext; + +/** + * @brief The result of reading a tileset with + * {@link TilesetReader::readTileset}. + */ +struct CESIUM3DTILESREADER_API TilesetReaderResult { + /** + * @brief The read tileset, or std::nullopt if the tileset could not be read. + */ + std::optional tileset; + + /** + * @brief Errors, if any, that occurred during the load process. + */ + std::vector errors; + + /** + * @brief Warnings, if any, that occurred during the load process. + */ + std::vector warnings; +}; + +/** + * @brief The state of a tileset extension. + */ +enum class ExtensionState { + /** + * @brief The extension is enabled. + * + * If a statically-typed class is available for the extension, it will be + * used. Otherwise the extension will be represented as a + * {@link CesiumUtility::JsonValue}. + */ + Enabled, + + /** + * @brief The extension is enabled but will always be deserialized as a + * {@link CesiumUtility::JsonValue}. + * + * Even if a statically-typed class is available for the extension, it will + * not be used. + */ + JsonOnly, + + /** + * @brief The extension is disabled. + * + * It will not be represented in the loaded tileset at all. + */ + Disabled +}; + +/** + * @brief Options for how to read a tileset. + */ +struct CESIUM3DTILESREADER_API ReadTilesetOptions { + // TODO +}; + +/** + * @brief Reads tilesets. + */ +class CESIUM3DTILESREADER_API TilesetReader { +public: + /** + * @brief Constructs a new instance. + */ + TilesetReader(); + + /** + * @brief Registers an extension for a tileset object. + * + * @tparam TExtended The tileset object to extend. + * @tparam TExtensionHandler The extension's + * {@link CesiumJsonReader::JsonHandler}. + * @param extensionName The name of the extension. + */ + template + void registerExtension(const std::string& extensionName) { + auto it = + this->_extensions.emplace(extensionName, ObjectTypeToHandler()).first; + it->second.insert_or_assign( + TExtended::TypeName, + ExtensionReaderFactory([](const ReaderContext& context) { + return std::make_unique(context); + })); + } + + /** + * @brief Registers an extension for a tileset object. + * + * The extension name is obtained from `TExtensionHandler::ExtensionName`. + * + * @tparam TExtended The tileset object to extend. + * @tparam TExtensionHandler The extension's + * {@link CesiumJsonReader::JsonHandler}. + */ + template + void registerExtension() { + auto it = + this->_extensions + .emplace(TExtensionHandler::ExtensionName, ObjectTypeToHandler()) + .first; + it->second.insert_or_assign( + TExtended::TypeName, + ExtensionHandlerFactory([](const ReaderContext& context) { + return std::make_unique(context); + })); + } + + /** + * @brief Enables or disables a tileset extension. + * + * By default, all extensions are enabled. When an enabled extension is + * encountered in the source tileset, it is read into a statically-typed + * extension class, if one is registered, or into a + * {@link CesiumUtility::JsonValue} if not. + * + * When a disabled extension is encountered in the source tileset, it is + * ignored completely. + * + * An extension may also be set to `ExtensionState::JsonOnly`, in which case + * it will be read into a {@link CesiumUtility::JsonValue} even if a + * statically-typed extension class is registered. + * + * @param extensionName The name of the extension to be enabled or disabled. + * @param newState The new state for the extension. + */ + void + setExtensionState(const std::string& extensionName, ExtensionState newState); + + /** + * @brief Reads a tileset. + * + * @param data The buffer from which to read the tileset. + * @param options Options for how to read the tileset. + * @return The result of reading the tileset. + */ + TilesetReaderResult readTileset( + const gsl::span& data, + const ReadTilesetOptions& options = ReadTilesetOptions()) const; + + std::unique_ptr createExtensionHandler( + const ReaderContext& context, + const std::string_view& extensionName, + const std::string& extendedObjectType) const; + +private: + using ExtensionHandlerFactory = + std::function( + const ReaderContext&)>; + using ObjectTypeToHandler = std::map; + using ExtensionNameMap = std::map; + + ExtensionNameMap _extensions; + std::unordered_map _extensionStates; +}; + +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/src/ExtensibleObjectJsonHandler.cpp b/Cesium3DTilesReader/src/ExtensibleObjectJsonHandler.cpp new file mode 100644 index 000000000..c4c436295 --- /dev/null +++ b/Cesium3DTilesReader/src/ExtensibleObjectJsonHandler.cpp @@ -0,0 +1,36 @@ +#include "ExtensibleObjectJsonHandler.h" + +#include "Cesium3DTiles/ExtensibleObject.h" +#include "CesiumJsonReader/JsonHandler.h" +#include "CesiumJsonReader/ObjectJsonHandler.h" +#include "ExtensionsJsonHandler.h" + +using namespace Cesium3DTiles; +using namespace CesiumJsonReader; + +ExtensibleObjectJsonHandler::ExtensibleObjectJsonHandler( + const ReaderContext& context) noexcept + : ObjectJsonHandler(), _extras(), _extensions(context) {} + +void ExtensibleObjectJsonHandler::reset( + IJsonHandler* pParent, + ExtensibleObject* /*pObject*/) { + ObjectJsonHandler::reset(pParent); +} + +IJsonHandler* ExtensibleObjectJsonHandler::readObjectKeyExtensibleObject( + const std::string& objectType, + const std::string_view& str, + ExtensibleObject& o) { + using namespace std::string_literals; + + if ("extras"s == str) + return property("extras", this->_extras, o.extras); + + if ("extensions"s == str) { + this->_extensions.reset(this, &o, objectType); + return &this->_extensions; + } + + return this->ignoreAndContinue(); +} diff --git a/Cesium3DTilesReader/src/ExtensibleObjectJsonHandler.h b/Cesium3DTilesReader/src/ExtensibleObjectJsonHandler.h new file mode 100644 index 000000000..64d5cc5a6 --- /dev/null +++ b/Cesium3DTilesReader/src/ExtensibleObjectJsonHandler.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Cesium3DTiles/ReaderContext.h" +#include "CesiumJsonReader/DictionaryJsonHandler.h" +#include "CesiumJsonReader/JsonObjectJsonHandler.h" +#include "CesiumJsonReader/ObjectJsonHandler.h" +#include "CesiumUtility/JsonValue.h" +#include "ExtensionsJsonHandler.h" + +namespace Cesium3DTiles { +struct ExtensibleObject; + +class ExtensibleObjectJsonHandler : public CesiumJsonReader::ObjectJsonHandler { +public: + ExtensibleObjectJsonHandler(const ReaderContext& context) noexcept; + +protected: + void reset(IJsonHandler* pParent, ExtensibleObject* pObject); + IJsonHandler* readObjectKeyExtensibleObject( + const std::string& objectType, + const std::string_view& str, + ExtensibleObject& o); + +private: + CesiumJsonReader::DictionaryJsonHandler< + CesiumUtility::JsonValue, + CesiumJsonReader::JsonObjectJsonHandler> + _extras; + ExtensionsJsonHandler _extensions; +}; +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/src/ExtensionsJsonHandler.cpp b/Cesium3DTilesReader/src/ExtensionsJsonHandler.cpp new file mode 100644 index 000000000..0a8553f03 --- /dev/null +++ b/Cesium3DTilesReader/src/ExtensionsJsonHandler.cpp @@ -0,0 +1,33 @@ +#include "ExtensionsJsonHandler.h" + +#include "Cesium3DTiles/ReaderContext.h" +#include "Cesium3DTiles/TilesetReader.h" + +using namespace Cesium3DTiles; +using namespace CesiumJsonReader; + +void ExtensionsJsonHandler::reset( + IJsonHandler* pParent, + ExtensibleObject* pObject, + const std::string& objectType) { + ObjectJsonHandler::reset(pParent); + this->_pObject = pObject; + + if (this->_objectType != objectType) { + this->_objectType = objectType; + } +} + +IJsonHandler* +ExtensionsJsonHandler::readObjectKey(const std::string_view& str) { + this->_currentExtensionHandler = this->_context.reader.createExtensionHandler( + this->_context, + str, + this->_objectType); + if (this->_currentExtensionHandler) { + this->_currentExtensionHandler->reset(this, *this->_pObject, str); + return this->_currentExtensionHandler.get(); + } else { + return this->ignoreAndContinue(); + } +} diff --git a/Cesium3DTilesReader/src/ExtensionsJsonHandler.h b/Cesium3DTilesReader/src/ExtensionsJsonHandler.h new file mode 100644 index 000000000..5885d8eb7 --- /dev/null +++ b/Cesium3DTilesReader/src/ExtensionsJsonHandler.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Cesium3DTiles/IExtensionJsonHandler.h" +#include "CesiumJsonReader/ObjectJsonHandler.h" + +#include + +namespace Cesium3DTiles { +struct ReaderContext; +struct ExtensibleObject; + +class ExtensionsJsonHandler : public CesiumJsonReader::ObjectJsonHandler { +public: + ExtensionsJsonHandler(const ReaderContext& context) noexcept + : ObjectJsonHandler(), + _context(context), + _pObject(nullptr), + _currentExtensionHandler() {} + + void reset( + IJsonHandler* pParent, + ExtensibleObject* pObject, + const std::string& objectType); + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +private: + const ReaderContext& _context; + ExtensibleObject* _pObject = nullptr; + std::string _objectType; + std::unique_ptr _currentExtensionHandler; +}; + +} // namespace Cesium3DTiles diff --git a/Cesium3DTilesReader/src/TilesetReader.cpp b/Cesium3DTilesReader/src/TilesetReader.cpp new file mode 100644 index 000000000..6ac79351c --- /dev/null +++ b/Cesium3DTilesReader/src/TilesetReader.cpp @@ -0,0 +1,154 @@ +#include "Cesium3DTiles/TilesetReader.h" + +#include "Cesium3DTiles/IExtensionJsonHandler.h" +#include "Cesium3DTiles/ReaderContext.h" +#include "CesiumJsonReader/JsonHandler.h" +#include "CesiumJsonReader/JsonReader.h" +#include "CesiumUtility/Tracing.h" +#include "TilesetJsonHandler.h" + +#include + +#include +#include +#include +#include +#include + +using namespace Cesium3DTiles; +using namespace CesiumJsonReader; +using namespace CesiumUtility; + +namespace { + +TilesetReaderResult readTilesetJson( + const ReaderContext& context, + const gsl::span& data) { + + CESIUM_TRACE("Cesium3DTiles::TilesetReader::readTilesetJson"); + + TilesetJsonHandler tilesetHandler(context); + ReadJsonResult jsonResult = + JsonReader::readJson(data, tilesetHandler); + + return TilesetReaderResult{ + std::move(jsonResult.value), + std::move(jsonResult.errors), + std::move(jsonResult.warnings)}; +} + +class AnyExtensionJsonHandler : public JsonObjectJsonHandler, + public IExtensionJsonHandler { +public: + AnyExtensionJsonHandler(const ReaderContext& /* context */) noexcept + : JsonObjectJsonHandler() {} + + virtual void reset( + IJsonHandler* pParentHandler, + ExtensibleObject& o, + const std::string_view& extensionName) override { + std::any& value = + o.extensions.emplace(extensionName, JsonValue(JsonValue::Object())) + .first->second; + JsonObjectJsonHandler::reset( + pParentHandler, + &std::any_cast(value)); + } + + virtual IJsonHandler* readNull() override { + return JsonObjectJsonHandler::readNull(); + }; + virtual IJsonHandler* readBool(bool b) override { + return JsonObjectJsonHandler::readBool(b); + } + virtual IJsonHandler* readInt32(int32_t i) override { + return JsonObjectJsonHandler::readInt32(i); + } + virtual IJsonHandler* readUint32(uint32_t i) override { + return JsonObjectJsonHandler::readUint32(i); + } + virtual IJsonHandler* readInt64(int64_t i) override { + return JsonObjectJsonHandler::readInt64(i); + } + virtual IJsonHandler* readUint64(uint64_t i) override { + return JsonObjectJsonHandler::readUint64(i); + } + virtual IJsonHandler* readDouble(double d) override { + return JsonObjectJsonHandler::readDouble(d); + } + virtual IJsonHandler* readString(const std::string_view& str) override { + return JsonObjectJsonHandler::readString(str); + } + virtual IJsonHandler* readObjectStart() override { + return JsonObjectJsonHandler::readObjectStart(); + } + virtual IJsonHandler* readObjectKey(const std::string_view& str) override { + return JsonObjectJsonHandler::readObjectKey(str); + } + virtual IJsonHandler* readObjectEnd() override { + return JsonObjectJsonHandler::readObjectEnd(); + } + virtual IJsonHandler* readArrayStart() override { + return JsonObjectJsonHandler::readArrayStart(); + } + virtual IJsonHandler* readArrayEnd() override { + return JsonObjectJsonHandler::readArrayEnd(); + } + + virtual void reportWarning( + const std::string& warning, + std::vector&& context = + std::vector()) override { + JsonObjectJsonHandler::reportWarning(warning, std::move(context)); + } +}; + +} // namespace + +TilesetReader::TilesetReader() { + // TODO: register extensions here +} + +void TilesetReader::setExtensionState( + const std::string& extensionName, + ExtensionState newState) { + this->_extensionStates[extensionName] = newState; +} + +TilesetReaderResult TilesetReader::readTileset( + const gsl::span& data, + const ReadTilesetOptions& /*options*/) const { + ReaderContext context{*this}; + TilesetReaderResult result = readTilesetJson(context, data); + + return result; +} + +std::unique_ptr TilesetReader::createExtensionHandler( + const ReaderContext& context, + const std::string_view& extensionName, + const std::string& extendedObjectType) const { + + std::string extensionNameString{extensionName}; + + auto stateIt = this->_extensionStates.find(extensionNameString); + if (stateIt != this->_extensionStates.end()) { + if (stateIt->second == ExtensionState::Disabled) { + return nullptr; + } else if (stateIt->second == ExtensionState::JsonOnly) { + return std::make_unique(context); + } + } + + auto extensionNameIt = this->_extensions.find(extensionNameString); + if (extensionNameIt == this->_extensions.end()) { + return std::make_unique(context); + } + + auto objectTypeIt = extensionNameIt->second.find(extendedObjectType); + if (objectTypeIt == extensionNameIt->second.end()) { + return std::make_unique(context); + } + + return objectTypeIt->second(context); +} diff --git a/Cesium3DTilesReader/test/TestReader.cpp b/Cesium3DTilesReader/test/TestReader.cpp new file mode 100644 index 000000000..cdcac2187 --- /dev/null +++ b/Cesium3DTilesReader/test/TestReader.cpp @@ -0,0 +1,118 @@ +#include "Cesium3DTiles/TilesetReader.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include + +using namespace Cesium3DTiles; +using namespace CesiumUtility; + +namespace { +std::vector readFile(const std::filesystem::path& fileName) { + std::ifstream file(fileName, std::ios::binary | std::ios::ate); + REQUIRE(file); + + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); + + std::vector buffer(static_cast(size)); + file.read(reinterpret_cast(buffer.data()), size); + + return buffer; +} +} // namespace + +TEST_CASE("Cesium3DTiles::TilesetReader") { + using namespace std::string_literals; + + std::filesystem::path tilesetFile = Cesium3DTilesReader_TEST_DATA_DIR; + tilesetFile /= "tileset.json"; + std::vector data = readFile(tilesetFile); + Cesium3DTiles::TilesetReader reader; + TilesetReaderResult result = reader.readTileset(data); + REQUIRE(result.tileset); + + const Tileset& tileset = result.tileset.value(); + + REQUIRE(tileset.asset.version == "1.0"); + REQUIRE(tileset.geometricError == 494.50961650991815); + REQUIRE(tileset.extensionsUsed.size() == 0); + REQUIRE(tileset.extensionsRequired.size() == 0); + + REQUIRE(tileset.properties.size() == 3); + CHECK(tileset.properties.at("Longitude").minimum == -0.0005589940528287436); + CHECK(tileset.properties.at("Longitude").maximum == 0.0001096066770252439); + CHECK(tileset.properties.at("Latitude").minimum == 0.8987242766850329); + CHECK(tileset.properties.at("Latitude").maximum == 0.899060112939701); + CHECK(tileset.properties.at("Height").minimum == 1.0); + CHECK(tileset.properties.at("Height").maximum == 241.6); + + CHECK(tileset.root.content->uri == "0/0/0.b3dm"); + CHECK(tileset.root.geometricError == 268.37878244706053); + CHECK(tileset.root.refine == Tile::Refine::ADD); + CHECK_FALSE(tileset.root.viewerRequestVolume); + + std::vector expectedRegion = { + -0.0005682966577418737, + 0.8987233516605286, + 0.00011646582098558159, + 0.8990603398325034, + 0, + 241.6}; + + std::vector expectedContentRegion = { + -0.0004001690908972599, + 0.8988700116775743, + 0.00010096729722787196, + 0.8989625664878067, + 0, + 241.6}; + + std::vector expectedChildRegion = { + -0.0004853062518095434, + 0.898741188925484, + -0.0002736676267127107, + 0.8989037314387226, + 0, + 158.4}; + + std::vector expectedChildContentRegion = { + -0.0004058588642587614, + 0.898746512179703, + -0.0002736676267127107, + 0.8989037314387226, + 0, + 158.4}; + + REQUIRE_THAT( + tileset.root.boundingVolume.region, + Catch::Matchers::Approx(expectedRegion)); + + REQUIRE_THAT( + tileset.root.content->boundingVolume->region, + Catch::Matchers::Approx(expectedContentRegion)); + + REQUIRE(tileset.root.children.size() == 4); + + const Tile& child = tileset.root.children[0]; + + REQUIRE_THAT( + child.boundingVolume.region, + Catch::Matchers::Approx(expectedChildRegion)); + + REQUIRE_THAT( + child.content->boundingVolume->region, + Catch::Matchers::Approx(expectedChildContentRegion)); + + CHECK(child.content->uri == "1/0/0.b3dm"); + CHECK(child.geometricError == 159.43385994848); + CHECK(child.children.size() == 4); + CHECK_FALSE(child.viewerRequestVolume); +} diff --git a/Cesium3DTilesReader/test/data/tileset.json b/Cesium3DTilesReader/test/data/tileset.json new file mode 100644 index 000000000..0bf6b2f5b --- /dev/null +++ b/Cesium3DTilesReader/test/data/tileset.json @@ -0,0 +1,418 @@ +{ + "asset": { + "version" : "1.0" + }, + "properties": { + "Longitude": { + "minimum": -0.0005589940528287436, + "maximum": 0.0001096066770252439 + }, + "Latitude": { + "minimum": 0.8987242766850329, + "maximum": 0.899060112939701 + }, + "Height": { + "minimum": 1, + "maximum": 241.6 + } + }, + "geometricError": 494.50961650991815, + "root": { + "boundingVolume": { + "region": [ + -0.0005682966577418737, + 0.8987233516605286, + 0.00011646582098558159, + 0.8990603398325034, + 0, + 241.6 + ] + }, + "content": { + "boundingVolume": { + "region": [ + -0.0004001690908972599, + 0.8988700116775743, + 0.00010096729722787196, + 0.8989625664878067, + 0, + 241.6 + ] + }, + "uri": "0/0/0.b3dm" + }, + "geometricError": 268.37878244706053, + "refine": "ADD", + "children": [ + { + "boundingVolume": { + "region": [ + -0.0004853062518095434, + 0.898741188925484, + -0.0002736676267127107, + 0.8989037314387226, + 0, + 158.4 + ] + }, + "content": { + "boundingVolume": { + "region": [ + -0.0004058588642587614, + 0.898746512179703, + -0.0002736676267127107, + 0.8989037314387226, + 0, + 158.4 + ] + }, + "uri": "1/0/0.b3dm" + }, + "geometricError": 159.43385994848, + "children": [ + { + "boundingVolume": { + "region": [ + -0.0004853062518095434, + 0.898741188925484, + -0.0003930656008416433, + 0.898818995703538, + 0, + 66.7 + ] + }, + "content": { + "uri": "2/0/0.b3dm" + }, + "geometricError": 10.831613588830955 + }, + { + "boundingVolume": { + "region": [ + -0.0003984063083527456, + 0.8987434753068045, + -0.00028070130359824817, + 0.8988027117816164, + 0, + 48.2 + ] + }, + "content": { + "uri": "2/1/0.b3dm" + }, + "geometricError": 11.833855250694043 + }, + { + "boundingVolume": { + "region": [ + -0.00039631191325035245, + 0.8988008442793176, + -0.000280491864088009, + 0.8989002407802179, + 0, + 78.1 + ] + }, + "content": { + "uri": "2/1/1.b3dm" + }, + "geometricError": 24.187299340965403 + }, + { + "boundingVolume": { + "region": [ + -0.00047979101137324135, + 0.8988092742196048, + -0.0003937113726648811, + 0.898901462510695, + 0, + 122.2 + ] + }, + "content": { + "uri": "2/0/1.b3dm" + }, + "geometricError": 48.508446081365975 + } + ] + }, + { + "boundingVolume": { + "region": [ + -0.0002874033679259065, + 0.8987233516605286, + 0.00009827949017980081, + 0.8988939226883266, + 0, + 75.2 + ] + }, + "content": { + "boundingVolume": { + "region": [ + -0.00028230700651008276, + 0.8987309438427749, + -0.00011402236003278958, + 0.8988939226883266, + 0, + 75.2 + ] + }, + "uri": "1/1/0.b3dm" + }, + "geometricError": 132.82048511777703, + "children": [ + { + "boundingVolume": { + "region": [ + -0.0002874033679259065, + 0.8987293381398633, + -0.00018024015185345448, + 0.8987995352823785, + 0, + 38.1 + ] + }, + "content": { + "uri": "2/2/0.b3dm" + }, + "geometricError": 4.206139430532202 + }, + { + "boundingVolume": { + "region": [ + -0.00018407987620784196, + 0.8987233516605286, + -0.0000894132175796695, + 0.8987836876927705, + 0, + 72.9 + ] + }, + "content": { + "uri": "2/3/0.b3dm" + }, + "geometricError": 0 + }, + { + "boundingVolume": { + "region": [ + -0.00018493508754131914, + 0.8987896218122265, + 0.00009827949017980081, + 0.8988920377327339, + 0, + 46.9 + ] + }, + "content": { + "uri": "2/3/1.b3dm" + }, + "geometricError": 0 + }, + { + "boundingVolume": { + "region": [ + -0.00027722809838677943, + 0.8987969696483782, + -0.00017832028967626075, + 0.8988916014004213, + 0, + 55.4 + ] + }, + "content": { + "uri": "2/2/1.b3dm" + }, + "geometricError": 0 + } + ] + }, + { + "boundingVolume": { + "region": [ + -0.0002821848334624433, + 0.8988867144785156, + 0.00011646582098558159, + 0.8990603398325034, + 0, + 158 + ] + }, + "content": { + "boundingVolume": { + "region": [ + -0.0002782229360604159, + 0.8989292306990948, + 0.000006946410422937427, + 0.899046220118855, + 0, + 158 + ] + }, + "uri": "1/1/1.b3dm" + }, + "geometricError": 156.46285780389445, + "children": [ + { + "boundingVolume": { + "region": [ + -0.00027865926837341453, + 0.8988880758353316, + -0.00014501940754820897, + 0.8989746092596459, + 0, + 77.3 + ] + }, + "content": { + "uri": "2/2/2.b3dm" + }, + "geometricError": 0 + }, + { + "boundingVolume": { + "region": [ + -0.00015598007525073333, + 0.8988867144785156, + 0.00011646582098558159, + 0.8989826028676196, + 0, + 106.2 + ] + }, + "content": { + "uri": "2/3/2.b3dm" + }, + "geometricError": 0 + }, + { + "boundingVolume": { + "region": [ + -0.00015252432333178438, + 0.8989769130942584, + 0.00003328342883553189, + 0.8990603398325034, + 0, + 67.9 + ] + }, + "content": { + "uri": "2/3/3.b3dm" + }, + "geometricError": 8.010233984367021 + }, + { + "boundingVolume": { + "region": [ + -0.0002821848334624433, + 0.8989765465751156, + -0.0001477072145962801, + 0.899040914317929, + 0, + 76 + ] + }, + "content": { + "uri": "2/2/3.b3dm" + }, + "geometricError": 40.38435697163592 + } + ] + }, + { + "boundingVolume": { + "region": [ + -0.0005682966577418737, + 0.8989007643789939, + -0.0002669481090925327, + 0.8990582279841088, + 0, + 204 + ] + }, + "content": { + "boundingVolume": { + "region": [ + -0.0005526410543514849, + 0.8989100669839071, + -0.0002669481090925327, + 0.8990037911647392, + 0, + 204 + ] + }, + "uri": "1/0/1.b3dm" + }, + "geometricError": 149.600454457028, + "children": [ + { + "boundingVolume": { + "region": [ + -0.0005474399731805417, + 0.8989017068567899, + -0.00040917498983755046, + 0.8990014698768336, + 0, + 81.2 + ] + }, + "content": { + "uri": "2/0/2.b3dm" + }, + "geometricError": 0 + }, + { + "boundingVolume": { + "region": [ + -0.00041203732981082115, + 0.8989007643789939, + -0.00027176521782803744, + 0.8989922894449685, + 0, + 108.7 + ] + }, + "content": { + "uri": "2/1/2.b3dm" + }, + "geometricError": 0 + }, + { + "boundingVolume": { + "region": [ + -0.0004253716452960582, + 0.8989891478523147, + -0.0002760587277879431, + 0.8990362368355337, + 0, + 30.1 + ] + }, + "content": { + "uri": "2/1/3.b3dm" + }, + "geometricError": 18.837170280352364 + }, + { + "boundingVolume": { + "region": [ + -0.0005682966577418737, + 0.8989984853638134, + -0.000407220221075317, + 0.8990582279841088, + 0, + 53.3 + ] + }, + "content": { + "uri": "2/0/3.b3dm" + }, + "geometricError": 67.4774528507299 + } + ] + } + ] + } +} + diff --git a/CesiumGltfReader/test/TestReader.cpp b/CesiumGltfReader/test/TestReader.cpp index 59ea96923..7ae9594d0 100644 --- a/CesiumGltfReader/test/TestReader.cpp +++ b/CesiumGltfReader/test/TestReader.cpp @@ -7,54 +7,73 @@ #include #include -#include -#include -#include #include +#include #include using namespace CesiumGltf; using namespace CesiumUtility; namespace { -std::vector readFile(const std::string& path) { - FILE* fp = std::fopen(path.c_str(), "rb"); - REQUIRE(fp); +std::vector readFile(const std::filesystem::path& fileName) { + std::ifstream file(fileName, std::ios::binary | std::ios::ate); + REQUIRE(file); - try { - std::fseek(fp, 0, SEEK_END); - long pos = std::ftell(fp); - std::fseek(fp, 0, SEEK_SET); + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); - std::vector result(static_cast(pos)); - size_t itemsRead = std::fread(result.data(), 1, result.size(), fp); - REQUIRE(itemsRead == result.size()); + std::vector buffer(static_cast(size)); + file.read(reinterpret_cast(buffer.data()), size); - std::fclose(fp); - - return result; - } catch (...) { - if (fp) { - std::fclose(fp); - } - throw; - } + return buffer; } } // namespace TEST_CASE("CesiumGltf::GltfReader") { using namespace std::string_literals; - std::string s = - "{"s + " \"accessors\": ["s + " {"s + - " \"count\": 4,"s + //{\"test\":true},"s + - " \"componentType\":5121,"s + " \"type\":\"VEC2\","s + - " \"max\":[1.0, 2.2, 3.3],"s + " \"min\":[0.0, -1.2]"s + - " }"s + " ],"s + " \"meshes\": [{"s + " \"primitives\": [{"s + - " \"attributes\": {"s + " \"POSITION\": 0,"s + - " \"NORMAL\": 1"s + " },"s + " \"targets\": ["s + - " {\"POSITION\": 10, \"NORMAL\": 11}"s + " ]"s + " }]"s + - " }],"s + " \"surprise\":{\"foo\":true}"s + "}"s; + std::string s = R"( + { + "accessors": [ + { + "count": 4, + "componentType": 5121, + "type": "VEC2", + "max": [ + 1, + 2.2, + 3.3 + ], + "min": [ + 0, + -1.2 + ] + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "POSITION": 0, + "NORMAL": 1 + }, + "targets": [ + { + "POSITION": 10, + "NORMAL": 11 + } + ] + } + ] + } + ], + "surprise": { + "foo": true + } + } + )"; + CesiumGltf::GltfReader reader; ModelReaderResult result = reader.readModel( gsl::span(reinterpret_cast(s.c_str()), s.size())); @@ -90,7 +109,7 @@ TEST_CASE("Read TriangleWithoutIndices") { std::filesystem::path gltfFile = CesiumGltfReader_TEST_DATA_DIR; gltfFile /= "TriangleWithoutIndices/glTF-Embedded/TriangleWithoutIndices.gltf"; - std::vector data = readFile(gltfFile.string()); + std::vector data = readFile(gltfFile); CesiumGltf::GltfReader reader; ModelReaderResult result = reader.readModel(data); REQUIRE(result.model); @@ -111,7 +130,7 @@ TEST_CASE("Read TriangleWithoutIndices") { TEST_CASE("Read BoxTexturedWebp (with error messages)") { std::filesystem::path gltfFile = CesiumGltfReader_TEST_DATA_DIR; gltfFile /= "BoxTexturedWebp/glTF/BoxTexturedWebp.gltf"; - std::vector data = readFile(gltfFile.string()); + std::vector data = readFile(gltfFile); CesiumGltf::GltfReader reader; ModelReaderResult result = reader.readModel(data); REQUIRE(result.model); diff --git a/CesiumJsonReader/include/CesiumJsonReader/ArrayJsonHandler.h b/CesiumJsonReader/include/CesiumJsonReader/ArrayJsonHandler.h index 2eed1d73d..d2902cc0b 100644 --- a/CesiumJsonReader/include/CesiumJsonReader/ArrayJsonHandler.h +++ b/CesiumJsonReader/include/CesiumJsonReader/ArrayJsonHandler.h @@ -7,6 +7,8 @@ #include "StringJsonHandler.h" #include +#include +#include #include namespace CesiumJsonReader { @@ -15,12 +17,16 @@ class CESIUMJSONREADER_API ArrayJsonHandler : public JsonHandler { public: template ArrayJsonHandler(Ts&&... args) noexcept - : JsonHandler(), _objectHandler(std::forward(args)...) {} + : JsonHandler(), + _handlerFactory( + std::bind(handlerFactory, std::forward(args)...)), + _objectHandler() {} void reset(IJsonHandler* pParent, std::vector* pArray) { JsonHandler::reset(pParent); this->_pArray = pArray; this->_arrayIsOpen = false; + this->_objectHandler.reset(this->_handlerFactory()); } virtual IJsonHandler* readNull() override { @@ -62,8 +68,8 @@ class CESIUMJSONREADER_API ArrayJsonHandler : public JsonHandler { assert(this->_pArray); T& o = this->_pArray->emplace_back(); - this->_objectHandler.reset(this, &o); - return this->_objectHandler.readObjectStart(); + this->_objectHandler->reset(this, &o); + return this->_objectHandler->readObjectStart(); } virtual IJsonHandler* @@ -108,9 +114,15 @@ class CESIUMJSONREADER_API ArrayJsonHandler : public JsonHandler { } } + template static THandler* handlerFactory(Ts&&... args) { + return new THandler(std::forward(args)...); + } + std::vector* _pArray = nullptr; bool _arrayIsOpen = false; - THandler _objectHandler; + + std::function _handlerFactory; + std::unique_ptr _objectHandler; }; template <> diff --git a/CesiumNativeTests/CMakeLists.txt b/CesiumNativeTests/CMakeLists.txt index 04ffbb757..c62cdcaf9 100644 --- a/CesiumNativeTests/CMakeLists.txt +++ b/CesiumNativeTests/CMakeLists.txt @@ -5,6 +5,7 @@ configure_cesium_library(cesium-native-tests) # properties. set(cesium_native_targets Cesium3DTiles + Cesium3DTilesReader Cesium3DTilesSelection CesiumAsync CesiumGeometry diff --git a/README.md b/README.md index ce5ff8918..bcbcb044d 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Currently Cesium Native is used to develop [Cesium for Unreal](https://github.co | Library | Description | | -- | -- | | **Cesium3DTiles** | Lightweight 3D Tiles classes. | +| **Cesium3DTilesReader** | 3D Tiles deserialization, including 3D Tiles extension support. | | **Cesium3DTilesSelection** | Runtime streaming, decoding, level of detail selection, culling, cache management, and decoding of 3D Tiles. | | **CesiumAsync** | Classes for multi-threaded asynchronous tasks. | | **CesiumGeometry** | Common 3D geometry classes; and bounds testing, intersection testing, and spatial indexing algorithms. | diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 5a471ede3..8a386230f 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -4,6 +4,7 @@ if (DOXYGEN_FOUND) set( LIB_DIRS ../Cesium3DTiles/include + ../Cesium3DTilesReader/include ../Cesium3DTilesSelection/include ../CesiumAsync/include ../CesiumGeometry/include @@ -18,6 +19,7 @@ if (DOXYGEN_FOUND) set( DOXYGEN_EXAMPLE_PATH ../Cesium3DTiles/test + ../Cesium3DTilesReader/test ../Cesium3DTilesSelection/test ../CesiumAsync/test ../CesiumGeometry/test