From 7a2b09752501a7ef538619a3e3708fb7a525f158 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 21 Jan 2021 18:45:09 +1100 Subject: [PATCH 01/13] Support multiple b3dms in a cmpt. --- Cesium3DTiles/src/CompositeContent.cpp | 18 +- CesiumGltf/include/CesiumGltf/Model.h | 13 ++ CesiumGltf/src/Model.cpp | 197 ++++++++++++++++++ .../src/JsonObjectJsonHandler.cpp | 8 +- CesiumGltfReader/src/JsonObjectJsonHandler.h | 7 - 5 files changed, 227 insertions(+), 16 deletions(-) diff --git a/Cesium3DTiles/src/CompositeContent.cpp b/Cesium3DTiles/src/CompositeContent.cpp index e6c71defe..0d485ea5a 100644 --- a/Cesium3DTiles/src/CompositeContent.cpp +++ b/Cesium3DTiles/src/CompositeContent.cpp @@ -107,9 +107,21 @@ namespace Cesium3DTiles { } else if (innerTiles.size() == 1) { return std::move(innerTiles[0]); } else { - // TODO: combine all inner tiles into one glTF instead of return only the first. - SPDLOG_LOGGER_WARN(pLogger, "Composite tile contains multiple loadable inner tiles. Due to a temporary limitation, only the first will be used."); - return std::move(innerTiles[0]); + std::unique_ptr pResult = std::move(innerTiles[0]); + + for (size_t i = 1; i < innerTiles.size(); ++i) { + if (!innerTiles[i]->model) { + continue; + } + + if (pResult->model) { + pResult->model.value().merge(std::move(innerTiles[i]->model.value())); + } else { + pResult->model = std::move(innerTiles[i]->model); + } + } + + return pResult; } } diff --git a/CesiumGltf/include/CesiumGltf/Model.h b/CesiumGltf/include/CesiumGltf/Model.h index 46644b547..886e8f0d9 100644 --- a/CesiumGltf/include/CesiumGltf/Model.h +++ b/CesiumGltf/include/CesiumGltf/Model.h @@ -5,6 +5,19 @@ namespace CesiumGltf { /** @copydoc ModelSpec */ struct Model : public ModelSpec { + /** + * @brief Merges another model into this one. + * + * After this method returns, this `Model` contains all of the + * elements that were originally in it _plus_ all of the elements + * that were in `rhs`. Element indices are updated accordingly. + * However, element indices in {@ExtensibleObject::extras}, if any, + * are _not_ updated. + * + * @param rhs The model to merge into this one. + */ + void merge(Model&& rhs); + /** * @brief Safely gets the element with a given index, returning a default instance if the index is outside the range. * diff --git a/CesiumGltf/src/Model.cpp b/CesiumGltf/src/Model.cpp index 5865dd096..36aef4da5 100644 --- a/CesiumGltf/src/Model.cpp +++ b/CesiumGltf/src/Model.cpp @@ -1 +1,198 @@ #include "CesiumGltf/Model.h" +#include "CesiumGltf/KHR_draco_mesh_compression.h" +#include + +using namespace CesiumGltf; + +namespace { + template + size_t copyElements(std::vector& to, std::vector& from) { + size_t out = to.size(); + to.resize(out + from.size()); + for (size_t i = 0; i < from.size(); ++i) { + to[out + i] = std::move(from[i]); + } + + return out; + } + + void updateIndex(int32_t& index, size_t offset) { + if (index == -1) { + return; + } + index += int32_t(offset); + } +} + +void Model::merge(Model&& rhs) { + // TODO: we could generate this pretty easily if the glTF JSON schema made + // it clear which index properties refer to which types of objects. + + // Copy all the source data into this instance. + copyElements(this->extensionsUsed, rhs.extensionsUsed); + std::sort(this->extensionsUsed.begin(), this->extensionsUsed.end()); + this->extensionsUsed.erase(std::unique(this->extensionsUsed.begin(), this->extensionsUsed.end()), this->extensionsUsed.end()); + + copyElements(this->extensionsRequired, rhs.extensionsRequired); + std::sort(this->extensionsRequired.begin(), this->extensionsRequired.end()); + this->extensionsRequired.erase(std::unique(this->extensionsRequired.begin(), this->extensionsRequired.end()), this->extensionsRequired.end()); + + size_t firstAccessor = copyElements(this->accessors, rhs.accessors); + size_t firstAnimation = copyElements(this->animations, rhs.animations); + size_t firstBuffer = copyElements(this->buffers, rhs.buffers); + size_t firstBufferView = copyElements(this->bufferViews, rhs.bufferViews); + size_t firstCamera = copyElements(this->cameras, rhs.cameras); + size_t firstImage = copyElements(this->images, rhs.images); + size_t firstMaterial = copyElements(this->materials, rhs.materials); + size_t firstMesh = copyElements(this->meshes, rhs.meshes); + size_t firstNode = copyElements(this->nodes, rhs.nodes); + size_t firstSampler = copyElements(this->samplers, rhs.samplers); + size_t firstScene = copyElements(this->scenes, rhs.scenes); + size_t firstSkin = copyElements(this->skins, rhs.skins); + size_t firstTexture = copyElements(this->textures, rhs.textures); + + // Update the copied indices + for (size_t i = firstAccessor; i < this->accessors.size(); ++i) { + Accessor& accessor = this->accessors[i]; + updateIndex(accessor.bufferView, firstBufferView); + + if (accessor.sparse) { + updateIndex(accessor.sparse.value().indices.bufferView, firstBufferView); + updateIndex(accessor.sparse.value().values.bufferView, firstBufferView); + } + } + + for (size_t i = firstAnimation; i < this->animations.size(); ++i) { + Animation& animation = this->animations[i]; + + for (AnimationChannel& channel : animation.channels) { + updateIndex(channel.sampler, firstSampler); + updateIndex(channel.target.node, firstNode); + } + + for (AnimationSampler& sampler : animation.samplers) { + updateIndex(sampler.input, firstAccessor); + updateIndex(sampler.output, firstAccessor); + } + } + + for (size_t i = firstBufferView; i < this->bufferViews.size(); ++i) { + BufferView& bufferView = this->bufferViews[i]; + updateIndex(bufferView.buffer, firstBuffer); + } + + for (size_t i = firstImage; i < this->images.size(); ++i) { + Image& image = this->images[i]; + updateIndex(image.bufferView, firstBufferView); + } + + for (size_t i = firstMesh; i < this->meshes.size(); ++i) { + Mesh& mesh = this->meshes[i]; + + for (MeshPrimitive& primitive : mesh.primitives) { + updateIndex(primitive.indices, firstAccessor); + updateIndex(primitive.material, firstMaterial); + + for (auto& attribute : primitive.attributes) { + updateIndex(attribute.second, firstAccessor); + } + + for (auto& target : primitive.targets) { + for (auto& displacement : target) { + updateIndex(displacement.second, firstAccessor); + } + } + + KHR_draco_mesh_compression* pDraco = primitive.getExtension(); + if (pDraco) { + updateIndex(pDraco->bufferView, firstBufferView); + } + } + } + + for (size_t i = firstNode; i < this->nodes.size(); ++i) { + Node& node = this->nodes[i]; + + updateIndex(node.camera, firstCamera); + updateIndex(node.skin, firstSkin); + updateIndex(node.mesh, firstMesh); + + for (auto& nodeIndex : node.children) { + updateIndex(nodeIndex, firstNode); + } + } + + for (size_t i = firstScene; i < this->scenes.size(); ++i) { + Scene& currentScene = this->scenes[i]; + for (int32_t& node : currentScene.nodes) { + updateIndex(node, firstNode); + } + } + + for (size_t i = firstSkin; i < this->skins.size(); ++i) { + Skin& skin = this->skins[i]; + + updateIndex(skin.inverseBindMatrices, firstAccessor); + updateIndex(skin.skeleton, firstNode); + + for (int32_t& nodeIndex : skin.joints) { + updateIndex(nodeIndex, firstNode); + } + } + + for (size_t i = firstTexture; i < this->textures.size(); ++i) { + Texture& texture = this->textures[i]; + + updateIndex(texture.sampler, firstSampler); + updateIndex(texture.source, firstImage); + } + + for (size_t i = firstMaterial; i < this->materials.size(); ++i) { + Material& material = this->materials[i]; + + if (material.normalTexture) { + updateIndex(material.normalTexture.value().index, firstTexture); + } + if (material.occlusionTexture) { + updateIndex(material.occlusionTexture.value().index, firstTexture); + } + if (material.pbrMetallicRoughness) { + MaterialPBRMetallicRoughness& pbr = material.pbrMetallicRoughness.value(); + if (pbr.baseColorTexture) { + updateIndex(pbr.baseColorTexture.value().index, firstTexture); + } + if (pbr.metallicRoughnessTexture) { + updateIndex(pbr.metallicRoughnessTexture.value().index, firstTexture); + } + } + if (material.emissiveTexture) { + updateIndex(material.emissiveTexture.value().index, firstTexture); + } + } + + Scene* pThisDefaultScene = Model::getSafe(&this->scenes, this->scene); + Scene* pRhsDefaultScene = Model::getSafe(&this->scenes, int32_t(rhs.scene + firstScene)); + + if (!pThisDefaultScene) { + this->scene = rhs.scene; + updateIndex(this->scene, firstScene); + } else if (pRhsDefaultScene) { + // Create a new default scene that has all the root nodes in + // the default scene of either model. + Scene& newScene = this->scenes.emplace_back(); + + // Refresh the scene pointers potentially invalidated by the above. + pThisDefaultScene = Model::getSafe(&this->scenes, this->scene); + pRhsDefaultScene = Model::getSafe(&this->scenes, int32_t(rhs.scene + firstScene)); + + newScene.nodes = pThisDefaultScene->nodes; + size_t originalNodeCount = newScene.nodes.size(); + newScene.nodes.resize(originalNodeCount + pRhsDefaultScene->nodes.size()); + std::copy(pRhsDefaultScene->nodes.begin(), pRhsDefaultScene->nodes.end(), newScene.nodes.begin() + originalNodeCount); + + // No need to update indices because they've already been updated when + // we copied them from rhs to this. + + this->scene = int32_t(this->scenes.size() - 1); + } +} diff --git a/CesiumGltfReader/src/JsonObjectJsonHandler.cpp b/CesiumGltfReader/src/JsonObjectJsonHandler.cpp index 43f5f5949..860ce5466 100644 --- a/CesiumGltfReader/src/JsonObjectJsonHandler.cpp +++ b/CesiumGltfReader/src/JsonObjectJsonHandler.cpp @@ -83,12 +83,8 @@ IJsonHandler* JsonObjectJsonHandler::Key(const char* str, size_t /* length */, b auto it = pObject->emplace(str, JsonValue()).first; this->_stack.push_back(&it->second); - - return property( - it->first.c_str(), - *this, - it->second - ); + this->_currentKey = str; + return this; } IJsonHandler* JsonObjectJsonHandler::EndObject(size_t /* memberCount */) { diff --git a/CesiumGltfReader/src/JsonObjectJsonHandler.h b/CesiumGltfReader/src/JsonObjectJsonHandler.h index 9007136c2..38719824e 100644 --- a/CesiumGltfReader/src/JsonObjectJsonHandler.h +++ b/CesiumGltfReader/src/JsonObjectJsonHandler.h @@ -25,13 +25,6 @@ namespace CesiumGltf { virtual IJsonHandler* EndArray(size_t elementCount) override; private: - template - IJsonHandler* property(const char* currentKey, TAccessor& accessor, TProperty& value) { - this->_currentKey = currentKey; - accessor.reset(this, &value); - return &accessor; - } - IJsonHandler* doneElement(); std::vector _stack; From dff2d63b2f22b2be267c3fe0a7f095f3bebb5544 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 21 Jan 2021 23:40:47 +1100 Subject: [PATCH 02/13] Add name to glTF model to aid debugging. --- Cesium3DTiles/src/GltfContent.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cesium3DTiles/src/GltfContent.cpp b/Cesium3DTiles/src/GltfContent.cpp index 8eed5c24b..240a0ba24 100644 --- a/Cesium3DTiles/src/GltfContent.cpp +++ b/Cesium3DTiles/src/GltfContent.cpp @@ -33,6 +33,10 @@ namespace Cesium3DTiles { pResult->model = std::move(loadedModel.model); + if (pResult->model) { + pResult->model.value().extras["Cesium3DTiles_TileUrl"] = url; + } + return pResult; } From 06fe04dd16a4525c4a2ed626b87dbe586f68a3b1 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Fri, 22 Jan 2021 18:49:37 +1100 Subject: [PATCH 03/13] Preserve precision in upsampled tile rectangles. --- Cesium3DTiles/include/Cesium3DTiles/TileID.h | 7 ++- Cesium3DTiles/src/QuantizedMeshContent.cpp | 4 ++ Cesium3DTiles/src/Tile.cpp | 50 ++++++++++++++----- Cesium3DTiles/src/Tileset.cpp | 2 +- .../src/upsampleGltfForRasterOverlays.cpp | 32 +++++++----- .../src/upsampleGltfForRasterOverlays.h | 2 +- .../test/TestUpsampleGltfForRasterOverlay.cpp | 21 +++++--- .../include/CesiumGeometry/QuadtreeTileID.h | 29 ++--------- 8 files changed, 82 insertions(+), 65 deletions(-) diff --git a/Cesium3DTiles/include/Cesium3DTiles/TileID.h b/Cesium3DTiles/include/Cesium3DTiles/TileID.h index afcb23ccd..b7b7444b7 100644 --- a/Cesium3DTiles/include/Cesium3DTiles/TileID.h +++ b/Cesium3DTiles/include/Cesium3DTiles/TileID.h @@ -25,16 +25,15 @@ namespace Cesium3DTiles { * * A {@link CesiumGeometry::OctreeTileID}: This is an implicit * tile in the octree. The URL of the tile's content is formed * by instantiating the context's template URL with this ID. - * * A {@link CesiumGeometry::QuadtreeChild}: This tile doesn't + * * A {@link CesiumGeometry::UpsampledQuadtreeNode}: This tile doesn't * have any content, but content for it can be created by subdividing - * the parent tile's content into four equal tiles and taking the - * quadrant identified. + * the parent tile's content. */ typedef std::variant< std::string, CesiumGeometry::QuadtreeTileID, CesiumGeometry::OctreeTileID, - CesiumGeometry::QuadtreeChild + CesiumGeometry::UpsampledQuadtreeNode > TileID; } diff --git a/Cesium3DTiles/src/QuantizedMeshContent.cpp b/Cesium3DTiles/src/QuantizedMeshContent.cpp index 6280492c6..e8e83e172 100644 --- a/Cesium3DTiles/src/QuantizedMeshContent.cpp +++ b/Cesium3DTiles/src/QuantizedMeshContent.cpp @@ -948,6 +948,10 @@ namespace Cesium3DTiles { pResult->updatedBoundingVolume = BoundingRegion(rectangle, minimumHeight, maximumHeight); + if (pResult->model) { + pResult->model.value().extras["Cesium3DTiles_TileUrl"] = url; + } + return pResult; } diff --git a/Cesium3DTiles/src/Tile.cpp b/Cesium3DTiles/src/Tile.cpp index b17346fc7..16e371159 100644 --- a/Cesium3DTiles/src/Tile.cpp +++ b/Cesium3DTiles/src/Tile.cpp @@ -186,7 +186,7 @@ namespace Cesium3DTiles { if (!maybeRequestFuture) { // There is no content to load. But we may need to upsample. - const QuadtreeChild* pSubdivided = std::get_if(&this->getTileID()); + const UpsampledQuadtreeNode* pSubdivided = std::get_if(&this->getTileID()); if (pSubdivided) { // We can't upsample this tile until its parent tile is done loading. if (this->getParent() && this->getParent()->getState() == LoadState::Done) { @@ -316,7 +316,7 @@ namespace Cesium3DTiles { for (const Tile& child : this->getChildren()) { if ( child.getState() == Tile::LoadState::ContentLoading && - std::get_if(&child.getTileID()) != nullptr + std::get_if(&child.getTileID()) != nullptr ) { return false; } @@ -385,6 +385,32 @@ namespace Cesium3DTiles { return; } + // TODO: support upsampling non-quadtrees. + const QuadtreeTileID* pParentTileID = std::get_if(&parent.getTileID()); + if (!pParentTileID) { + const UpsampledQuadtreeNode* pUpsampledID = std::get_if(&parent.getTileID()); + if (pUpsampledID) { + pParentTileID = &pUpsampledID->tileID; + } + } + + if (!pParentTileID) { + return; + } + + // TODO: support upsampling non-implicit tiles. + if (!parent.getContext()->implicitContext) { + return; + } + + QuadtreeTileID swID(pParentTileID->level + 1, pParentTileID->x * 2, pParentTileID->y * 2); + QuadtreeTileID seID(swID.level, swID.x + 1, swID.y); + QuadtreeTileID nwID(swID.level, swID.x, swID.y + 1); + QuadtreeTileID neID(swID.level, swID.x + 1, swID.y + 1); + + QuadtreeTilingScheme& tilingScheme = parent.getContext()->implicitContext.value().tilingScheme; + Projection& projection = parent.getContext()->implicitContext.value().projection; + parent.createChildTiles(4); gsl::span children = parent.getChildren(); @@ -409,33 +435,31 @@ namespace Cesium3DTiles { nw.setParent(&parent); ne.setParent(&parent); - sw.setTileID(QuadtreeChild::LowerLeft); - se.setTileID(QuadtreeChild::LowerRight); - nw.setTileID(QuadtreeChild::UpperLeft); - ne.setTileID(QuadtreeChild::UpperRight); + sw.setTileID(UpsampledQuadtreeNode { swID }); + se.setTileID(UpsampledQuadtreeNode { seID }); + nw.setTileID(UpsampledQuadtreeNode { nwID }); + ne.setTileID(UpsampledQuadtreeNode { neID }); - const GlobeRectangle& rectangle = pRegion->getRectangle(); - CesiumGeospatial::Cartographic center = rectangle.computeCenter(); double minimumHeight = pRegion->getMinimumHeight(); double maximumHeight = pRegion->getMaximumHeight(); sw.setBoundingVolume(BoundingRegionWithLooseFittingHeights(BoundingRegion( - GlobeRectangle(rectangle.getWest(), rectangle.getSouth(), center.longitude, center.latitude), + unprojectRectangleSimple(projection, tilingScheme.tileToRectangle(swID)), minimumHeight, maximumHeight ))); se.setBoundingVolume(BoundingRegionWithLooseFittingHeights(BoundingRegion( - GlobeRectangle(center.longitude, rectangle.getSouth(), rectangle.getEast(), center.latitude), + unprojectRectangleSimple(projection, tilingScheme.tileToRectangle(seID)), minimumHeight, maximumHeight ))); nw.setBoundingVolume(BoundingRegionWithLooseFittingHeights(BoundingRegion( - GlobeRectangle(rectangle.getWest(), center.latitude, center.longitude, rectangle.getNorth()), + unprojectRectangleSimple(projection, tilingScheme.tileToRectangle(nwID)), minimumHeight, maximumHeight ))); ne.setBoundingVolume(BoundingRegionWithLooseFittingHeights(BoundingRegion( - GlobeRectangle(center.longitude, center.latitude, rectangle.getEast(), rectangle.getNorth()), + unprojectRectangleSimple(projection, tilingScheme.tileToRectangle(neID)), minimumHeight, maximumHeight ))); @@ -645,7 +669,7 @@ namespace Cesium3DTiles { void Tile::upsampleParent(std::vector&& projections) { Tile* pParent = this->getParent(); - const QuadtreeChild* pSubdividedParentID = std::get_if(&this->getTileID()); + const UpsampledQuadtreeNode* pSubdividedParentID = std::get_if(&this->getTileID()); assert(pParent != nullptr); assert(pParent->getState() == LoadState::Done); diff --git a/Cesium3DTiles/src/Tileset.cpp b/Cesium3DTiles/src/Tileset.cpp index cacbaf269..f8ae40b9e 100644 --- a/Cesium3DTiles/src/Tileset.cpp +++ b/Cesium3DTiles/src/Tileset.cpp @@ -1252,7 +1252,7 @@ namespace Cesium3DTiles { }); } - std::string operator()(QuadtreeChild /*subdividedParent*/) { + std::string operator()(UpsampledQuadtreeNode /*subdividedParent*/) { return std::string(); } }; diff --git a/Cesium3DTiles/src/upsampleGltfForRasterOverlays.cpp b/Cesium3DTiles/src/upsampleGltfForRasterOverlays.cpp index b3b584a68..d77e8c5b2 100644 --- a/Cesium3DTiles/src/upsampleGltfForRasterOverlays.cpp +++ b/Cesium3DTiles/src/upsampleGltfForRasterOverlays.cpp @@ -27,7 +27,7 @@ namespace Cesium3DTiles { Model& model, Mesh& mesh, MeshPrimitive& primitive, - CesiumGeometry::QuadtreeChild childID + CesiumGeometry::UpsampledQuadtreeNode childID ); struct FloatVertexAttribute { @@ -72,14 +72,22 @@ namespace Cesium3DTiles { static void addSkirts(std::vector& output, std::vector& indices, std::vector& attributes, - CesiumGeometry::QuadtreeChild childID, + CesiumGeometry::UpsampledQuadtreeNode childID, SkirtMeshMetadata ¤tSkirt, const SkirtMeshMetadata &parentSkirt, EdgeIndices &edgeIndices, int64_t vertexSizeFloats, int32_t positionAttributeIndex); - Model upsampleGltfForRasterOverlays(const Model& parentModel, CesiumGeometry::QuadtreeChild childID) { + static bool isWestChild(CesiumGeometry::UpsampledQuadtreeNode childID) { + return (childID.tileID.x % 2) == 0; + } + + static bool isSouthChild(CesiumGeometry::UpsampledQuadtreeNode childID) { + return (childID.tileID.y % 2) == 0; + } + + Model upsampleGltfForRasterOverlays(const Model& parentModel, CesiumGeometry::UpsampledQuadtreeNode childID) { Model result; // Copy the entire parent model except for the buffers, bufferViews, and accessors, which we'll be rewriting. @@ -283,7 +291,7 @@ namespace Cesium3DTiles { Model& model, Mesh& /*mesh*/, MeshPrimitive& primitive, - CesiumGeometry::QuadtreeChild childID + CesiumGeometry::UpsampledQuadtreeNode childID ) { // Add up the per-vertex size of all attributes and create buffers, bufferViews, and accessors std::vector attributes; @@ -392,8 +400,8 @@ namespace Cesium3DTiles { primitive.attributes.erase(attribute); } - bool keepAboveU = childID == CesiumGeometry::QuadtreeChild::LowerRight || childID == CesiumGeometry::QuadtreeChild::UpperRight; - bool keepAboveV = childID == CesiumGeometry::QuadtreeChild::UpperLeft || childID == CesiumGeometry::QuadtreeChild::UpperRight; + bool keepAboveU = !isWestChild(childID); + bool keepAboveV = !isSouthChild(childID); AccessorView uvView(parentModel, uvAccessorIndex); AccessorView indicesView(parentModel, primitive.indices); @@ -723,7 +731,7 @@ namespace Cesium3DTiles { static void addSkirts(std::vector& output, std::vector& indices, std::vector& attributes, - CesiumGeometry::QuadtreeChild childID, + CesiumGeometry::UpsampledQuadtreeNode childID, SkirtMeshMetadata ¤tSkirt, const SkirtMeshMetadata &parentSkirt, EdgeIndices &edgeIndices, @@ -736,7 +744,7 @@ namespace Cesium3DTiles { shortestSkirtHeight = glm::min(shortestSkirtHeight, parentSkirt.skirtNorthHeight); // west - if (childID == CesiumGeometry::QuadtreeChild::LowerLeft || childID == CesiumGeometry::QuadtreeChild::UpperLeft) { + if (isWestChild(childID)) { currentSkirt.skirtWestHeight = parentSkirt.skirtWestHeight; } else { @@ -763,7 +771,7 @@ namespace Cesium3DTiles { positionAttributeIndex); // south - if (childID == CesiumGeometry::QuadtreeChild::LowerLeft || childID == CesiumGeometry::QuadtreeChild::LowerRight) { + if (isSouthChild(childID)) { currentSkirt.skirtSouthHeight = parentSkirt.skirtSouthHeight; } else { @@ -790,7 +798,7 @@ namespace Cesium3DTiles { positionAttributeIndex); // east - if (childID == CesiumGeometry::QuadtreeChild::LowerRight || childID == CesiumGeometry::QuadtreeChild::UpperRight) { + if (!isWestChild(childID)) { currentSkirt.skirtEastHeight = parentSkirt.skirtEastHeight; } else { @@ -817,7 +825,7 @@ namespace Cesium3DTiles { positionAttributeIndex); // north - if (childID == CesiumGeometry::QuadtreeChild::UpperLeft || childID == CesiumGeometry::QuadtreeChild::UpperRight) { + if (!isSouthChild(childID)) { currentSkirt.skirtNorthHeight = parentSkirt.skirtNorthHeight; } else { @@ -849,7 +857,7 @@ namespace Cesium3DTiles { Model& model, Mesh& mesh, MeshPrimitive& primitive, - CesiumGeometry::QuadtreeChild childID + CesiumGeometry::UpsampledQuadtreeNode childID ) { if ( primitive.mode != MeshPrimitive::Mode::TRIANGLES || diff --git a/Cesium3DTiles/src/upsampleGltfForRasterOverlays.h b/Cesium3DTiles/src/upsampleGltfForRasterOverlays.h index 2ab75fbd8..32e19e512 100644 --- a/Cesium3DTiles/src/upsampleGltfForRasterOverlays.h +++ b/Cesium3DTiles/src/upsampleGltfForRasterOverlays.h @@ -5,6 +5,6 @@ namespace Cesium3DTiles { - CesiumGltf::Model upsampleGltfForRasterOverlays(const CesiumGltf::Model& parentModel, CesiumGeometry::QuadtreeChild childID); + CesiumGltf::Model upsampleGltfForRasterOverlays(const CesiumGltf::Model& parentModel, CesiumGeometry::UpsampledQuadtreeNode childID); } diff --git a/Cesium3DTiles/test/TestUpsampleGltfForRasterOverlay.cpp b/Cesium3DTiles/test/TestUpsampleGltfForRasterOverlay.cpp index 3741aed14..015103852 100644 --- a/Cesium3DTiles/test/TestUpsampleGltfForRasterOverlay.cpp +++ b/Cesium3DTiles/test/TestUpsampleGltfForRasterOverlay.cpp @@ -134,8 +134,13 @@ TEST_CASE("Test upsample tile without skirts") { center.x, center.z, -center.y, 1.0 }; + CesiumGeometry::UpsampledQuadtreeNode lowerLeft { CesiumGeometry::QuadtreeTileID(1, 0, 0) }; + CesiumGeometry::UpsampledQuadtreeNode upperLeft { CesiumGeometry::QuadtreeTileID(1, 0, 1) }; + CesiumGeometry::UpsampledQuadtreeNode lowerRight { CesiumGeometry::QuadtreeTileID(1, 1, 0) }; + CesiumGeometry::UpsampledQuadtreeNode upperRight { CesiumGeometry::QuadtreeTileID(1, 1, 1) }; + SECTION("Upsample bottom left child") { - Model upsampledModel = upsampleGltfForRasterOverlays(model, CesiumGeometry::QuadtreeChild::LowerLeft); + Model upsampledModel = upsampleGltfForRasterOverlays(model, lowerLeft); REQUIRE(upsampledModel.meshes.size() == 1); const Mesh& upsampledMesh = upsampledModel.meshes.back(); @@ -171,7 +176,7 @@ TEST_CASE("Test upsample tile without skirts") { } SECTION("Upsample upper left child") { - Model upsampledModel = upsampleGltfForRasterOverlays(model, CesiumGeometry::QuadtreeChild::UpperLeft); + Model upsampledModel = upsampleGltfForRasterOverlays(model, upperLeft); REQUIRE(upsampledModel.meshes.size() == 1); const Mesh& upsampledMesh = upsampledModel.meshes.back(); @@ -207,7 +212,7 @@ TEST_CASE("Test upsample tile without skirts") { } SECTION("Upsample upper right child") { - Model upsampledModel = upsampleGltfForRasterOverlays(model, CesiumGeometry::QuadtreeChild::UpperRight); + Model upsampledModel = upsampleGltfForRasterOverlays(model, upperRight); REQUIRE(upsampledModel.meshes.size() == 1); const Mesh& upsampledMesh = upsampledModel.meshes.back(); @@ -243,7 +248,7 @@ TEST_CASE("Test upsample tile without skirts") { } SECTION("Upsample bottom right child") { - Model upsampledModel = upsampleGltfForRasterOverlays(model, CesiumGeometry::QuadtreeChild::LowerRight); + Model upsampledModel = upsampleGltfForRasterOverlays(model, lowerRight); REQUIRE(upsampledModel.meshes.size() == 1); const Mesh& upsampledMesh = upsampledModel.meshes.back(); @@ -293,7 +298,7 @@ TEST_CASE("Test upsample tile without skirts") { primitive.extras = SkirtMeshMetadata::createGltfExtras(skirtMeshMetadata); SECTION("Check bottom left skirt") { - Model upsampledModel = upsampleGltfForRasterOverlays(model, CesiumGeometry::QuadtreeChild::LowerLeft); + Model upsampledModel = upsampleGltfForRasterOverlays(model, lowerLeft); REQUIRE(upsampledModel.meshes.size() == 1); const Mesh& upsampledMesh = upsampledModel.meshes.back(); @@ -328,7 +333,7 @@ TEST_CASE("Test upsample tile without skirts") { } SECTION("Check upper left skirt") { - Model upsampledModel = upsampleGltfForRasterOverlays(model, CesiumGeometry::QuadtreeChild::UpperLeft); + Model upsampledModel = upsampleGltfForRasterOverlays(model, upperLeft); REQUIRE(upsampledModel.meshes.size() == 1); const Mesh& upsampledMesh = upsampledModel.meshes.back(); @@ -367,7 +372,7 @@ TEST_CASE("Test upsample tile without skirts") { } SECTION("Check upper right skirt") { - Model upsampledModel = upsampleGltfForRasterOverlays(model, CesiumGeometry::QuadtreeChild::UpperRight); + Model upsampledModel = upsampleGltfForRasterOverlays(model, upperRight); REQUIRE(upsampledModel.meshes.size() == 1); const Mesh& upsampledMesh = upsampledModel.meshes.back(); @@ -402,7 +407,7 @@ TEST_CASE("Test upsample tile without skirts") { } SECTION("Check bottom right skirt") { - Model upsampledModel = upsampleGltfForRasterOverlays(model, CesiumGeometry::QuadtreeChild::LowerRight); + Model upsampledModel = upsampleGltfForRasterOverlays(model, lowerRight); REQUIRE(upsampledModel.meshes.size() == 1); const Mesh& upsampledMesh = upsampledModel.meshes.back(); diff --git a/CesiumGeometry/include/CesiumGeometry/QuadtreeTileID.h b/CesiumGeometry/include/CesiumGeometry/QuadtreeTileID.h index 21f2aafa4..5547d099c 100644 --- a/CesiumGeometry/include/CesiumGeometry/QuadtreeTileID.h +++ b/CesiumGeometry/include/CesiumGeometry/QuadtreeTileID.h @@ -5,32 +5,6 @@ namespace CesiumGeometry { class QuadtreeTilingScheme; - /** - * @brief Identifies one of the four children of a quadtree node. - */ - enum class QuadtreeChild { - - /** - * @brief The lower left child node. - */ - LowerLeft = 0, - - /** - * @brief The lower right child node. - */ - LowerRight = 1, - - /** - * @brief The upper left child node. - */ - UpperLeft = 2, - - /** - * @brief The upper right child node. - */ - UpperRight = 3 - }; - /** * @brief Uniquely identifies a node in a quadtree. * @@ -98,6 +72,9 @@ namespace CesiumGeometry { uint32_t y; }; + struct CESIUMGEOMETRY_API UpsampledQuadtreeNode final { + QuadtreeTileID tileID; + }; } namespace std { From d4cea4fced8bb62b692233f585017c3ceed97085 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 25 Jan 2021 11:32:56 +1100 Subject: [PATCH 04/13] Final, doc, examples. --- CesiumGltf/include/CesiumGltf/Accessor.h | 3 +- .../include/CesiumGltf/AccessorSparse.h | 3 +- .../CesiumGltf/AccessorSparseIndices.h | 3 +- .../include/CesiumGltf/AccessorSparseValues.h | 3 +- CesiumGltf/include/CesiumGltf/AccessorSpec.h | 10 +++- CesiumGltf/include/CesiumGltf/AccessorView.h | 46 +++++++++++++++---- CesiumGltf/include/CesiumGltf/Animation.h | 3 +- .../include/CesiumGltf/AnimationChannel.h | 3 +- .../CesiumGltf/AnimationChannelTarget.h | 3 +- .../include/CesiumGltf/AnimationSampler.h | 3 +- CesiumGltf/include/CesiumGltf/Asset.h | 3 +- CesiumGltf/include/CesiumGltf/Buffer.h | 3 +- CesiumGltf/include/CesiumGltf/BufferCesium.h | 6 ++- CesiumGltf/include/CesiumGltf/BufferSpec.h | 10 +++- CesiumGltf/include/CesiumGltf/BufferView.h | 3 +- CesiumGltf/include/CesiumGltf/Camera.h | 3 +- .../include/CesiumGltf/CameraOrthographic.h | 3 +- .../include/CesiumGltf/CameraPerspective.h | 3 +- .../include/CesiumGltf/ExtensibleObject.h | 3 +- CesiumGltf/include/CesiumGltf/Image.h | 3 +- CesiumGltf/include/CesiumGltf/ImageCesium.h | 18 +++++--- CesiumGltf/include/CesiumGltf/ImageSpec.h | 10 +++- CesiumGltf/include/CesiumGltf/JsonValue.h | 3 +- .../CesiumGltf/KHR_draco_mesh_compression.h | 3 +- CesiumGltf/include/CesiumGltf/Library.h | 16 +++++++ CesiumGltf/include/CesiumGltf/Material.h | 3 +- .../CesiumGltf/MaterialNormalTextureInfo.h | 3 +- .../CesiumGltf/MaterialOcclusionTextureInfo.h | 3 +- .../CesiumGltf/MaterialPBRMetallicRoughness.h | 3 +- CesiumGltf/include/CesiumGltf/Mesh.h | 3 +- CesiumGltf/include/CesiumGltf/MeshPrimitive.h | 3 +- CesiumGltf/include/CesiumGltf/Model.h | 3 +- CesiumGltf/include/CesiumGltf/ModelSpec.h | 10 +++- CesiumGltf/include/CesiumGltf/NamedObject.h | 3 +- CesiumGltf/include/CesiumGltf/Node.h | 3 +- CesiumGltf/include/CesiumGltf/Sampler.h | 3 +- CesiumGltf/include/CesiumGltf/Scene.h | 3 +- CesiumGltf/include/CesiumGltf/Skin.h | 3 +- CesiumGltf/include/CesiumGltf/Texture.h | 3 +- CesiumGltf/include/CesiumGltf/TextureInfo.h | 3 +- CesiumGltf/test/TestAccessorView.cpp | 39 ++++++++++++++++ CesiumGltfReader/include/CesiumGltf/Reader.h | 11 +++-- .../include/CesiumGltf/ReaderLibrary.h | 11 +++++ tools/generate-gltf-classes/generate.js | 23 ++++++++-- tools/generate-gltf-classes/glTF.json | 3 ++ 45 files changed, 246 insertions(+), 63 deletions(-) create mode 100644 CesiumGltf/include/CesiumGltf/Library.h create mode 100644 CesiumGltf/test/TestAccessorView.cpp create mode 100644 CesiumGltfReader/include/CesiumGltf/ReaderLibrary.h diff --git a/CesiumGltf/include/CesiumGltf/Accessor.h b/CesiumGltf/include/CesiumGltf/Accessor.h index 5c0290434..11014fdfb 100644 --- a/CesiumGltf/include/CesiumGltf/Accessor.h +++ b/CesiumGltf/include/CesiumGltf/Accessor.h @@ -1,13 +1,14 @@ #pragma once #include "CesiumGltf/AccessorSpec.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { struct Model; /** @copydoc AccessorSpec */ - struct Accessor : public AccessorSpec { + struct CESIUMGLTF_API Accessor final : public AccessorSpec { /** * @brief Computes the number of components for a given accessor type. * diff --git a/CesiumGltf/include/CesiumGltf/AccessorSparse.h b/CesiumGltf/include/CesiumGltf/AccessorSparse.h index f8a494c00..8c1019c1d 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorSparse.h +++ b/CesiumGltf/include/CesiumGltf/AccessorSparse.h @@ -5,13 +5,14 @@ #include "CesiumGltf/AccessorSparseIndices.h" #include "CesiumGltf/AccessorSparseValues.h" #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { /** * @brief Sparse storage of attributes that deviate from their initialization value. */ - struct AccessorSparse : public ExtensibleObject { + struct CESIUMGLTF_API AccessorSparse final : public ExtensibleObject { /** * @brief Number of entries stored in the sparse array. diff --git a/CesiumGltf/include/CesiumGltf/AccessorSparseIndices.h b/CesiumGltf/include/CesiumGltf/AccessorSparseIndices.h index 39b923453..f484a2e6f 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorSparseIndices.h +++ b/CesiumGltf/include/CesiumGltf/AccessorSparseIndices.h @@ -3,13 +3,14 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { /** * @brief Indices of those attributes that deviate from their initialization value. */ - struct AccessorSparseIndices : public ExtensibleObject { + struct CESIUMGLTF_API AccessorSparseIndices final : public ExtensibleObject { enum class ComponentType { UNSIGNED_BYTE = 5121, diff --git a/CesiumGltf/include/CesiumGltf/AccessorSparseValues.h b/CesiumGltf/include/CesiumGltf/AccessorSparseValues.h index 07a7427b4..6c496b544 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorSparseValues.h +++ b/CesiumGltf/include/CesiumGltf/AccessorSparseValues.h @@ -3,13 +3,14 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { /** * @brief Array of size `accessor.sparse.count` times number of components storing the displaced accessor attributes pointed by `accessor.sparse.indices`. */ - struct AccessorSparseValues : public ExtensibleObject { + struct CESIUMGLTF_API AccessorSparseValues final : public ExtensibleObject { /** * @brief The index of the bufferView with sparse values. Referenced bufferView can't have ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER target. diff --git a/CesiumGltf/include/CesiumGltf/AccessorSpec.h b/CesiumGltf/include/CesiumGltf/AccessorSpec.h index 658039b67..7eb9c2fe2 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorSpec.h +++ b/CesiumGltf/include/CesiumGltf/AccessorSpec.h @@ -3,6 +3,7 @@ #pragma once #include "CesiumGltf/AccessorSparse.h" +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include #include @@ -12,7 +13,7 @@ namespace CesiumGltf { /** * @brief A typed view into a bufferView. A bufferView contains raw binary data. An accessor provides a typed view into a bufferView or a subset of a bufferView similar to how WebGL's `vertexAttribPointer()` defines an attribute in a buffer. */ - struct AccessorSpec : public NamedObject { + struct CESIUMGLTF_API AccessorSpec : public NamedObject { enum class ComponentType { BYTE = 5120, @@ -106,5 +107,12 @@ namespace CesiumGltf { */ std::optional sparse; + private: + /** + * @brief This class is not mean to be instantiated directly. Use {@link Accessor} instead. + */ + AccessorSpec() = default; + friend struct Accessor; + }; } diff --git a/CesiumGltf/include/CesiumGltf/AccessorView.h b/CesiumGltf/include/CesiumGltf/AccessorView.h index 5049c5563..1efbd6c59 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorView.h +++ b/CesiumGltf/include/CesiumGltf/AccessorView.h @@ -4,7 +4,13 @@ #include namespace CesiumGltf { - + /** + * @brief Indicates the status of an {@link AccessorView}. + * + * The {@link AccessorView} constructor always completes successfully. However, it may not + * always reflect the actual content of the {@link Accessor}, but instead indicate that + * its {@link AccessorView::size} is 0. This enumeration provides the reason. + */ enum class AccessorViewStatus { /** * @brief This accessor is valid and ready to use. @@ -47,14 +53,10 @@ namespace CesiumGltf { * * It provides the actual accessor data like an array of elements. * The type of the accessor elements is determined by the template - * parameter. Instances are usually created by {@link Accessor::createView}, + * parameter. Instances are usually from an {@link Accessor}, * and the {@link operator[]()} can be used to access the elements: * - * ``` - * CesiumGltf::Model model; - * AccessorView positions = model.accessors[0].createViewcreate(model, accessor); } - AccessorView(const Model& model, int32_t accessorIndex) : + + /** + * @brief Creates a new instance from a given model and accessor index. + * + * If the accessor cannot be viewed, the construct will still complete successfully + * without throwing an exception. However, {@link size} will return 0 and + * {@link status} will indicate what went wrong. + * + * @param model The model to access. + * @param accessorIndex The index of the accessor to view in the model's {@link Model::accessors} list. + */ + AccessorView(const Model& model, int32_t accessorIndex) noexcept : AccessorView() { const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex); diff --git a/CesiumGltf/include/CesiumGltf/Animation.h b/CesiumGltf/include/CesiumGltf/Animation.h index 268d34ab3..be2d6e4fd 100644 --- a/CesiumGltf/include/CesiumGltf/Animation.h +++ b/CesiumGltf/include/CesiumGltf/Animation.h @@ -4,6 +4,7 @@ #include "CesiumGltf/AnimationChannel.h" #include "CesiumGltf/AnimationSampler.h" +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include @@ -11,7 +12,7 @@ namespace CesiumGltf { /** * @brief A keyframe animation. */ - struct Animation : public NamedObject { + struct CESIUMGLTF_API Animation final : public NamedObject { /** * @brief An array of channels, each of which targets an animation's sampler at a node's property. Different channels of the same animation can't have equal targets. diff --git a/CesiumGltf/include/CesiumGltf/AnimationChannel.h b/CesiumGltf/include/CesiumGltf/AnimationChannel.h index 0c3484c20..96fc660d4 100644 --- a/CesiumGltf/include/CesiumGltf/AnimationChannel.h +++ b/CesiumGltf/include/CesiumGltf/AnimationChannel.h @@ -4,13 +4,14 @@ #include "CesiumGltf/AnimationChannelTarget.h" #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { /** * @brief Targets an animation's sampler at a node's property. */ - struct AnimationChannel : public ExtensibleObject { + struct CESIUMGLTF_API AnimationChannel final : public ExtensibleObject { /** * @brief The index of a sampler in this animation used to compute the value for the target. diff --git a/CesiumGltf/include/CesiumGltf/AnimationChannelTarget.h b/CesiumGltf/include/CesiumGltf/AnimationChannelTarget.h index 916eea6b0..6c95148eb 100644 --- a/CesiumGltf/include/CesiumGltf/AnimationChannelTarget.h +++ b/CesiumGltf/include/CesiumGltf/AnimationChannelTarget.h @@ -3,13 +3,14 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { /** * @brief The index of the node and TRS property that an animation channel targets. */ - struct AnimationChannelTarget : public ExtensibleObject { + struct CESIUMGLTF_API AnimationChannelTarget final : public ExtensibleObject { enum class Path { translation, diff --git a/CesiumGltf/include/CesiumGltf/AnimationSampler.h b/CesiumGltf/include/CesiumGltf/AnimationSampler.h index 458ef00fb..f8d2a8fa1 100644 --- a/CesiumGltf/include/CesiumGltf/AnimationSampler.h +++ b/CesiumGltf/include/CesiumGltf/AnimationSampler.h @@ -3,13 +3,14 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { /** * @brief Combines input and output accessors with an interpolation algorithm to define a keyframe graph (but not its target). */ - struct AnimationSampler : public ExtensibleObject { + struct CESIUMGLTF_API AnimationSampler final : public ExtensibleObject { enum class Interpolation { LINEAR, diff --git a/CesiumGltf/include/CesiumGltf/Asset.h b/CesiumGltf/include/CesiumGltf/Asset.h index e107a32ed..69cf43fea 100644 --- a/CesiumGltf/include/CesiumGltf/Asset.h +++ b/CesiumGltf/include/CesiumGltf/Asset.h @@ -3,6 +3,7 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include #include @@ -10,7 +11,7 @@ namespace CesiumGltf { /** * @brief Metadata about the glTF asset. */ - struct Asset : public ExtensibleObject { + struct CESIUMGLTF_API Asset final : public ExtensibleObject { /** * @brief A copyright message suitable for display to credit the content creator. diff --git a/CesiumGltf/include/CesiumGltf/Buffer.h b/CesiumGltf/include/CesiumGltf/Buffer.h index 6d1e90c3d..47a6bf2b9 100644 --- a/CesiumGltf/include/CesiumGltf/Buffer.h +++ b/CesiumGltf/include/CesiumGltf/Buffer.h @@ -2,10 +2,11 @@ #include "CesiumGltf/BufferCesium.h" #include "CesiumGltf/BufferSpec.h" +#include "CesiumGltf/Library.h" namespace CesiumGltf { /** @copydoc BufferSpec */ - struct Buffer : public BufferSpec { + struct CESIUMGLTF_API Buffer final : public BufferSpec { /** * @brief Holds properties that are specific to the glTF loader rather than part of the glTF spec. */ diff --git a/CesiumGltf/include/CesiumGltf/BufferCesium.h b/CesiumGltf/include/CesiumGltf/BufferCesium.h index dce15adeb..4e4ed068a 100644 --- a/CesiumGltf/include/CesiumGltf/BufferCesium.h +++ b/CesiumGltf/include/CesiumGltf/BufferCesium.h @@ -1,9 +1,13 @@ #pragma once +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { - struct BufferCesium final { + /** + * @brief Holds {@link Buffer} properties that are specific to the glTF loader rather than part of the glTF spec. + */ + struct CESIUMGLTF_API BufferCesium final { /** * @brief The buffer's data. */ diff --git a/CesiumGltf/include/CesiumGltf/BufferSpec.h b/CesiumGltf/include/CesiumGltf/BufferSpec.h index d8a5771c1..b3c355e2f 100644 --- a/CesiumGltf/include/CesiumGltf/BufferSpec.h +++ b/CesiumGltf/include/CesiumGltf/BufferSpec.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include #include @@ -11,7 +12,7 @@ namespace CesiumGltf { /** * @brief A buffer points to binary geometry, animation, or skins. */ - struct BufferSpec : public NamedObject { + struct CESIUMGLTF_API BufferSpec : public NamedObject { /** * @brief The uri of the buffer. @@ -25,5 +26,12 @@ namespace CesiumGltf { */ int64_t byteLength = int64_t(); + private: + /** + * @brief This class is not mean to be instantiated directly. Use {@link Buffer} instead. + */ + BufferSpec() = default; + friend struct Buffer; + }; } diff --git a/CesiumGltf/include/CesiumGltf/BufferView.h b/CesiumGltf/include/CesiumGltf/BufferView.h index bc4d23195..9f6816ab4 100644 --- a/CesiumGltf/include/CesiumGltf/BufferView.h +++ b/CesiumGltf/include/CesiumGltf/BufferView.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include #include @@ -10,7 +11,7 @@ namespace CesiumGltf { /** * @brief A view into a buffer generally representing a subset of the buffer. */ - struct BufferView : public NamedObject { + struct CESIUMGLTF_API BufferView final : public NamedObject { enum class Target { ARRAY_BUFFER = 34962, diff --git a/CesiumGltf/include/CesiumGltf/Camera.h b/CesiumGltf/include/CesiumGltf/Camera.h index ce0d56300..e3aa50881 100644 --- a/CesiumGltf/include/CesiumGltf/Camera.h +++ b/CesiumGltf/include/CesiumGltf/Camera.h @@ -4,6 +4,7 @@ #include "CesiumGltf/CameraOrthographic.h" #include "CesiumGltf/CameraPerspective.h" +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include @@ -11,7 +12,7 @@ namespace CesiumGltf { /** * @brief A camera's projection. A node can reference a camera to apply a transform to place the camera in the scene. */ - struct Camera : public NamedObject { + struct CESIUMGLTF_API Camera final : public NamedObject { enum class Type { perspective, diff --git a/CesiumGltf/include/CesiumGltf/CameraOrthographic.h b/CesiumGltf/include/CesiumGltf/CameraOrthographic.h index 46b66a7be..c354bf7f9 100644 --- a/CesiumGltf/include/CesiumGltf/CameraOrthographic.h +++ b/CesiumGltf/include/CesiumGltf/CameraOrthographic.h @@ -3,12 +3,13 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" namespace CesiumGltf { /** * @brief An orthographic camera containing properties to create an orthographic projection matrix. */ - struct CameraOrthographic : public ExtensibleObject { + struct CESIUMGLTF_API CameraOrthographic final : public ExtensibleObject { /** * @brief The floating-point horizontal magnification of the view. Must not be zero. diff --git a/CesiumGltf/include/CesiumGltf/CameraPerspective.h b/CesiumGltf/include/CesiumGltf/CameraPerspective.h index 78be30ca0..af427d1c2 100644 --- a/CesiumGltf/include/CesiumGltf/CameraPerspective.h +++ b/CesiumGltf/include/CesiumGltf/CameraPerspective.h @@ -3,13 +3,14 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { /** * @brief A perspective camera containing properties to create a perspective projection matrix. */ - struct CameraPerspective : public ExtensibleObject { + struct CESIUMGLTF_API CameraPerspective final : public ExtensibleObject { /** * @brief The floating-point aspect ratio of the field of view. diff --git a/CesiumGltf/include/CesiumGltf/ExtensibleObject.h b/CesiumGltf/include/CesiumGltf/ExtensibleObject.h index 79a58b064..c855c6921 100644 --- a/CesiumGltf/include/CesiumGltf/ExtensibleObject.h +++ b/CesiumGltf/include/CesiumGltf/ExtensibleObject.h @@ -1,6 +1,7 @@ #pragma once #include "CesiumGltf/JsonValue.h" +#include "CesiumGltf/Library.h" #include #include @@ -8,7 +9,7 @@ namespace CesiumGltf { /** * @brief The base class for objects in a glTF that have extensions and extras. */ - struct ExtensibleObject { + struct CESIUMGLTF_API ExtensibleObject { // TODO: extras /** diff --git a/CesiumGltf/include/CesiumGltf/Image.h b/CesiumGltf/include/CesiumGltf/Image.h index 9bfd81c23..d34d4aa3d 100644 --- a/CesiumGltf/include/CesiumGltf/Image.h +++ b/CesiumGltf/include/CesiumGltf/Image.h @@ -2,10 +2,11 @@ #include "CesiumGltf/ImageCesium.h" #include "CesiumGltf/ImageSpec.h" +#include "CesiumGltf/Library.h" namespace CesiumGltf { /** @copydoc ImageSpec */ - struct Image : public ImageSpec { + struct CESIUMGLTF_API Image final : public ImageSpec { /** * @brief Holds properties that are specific to the glTF loader rather than part of the glTF spec. */ diff --git a/CesiumGltf/include/CesiumGltf/ImageCesium.h b/CesiumGltf/include/CesiumGltf/ImageCesium.h index f955dbc33..0e446b039 100644 --- a/CesiumGltf/include/CesiumGltf/ImageCesium.h +++ b/CesiumGltf/include/CesiumGltf/ImageCesium.h @@ -1,10 +1,14 @@ #pragma once +#include "CesiumGltf/Library.h" #include #include namespace CesiumGltf { - struct ImageCesium final { + /** + * @brief Holds {@link Image} properties that are specific to the glTF loader rather than part of the glTF spec. + */ + struct CESIUMGLTF_API ImageCesium final { /** * @brief The width of the image in pixels. */ @@ -36,12 +40,12 @@ namespace CesiumGltf { * * The channels and their meaning are as follows: * - * | Number of Channels | Channel Meaning | - * |--------------------|-------------------------| - * | 1 | grey | - * | 2 | grey, alpha | - * | 3 | red, green, blue | - * | 4 | red, green, blue, alpha | + * | Number of Channels | Channel Order and Meaning | + * |--------------------|---------------------------| + * | 1 | grey | + * | 2 | grey, alpha | + * | 3 | red, green, blue | + * | 4 | red, green, blue, alpha | */ std::vector pixelData; }; diff --git a/CesiumGltf/include/CesiumGltf/ImageSpec.h b/CesiumGltf/include/CesiumGltf/ImageSpec.h index d76f42dd0..02769ee68 100644 --- a/CesiumGltf/include/CesiumGltf/ImageSpec.h +++ b/CesiumGltf/include/CesiumGltf/ImageSpec.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include #include @@ -11,7 +12,7 @@ namespace CesiumGltf { /** * @brief Image data used to create a texture. Image can be referenced by URI or `bufferView` index. `mimeType` is required in the latter case. */ - struct ImageSpec : public NamedObject { + struct CESIUMGLTF_API ImageSpec : public NamedObject { enum class MimeType { image_jpeg, @@ -35,5 +36,12 @@ namespace CesiumGltf { */ int32_t bufferView = -1; + private: + /** + * @brief This class is not mean to be instantiated directly. Use {@link Image} instead. + */ + ImageSpec() = default; + friend struct Image; + }; } diff --git a/CesiumGltf/include/CesiumGltf/JsonValue.h b/CesiumGltf/include/CesiumGltf/JsonValue.h index 97fc48a9e..3fa2c3eb3 100644 --- a/CesiumGltf/include/CesiumGltf/JsonValue.h +++ b/CesiumGltf/include/CesiumGltf/JsonValue.h @@ -1,5 +1,6 @@ #pragma once +#include "CesiumGltf/Library.h" #include #include #include @@ -8,7 +9,7 @@ #include namespace CesiumGltf { - class JsonValue final { + class CESIUMGLTF_API JsonValue final { public: using Null = std::nullptr_t; using Number = double; diff --git a/CesiumGltf/include/CesiumGltf/KHR_draco_mesh_compression.h b/CesiumGltf/include/CesiumGltf/KHR_draco_mesh_compression.h index eed688e17..6ed3a992d 100644 --- a/CesiumGltf/include/CesiumGltf/KHR_draco_mesh_compression.h +++ b/CesiumGltf/include/CesiumGltf/KHR_draco_mesh_compression.h @@ -3,6 +3,7 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include #include @@ -10,7 +11,7 @@ namespace CesiumGltf { /** * @brief undefined */ - struct KHR_draco_mesh_compression : public ExtensibleObject { + struct CESIUMGLTF_API KHR_draco_mesh_compression final : public ExtensibleObject { /** * @brief The index of the bufferView. diff --git a/CesiumGltf/include/CesiumGltf/Library.h b/CesiumGltf/include/CesiumGltf/Library.h new file mode 100644 index 000000000..4c2bcd144 --- /dev/null +++ b/CesiumGltf/include/CesiumGltf/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for working with [glTF](https://www.khronos.org/gltf/) models. + */ +namespace CesiumGltf {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) + #ifdef CESIUMGLTF_BUILDING + #define CESIUMGLTF_API __declspec(dllexport) + #else + #define CESIUMGLTF_API __declspec(dllimport) + #endif +#else + #define CESIUMGLTF_API +#endif diff --git a/CesiumGltf/include/CesiumGltf/Material.h b/CesiumGltf/include/CesiumGltf/Material.h index 9d63ad621..5596b7388 100644 --- a/CesiumGltf/include/CesiumGltf/Material.h +++ b/CesiumGltf/include/CesiumGltf/Material.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/MaterialNormalTextureInfo.h" #include "CesiumGltf/MaterialOcclusionTextureInfo.h" #include "CesiumGltf/MaterialPBRMetallicRoughness.h" @@ -14,7 +15,7 @@ namespace CesiumGltf { /** * @brief The material appearance of a primitive. */ - struct Material : public NamedObject { + struct CESIUMGLTF_API Material final : public NamedObject { enum class AlphaMode { OPAQUE, diff --git a/CesiumGltf/include/CesiumGltf/MaterialNormalTextureInfo.h b/CesiumGltf/include/CesiumGltf/MaterialNormalTextureInfo.h index 8bf8dec38..8f2fa5d4d 100644 --- a/CesiumGltf/include/CesiumGltf/MaterialNormalTextureInfo.h +++ b/CesiumGltf/include/CesiumGltf/MaterialNormalTextureInfo.h @@ -2,13 +2,14 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/TextureInfo.h" namespace CesiumGltf { /** * @brief undefined */ - struct MaterialNormalTextureInfo : public TextureInfo { + struct CESIUMGLTF_API MaterialNormalTextureInfo final : public TextureInfo { /** * @brief The scalar multiplier applied to each normal vector of the normal texture. diff --git a/CesiumGltf/include/CesiumGltf/MaterialOcclusionTextureInfo.h b/CesiumGltf/include/CesiumGltf/MaterialOcclusionTextureInfo.h index 5875eada6..917c370cd 100644 --- a/CesiumGltf/include/CesiumGltf/MaterialOcclusionTextureInfo.h +++ b/CesiumGltf/include/CesiumGltf/MaterialOcclusionTextureInfo.h @@ -2,13 +2,14 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/TextureInfo.h" namespace CesiumGltf { /** * @brief undefined */ - struct MaterialOcclusionTextureInfo : public TextureInfo { + struct CESIUMGLTF_API MaterialOcclusionTextureInfo final : public TextureInfo { /** * @brief A scalar multiplier controlling the amount of occlusion applied. diff --git a/CesiumGltf/include/CesiumGltf/MaterialPBRMetallicRoughness.h b/CesiumGltf/include/CesiumGltf/MaterialPBRMetallicRoughness.h index 7b43d3f85..3cc2e13df 100644 --- a/CesiumGltf/include/CesiumGltf/MaterialPBRMetallicRoughness.h +++ b/CesiumGltf/include/CesiumGltf/MaterialPBRMetallicRoughness.h @@ -3,6 +3,7 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include "CesiumGltf/TextureInfo.h" #include #include @@ -11,7 +12,7 @@ namespace CesiumGltf { /** * @brief A set of parameter values that are used to define the metallic-roughness material model from Physically-Based Rendering (PBR) methodology. */ - struct MaterialPBRMetallicRoughness : public ExtensibleObject { + struct CESIUMGLTF_API MaterialPBRMetallicRoughness final : public ExtensibleObject { /** * @brief The material's base color factor. diff --git a/CesiumGltf/include/CesiumGltf/Mesh.h b/CesiumGltf/include/CesiumGltf/Mesh.h index 607831909..e679b6706 100644 --- a/CesiumGltf/include/CesiumGltf/Mesh.h +++ b/CesiumGltf/include/CesiumGltf/Mesh.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/MeshPrimitive.h" #include "CesiumGltf/NamedObject.h" #include @@ -10,7 +11,7 @@ namespace CesiumGltf { /** * @brief A set of primitives to be rendered. A node can contain one mesh. A node's transform places the mesh in the scene. */ - struct Mesh : public NamedObject { + struct CESIUMGLTF_API Mesh final : public NamedObject { /** * @brief An array of primitives, each defining geometry to be rendered with a material. diff --git a/CesiumGltf/include/CesiumGltf/MeshPrimitive.h b/CesiumGltf/include/CesiumGltf/MeshPrimitive.h index 13ff0d94d..2172fab35 100644 --- a/CesiumGltf/include/CesiumGltf/MeshPrimitive.h +++ b/CesiumGltf/include/CesiumGltf/MeshPrimitive.h @@ -3,6 +3,7 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include #include #include @@ -11,7 +12,7 @@ namespace CesiumGltf { /** * @brief Geometry to be rendered with the given material. */ - struct MeshPrimitive : public ExtensibleObject { + struct CESIUMGLTF_API MeshPrimitive final : public ExtensibleObject { enum class Mode { POINTS = 0, diff --git a/CesiumGltf/include/CesiumGltf/Model.h b/CesiumGltf/include/CesiumGltf/Model.h index 886e8f0d9..cdf2582d5 100644 --- a/CesiumGltf/include/CesiumGltf/Model.h +++ b/CesiumGltf/include/CesiumGltf/Model.h @@ -1,10 +1,11 @@ #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/ModelSpec.h" namespace CesiumGltf { /** @copydoc ModelSpec */ - struct Model : public ModelSpec { + struct CESIUMGLTF_API Model : public ModelSpec { /** * @brief Merges another model into this one. * diff --git a/CesiumGltf/include/CesiumGltf/ModelSpec.h b/CesiumGltf/include/CesiumGltf/ModelSpec.h index c169cf018..3e1c272cf 100644 --- a/CesiumGltf/include/CesiumGltf/ModelSpec.h +++ b/CesiumGltf/include/CesiumGltf/ModelSpec.h @@ -10,6 +10,7 @@ #include "CesiumGltf/Camera.h" #include "CesiumGltf/ExtensibleObject.h" #include "CesiumGltf/Image.h" +#include "CesiumGltf/Library.h" #include "CesiumGltf/Material.h" #include "CesiumGltf/Mesh.h" #include "CesiumGltf/Node.h" @@ -25,7 +26,7 @@ namespace CesiumGltf { /** * @brief The root object for a glTF asset. */ - struct ModelSpec : public ExtensibleObject { + struct CESIUMGLTF_API ModelSpec : public ExtensibleObject { /** * @brief Names of glTF extensions used somewhere in this asset. @@ -130,5 +131,12 @@ namespace CesiumGltf { */ std::vector textures; + private: + /** + * @brief This class is not mean to be instantiated directly. Use {@link Model} instead. + */ + ModelSpec() = default; + friend struct Model; + }; } diff --git a/CesiumGltf/include/CesiumGltf/NamedObject.h b/CesiumGltf/include/CesiumGltf/NamedObject.h index 1ddf52308..cbfbeff69 100644 --- a/CesiumGltf/include/CesiumGltf/NamedObject.h +++ b/CesiumGltf/include/CesiumGltf/NamedObject.h @@ -1,6 +1,7 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { @@ -9,7 +10,7 @@ namespace CesiumGltf { * * A named object is also an {@link ExtensibleObject}. */ - struct NamedObject : public ExtensibleObject { + struct CESIUMGLTF_API NamedObject : public ExtensibleObject { /** * @brief The user-defined name of this object. * diff --git a/CesiumGltf/include/CesiumGltf/Node.h b/CesiumGltf/include/CesiumGltf/Node.h index ff9540cbb..230f92111 100644 --- a/CesiumGltf/include/CesiumGltf/Node.h +++ b/CesiumGltf/include/CesiumGltf/Node.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include #include @@ -10,7 +11,7 @@ namespace CesiumGltf { /** * @brief A node in the node hierarchy. When the node contains `skin`, all `mesh.primitives` must contain `JOINTS_0` and `WEIGHTS_0` attributes. A node can have either a `matrix` or any combination of `translation`/`rotation`/`scale` (TRS) properties. TRS properties are converted to matrices and postmultiplied in the `T * R * S` order to compose the transformation matrix; first the scale is applied to the vertices, then the rotation, and then the translation. If none are provided, the transform is the identity. When a node is targeted for animation (referenced by an animation.channel.target), only TRS properties may be present; `matrix` will not be present. */ - struct Node : public NamedObject { + struct CESIUMGLTF_API Node final : public NamedObject { /** * @brief The index of the camera referenced by this node. diff --git a/CesiumGltf/include/CesiumGltf/Sampler.h b/CesiumGltf/include/CesiumGltf/Sampler.h index 1fd97d8be..956e13a7b 100644 --- a/CesiumGltf/include/CesiumGltf/Sampler.h +++ b/CesiumGltf/include/CesiumGltf/Sampler.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include @@ -9,7 +10,7 @@ namespace CesiumGltf { /** * @brief Texture sampler properties for filtering and wrapping modes. */ - struct Sampler : public NamedObject { + struct CESIUMGLTF_API Sampler final : public NamedObject { enum class MagFilter { NEAREST = 9728, diff --git a/CesiumGltf/include/CesiumGltf/Scene.h b/CesiumGltf/include/CesiumGltf/Scene.h index 53771fb45..7ffaa539f 100644 --- a/CesiumGltf/include/CesiumGltf/Scene.h +++ b/CesiumGltf/include/CesiumGltf/Scene.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include #include @@ -10,7 +11,7 @@ namespace CesiumGltf { /** * @brief The root nodes of a scene. */ - struct Scene : public NamedObject { + struct CESIUMGLTF_API Scene final : public NamedObject { /** * @brief The indices of each root node. diff --git a/CesiumGltf/include/CesiumGltf/Skin.h b/CesiumGltf/include/CesiumGltf/Skin.h index f69c1b460..7ed2c2740 100644 --- a/CesiumGltf/include/CesiumGltf/Skin.h +++ b/CesiumGltf/include/CesiumGltf/Skin.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include #include @@ -10,7 +11,7 @@ namespace CesiumGltf { /** * @brief Joints and matrices defining a skin. */ - struct Skin : public NamedObject { + struct CESIUMGLTF_API Skin final : public NamedObject { /** * @brief The index of the accessor containing the floating-point 4x4 inverse-bind matrices. The default is that each matrix is a 4x4 identity matrix, which implies that inverse-bind matrices were pre-applied. diff --git a/CesiumGltf/include/CesiumGltf/Texture.h b/CesiumGltf/include/CesiumGltf/Texture.h index 9767d3f37..7f1f07177 100644 --- a/CesiumGltf/include/CesiumGltf/Texture.h +++ b/CesiumGltf/include/CesiumGltf/Texture.h @@ -2,6 +2,7 @@ // DO NOT EDIT THIS FILE! #pragma once +#include "CesiumGltf/Library.h" #include "CesiumGltf/NamedObject.h" #include @@ -9,7 +10,7 @@ namespace CesiumGltf { /** * @brief A texture and its sampler. */ - struct Texture : public NamedObject { + struct CESIUMGLTF_API Texture final : public NamedObject { /** * @brief The index of the sampler used by this texture. When undefined, a sampler with repeat wrapping and auto filtering should be used. diff --git a/CesiumGltf/include/CesiumGltf/TextureInfo.h b/CesiumGltf/include/CesiumGltf/TextureInfo.h index deda7ae09..eecc20850 100644 --- a/CesiumGltf/include/CesiumGltf/TextureInfo.h +++ b/CesiumGltf/include/CesiumGltf/TextureInfo.h @@ -3,13 +3,14 @@ #pragma once #include "CesiumGltf/ExtensibleObject.h" +#include "CesiumGltf/Library.h" #include namespace CesiumGltf { /** * @brief Reference to a texture. */ - struct TextureInfo : public ExtensibleObject { + struct CESIUMGLTF_API TextureInfo : public ExtensibleObject { /** * @brief The index of the texture. diff --git a/CesiumGltf/test/TestAccessorView.cpp b/CesiumGltf/test/TestAccessorView.cpp new file mode 100644 index 000000000..b84a24cd3 --- /dev/null +++ b/CesiumGltf/test/TestAccessorView.cpp @@ -0,0 +1,39 @@ +#include "catch2/catch.hpp" +#include "CesiumGltf/Model.h" +#include "CesiumGltf/AccessorView.h" +#include + +TEST_CASE("AccessorView construct and read example") { + auto anyOldFunctionToGetAModel = []() { + CesiumGltf::Model model; + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.bufferView = 0; + accessor.componentType = CesiumGltf::Accessor::ComponentType::FLOAT; + accessor.type = CesiumGltf::Accessor::Type::VEC3; + accessor.count = 1; + + CesiumGltf::BufferView& bufferView = model.bufferViews.emplace_back(); + bufferView.buffer = 0; + bufferView.byteLength = accessor.count * sizeof(float) * 3; + + CesiumGltf::Buffer& buffer = model.buffers.emplace_back(); + buffer.byteLength = bufferView.byteLength; + buffer.cesium.data.resize(buffer.byteLength); + + float* p = reinterpret_cast(buffer.cesium.data.data()); + p[0] = 1.0f; + p[1] = 2.0f; + p[2] = 3.0f; + + return model; + }; + + //! [createFromAccessorAndRead] + CesiumGltf::Model model = anyOldFunctionToGetAModel(); + CesiumGltf::AccessorView positions(model, 0); + glm::vec3 firstPosition = positions[0]; + //! [createFromAccessorAndRead] + + CHECK(firstPosition == glm::vec3(1.0f, 2.0f, 3.0f)); +} diff --git a/CesiumGltfReader/include/CesiumGltf/Reader.h b/CesiumGltfReader/include/CesiumGltf/Reader.h index 2d41e5e83..c97ec2fe2 100644 --- a/CesiumGltfReader/include/CesiumGltf/Reader.h +++ b/CesiumGltfReader/include/CesiumGltf/Reader.h @@ -1,5 +1,6 @@ #pragma once +#include "CesiumGltf/ReaderLibrary.h" #include "CesiumGltf/Model.h" #include #include @@ -7,25 +8,25 @@ #include namespace CesiumGltf { - struct ModelReaderResult { + struct CESIUMGLTFREADER_API ModelReaderResult { std::optional model; std::vector errors; std::vector warnings; }; - struct ReadModelOptions { + struct CESIUMGLTFREADER_API ReadModelOptions { bool decodeDataUris = true; bool decodeEmbeddedImages = true; bool decodeDraco = true; }; - ModelReaderResult readModel(const gsl::span& data, const ReadModelOptions& options = ReadModelOptions()); + CESIUMGLTFREADER_API ModelReaderResult readModel(const gsl::span& data, const ReadModelOptions& options = ReadModelOptions()); - struct ImageReaderResult { + struct CESIUMGLTFREADER_API ImageReaderResult { std::optional image; std::vector errors; std::vector warnings; }; - ImageReaderResult readImage(const gsl::span& data); + CESIUMGLTFREADER_API ImageReaderResult readImage(const gsl::span& data); } diff --git a/CesiumGltfReader/include/CesiumGltf/ReaderLibrary.h b/CesiumGltfReader/include/CesiumGltf/ReaderLibrary.h new file mode 100644 index 000000000..4bd5ae889 --- /dev/null +++ b/CesiumGltfReader/include/CesiumGltf/ReaderLibrary.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(_WIN32) && defined(CESIUM_SHARED) + #ifdef CESIUMGLTFREADER_BUILDING + #define CESIUMGLTFREADER_API __declspec(dllexport) + #else + #define CESIUMGLTFREADER_API __declspec(dllimport) + #endif +#else + #define CESIUMGLTFREADER_API +#endif diff --git a/tools/generate-gltf-classes/generate.js b/tools/generate-gltf-classes/generate.js index 26d8a7801..e988ab17e 100644 --- a/tools/generate-gltf-classes/generate.js +++ b/tools/generate-gltf-classes/generate.js @@ -38,9 +38,11 @@ function generate(options, schema) { lodash.flatten(properties.map((property) => property.localTypes)) ); - const headers = lodash.uniq( - [`"CesiumGltf/${base}.h"`, ...lodash.flatten(properties.map((property) => property.headers))] - ); + const headers = lodash.uniq([ + `"CesiumGltf/Library.h"`, + `"CesiumGltf/${base}.h"`, + ...lodash.flatten(properties.map((property) => property.headers)) + ]); headers.sort(); @@ -55,7 +57,7 @@ function generate(options, schema) { /** * @brief ${schema.description} */ - struct ${name}${thisConfig.toBeInherited ? "Spec" : ""} : public ${base} { + struct CESIUMGLTF_API ${name}${thisConfig.toBeInherited ? "Spec" : (thisConfig.isBaseClass ? "" : " final")} : public ${base} { ${indent(localTypes.join("\n\n"), 16)} ${indent( @@ -65,7 +67,7 @@ function generate(options, schema) { .join("\n\n"), 16 )} - + ${thisConfig.toBeInherited ? privateSpecConstructor(name) : ""} }; } `; @@ -224,4 +226,15 @@ function formatReaderPropertyImpl(property) { return `if ("${property.name}"s == str) return property("${property.name}", this->_${property.name}, o.${property.name});`; } +function privateSpecConstructor(name) { + return ` + private: + /** + * @brief This class is not mean to be instantiated directly. Use {@link ${name}} instead. + */ + ${name}Spec() = default; + friend struct ${name}; + `; +} + module.exports = generate; diff --git a/tools/generate-gltf-classes/glTF.json b/tools/generate-gltf-classes/glTF.json index 98b43b0c2..91d74ee05 100644 --- a/tools/generate-gltf-classes/glTF.json +++ b/tools/generate-gltf-classes/glTF.json @@ -18,6 +18,9 @@ }, "Accessor": { "toBeInherited": true + }, + "Texture Info": { + "isBaseClass": true } }, "extensions": [ From 4eff25045a573ac3bda8b3aa7ff7491a97e9494e Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 25 Jan 2021 17:41:32 +1100 Subject: [PATCH 05/13] Fix crash caused by runaway refinement. --- .../include/Cesium3DTiles/RasterMappedTo3DTile.h | 1 + Cesium3DTiles/src/RasterMappedTo3DTile.cpp | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Cesium3DTiles/include/Cesium3DTiles/RasterMappedTo3DTile.h b/Cesium3DTiles/include/Cesium3DTiles/RasterMappedTo3DTile.h index d932b4cbe..ce397dfb0 100644 --- a/Cesium3DTiles/include/Cesium3DTiles/RasterMappedTo3DTile.h +++ b/Cesium3DTiles/include/Cesium3DTiles/RasterMappedTo3DTile.h @@ -187,6 +187,7 @@ namespace Cesium3DTiles { glm::dvec2 _translation; glm::dvec2 _scale; AttachmentState _state; + bool _originalFailed; }; } diff --git a/Cesium3DTiles/src/RasterMappedTo3DTile.cpp b/Cesium3DTiles/src/RasterMappedTo3DTile.cpp index 54f6d2bb5..8bef69884 100644 --- a/Cesium3DTiles/src/RasterMappedTo3DTile.cpp +++ b/Cesium3DTiles/src/RasterMappedTo3DTile.cpp @@ -19,19 +19,24 @@ namespace Cesium3DTiles { _textureCoordinateRectangle(textureCoordinateRectangle), _translation(0.0, 0.0), _scale(1.0, 1.0), - _state(AttachmentState::Unattached) + _state(AttachmentState::Unattached), + _originalFailed(false) { } RasterMappedTo3DTile::MoreDetailAvailable RasterMappedTo3DTile::update(Tile& tile) { if (this->getState() == AttachmentState::Attached) { - return this->_pReadyTile && this->_pReadyTile->getID().level < this->_pReadyTile->getOverlay().getTileProvider()->getMaximumLevel() + return !this->_originalFailed && this->_pReadyTile && this->_pReadyTile->getID().level < this->_pReadyTile->getOverlay().getTileProvider()->getMaximumLevel() ? MoreDetailAvailable::Yes : MoreDetailAvailable::No; } // If the loading tile has failed, try its parent. while (this->_pLoadingTile && this->_pLoadingTile->getState() == RasterOverlayTile::LoadState::Failed && this->_pLoadingTile->getID().level > 0) { + // Note when our original tile fails to load so that we don't report more data available. + // This means - by design - we won't refine past a failed tile. + this->_originalFailed = true; + CesiumGeometry::QuadtreeTileID thisID = this->_pLoadingTile->getID(); CesiumGeometry::QuadtreeTileID parentID(thisID.level - 1, thisID.x >> 1, thisID.y >> 1); this->_pLoadingTile = this->_pLoadingTile->getOverlay().getTileProvider()->getTile(parentID); @@ -52,7 +57,7 @@ namespace Cesium3DTiles { this->_state = AttachmentState::Unattached; } - // Mark the loading tile read. + // Mark the loading tile ready. this->_pReadyTile = this->_pLoadingTile; this->_pLoadingTile = nullptr; @@ -119,7 +124,7 @@ namespace Cesium3DTiles { if (this->_pLoadingTile) { return MoreDetailAvailable::Unknown; } else { - return this->_pReadyTile && this->_pReadyTile->getID().level < this->_pReadyTile->getOverlay().getTileProvider()->getMaximumLevel() + return !this->_originalFailed && this->_pReadyTile && this->_pReadyTile->getID().level < this->_pReadyTile->getOverlay().getTileProvider()->getMaximumLevel() ? MoreDetailAvailable::Yes : MoreDetailAvailable::No; } From 05d626285be2bf8b3518c216c42a07a0211641da Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 25 Jan 2021 22:43:34 +1100 Subject: [PATCH 06/13] Add AccessorVisitor. I'm not quite convinced this is the right approach yet. --- CesiumGltf/include/CesiumGltf/AccessorView.h | 1 - .../include/CesiumGltf/AccessorVisitor.h | 222 ++++++++++++++++++ 2 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 CesiumGltf/include/CesiumGltf/AccessorVisitor.h diff --git a/CesiumGltf/include/CesiumGltf/AccessorView.h b/CesiumGltf/include/CesiumGltf/AccessorView.h index 1efbd6c59..9a9f29a41 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorView.h +++ b/CesiumGltf/include/CesiumGltf/AccessorView.h @@ -122,7 +122,6 @@ namespace CesiumGltf { this->create(model, accessor); } - /** * @brief Creates a new instance from a given model and accessor index. * diff --git a/CesiumGltf/include/CesiumGltf/AccessorVisitor.h b/CesiumGltf/include/CesiumGltf/AccessorVisitor.h new file mode 100644 index 000000000..8478ac354 --- /dev/null +++ b/CesiumGltf/include/CesiumGltf/AccessorVisitor.h @@ -0,0 +1,222 @@ +#pragma once + +#include "CesiumGltf/AccessorView.h" + +namespace CesiumGltf { + + struct AccessorTypes { + #pragma pack(push, 1) + + template + struct SCALAR { + T value[1]; + }; + + template + struct VEC2 { + T value[2]; + }; + + template + struct VEC3 { + T value[3]; + }; + + template + struct VEC4 { + T value[4]; + }; + + template + struct MAT2 { + T value[4]; + }; + + template + struct MAT3 { + T value[9]; + }; + + template + struct MAT4 { + T value[9]; + }; + + #pragma pack(pop) + }; + + template + class AccessorVisitor { + public: + using ResultType = std::invoke_result_t; + + /** + * @brief Construct a new instance not pointing to any data. + * + * The new instance will have a {@link size} of 0 and a {@link status} of `AccessorViewStatus::InvalidAccessorIndex`. + */ + AccessorVisitor(TVisitor&& visitor) : + _visitor(std::forward(visitor)), + _pDispatcher(std::make_unique>(AccessorView())), + _size(0) + { + } + + /** + * @brief Creates a new instance from a given model and {@link Accessor}. + * + * If the accessor cannot be viewed, the construct will still complete successfully + * without throwing an exception. However, {@link size} will return 0 and + * {@link status} will indicate what went wrong. + * + * @param model The model to access. + * @param accessor The accessor to view. + * @param visitor The functor to receive callbacks on calls to {@link visit}. + */ + AccessorVisitor(const Model& model, const Accessor& accessor, TVisitor&& visitor) noexcept : + AccessorVisitor(std::forward(visitor)) + { + this->create(model, accessor); + } + + /** + * @brief Creates a new instance from a given model and accessor index. + * + * If the accessor cannot be viewed, the construct will still complete successfully + * without throwing an exception. However, {@link size} will return 0 and + * {@link status} will indicate what went wrong. + * + * @param model The model to access. + * @param accessorIndex The index of the accessor to view in the model's {@link Model::accessors} list. + * @param visitor The functor to receive callbacks on calls to {@link visit}. + */ + AccessorVisitor(const Model& model, int32_t accessorIndex, TVisitor&& visitor) noexcept : + AccessorVisitor(std::forward(visitor)) + { + const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex); + if (!pAccessor) { + return; + } + + this->create(model, *pAccessor); + + this->_size = this->_pDispatcher->size(); + } + + ResultType visit(int64_t i) { + return this->_pDispatcher->dispatch(this->_visitor, i); + } + + int64_t size() const noexcept { + return this->_size; + } + + TVisitor& getVisitor() noexcept { + return this->_visitor; + } + + const TVisitor& getVisitor() const noexcept { + return this->_visitor; + } + + private: + class IDispatcher { + public: + virtual ~IDispatcher() = default; + virtual ResultType dispatch(TVisitor& visitor, int64_t i) = 0; + virtual int64_t size() const = 0; + }; + + template + class Dispatcher : public IDispatcher { + public: + Dispatcher(const AccessorView& view) : + _view(view) + { + } + + virtual ResultType dispatch(TVisitor& visitor, int64_t i) override { + return visitor(i, this->_view[i]); + } + + virtual int64_t size() const override { + return this->_view.size(); + } + + private: + AccessorView _view; + }; + + template + void create(const Model& model, const Accessor& accessor) { + switch (accessor.type) { + case Accessor::Type::SCALAR: + this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); + break; + case Accessor::Type::VEC2: + this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); + break; + case Accessor::Type::VEC3: + this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); + break; + case Accessor::Type::VEC4: + this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); + break; + case Accessor::Type::MAT2: + this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); + break; + case Accessor::Type::MAT3: + this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); + break; + case Accessor::Type::MAT4: + this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); + break; + } + } + + void create(const Model& model, const Accessor& accessor) { + switch (accessor.componentType) { + case Accessor::ComponentType::BYTE: + this->create(model, accessor); + break; + case Accessor::ComponentType::UNSIGNED_BYTE: + this->create(model, accessor); + break; + case Accessor::ComponentType::SHORT: + this->create(model, accessor); + break; + case Accessor::ComponentType::UNSIGNED_SHORT: + this->create(model, accessor); + break; + case Accessor::ComponentType::UNSIGNED_INT: + this->create(model, accessor); + break; + case Accessor::ComponentType::FLOAT: + this->create(model, accessor); + break; + } + } + + // TODO: All Dispatcher will be the same size, so we should reserve + // that much space and use placement new to avoid a heap allocation. + TVisitor _visitor; + std::unique_ptr _pDispatcher; + int64_t _size; + }; + + template + AccessorVisitor createAccessorVisitor(TVisitor&& visitor) { + return AccessorVIsitor(std::forward(visitor)); + } + + template + AccessorVisitor createAccessorVisitor(const Model& model, const Accessor& accessor, TVisitor&& visitor) { + return AccessorVIsitor(model, accessor, std::forward(visitor)); + } + + template + AccessorVisitor createAccessorVisitor(const Model& model, int32_t accessorIndex, TVisitor&& visitor) { + return AccessorVisitor(model, accessorIndex, std::forward(visitor)); + } + +} From 358e2a5b2d4491d1f3ccc5f1d89954326a8fbf21 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 25 Jan 2021 23:56:38 +1100 Subject: [PATCH 07/13] Remove AccessorView, replace with an AccessorView helper. --- CesiumGltf/include/CesiumGltf/AccessorView.h | 123 ++++++++++ .../include/CesiumGltf/AccessorVisitor.h | 222 ------------------ 2 files changed, 123 insertions(+), 222 deletions(-) delete mode 100644 CesiumGltf/include/CesiumGltf/AccessorVisitor.h diff --git a/CesiumGltf/include/CesiumGltf/AccessorView.h b/CesiumGltf/include/CesiumGltf/AccessorView.h index 9a9f29a41..a8a25c56e 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorView.h +++ b/CesiumGltf/include/CesiumGltf/AccessorView.h @@ -227,4 +227,127 @@ namespace CesiumGltf { } }; + namespace Impl { + template + std::invoke_result_t> createAccessorView(const Model& model, const Accessor& accessor, TCallback&& callback) { + switch (accessor.type) { + case Accessor::Type::SCALAR: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::VEC2: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::VEC3: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::VEC4: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::MAT2: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::MAT3: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::MAT4: + return callback(AccessorView>(model, accessor)); + default: + return callback(AccessorView()); + } + } + } + + /** + * @brief Contains types that may optionally be used with {@link AccessorView} for various {@link Accessor::componentType} values. + */ + struct AccessorTypes { + #pragma pack(push, 1) + + template + struct SCALAR { + T value[1]; + }; + + template + struct VEC2 { + T value[2]; + }; + + template + struct VEC3 { + T value[3]; + }; + + template + struct VEC4 { + T value[4]; + }; + + template + struct MAT2 { + T value[4]; + }; + + template + struct MAT3 { + T value[9]; + }; + + template + struct MAT4 { + T value[9]; + }; + + #pragma pack(pop) + }; + + /** + * @brief Creates an appropriate {@link AccessorView} for a given accessor. + * + * The created accessor is provided via a callback, which is a function that can be + * invoked with all possible {@link AccessorView} types. If an accessor cannot be + * created, the callback will be invoked with `AccessorView`. + * + * @tparam TCallback The callback. + * @param model The model to access. + * @param accessor The accessor to view. + * @param callback The callback that receives the created accessor. + * @return The value returned by the callback. + */ + template + std::invoke_result_t> createAccessorView(const Model& model, const Accessor& accessor, TCallback&& callback) { + switch (accessor.componentType) { + case Accessor::ComponentType::BYTE: + return ::CesiumGltf::Impl::createAccessorView(model, accessor, std::forward(callback)); + case Accessor::ComponentType::UNSIGNED_BYTE: + return ::CesiumGltf::Impl::createAccessorView(model, accessor, std::forward(callback)); + case Accessor::ComponentType::SHORT: + return ::CesiumGltf::Impl::createAccessorView(model, accessor, std::forward(callback)); + case Accessor::ComponentType::UNSIGNED_SHORT: + return ::CesiumGltf::Impl::createAccessorView(model, accessor, std::forward(callback)); + case Accessor::ComponentType::UNSIGNED_INT: + return ::CesiumGltf::Impl::createAccessorView(model, accessor, std::forward(callback)); + case Accessor::ComponentType::FLOAT: + return ::CesiumGltf::Impl::createAccessorView(model, accessor, std::forward(callback)); + default: + return callback(AccessorView()); + } + } + + /** + * @brief Creates an appropriate {@link AccessorView} for a given accessor. + * + * The created accessor is provided via a callback, which is a function that can be + * invoked with all possible {@link AccessorView} types. If an accessor cannot be + * created, the callback will be invoked with `AccessorView`. + * + * @tparam TCallback The callback. + * @param model The model to access. + * @param accessorIndex The index of the accessor to view in {@link Model::accessors}. + * @param callback The callback that receives the created accessor. + * @return The value returned by the callback. + */ + template + std::invoke_result_t> createAccessorView(const Model& model, int32_t accessorIndex, TCallback&& callback) { + const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex); + if (!pAccessor) { + return callback(AccessorView()); + } + + return createAccessorView(model, *pAccessor, callback); + } } diff --git a/CesiumGltf/include/CesiumGltf/AccessorVisitor.h b/CesiumGltf/include/CesiumGltf/AccessorVisitor.h deleted file mode 100644 index 8478ac354..000000000 --- a/CesiumGltf/include/CesiumGltf/AccessorVisitor.h +++ /dev/null @@ -1,222 +0,0 @@ -#pragma once - -#include "CesiumGltf/AccessorView.h" - -namespace CesiumGltf { - - struct AccessorTypes { - #pragma pack(push, 1) - - template - struct SCALAR { - T value[1]; - }; - - template - struct VEC2 { - T value[2]; - }; - - template - struct VEC3 { - T value[3]; - }; - - template - struct VEC4 { - T value[4]; - }; - - template - struct MAT2 { - T value[4]; - }; - - template - struct MAT3 { - T value[9]; - }; - - template - struct MAT4 { - T value[9]; - }; - - #pragma pack(pop) - }; - - template - class AccessorVisitor { - public: - using ResultType = std::invoke_result_t; - - /** - * @brief Construct a new instance not pointing to any data. - * - * The new instance will have a {@link size} of 0 and a {@link status} of `AccessorViewStatus::InvalidAccessorIndex`. - */ - AccessorVisitor(TVisitor&& visitor) : - _visitor(std::forward(visitor)), - _pDispatcher(std::make_unique>(AccessorView())), - _size(0) - { - } - - /** - * @brief Creates a new instance from a given model and {@link Accessor}. - * - * If the accessor cannot be viewed, the construct will still complete successfully - * without throwing an exception. However, {@link size} will return 0 and - * {@link status} will indicate what went wrong. - * - * @param model The model to access. - * @param accessor The accessor to view. - * @param visitor The functor to receive callbacks on calls to {@link visit}. - */ - AccessorVisitor(const Model& model, const Accessor& accessor, TVisitor&& visitor) noexcept : - AccessorVisitor(std::forward(visitor)) - { - this->create(model, accessor); - } - - /** - * @brief Creates a new instance from a given model and accessor index. - * - * If the accessor cannot be viewed, the construct will still complete successfully - * without throwing an exception. However, {@link size} will return 0 and - * {@link status} will indicate what went wrong. - * - * @param model The model to access. - * @param accessorIndex The index of the accessor to view in the model's {@link Model::accessors} list. - * @param visitor The functor to receive callbacks on calls to {@link visit}. - */ - AccessorVisitor(const Model& model, int32_t accessorIndex, TVisitor&& visitor) noexcept : - AccessorVisitor(std::forward(visitor)) - { - const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex); - if (!pAccessor) { - return; - } - - this->create(model, *pAccessor); - - this->_size = this->_pDispatcher->size(); - } - - ResultType visit(int64_t i) { - return this->_pDispatcher->dispatch(this->_visitor, i); - } - - int64_t size() const noexcept { - return this->_size; - } - - TVisitor& getVisitor() noexcept { - return this->_visitor; - } - - const TVisitor& getVisitor() const noexcept { - return this->_visitor; - } - - private: - class IDispatcher { - public: - virtual ~IDispatcher() = default; - virtual ResultType dispatch(TVisitor& visitor, int64_t i) = 0; - virtual int64_t size() const = 0; - }; - - template - class Dispatcher : public IDispatcher { - public: - Dispatcher(const AccessorView& view) : - _view(view) - { - } - - virtual ResultType dispatch(TVisitor& visitor, int64_t i) override { - return visitor(i, this->_view[i]); - } - - virtual int64_t size() const override { - return this->_view.size(); - } - - private: - AccessorView _view; - }; - - template - void create(const Model& model, const Accessor& accessor) { - switch (accessor.type) { - case Accessor::Type::SCALAR: - this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); - break; - case Accessor::Type::VEC2: - this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); - break; - case Accessor::Type::VEC3: - this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); - break; - case Accessor::Type::VEC4: - this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); - break; - case Accessor::Type::MAT2: - this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); - break; - case Accessor::Type::MAT3: - this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); - break; - case Accessor::Type::MAT4: - this->_pDispatcher = std::make_unique>>(AccessorView>(model, accessor)); - break; - } - } - - void create(const Model& model, const Accessor& accessor) { - switch (accessor.componentType) { - case Accessor::ComponentType::BYTE: - this->create(model, accessor); - break; - case Accessor::ComponentType::UNSIGNED_BYTE: - this->create(model, accessor); - break; - case Accessor::ComponentType::SHORT: - this->create(model, accessor); - break; - case Accessor::ComponentType::UNSIGNED_SHORT: - this->create(model, accessor); - break; - case Accessor::ComponentType::UNSIGNED_INT: - this->create(model, accessor); - break; - case Accessor::ComponentType::FLOAT: - this->create(model, accessor); - break; - } - } - - // TODO: All Dispatcher will be the same size, so we should reserve - // that much space and use placement new to avoid a heap allocation. - TVisitor _visitor; - std::unique_ptr _pDispatcher; - int64_t _size; - }; - - template - AccessorVisitor createAccessorVisitor(TVisitor&& visitor) { - return AccessorVIsitor(std::forward(visitor)); - } - - template - AccessorVisitor createAccessorVisitor(const Model& model, const Accessor& accessor, TVisitor&& visitor) { - return AccessorVIsitor(model, accessor, std::forward(visitor)); - } - - template - AccessorVisitor createAccessorVisitor(const Model& model, int32_t accessorIndex, TVisitor&& visitor) { - return AccessorVisitor(model, accessorIndex, std::forward(visitor)); - } - -} From 549ed2979ca8660b37240fcb72e485b531b98e96 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Jan 2021 11:31:30 -0500 Subject: [PATCH 08/13] upgrade draco index --- CesiumGltfReader/src/decodeDraco.cpp | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CesiumGltfReader/src/decodeDraco.cpp b/CesiumGltfReader/src/decodeDraco.cpp index b5dda07e7..a56f1086e 100644 --- a/CesiumGltfReader/src/decodeDraco.cpp +++ b/CesiumGltfReader/src/decodeDraco.cpp @@ -96,6 +96,35 @@ namespace { pIndicesAccessor->count = pMesh->num_faces() * 3; } + draco::PointIndex::ValueType numPoint = pMesh->num_points(); + Accessor::ComponentType supposedComponentType = Accessor::ComponentType::BYTE; + if (numPoint <= + static_cast(std::numeric_limits::max())) + { + supposedComponentType = Accessor::ComponentType::BYTE; + } else if (numPoint <= + static_cast(std::numeric_limits::max())) + { + supposedComponentType = Accessor::ComponentType::UNSIGNED_BYTE; + } else if (numPoint <= + static_cast(std::numeric_limits::max())) + { + supposedComponentType = Accessor::ComponentType::UNSIGNED_SHORT; + } else if (numPoint <= + static_cast(std::numeric_limits::max())) + { + supposedComponentType = Accessor::ComponentType::UNSIGNED_SHORT; + } else if (numPoint <= + static_cast(std::numeric_limits::max())) { + supposedComponentType = Accessor::ComponentType::UNSIGNED_INT; + } else { + supposedComponentType = Accessor::ComponentType::FLOAT; + } + + if (static_cast(supposedComponentType) > static_cast(pIndicesAccessor->componentType)) { + pIndicesAccessor->componentType = supposedComponentType; + } + pIndicesAccessor->bufferView = static_cast(model.bufferViews.size()); BufferView& indicesBufferView = model.bufferViews.emplace_back(); From b8a22346b45a798d5ab01f1bbc14e8080a121ac0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Jan 2021 17:20:17 -0500 Subject: [PATCH 09/13] only use unsigned type for draco indices --- CesiumGltfReader/src/decodeDraco.cpp | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/CesiumGltfReader/src/decodeDraco.cpp b/CesiumGltfReader/src/decodeDraco.cpp index a56f1086e..6ee739e45 100644 --- a/CesiumGltfReader/src/decodeDraco.cpp +++ b/CesiumGltfReader/src/decodeDraco.cpp @@ -98,27 +98,15 @@ namespace { draco::PointIndex::ValueType numPoint = pMesh->num_points(); Accessor::ComponentType supposedComponentType = Accessor::ComponentType::BYTE; - if (numPoint <= - static_cast(std::numeric_limits::max())) - { - supposedComponentType = Accessor::ComponentType::BYTE; - } else if (numPoint <= - static_cast(std::numeric_limits::max())) - { + if (numPoint < static_cast(std::numeric_limits::max())) { supposedComponentType = Accessor::ComponentType::UNSIGNED_BYTE; - } else if (numPoint <= - static_cast(std::numeric_limits::max())) - { + } else if (numPoint < static_cast(std::numeric_limits::max())) { supposedComponentType = Accessor::ComponentType::UNSIGNED_SHORT; - } else if (numPoint <= - static_cast(std::numeric_limits::max())) - { - supposedComponentType = Accessor::ComponentType::UNSIGNED_SHORT; - } else if (numPoint <= - static_cast(std::numeric_limits::max())) { + } else if (numPoint < static_cast(std::numeric_limits::max())) { supposedComponentType = Accessor::ComponentType::UNSIGNED_INT; } else { - supposedComponentType = Accessor::ComponentType::FLOAT; + readModel.warnings.emplace_back("Primitive indices accessor's required component type is over the maximum of UNSIGNED_INT."); + return; } if (static_cast(supposedComponentType) > static_cast(pIndicesAccessor->componentType)) { From 1087f4fc6ce60007e19e148fdf44987eea840f7b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Jan 2021 17:38:02 -0500 Subject: [PATCH 10/13] initialize draco accessor index to be unsigned byte --- CesiumGltfReader/src/decodeDraco.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CesiumGltfReader/src/decodeDraco.cpp b/CesiumGltfReader/src/decodeDraco.cpp index 6ee739e45..88cbf2a71 100644 --- a/CesiumGltfReader/src/decodeDraco.cpp +++ b/CesiumGltfReader/src/decodeDraco.cpp @@ -97,7 +97,7 @@ namespace { } draco::PointIndex::ValueType numPoint = pMesh->num_points(); - Accessor::ComponentType supposedComponentType = Accessor::ComponentType::BYTE; + Accessor::ComponentType supposedComponentType = Accessor::ComponentType::UNSIGNED_BYTE; if (numPoint < static_cast(std::numeric_limits::max())) { supposedComponentType = Accessor::ComponentType::UNSIGNED_BYTE; } else if (numPoint < static_cast(std::numeric_limits::max())) { From fab67810d6ea2c4ed89265da04966baccfca5884 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Jan 2021 17:41:30 -0500 Subject: [PATCH 11/13] use unsigned int if num of draco vertices over max uint16_t --- CesiumGltfReader/src/decodeDraco.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CesiumGltfReader/src/decodeDraco.cpp b/CesiumGltfReader/src/decodeDraco.cpp index 88cbf2a71..2e953a78e 100644 --- a/CesiumGltfReader/src/decodeDraco.cpp +++ b/CesiumGltfReader/src/decodeDraco.cpp @@ -102,12 +102,9 @@ namespace { supposedComponentType = Accessor::ComponentType::UNSIGNED_BYTE; } else if (numPoint < static_cast(std::numeric_limits::max())) { supposedComponentType = Accessor::ComponentType::UNSIGNED_SHORT; - } else if (numPoint < static_cast(std::numeric_limits::max())) { - supposedComponentType = Accessor::ComponentType::UNSIGNED_INT; } else { - readModel.warnings.emplace_back("Primitive indices accessor's required component type is over the maximum of UNSIGNED_INT."); - return; - } + supposedComponentType = Accessor::ComponentType::UNSIGNED_INT; + } if (static_cast(supposedComponentType) > static_cast(pIndicesAccessor->componentType)) { pIndicesAccessor->componentType = supposedComponentType; From 8bc5d739591f0ced041dd530278b1fabb2b07496 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Fri, 29 Jan 2021 13:34:48 +1100 Subject: [PATCH 12/13] Fix gcc/clang build errors. --- CesiumGltf/include/CesiumGltf/AccessorView.h | 52 ++++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/CesiumGltf/include/CesiumGltf/AccessorView.h b/CesiumGltf/include/CesiumGltf/AccessorView.h index a8a25c56e..1f4d6a09a 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorView.h +++ b/CesiumGltf/include/CesiumGltf/AccessorView.h @@ -227,30 +227,6 @@ namespace CesiumGltf { } }; - namespace Impl { - template - std::invoke_result_t> createAccessorView(const Model& model, const Accessor& accessor, TCallback&& callback) { - switch (accessor.type) { - case Accessor::Type::SCALAR: - return callback(AccessorView>(model, accessor)); - case Accessor::Type::VEC2: - return callback(AccessorView>(model, accessor)); - case Accessor::Type::VEC3: - return callback(AccessorView>(model, accessor)); - case Accessor::Type::VEC4: - return callback(AccessorView>(model, accessor)); - case Accessor::Type::MAT2: - return callback(AccessorView>(model, accessor)); - case Accessor::Type::MAT3: - return callback(AccessorView>(model, accessor)); - case Accessor::Type::MAT4: - return callback(AccessorView>(model, accessor)); - default: - return callback(AccessorView()); - } - } - } - /** * @brief Contains types that may optionally be used with {@link AccessorView} for various {@link Accessor::componentType} values. */ @@ -295,6 +271,30 @@ namespace CesiumGltf { #pragma pack(pop) }; + namespace Impl { + template + std::invoke_result_t> createAccessorView(const Model& model, const Accessor& accessor, TCallback&& callback) { + switch (accessor.type) { + case Accessor::Type::SCALAR: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::VEC2: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::VEC3: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::VEC4: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::MAT2: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::MAT3: + return callback(AccessorView>(model, accessor)); + case Accessor::Type::MAT4: + return callback(AccessorView>(model, accessor)); + default: + return callback(AccessorView()); + } + } + } + /** * @brief Creates an appropriate {@link AccessorView} for a given accessor. * @@ -324,7 +324,7 @@ namespace CesiumGltf { case Accessor::ComponentType::FLOAT: return ::CesiumGltf::Impl::createAccessorView(model, accessor, std::forward(callback)); default: - return callback(AccessorView()); + return callback(AccessorView()); } } @@ -345,7 +345,7 @@ namespace CesiumGltf { std::invoke_result_t> createAccessorView(const Model& model, int32_t accessorIndex, TCallback&& callback) { const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex); if (!pAccessor) { - return callback(AccessorView()); + return callback(AccessorView()); } return createAccessorView(model, *pAccessor, callback); From 13ce898f6fd4341cea5d49c0bff70c25f5ab9ad7 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 2 Feb 2021 11:47:13 +1100 Subject: [PATCH 13/13] Fix copy/paste fail. --- CesiumGltf/include/CesiumGltf/AccessorView.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CesiumGltf/include/CesiumGltf/AccessorView.h b/CesiumGltf/include/CesiumGltf/AccessorView.h index 1f4d6a09a..229da9a8a 100644 --- a/CesiumGltf/include/CesiumGltf/AccessorView.h +++ b/CesiumGltf/include/CesiumGltf/AccessorView.h @@ -265,7 +265,7 @@ namespace CesiumGltf { template struct MAT4 { - T value[9]; + T value[16]; }; #pragma pack(pop)