3 #include "CesiumGltf/PropertyArrayView.h"
4 #include "CesiumGltf/PropertyTransformations.h"
5 #include "CesiumGltf/PropertyTypeTraits.h"
6 #include "CesiumGltf/PropertyView.h"
8 #include <CesiumUtility/Assert.h>
14 #include <string_view>
15 #include <type_traits>
80 static const PropertyViewStatusType
87 static const PropertyViewStatusType
137 int64_t getOffsetTypeSize(PropertyComponentType offsetType) noexcept;
143 template <
typename ElementType,
bool Normalized = false>
160 template <
typename ElementType>
172 _arrayOffsetType{PropertyComponentType::None},
173 _arrayOffsetTypeSize{0},
175 _stringOffsetType{PropertyComponentType::None},
176 _stringOffsetTypeSize{0} {}
188 _arrayOffsetType{PropertyComponentType::None},
189 _arrayOffsetTypeSize{0},
191 _stringOffsetType{PropertyComponentType::None},
192 _stringOffsetTypeSize{0} {
195 "An empty property view should not be constructed with a valid status");
212 _arrayOffsetType{PropertyComponentType::None},
213 _arrayOffsetTypeSize{0},
215 _stringOffsetType{PropertyComponentType::None},
216 _stringOffsetTypeSize{0} {
248 gsl::span<const std::byte> values) noexcept
254 _arrayOffsetType{PropertyComponentType::None},
255 _arrayOffsetTypeSize{0},
257 _stringOffsetType{PropertyComponentType::None},
258 _stringOffsetTypeSize{0} {}
276 gsl::span<const std::byte> values,
277 gsl::span<const std::byte> arrayOffsets,
278 gsl::span<const std::byte> stringOffsets,
279 PropertyComponentType arrayOffsetType,
280 PropertyComponentType stringOffsetType) noexcept
285 _arrayOffsets{arrayOffsets},
286 _arrayOffsetType{arrayOffsetType},
287 _arrayOffsetTypeSize{getOffsetTypeSize(arrayOffsetType)},
288 _stringOffsets{stringOffsets},
289 _stringOffsetType{stringOffsetType},
290 _stringOffsetTypeSize{getOffsetTypeSize(stringOffsetType)} {}
307 std::optional<PropertyValueViewToCopy<ElementType>>
308 get(int64_t index)
const noexcept {
311 CESIUM_ASSERT(index >= 0 &&
"index must be non-negative");
312 CESIUM_ASSERT(index < size() &&
"index must be less than size");
314 return propertyValueViewToCopy(this->defaultValue());
317 ElementType value = getRaw(index);
319 if (value == this->noData()) {
320 return propertyValueViewToCopy(this->defaultValue());
322 return transformValue(value, this->offset(), this->scale());
324 return transformArray(value, this->offset(), this->scale());
340 ElementType
getRaw(int64_t index)
const noexcept {
343 "Check the status() first to make sure view is valid");
346 "Check the size() of the view to make sure it's not empty");
347 CESIUM_ASSERT(index >= 0 &&
"index must be non-negative");
348 CESIUM_ASSERT(index < size() &&
"index must be less than size");
351 return getNumericValue(index);
355 return getBooleanValue(index);
359 return getStringValue(index);
363 return getNumericArrayValues<
364 typename MetadataArrayType<ElementType>::type>(index);
368 return getBooleanArrayValues(index);
372 return getStringArrayValues(index);
383 int64_t
size() const noexcept {
return _size; }
386 ElementType getNumericValue(int64_t index)
const noexcept {
387 return reinterpret_cast<const ElementType*
>(_values.data())[index];
390 bool getBooleanValue(int64_t index)
const noexcept {
391 const int64_t byteIndex = index / 8;
392 const int64_t bitIndex = index % 8;
393 const int bitValue =
static_cast<int>(_values[byteIndex] >> bitIndex) & 1;
394 return bitValue == 1;
397 std::string_view getStringValue(int64_t index)
const noexcept {
398 const size_t currentOffset =
399 getOffsetFromOffsetsBuffer(index, _stringOffsets, _stringOffsetType);
400 const size_t nextOffset = getOffsetFromOffsetsBuffer(
404 return std::string_view(
405 reinterpret_cast<const char*
>(_values.data() + currentOffset),
406 nextOffset - currentOffset);
409 template <
typename T>
410 PropertyArrayView<T> getNumericArrayValues(int64_t index)
const noexcept {
411 size_t count =
static_cast<size_t>(this->arrayCount());
414 size_t arraySize = count *
sizeof(T);
415 const gsl::span<const std::byte> values(
416 _values.data() + index * arraySize,
418 return PropertyArrayView<T>{values};
423 const size_t currentOffset =
424 getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType) *
426 const size_t nextOffset =
427 getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType) *
429 const gsl::span<const std::byte> values(
430 _values.data() + currentOffset,
431 nextOffset - currentOffset);
432 return PropertyArrayView<T>{values};
435 PropertyArrayView<std::string_view>
436 getStringArrayValues(int64_t index)
const noexcept {
437 size_t count =
static_cast<size_t>(this->arrayCount());
441 const size_t arraySize = count * _stringOffsetTypeSize;
442 const gsl::span<const std::byte> stringOffsetValues(
443 _stringOffsets.data() + index * arraySize,
444 arraySize + _stringOffsetTypeSize);
445 return PropertyArrayView<std::string_view>(
453 const size_t currentArrayOffset =
454 getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType);
455 const size_t nextArrayOffset =
456 getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType);
457 const size_t arraySize = nextArrayOffset - currentArrayOffset;
458 const gsl::span<const std::byte> stringOffsetValues(
459 _stringOffsets.data() + currentArrayOffset,
460 arraySize + _arrayOffsetTypeSize);
461 return PropertyArrayView<std::string_view>(
465 arraySize / _arrayOffsetTypeSize);
468 PropertyArrayView<bool> getBooleanArrayValues(int64_t index)
const noexcept {
469 size_t count =
static_cast<size_t>(this->arrayCount());
472 const size_t offsetBits = count * index;
473 const size_t nextOffsetBits = count * (index + 1);
474 const gsl::span<const std::byte> buffer(
475 _values.data() + offsetBits / 8,
476 (nextOffsetBits / 8 - offsetBits / 8 + 1));
477 return PropertyArrayView<bool>(buffer, offsetBits % 8, count);
481 const size_t currentOffset =
482 getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType);
483 const size_t nextOffset =
484 getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType);
485 const size_t totalBits = nextOffset - currentOffset;
486 const gsl::span<const std::byte> buffer(
487 _values.data() + currentOffset / 8,
488 (nextOffset / 8 - currentOffset / 8 + 1));
489 return PropertyArrayView<bool>(buffer, currentOffset % 8, totalBits);
492 gsl::span<const std::byte> _values;
495 gsl::span<const std::byte> _arrayOffsets;
496 PropertyComponentType _arrayOffsetType;
497 int64_t _arrayOffsetTypeSize;
499 gsl::span<const std::byte> _stringOffsets;
500 PropertyComponentType _stringOffsetType;
501 int64_t _stringOffsetTypeSize;
518 template <
typename ElementType>
533 _arrayOffsetType{PropertyComponentType::None},
534 _arrayOffsetTypeSize{0} {}
546 _arrayOffsetType{PropertyComponentType::None},
547 _arrayOffsetTypeSize{0} {
550 "An empty property view should not be constructed with a valid status");
567 _arrayOffsetType{PropertyComponentType::None},
568 _arrayOffsetTypeSize{0} {
600 gsl::span<const std::byte> values) noexcept
606 _arrayOffsetType{PropertyComponentType::None},
607 _arrayOffsetTypeSize{0} {}
624 gsl::span<const std::byte> values,
625 gsl::span<const std::byte> arrayOffsets,
626 PropertyComponentType arrayOffsetType) noexcept
631 _arrayOffsets{arrayOffsets},
632 _arrayOffsetType{arrayOffsetType},
633 _arrayOffsetTypeSize{getOffsetTypeSize(arrayOffsetType)} {}
650 std::optional<PropertyValueViewToCopy<NormalizedType>>
651 get(int64_t index)
const noexcept {
654 CESIUM_ASSERT(index >= 0 &&
"index must be non-negative");
655 CESIUM_ASSERT(index < size() &&
"index must be less than size");
657 return propertyValueViewToCopy(this->defaultValue());
660 ElementType value = getRaw(index);
661 if (this->noData() && value == *(this->noData())) {
662 return propertyValueViewToCopy(this->defaultValue());
664 return transformValue<NormalizedType>(
665 normalize<ElementType>(value),
669 constexpr glm::length_t N = ElementType::length();
670 using T =
typename ElementType::value_type;
671 using NormalizedT =
typename NormalizedType::value_type;
672 return transformValue<glm::vec<N, NormalizedT>>(
673 normalize<N, T>(value),
677 constexpr glm::length_t N = ElementType::length();
678 using T =
typename ElementType::value_type;
679 using NormalizedT =
typename NormalizedType::value_type;
680 return transformValue<glm::mat<N, N, NormalizedT>>(
681 normalize<N, T>(value),
685 using ArrayElementType =
typename MetadataArrayType<ElementType>::type;
687 return transformNormalizedArray<ArrayElementType>(
692 constexpr glm::length_t N = ArrayElementType::length();
693 using T =
typename ArrayElementType::value_type;
694 return transformNormalizedVecNArray<N, T>(
699 constexpr glm::length_t N = ArrayElementType::length();
700 using T =
typename ArrayElementType::value_type;
701 return transformNormalizedMatNArray<N, T>(
719 ElementType
getRaw(int64_t index)
const noexcept {
722 "Check the status() first to make sure view is valid");
725 "Check the size() of the view to make sure it's not empty");
726 CESIUM_ASSERT(index >= 0 &&
"index must be non-negative");
727 CESIUM_ASSERT(index < size() &&
"index must be less than size");
730 return getValue(index);
734 return getArrayValues<typename MetadataArrayType<ElementType>::type>(
746 int64_t
size() const noexcept {
751 ElementType getValue(int64_t index)
const noexcept {
752 return reinterpret_cast<const ElementType*
>(_values.data())[index];
755 template <
typename T>
756 PropertyArrayView<T> getArrayValues(int64_t index)
const noexcept {
757 size_t count =
static_cast<size_t>(this->arrayCount());
760 size_t arraySize = count *
sizeof(T);
761 const gsl::span<const std::byte> values(
762 _values.data() + index * arraySize,
764 return PropertyArrayView<T>{values};
769 const size_t currentOffset =
770 getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType) *
772 const size_t nextOffset =
773 getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType) *
775 const gsl::span<const std::byte> values(
776 _values.data() + currentOffset,
777 nextOffset - currentOffset);
778 return PropertyArrayView<T>{values};
781 gsl::span<const std::byte> _values;
784 gsl::span<const std::byte> _arrayOffsets;
785 PropertyComponentType _arrayOffsetType;
786 int64_t _arrayOffsetTypeSize;
Indicates the status of a property table property view.
static const PropertyViewStatusType ErrorBufferViewSizeDoesNotMatchPropertyTableCount
This property view has an invalid buffer view; its length does not match the size of the property tab...
static const PropertyViewStatusType ErrorInvalidArrayOffsetBufferView
This array property view does not have a valid array offset buffer view index.
static const PropertyViewStatusType ErrorBufferViewOutOfBounds
This property view has a buffer view that points outside the bounds of its target buffer.
static const PropertyViewStatusType ErrorArrayCountAndOffsetBufferCoexist
This array property view has both a fixed length and an offset buffer view defined.
static const PropertyViewStatusType ErrorInvalidValueBufferView
This property view does not have a valid value buffer view index.
static const PropertyViewStatusType ErrorInvalidStringOffsetBuffer
This property view has a valid string offset buffer view, but the buffer view specifies an invalid bu...
static const PropertyViewStatusType ErrorInvalidStringOffsetType
This property view has an unknown string offset type.
static const PropertyViewStatusType ErrorArrayCountAndOffsetBufferDontExist
This array property view has neither a fixed length nor an offset buffer view defined.
static const PropertyViewStatusType ErrorArrayOffsetsNotSorted
This property view's array offset values are not sorted in ascending order.
static const PropertyViewStatusType ErrorInvalidArrayOffsetBuffer
This property view has a valid array string buffer view, but the buffer view specifies an invalid buf...
static const PropertyViewStatusType ErrorArrayOffsetOutOfBounds
This property view has an array offset that is out of bounds.
static const PropertyViewStatusType ErrorInvalidPropertyTable
This property view was initialized from an invalid PropertyTable.
static const PropertyViewStatusType ErrorInvalidValueBuffer
This property view has a valid value buffer view, but the buffer view specifies an invalid buffer ind...
static const PropertyViewStatusType ErrorInvalidStringOffsetBufferView
This string property view does not have a valid string offset buffer view index.
static const PropertyViewStatusType ErrorInvalidArrayOffsetType
This property view has an unknown array offset type.
static const PropertyViewStatusType ErrorStringOffsetsNotSorted
This property view's string offset values are not sorted in ascending order.
static const PropertyViewStatusType ErrorStringOffsetOutOfBounds
This property view has a string offset that is out of bounds.
static const PropertyViewStatusType ErrorBufferViewSizeNotDivisibleByTypeSize
This property view has an invalid buffer view; its length is not a multiple of the size of its type /...
PropertyTablePropertyView(const ClassProperty &classProperty, int64_t size)
Constructs an instance of an empty property that specifies a default value. Although this property ha...
PropertyTablePropertyView()
Constructs an invalid instance for a non-existent property.
PropertyTablePropertyView(const PropertyTableProperty &property, const ClassProperty &classProperty, int64_t size, gsl::span< const std::byte > values) noexcept
Construct an instance pointing to data specified by a PropertyTableProperty. Used for non-array or fi...
ElementType getRaw(int64_t index) const noexcept
Get the raw value of an element of the PropertyTable, without offset or scale applied.
PropertyTablePropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
int64_t size() const noexcept
Get the number of elements in this PropertyTablePropertyView. If the view is valid,...
PropertyTablePropertyView(const PropertyTableProperty &property, const ClassProperty &classProperty, int64_t size, gsl::span< const std::byte > values, gsl::span< const std::byte > arrayOffsets, gsl::span< const std::byte > stringOffsets, PropertyComponentType arrayOffsetType, PropertyComponentType stringOffsetType) noexcept
Construct an instance pointing to the data specified by a PropertyTableProperty.
std::optional< PropertyValueViewToCopy< ElementType > > get(int64_t index) const noexcept
Get the value of an element in the PropertyTable, with all value transforms applied....
PropertyTablePropertyView()
Constructs an invalid instance for a non-existent property.
ElementType getRaw(int64_t index) const noexcept
Get the raw value of an element of the PropertyTable, without offset, scale, or normalization applied...
std::optional< PropertyValueViewToCopy< NormalizedType > > get(int64_t index) const noexcept
Get the value of an element of the PropertyTable, with normalization and other value transforms appli...
PropertyTablePropertyView(const PropertyTableProperty &property, const ClassProperty &classProperty, int64_t size, gsl::span< const std::byte > values) noexcept
Construct an instance pointing to data specified by a PropertyTableProperty. Used for non-array or fi...
PropertyTablePropertyView(const PropertyTableProperty &property, const ClassProperty &classProperty, int64_t size, gsl::span< const std::byte > values, gsl::span< const std::byte > arrayOffsets, PropertyComponentType arrayOffsetType) noexcept
Construct an instance pointing to the data specified by a PropertyTableProperty.
PropertyTablePropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
int64_t size() const noexcept
Get the number of elements in this PropertyTablePropertyView. If the view is valid,...
PropertyTablePropertyView(const ClassProperty &classProperty, int64_t size)
Constructs an instance of an empty property that specifies a default value. Although this property ha...
A view on the data of the PropertyTableProperty that is created by a PropertyTableView.
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...
Represents a normalized metadata property in EXT_structural_metadata.
Represents a metadata property in EXT_structural_metadata.
Classes for working with glTF models.
std::optional< CesiumUtility::JsonValue > defaultProperty
A default value to use when encountering a noData value or an omitted property. The value is given in...
An array of binary property values.
Convert an integer numeric type to the corresponding representation as a double type....