Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into ref-counted-thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
kring committed Feb 26, 2024
2 parents 1e7af45 + 6c48779 commit 23c1cc8
Show file tree
Hide file tree
Showing 18 changed files with 1,004 additions and 172 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

##### Additions :tada:

- Added `KhrTextureTransform`, a utility class that parses the `KHR_texture_transform` glTF extension and reports whether it is valid. UVs may be transformed on the CPU using `applyTransform`.
- Added `applyKhrTextureTransformExtension` to the constructors of `FeatureIdTextureView` and `PropertyTexturePropertyView`. When true, the views will automatically transform texture coordinates before retrieving features and metadata. This is false by default to avoid breaking existing implementations.
- Added `getTextureTransform` methods to `FeatureIdTextureView` and `PropertyTexturePropertyView`.
- Added `contains` method to `BoundingSphere`.
- Added `GlobeRectangle::MAXIMUM` static field.
- Added `ReferenceCountedThreadSafe` type alias.
Expand Down
5 changes: 4 additions & 1 deletion Cesium3DTilesSelection/src/Tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,10 @@ int64_t Tile::computeByteSize() const noexcept {
bytes -= bufferViews[size_t(bufferView)].byteLength;
}

bytes += int64_t(image.cesium.pixelData.size());
// lastKnownSizeInBytes is set in
// TilesetContentManager::ContentKindSetter, if not sooner (e.g., by the
// renderer implementation).
bytes += image.cesium.lastKnownSizeInBytes;
}
}

Expand Down
11 changes: 11 additions & 0 deletions Cesium3DTilesSelection/src/TilesetContentManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ struct ContentKindSetter {
}

void operator()(CesiumGltf::Model&& model) {
for (CesiumGltf::Image& image : model.images) {
// If the image size hasn't been overridden, store the pixelData
// size now. We'll be adding this number to our total memory usage soon,
// and remove it when the tile is later unloaded, and we must use
// the same size in each case.
if (image.cesium.lastKnownSizeInBytes < 0) {
image.cesium.lastKnownSizeInBytes =
int64_t(image.cesium.pixelData.size());
}
}

auto pRenderContent = std::make_unique<TileRenderContent>(std::move(model));
pRenderContent->setRenderResources(pRenderResources);
if (rasterOverlayDetails) {
Expand Down
72 changes: 61 additions & 11 deletions CesiumGltf/include/CesiumGltf/FeatureIdTextureView.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#pragma once

#include "CesiumGltf/FeatureIdTexture.h"
#include "CesiumGltf/Image.h"
#include "CesiumGltf/ImageCesium.h"
#include "CesiumGltf/KhrTextureTransform.h"
#include "CesiumGltf/Model.h"
#include "CesiumGltf/Texture.h"
#include "Image.h"
#include "ImageCesium.h"
#include "Model.h"

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <optional>

namespace CesiumGltf {
/**
Expand Down Expand Up @@ -82,15 +84,31 @@ class FeatureIdTextureView {
FeatureIdTextureView() noexcept;

/**
* @brief Construct a view of the data specified by a
* {@link FeatureIdTexture}.
* @brief Construct a view of the data specified by a {@link FeatureIdTexture}.
*
* A feature ID texture may contain the `KHR_texture_transform` extension,
* which transforms the texture coordinates used to sample the texture. The
* extension may also override the TEXCOORD set index that was originally
* specified by the feature ID texture.
*
* If a view is constructed with applyKhrTextureTransformExtension set to
* true, the view will automatically apply the texture transform to any UV
* coordinates used to sample the texture. If the extension defines its own
* TEXCOORD set index, it will override the original value.
*
* Otherwise, if the flag is set to false, UVs will not be transformed and
* the original TEXCOORD set index will be preserved. The extension's values
* may still be retrieved using getTextureTransform, if desired.
*
* @param model The glTF in which to look for the feature ID texture's data.
* @param featureIDTexture The feature ID texture to create a view for.
* @param featureIdTexture The feature ID texture to create a view for.
* @param applyKhrTextureTransformExtension Whether to automatically apply the
* `KHR_texture_transform` extension to the feature ID texture, if it exists.
*/
FeatureIdTextureView(
const Model& model,
const FeatureIdTexture& featureIdTexture) noexcept;
const FeatureIdTexture& featureIdTexture,
bool applyKhrTextureTransformExtension = false) noexcept;

/**
* @brief Get the feature ID from the texture at the given texture
Expand All @@ -109,15 +127,15 @@ class FeatureIdTextureView {
*
* If invalid, it will not be safe to sample feature IDs from this view.
*/
FeatureIdTextureViewStatus status() const { return _status; }
FeatureIdTextureViewStatus status() const noexcept { return this->_status; }

/**
* @brief Get the actual feature ID texture.
*
* This will be nullptr if the feature ID texture view runs into problems
* during construction.
*/
const ImageCesium* getImage() const { return _pImage; }
const ImageCesium* getImage() const noexcept { return this->_pImage; }

/**
* @brief Get the sampler describing how to sample the data from the
Expand All @@ -132,13 +150,42 @@ class FeatureIdTextureView {
* @brief Get the channels of this feature ID texture. The channels represent
* the bytes of the actual feature ID, in little-endian order.
*/
std::vector<int64_t> getChannels() const { return _channels; }
std::vector<int64_t> getChannels() const noexcept { return this->_channels; }

/**
* @brief Get the texture coordinate set index for this feature ID
* texture.
*
* If applyKhrTextureTransformExtension is true, and if the feature ID texture
* contains the `KHR_texture_transform` extension, this will return the value
* from the extension, as it is meant to override the original index. However,
* if the extension does not specify a TEXCOORD set index, then the original
* index of the feature ID texture is returned.
*/
int64_t getTexCoordSetIndex() const noexcept {
if (this->_applyTextureTransform && this->_textureTransform) {
return this->_textureTransform->getTexCoordSetIndex().value_or(
this->_texCoordSetIndex);
}
return this->_texCoordSetIndex;
}

/**
* @brief Get the KHR_texture_transform for this feature ID texture, if it
* exists.
*
* Even if this view was constructed with applyKhrTextureTransformExtension
* set to false, it will save the extension's values, and they may be
* retrieved through this function.
*
* If this view was constructed with applyKhrTextureTransformExtension set to
* true, any texture coordinates passed into `getFeatureID` will be
* automatically transformed, so there's no need to re-apply the transform
* here.
*/
int64_t getTexCoordSetIndex() const { return this->_texCoordSetIndex; }
std::optional<KhrTextureTransform> getTextureTransform() const noexcept {
return this->_textureTransform;
}

private:
FeatureIdTextureViewStatus _status;
Expand All @@ -147,5 +194,8 @@ class FeatureIdTextureView {

const ImageCesium* _pImage;
const Sampler* _pSampler;

bool _applyTextureTransform;
std::optional<KhrTextureTransform> _textureTransform;
};
} // namespace CesiumGltf
17 changes: 16 additions & 1 deletion CesiumGltf/include/CesiumGltf/ImageCesium.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ struct CESIUMGLTF_API ImageCesium final {
* Otherwise, this buffer will store the compressed pixel data in the
* specified format.
*
* If mipOffsets is not empty, this buffer will contains multiple mips
* If mipPositions is not empty, this buffer will contains multiple mips
* back-to-back.
*
* When this is an uncompressed texture:
Expand All @@ -95,5 +95,20 @@ struct CESIUMGLTF_API ImageCesium final {
* | 4 | red, green, blue, alpha |
*/
std::vector<std::byte> pixelData;

/**
* @brief The effective size of this image, in bytes, for estimating resource
* usage for caching purposes.
*
* When this value is less than zero (the default), the size of this image
* should be assumed to equal the size of the {@link pixelData} array. When
* it is greater than or equal to zero, the specified size should be used
* instead. For example, the overridden size may account for:
* * The `pixelData` being cleared during the load process in order to save
* memory.
* * The cost of any renderer resources (e.g., GPU textures) created for
* this image.
*/
int64_t lastKnownSizeInBytes = -1;
};
} // namespace CesiumGltf
87 changes: 87 additions & 0 deletions CesiumGltf/include/CesiumGltf/KhrTextureTransform.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#pragma once

#include "CesiumGltf/ExtensionKhrTextureTransform.h"

#include <glm/glm.hpp>

namespace CesiumGltf {
/**
* @brief The status of a parsed KHR_texture_transform.
*
* The {@link KhrTextureTransform} constructor always completes successfully,
* but it may not always reflect the actual transform if errors occur. This
* enumeration provides the reason.
*/
enum class KhrTextureTransformStatus {
Valid,
ErrorInvalidOffset,
ErrorInvalidScale
};

/**
* @brief A utility class that parses KHR_texture_transform parameters and
* transforms input texture coordinates.
*/
class KhrTextureTransform {
public:
/**
* @brief Constructs a texture transformation with identity values.
*/
KhrTextureTransform() noexcept;

/**
* @brief Constructs a texture transformation from the given extension.
*/
KhrTextureTransform(const ExtensionKhrTextureTransform& extension) noexcept;

KhrTextureTransformStatus status() const noexcept { return this->_status; }

/**
* @brief Gets the offset of the texture transform.
*/
glm::dvec2 offset() const noexcept { return this->_offset; }

/**
* @brief Gets the rotation (in radians) of the texture transform.
*/
double rotation() const noexcept { return this->_rotation; }

/**
* @brief Gets the sine and cosine of the rotation in the texture transform.
* This is cached to avoid re-computing the values in the future.
*/
glm::dvec2 rotationSineCosine() const noexcept {
return this->_rotationSineCosine;
}

/**
* @brief Gets the scale of the texture transform.
*/
glm::dvec2 scale() const noexcept { return this->_scale; }

/**
* @brief Applies this texture transformation to the input coordinates.
*/
glm::dvec2 applyTransform(double u, double v) const noexcept;

/**
* @brief Gets the texture coordinate set index used by this texture
* transform. If defined, this should override the set index of the texture's
* original textureInfo.
*/
std::optional<int64_t> getTexCoordSetIndex() const noexcept {
return this->_texCoordSetIndex;
}

private:
KhrTextureTransformStatus _status;
glm::dvec2 _offset;
double _rotation;
glm::dvec2 _scale;
std::optional<int64_t> _texCoordSetIndex;

// Cached values of sin(rotation) and cos(rotation).
glm::dvec2 _rotationSineCosine;
};

} // namespace CesiumGltf
Loading

0 comments on commit 23c1cc8

Please sign in to comment.