3#include <CesiumGltf/KhrTextureTransform.h>
4#include <CesiumGltf/PropertyTextureProperty.h>
5#include <CesiumGltf/PropertyTransformations.h>
6#include <CesiumGltf/PropertyTypeTraits.h>
7#include <CesiumGltf/PropertyView.h>
8#include <CesiumGltf/Sampler.h>
9#include <CesiumGltf/TextureView.h>
10#include <CesiumImage/ImageAsset.h>
11#include <CesiumUtility/Assert.h>
92template <
typename ElementType>
94 if constexpr (std::is_same_v<ElementType, float>) {
96 bytes.size() ==
sizeof(
float) &&
97 "Not enough channel inputs to construct a float.");
98 uint32_t resultAsUint = 0;
99 for (
size_t i = 0; i < bytes.size(); i++) {
100 resultAsUint |=
static_cast<uint32_t
>(bytes[i]) << i * 8;
108 std::memcpy(&resultAsFloat, &resultAsUint,
sizeof(
float));
109 return resultAsFloat;
113 using UintType = std::make_unsigned_t<ElementType>;
114 UintType resultAsUint = 0;
115 for (
size_t i = 0; i < bytes.size(); i++) {
117 static_cast<UintType
>(
static_cast<UintType
>(bytes[i]) << i * 8);
121 return *
reinterpret_cast<ElementType*
>(&resultAsUint);
132template <
typename ElementType>
134 ElementType result = ElementType();
136 [[maybe_unused]]
constexpr glm::length_t N =
138 using T =
typename ElementType::value_type;
141 sizeof(T) <= 2 &&
"Components cannot be larger than two bytes in size.");
143 if constexpr (std::is_same_v<T, int16_t>) {
145 N == 2 &&
"Only vec2s can contain two-byte integer components.");
146 uint16_t x =
static_cast<uint16_t
>(bytes[0]) |
147 static_cast<uint16_t
>(
static_cast<uint16_t
>(bytes[1]) << 8);
148 uint16_t y =
static_cast<uint16_t
>(bytes[2]) |
149 static_cast<uint16_t
>(
static_cast<uint16_t
>(bytes[3]) << 8);
151 result[0] = *
reinterpret_cast<int16_t*
>(&x);
152 result[1] = *
reinterpret_cast<int16_t*
>(&y);
155 if constexpr (std::is_same_v<T, uint16_t>) {
157 N == 2 &&
"Only vec2s can contain two-byte integer components.");
158 result[0] =
static_cast<uint16_t
>(bytes[0]) |
159 static_cast<uint16_t
>(
static_cast<uint16_t
>(bytes[1]) << 8);
160 result[1] =
static_cast<uint16_t
>(bytes[2]) |
161 static_cast<uint16_t
>(
static_cast<uint16_t
>(bytes[3]) << 8);
164 if constexpr (std::is_same_v<T, int8_t>) {
165 for (
size_t i = 0; i < bytes.size(); i++) {
166 result[int32_t(i)] = *
reinterpret_cast<const int8_t*
>(&bytes[i]);
170 if constexpr (std::is_same_v<T, uint8_t>) {
171 for (
size_t i = 0; i < bytes.size(); i++) {
172 result[int32_t(i)] = bytes[i];
189 std::vector<T> result(bytes.size() /
sizeof(T));
191 if constexpr (
sizeof(T) == 2) {
192 for (
size_t i = 0, b = 0; i < result.size(); i++, b += 2) {
193 using UintType = std::make_unsigned_t<T>;
194 UintType resultAsUint =
195 static_cast<UintType
>(bytes[b]) |
196 static_cast<UintType
>(
static_cast<UintType
>(bytes[b + 1]) << 8);
197 result[i] = *
reinterpret_cast<T*
>(&resultAsUint);
200 for (
size_t i = 0; i < bytes.size(); i++) {
201 result[i] = *
reinterpret_cast<const T*
>(&bytes[i]);
217template <
typename ElementType>
221 bytes.size() > 0 &&
"Channel input must have at least one value.");
237#pragma region Non - normalized property
252template <
typename ElementType,
bool Normalized = false>
264template <
typename ElementType>
290 "An empty property view should not be constructed with a valid status");
311 if (!classProperty.defaultProperty) {
339 :
PropertyView<ElementType, false>(classProperty, property),
346 _channels(property.channels),
375 _swizzle.reserve(_channels.size());
377 for (
size_t i = 0; i < _channels.size(); ++i) {
378 switch (_channels[i]) {
393 false &&
"A valid channels vector must be passed to the view.");
427 _channels(property.channels),
456 _swizzle.reserve(_channels.size());
458 for (
size_t i = 0; i < _channels.size(); ++i) {
459 switch (_channels[i]) {
474 false &&
"A valid channels vector must be passed to the view.");
496 std::optional<PropertyValueViewToCopy<ElementType>>
497 get(
double u,
double v)
const noexcept {
505 if (value == this->
noData()) {
511 propertyValueCopyToView(value),
534 getRaw(
double u,
double v)
const noexcept {
537 "Check the status() first to make sure view is valid");
539 std::vector<uint8_t> sample =
543 std::span(sample.data(), this->_channels.size()));
550 return this->_channels;
556 const std::string&
getSwizzle() const noexcept {
return this->_swizzle; }
559 std::vector<int64_t> _channels;
560 std::string _swizzle;
565#pragma region Normalized property
574template <
typename ElementType>
603 "An empty property view should not be constructed with a valid "
655 :
PropertyView<ElementType, true>(classProperty, property),
662 _channels(property.channels),
691 _swizzle.reserve(_channels.size());
692 for (
size_t i = 0; i < _channels.size(); ++i) {
693 switch (_channels[i]) {
708 false &&
"A valid channels vector must be passed to the view.");
731 std::optional<PropertyValueViewToCopy<NormalizedType>>
732 get(
double u,
double v)
const noexcept {
740 if (value == this->
noData()) {
748 constexpr glm::length_t N = ElementType::length();
749 using T =
typename ElementType::value_type;
750 using NormalizedT =
typename NormalizedType::value_type;
759 propertyValueCopyToView(value),
763 constexpr glm::length_t N = ArrayElementType::length();
764 using T =
typename ArrayElementType::value_type;
766 propertyValueCopyToView(value),
788 getRaw(
double u,
double v)
const noexcept {
791 "Check the status() first to make sure view is valid");
793 std::vector<uint8_t> sample =
797 std::span(sample.data(), this->_channels.size()));
804 return this->_channels;
810 const std::string&
getSwizzle() const noexcept {
return this->_swizzle; }
813 std::vector<int64_t> _channels;
814 std::string _swizzle;
A copy of an array element of a PropertyTableProperty or PropertyTextureProperty.
Indicates the status of a property texture property view.
static const int ErrorUnsupportedProperty
This property view is associated with a ClassProperty of an unsupported type.
static const int ErrorChannelsAndTypeMismatch
The channels of this property texture property do not provide the exact number of bytes required by t...
static const int ErrorInvalidImage
This property view does not have a valid image index.
static const int ErrorInvalidChannels
The channels of this property texture property are invalid. Channels must be in the range 0-N,...
static const int ErrorInvalidBytesPerChannel
This property uses an image with multi-byte channels. Only single-byte channels are supported.
static const int ErrorInvalidSampler
This property view does not have a valid sampler index.
static const int ErrorInvalidPropertyTexture
This property view was initialized from an invalid PropertyTexture.
static const int ErrorInvalidTexture
This property view does not have a valid texture index.
static const int ErrorEmptyImage
This property is viewing an empty image.
PropertyTexturePropertyView(const PropertyTextureProperty &property, const ClassProperty &classProperty, const CesiumGltf::Enum *pEnumDefinition, const Sampler &sampler, const CesiumImage::ImageAsset &image, const TextureViewOptions &options=TextureViewOptions()) noexcept
Construct a view of the data specified by a PropertyTextureProperty.
const std::string & getSwizzle() const noexcept
Gets this property's channels as a swizzle string.
std::optional< PropertyValueViewToCopy< ElementType > > get(double u, double v) const noexcept
Gets the value of the property for the given texture coordinates with all value transforms applied....
PropertyTexturePropertyView(PropertyViewStatusType status) noexcept
Constructs an invalid instance for an erroneous property.
PropertyValueViewToCopy< ElementType > getRaw(double u, double v) const noexcept
Gets the raw value of the property for the given texture coordinates. The sampler's wrapping mode wil...
PropertyTexturePropertyView(const ClassProperty &classProperty) noexcept
Constructs an instance of an empty property that specifies a default value. Although this property ha...
PropertyTexturePropertyView(const PropertyTextureProperty &property, const ClassProperty &classProperty, const Sampler &sampler, const CesiumImage::ImageAsset &image, const TextureViewOptions &options=TextureViewOptions()) noexcept
Construct a view of the data specified by a PropertyTextureProperty.
PropertyTexturePropertyView() noexcept
Constructs an invalid instance for a non-existent property.
const std::vector< int64_t > & getChannels() const noexcept
Gets the channels of this property texture property.
PropertyValueViewToCopy< ElementType > getRaw(double u, double v) const noexcept
Gets the raw value of the property for the given texture coordinates. The sampler's wrapping mode wil...
PropertyTexturePropertyView(const ClassProperty &classProperty) noexcept
Constructs an instance of an empty property that specifies a default value. Although this property ha...
const std::string & getSwizzle() const noexcept
Gets this property's channels as a swizzle string.
PropertyTexturePropertyView() noexcept
Constructs an invalid instance for a non-existent property.
PropertyTexturePropertyView(const PropertyTextureProperty &property, const ClassProperty &classProperty, const Sampler &sampler, const CesiumImage::ImageAsset &image, const TextureViewOptions &options=TextureViewOptions()) noexcept
Construct a view of the data specified by a PropertyTextureProperty.
PropertyTexturePropertyView(PropertyViewStatusType status) noexcept
Constructs an invalid instance for an erroneous property.
std::optional< PropertyValueViewToCopy< NormalizedType > > get(double u, double v) const noexcept
Gets the value of the property for the given texture coordinates with all value transforms applied....
const std::vector< int64_t > & getChannels() const noexcept
Gets the channels of this property texture property.
A view of the data specified by a PropertyTextureProperty.
Indicates the status of a property view.
static const PropertyViewStatusType Valid
This property view is valid and ready to use.
static const PropertyViewStatusType ErrorNonexistentProperty
This property view is trying to view a property that does not exist.
static const PropertyViewStatusType EmptyPropertyWithDefault
This property view does not contain any data, but specifies a default value. This happens when a clas...
std::optional< ElementType > offset() const noexcept
Gets the offset to apply to property values. Only applicable to SCALAR, VECN, and MATN types when the...
std::optional< ElementType > scale() const noexcept
Gets the scale to apply to property values. Only applicable to SCALAR, VECN, and MATN types when the ...
std::optional< ElementType > defaultValue() const noexcept
Gets the default value to use when encountering a "no data" value or an omitted property....
PropertyViewStatusType _status
Indicates the status of a property view.
PropertyViewStatusType status() const noexcept
Gets the status of this property view, indicating whether an error occurred.
std::optional< ElementType > noData() const noexcept
Gets the "no data" value, i.e., the value representing missing data in the property wherever it appea...
PropertyView()
Constructs an empty property instance.
std::optional< ElementType > noData() const noexcept
Constructs an empty property instance. false>noData
PropertyViewStatusType _status
Indicates the status of a property view.
std::optional< NormalizedType > scale() const noexcept
Constructs an empty property instance. false>scale
PropertyView()
Constructs an empty property instance.
std::optional< NormalizedType > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
std::optional< NormalizedType > offset() const noexcept
Constructs an empty property instance. false>offset
TextureViewStatus getTextureViewStatus() const noexcept
Get the status of this texture view.
TextureView() noexcept
Constructs an empty, uninitialized texture view.
std::vector< uint8_t > sampleNearestPixel(double u, double v, const std::vector< int64_t > &channels) const noexcept
Samples the image at the specified texture coordinates using NEAREST pixel filtering,...
Classes for working with glTF models.
PropertyArrayCopy< glm::vec< N, double > > transformNormalizedVecNArray(const PropertyArrayView< glm::vec< N, T > > &value, const std::optional< PropertyArrayView< glm::vec< N, double > > > &offset, const std::optional< PropertyArrayView< glm::vec< N, double > > > &scale)
Normalizes each element of an array of vectors and transforms them by optional offset and scale facto...
ElementType assembleVecNValue(const std::span< uint8_t > bytes) noexcept
Attempts to obtain a vector value from the given span of bytes.
PropertyArrayCopy< NormalizedType > transformNormalizedArray(const PropertyArrayView< T > &value, const std::optional< PropertyArrayView< NormalizedType > > &offset, const std::optional< PropertyArrayView< NormalizedType > > &scale)
Normalizes each element of an array of values and transforms them by optional offset and scale factor...
T transformValue(const T &value, const std::optional< T > &offset, const std::optional< T > &scale)
Transforms the value by optional offset and scale factors.
double normalize(T value)
Normalizes the given value between [0, 1] if unsigned or [-1, 1] if signed, based on the type's maxim...
@ ErrorEmptyImage
This texture is viewing an empty image.
@ ErrorUninitialized
This texture view has not yet been initialized.
@ Valid
This texture view is valid and ready to use.
@ ErrorInvalidSampler
This texture view does not have a valid sampler index.
@ ErrorInvalidImage
This texture view does not have a valid image index.
@ ErrorInvalidBytesPerChannel
The image for this texture has channels that take up more than a byte. Only single-byte channels are ...
@ ErrorInvalidTexture
This texture view does not have a valid texture index.
PropertyArrayCopy< T > transformArray(const PropertyArrayView< T > &value, const std::optional< PropertyArrayView< T > > &offset, const std::optional< PropertyArrayView< T > > &scale)
Transforms each element of an array of values by optional offset and scale factors....
std::conditional_t< IsMetadataNumericArray< T >::value, PropertyArrayCopy< typename MetadataArrayType< T >::type >, T > PropertyValueViewToCopy
Transforms a property value type from a view to an equivalent type that owns the data it is viewing....
ElementType assembleScalarValue(const std::span< uint8_t > bytes) noexcept
Attempts to obtain a scalar value from the given span of bytes.
PropertyArrayCopy< T > assembleArrayValue(const std::span< uint8_t > bytes) noexcept
Attempts to obtain an array value from the given span of bytes.
PropertyValueViewToCopy< ElementType > assembleValueFromChannels(const std::span< uint8_t > bytes) noexcept
Assembles the given type from the provided channel values of sampling a texture.
int32_t PropertyViewStatusType
The type used for fields of PropertyViewStatus.
std::optional< CesiumUtility::JsonValue > defaultProperty
A default value to use when encountering a noData value or an omitted property. The value is given in...
This class is not meant to be instantiated directly. Use Enum instead.
glTF extension that enables shifting and scaling UV coordinates on a per-texture basis
A texture containing property values.
Texture sampler properties for filtering and wrapping modes.
Describes options for constructing a view on a glTF texture.
The number of dimensions that this type contains.
Convert an integer numeric type to the corresponding representation as a double type....
A 2D image asset, including its pixel data. The image may have mipmaps, and it may be encoded in a GP...