3#include "CesiumGltf/ClassProperty.h"
4#include "CesiumGltf/PropertyAttributeProperty.h"
5#include "CesiumGltf/PropertyTableProperty.h"
6#include "CesiumGltf/PropertyTextureProperty.h"
7#include "CesiumGltf/PropertyTypeTraits.h"
136 expectedComponentType !=
141 if (classProperty.
array) {
173 expectedComponentType !=
178 if (!classProperty.
array) {
206template <
typename VecType>
207static std::optional<VecType>
214 constexpr glm::length_t N = VecType::length();
215 if (array.size() != N) {
219 using T =
typename VecType::value_type;
222 for (glm::length_t i = 0; i < N; i++) {
223 std::optional<T> value = getScalar<T>(array[i]);
244template <
typename MatType>
245static std::optional<MatType>
252 constexpr glm::length_t N = MatType::length();
253 if (array.size() != N * N) {
257 using T =
typename MatType::value_type;
260 for (glm::length_t i = 0; i < N; i++) {
262 for (glm::length_t j = 0; j < N; j++) {
263 std::optional<T> value = getScalar<T>(array[i * N + j]);
268 result[i][j] = *value;
284template <
typename ElementType>
285int64_t
getCount(std::optional<std::vector<std::byte>>& buffer) {
290 return static_cast<int64_t
>(buffer->size() /
sizeof(ElementType));
296template <
typename ElementType,
bool Normalized = false>
class PropertyView;
310template <
typename ElementType>
class PropertyView<ElementType, false> {
318 _semantic(
std::nullopt),
319 _description(
std::nullopt),
320 _offset(
std::nullopt),
321 _scale(
std::nullopt),
325 _noData(
std::nullopt),
326 _defaultValue(
std::nullopt) {}
333 _name(classProperty.name),
334 _semantic(classProperty.semantic),
335 _description(classProperty.description),
336 _offset(
std::nullopt),
337 _scale(
std::nullopt),
340 _required(classProperty.required),
341 _noData(
std::nullopt),
342 _defaultValue(
std::nullopt) {
348 _status = PropertyViewStatus::ErrorNormalizationMismatch;
352 getNumericPropertyValues(classProperty);
357 if (classProperty.
noData) {
360 _noData = getValue(*classProperty.noData);
370 if (classProperty.defaultProperty) {
373 _defaultValue = getValue(*classProperty.defaultProperty);
376 if (!_defaultValue) {
394 _semantic(
std::nullopt),
395 _description(
std::nullopt),
396 _offset(
std::nullopt),
397 _scale(
std::nullopt),
401 _noData(
std::nullopt),
402 _defaultValue(
std::nullopt) {}
412 if (_status != PropertyViewStatus::Valid) {
417 getNumericPropertyValues(property);
428 if (_status != PropertyViewStatus::Valid) {
433 getNumericPropertyValues(property);
444 if (_status != PropertyViewStatus::Valid) {
449 getNumericPropertyValues(property);
465 const std::optional<std::string>&
name() const noexcept {
return _name; }
473 const std::optional<std::string>&
semantic() const noexcept {
505 std::optional<ElementType>
offset() const noexcept {
return _offset; }
514 std::optional<ElementType>
scale() const noexcept {
return _scale; }
525 std::optional<ElementType>
max() const noexcept {
return _max; }
536 std::optional<ElementType>
min() const noexcept {
return _min; }
543 bool required() const noexcept {
return _required; }
554 std::optional<ElementType>
noData() const noexcept {
return _noData; }
565 return _defaultValue;
573 std::optional<std::string> _name;
574 std::optional<std::string> _semantic;
575 std::optional<std::string> _description;
577 std::optional<ElementType> _offset;
578 std::optional<ElementType> _scale;
579 std::optional<ElementType> _max;
580 std::optional<ElementType> _min;
583 std::optional<ElementType> _noData;
584 std::optional<ElementType> _defaultValue;
596 static std::optional<ElementType>
599 return getScalar<ElementType>(jsonValue);
603 return getVecN<ElementType>(jsonValue);
607 return getMatN<ElementType>(jsonValue);
611 using PropertyDefinitionType = std::variant<
621 void getNumericPropertyValues(
const PropertyDefinitionType& inProperty) {
623 [
this](
auto property) {
624 if (property.offset) {
627 case PropertyComponentType::Float32:
628 case PropertyComponentType::Float64:
629 this->_offset = getValue(*property.offset);
636 this->_status = PropertyViewStatus::ErrorInvalidOffset;
641 if (property.scale) {
643 switch (TypeToPropertyType<ElementType>::component) {
644 case PropertyComponentType::Float32:
645 case PropertyComponentType::Float64:
646 this->_scale = getValue(*property.scale);
653 this->_status = PropertyViewStatus::ErrorInvalidScale;
659 this->_max = getValue(*property.max);
662 this->_status = PropertyViewStatus::ErrorInvalidMax;
668 this->_min = getValue(*property.min);
671 this->_status = PropertyViewStatus::ErrorInvalidMin;
704 _semantic(
std::nullopt),
705 _description(
std::nullopt),
706 _offset(
std::nullopt),
707 _scale(
std::nullopt),
711 _noData(
std::nullopt),
712 _defaultValue(
std::nullopt) {}
719 _name(classProperty.name),
720 _semantic(classProperty.semantic),
721 _description(classProperty.description),
722 _offset(
std::nullopt),
723 _scale(
std::nullopt),
726 _required(classProperty.required),
727 _noData(
std::nullopt),
728 _defaultValue(
std::nullopt) {
729 if (_status != PropertyViewStatus::Valid) {
734 _status = PropertyViewStatus::ErrorNormalizationMismatch;
737 getNumericPropertyValues(classProperty);
738 if (_status != PropertyViewStatus::Valid) {
742 if (classProperty.
noData) {
745 _noData = getValue<ElementType>(*classProperty.noData);
749 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
754 if (classProperty.defaultProperty) {
758 getValue<NormalizedType>(*classProperty.defaultProperty);
760 if (!_defaultValue) {
762 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
777 _semantic(
std::nullopt),
778 _description(
std::nullopt),
779 _offset(
std::nullopt),
780 _scale(
std::nullopt),
784 _noData(
std::nullopt),
785 _defaultValue(
std::nullopt) {}
795 if (_status != PropertyViewStatus::Valid) {
800 getNumericPropertyValues(property);
811 if (_status != PropertyViewStatus::Valid) {
816 getNumericPropertyValues(property);
827 if (_status != PropertyViewStatus::Valid) {
832 getNumericPropertyValues(property);
844 const std::optional<std::string>&
name() const noexcept {
return _name; }
849 const std::optional<std::string>&
semantic() const noexcept {
873 std::optional<NormalizedType>
offset() const noexcept {
return _offset; }
878 std::optional<NormalizedType>
scale() const noexcept {
return _scale; }
883 std::optional<NormalizedType>
max() const noexcept {
return _max; }
888 std::optional<NormalizedType>
min() const noexcept {
return _min; }
893 bool required() const noexcept {
return _required; }
898 std::optional<ElementType>
noData() const noexcept {
return _noData; }
904 return _defaultValue;
912 std::optional<std::string> _name;
913 std::optional<std::string> _semantic;
914 std::optional<std::string> _description;
916 std::optional<NormalizedType> _offset;
917 std::optional<NormalizedType> _scale;
918 std::optional<NormalizedType> _max;
919 std::optional<NormalizedType> _min;
922 std::optional<ElementType> _noData;
923 std::optional<NormalizedType> _defaultValue;
934 template <
typename T>
937 return getScalar<T>(jsonValue);
941 return getVecN<T>(jsonValue);
945 return getMatN<T>(jsonValue);
949 using PropertyDefinitionType = std::variant<
959 void getNumericPropertyValues(
const PropertyDefinitionType& inProperty) {
961 [
this](
auto property) {
962 if (property.offset) {
963 _offset = getValue<NormalizedType>(*property.offset);
966 _status = PropertyViewStatus::ErrorInvalidOffset;
971 if (property.scale) {
972 _scale = getValue<NormalizedType>(*property.scale);
975 _status = PropertyViewStatus::ErrorInvalidScale;
981 _max = getValue<NormalizedType>(*property.max);
984 _status = PropertyViewStatus::ErrorInvalidMax;
990 _min = getValue<NormalizedType>(*property.min);
993 _status = PropertyViewStatus::ErrorInvalidMin;
1013 _name(
std::nullopt),
1014 _semantic(
std::nullopt),
1015 _description(
std::nullopt),
1017 _defaultValue(
std::nullopt) {}
1024 _name(classProperty.name),
1025 _semantic(classProperty.semantic),
1026 _description(classProperty.description),
1027 _required(classProperty.required),
1028 _defaultValue(
std::nullopt) {
1029 if (_status != PropertyViewStatus::Valid) {
1035 _defaultValue = getBooleanValue(*classProperty.defaultProperty);
1038 if (!_defaultValue) {
1040 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1054 _name(
std::nullopt),
1055 _semantic(
std::nullopt),
1056 _description(
std::nullopt),
1058 _defaultValue(
std::nullopt) {}
1078 const std::optional<std::string>&
name() const noexcept {
return _name; }
1083 const std::optional<std::string>&
semantic() const noexcept {
1091 return _description;
1107 std::optional<bool>
offset() const noexcept {
return std::nullopt; }
1112 std::optional<bool>
scale() const noexcept {
return std::nullopt; }
1117 std::optional<bool>
max() const noexcept {
return std::nullopt; }
1122 std::optional<bool>
min() const noexcept {
return std::nullopt; }
1132 std::optional<bool>
noData() const noexcept {
return std::nullopt; }
1137 std::optional<bool>
defaultValue() const noexcept {
return _defaultValue; }
1144 std::optional<std::string> _name;
1145 std::optional<std::string> _semantic;
1146 std::optional<std::string> _description;
1149 std::optional<bool> _defaultValue;
1151 static std::optional<bool>
1154 return std::nullopt;
1172 _name(
std::nullopt),
1173 _semantic(
std::nullopt),
1174 _description(
std::nullopt),
1176 _noData(
std::nullopt),
1177 _defaultValue(
std::nullopt) {}
1184 _name(classProperty.name),
1185 _semantic(classProperty.semantic),
1186 _description(classProperty.description),
1187 _required(classProperty.required),
1188 _noData(
std::nullopt),
1189 _defaultValue(
std::nullopt) {
1190 if (_status != PropertyViewStatus::Valid) {
1194 if (classProperty.
noData) {
1196 _noData = getStringValue(*classProperty.noData);
1201 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
1206 if (classProperty.defaultProperty) {
1208 _defaultValue = getStringValue(*classProperty.defaultProperty);
1211 if (!_defaultValue) {
1213 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1227 _name(
std::nullopt),
1228 _semantic(
std::nullopt),
1229 _description(
std::nullopt),
1231 _noData(
std::nullopt),
1232 _defaultValue(
std::nullopt) {}
1252 const std::optional<std::string>&
name() const noexcept {
return _name; }
1257 const std::optional<std::string>&
semantic() const noexcept {
1265 return _description;
1281 std::optional<std::string_view>
offset() const noexcept {
1282 return std::nullopt;
1288 std::optional<std::string_view>
scale() const noexcept {
1289 return std::nullopt;
1295 std::optional<std::string_view>
max() const noexcept {
return std::nullopt; }
1300 std::optional<std::string_view>
min() const noexcept {
return std::nullopt; }
1310 std::optional<std::string_view>
noData() const noexcept {
1312 return std::string_view(*_noData);
1314 return std::nullopt;
1322 return std::string_view(*_defaultValue);
1324 return std::nullopt;
1332 std::optional<std::string> _name;
1333 std::optional<std::string> _semantic;
1334 std::optional<std::string> _description;
1337 std::optional<std::string> _noData;
1338 std::optional<std::string> _defaultValue;
1340 static std::optional<std::string>
1343 return std::nullopt;
1346 return std::string(value.
getString().c_str());
1363template <
typename ElementType>
1371 _name(
std::nullopt),
1372 _semantic(
std::nullopt),
1373 _description(
std::nullopt),
1375 _offset(
std::nullopt),
1376 _scale(
std::nullopt),
1380 _noData(
std::nullopt),
1381 _defaultValue(
std::nullopt) {}
1389 _name(classProperty.name),
1390 _semantic(classProperty.semantic),
1391 _description(classProperty.description),
1392 _count(_count = classProperty.count ? *classProperty.count : 0),
1393 _offset(
std::nullopt),
1394 _scale(
std::nullopt),
1397 _required(classProperty.required),
1398 _noData(
std::nullopt),
1399 _defaultValue(
std::nullopt) {
1400 if (_status != PropertyViewStatus::Valid) {
1405 _status = PropertyViewStatus::ErrorNormalizationMismatch;
1409 getNumericPropertyValues(classProperty);
1410 if (_status != PropertyViewStatus::Valid) {
1414 if (classProperty.
noData) {
1416 _noData = getArrayValue(*classProperty.noData);
1420 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
1425 if (classProperty.defaultProperty) {
1427 _defaultValue = getArrayValue(*classProperty.defaultProperty);
1430 if (!_defaultValue) {
1432 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1446 _name(
std::nullopt),
1447 _semantic(
std::nullopt),
1448 _description(
std::nullopt),
1450 _offset(
std::nullopt),
1451 _scale(
std::nullopt),
1455 _noData(
std::nullopt),
1456 _defaultValue(
std::nullopt) {}
1466 if (_status != PropertyViewStatus::Valid) {
1471 getNumericPropertyValues(property);
1482 if (_status != PropertyViewStatus::Valid) {
1487 getNumericPropertyValues(property);
1499 const std::optional<std::string>&
name() const noexcept {
return _name; }
1504 const std::optional<std::string>&
semantic() const noexcept {
1512 return _description;
1528 std::optional<PropertyArrayView<ElementType>>
offset() const noexcept {
1530 return std::nullopt;
1534 std::span<const std::byte>(_offset->data(), _offset->size()));
1540 std::optional<PropertyArrayView<ElementType>>
scale() const noexcept {
1542 return std::nullopt;
1546 std::span<const std::byte>(_scale->data(), _scale->size()));
1552 std::optional<PropertyArrayView<ElementType>>
max() const noexcept {
1554 return std::nullopt;
1558 std::span<const std::byte>(_max->data(), _max->size()));
1564 std::optional<PropertyArrayView<ElementType>>
min() const noexcept {
1566 return std::nullopt;
1570 std::span<const std::byte>(_min->data(), _min->size()));
1581 std::optional<PropertyArrayView<ElementType>>
noData() const noexcept {
1583 return std::nullopt;
1587 std::span<const std::byte>(_noData->data(), _noData->size()));
1593 std::optional<PropertyArrayView<ElementType>>
defaultValue() const noexcept {
1594 if (!_defaultValue) {
1595 return std::nullopt;
1599 _defaultValue->data(),
1600 _defaultValue->size()));
1608 std::optional<std::string> _name;
1609 std::optional<std::string> _semantic;
1610 std::optional<std::string> _description;
1614 std::optional<std::vector<std::byte>> _offset;
1615 std::optional<std::vector<std::byte>> _scale;
1616 std::optional<std::vector<std::byte>> _max;
1617 std::optional<std::vector<std::byte>> _min;
1620 std::optional<std::vector<std::byte>> _noData;
1621 std::optional<std::vector<std::byte>> _defaultValue;
1623 using PropertyDefinitionType = std::
1624 variant<ClassProperty, PropertyTableProperty, PropertyTextureProperty>;
1625 void getNumericPropertyValues(
const PropertyDefinitionType& inProperty) {
1627 [
this](
auto property) {
1628 if (property.offset) {
1631 case PropertyComponentType::Float32:
1632 case PropertyComponentType::Float64:
1633 if (this->_count > 0) {
1634 this->_offset = getArrayValue(*property.offset);
1636 if (this->_offset &&
1637 getCount<ElementType>(this->_offset) == this->_count) {
1643 this->_status = PropertyViewStatus::ErrorInvalidOffset;
1648 if (property.scale) {
1651 case PropertyComponentType::Float32:
1652 case PropertyComponentType::Float64:
1654 this->_scale = getArrayValue(*property.scale);
1657 getCount<ElementType>(this->_scale) == this->_count) {
1663 this->_status = PropertyViewStatus::ErrorInvalidScale;
1669 if (this->_count > 0) {
1670 this->_max = getArrayValue(*property.max);
1673 getCount<ElementType>(this->_max) != this->_count) {
1675 this->_status = PropertyViewStatus::ErrorInvalidMax;
1681 if (this->_count > 0) {
1682 this->_min = getArrayValue(*property.min);
1685 getCount<ElementType>(this->_min) != this->_count) {
1687 this->_status = PropertyViewStatus::ErrorInvalidMin;
1695 static std::optional<std::vector<std::byte>>
1698 return std::nullopt;
1702 std::vector<ElementType> values;
1703 values.reserve(array.size());
1705 if constexpr (IsMetadataScalar<ElementType>::value) {
1706 for (
size_t i = 0; i < array.size(); i++) {
1707 std::optional<ElementType> element = getScalar<ElementType>(array[i]);
1709 return std::nullopt;
1712 values.push_back(*element);
1715 if constexpr (IsMetadataVecN<ElementType>::value) {
1716 for (
size_t i = 0; i < array.size(); i++) {
1717 std::optional<ElementType> element = getVecN<ElementType>(array[i]);
1719 return std::nullopt;
1722 values.push_back(*element);
1726 if constexpr (IsMetadataMatN<ElementType>::value) {
1727 for (
size_t i = 0; i < array.size(); i++) {
1728 std::optional<ElementType> element = getMatN<ElementType>(array[i]);
1730 return std::nullopt;
1733 values.push_back(*element);
1737 std::vector<std::byte> result(values.size() *
sizeof(ElementType));
1738 std::memcpy(result.data(), values.data(), result.size());
1757template <
typename ElementType>
1768 _name(
std::nullopt),
1769 _semantic(
std::nullopt),
1770 _description(
std::nullopt),
1772 _offset(
std::nullopt),
1773 _scale(
std::nullopt),
1777 _noData(
std::nullopt),
1778 _defaultValue(
std::nullopt) {}
1786 _name(classProperty.name),
1787 _semantic(classProperty.semantic),
1788 _description(classProperty.description),
1789 _count(_count = classProperty.count ? *classProperty.count : 0),
1790 _offset(
std::nullopt),
1791 _scale(
std::nullopt),
1794 _required(classProperty.required),
1795 _noData(
std::nullopt),
1796 _defaultValue(
std::nullopt) {
1797 if (_status != PropertyViewStatus::Valid) {
1802 _status = PropertyViewStatus::ErrorNormalizationMismatch;
1806 getNumericPropertyValues(classProperty);
1807 if (_status != PropertyViewStatus::Valid) {
1811 if (classProperty.
noData) {
1813 _noData = getArrayValue<ElementType>(*classProperty.noData);
1817 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
1822 if (classProperty.defaultProperty) {
1825 getArrayValue<NormalizedType>(*classProperty.defaultProperty);
1828 if (!_defaultValue) {
1829 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1843 _name(
std::nullopt),
1844 _semantic(
std::nullopt),
1845 _description(
std::nullopt),
1847 _offset(
std::nullopt),
1848 _scale(
std::nullopt),
1852 _noData(
std::nullopt),
1853 _defaultValue(
std::nullopt) {}
1863 if (_status != PropertyViewStatus::Valid) {
1868 getNumericPropertyValues(property);
1879 if (_status != PropertyViewStatus::Valid) {
1884 getNumericPropertyValues(property);
1896 const std::optional<std::string>&
name() const noexcept {
return _name; }
1901 const std::optional<std::string>&
semantic() const noexcept {
1909 return _description;
1925 std::optional<PropertyArrayView<NormalizedType>>
offset() const noexcept {
1927 return std::nullopt;
1931 std::span<const std::byte>(_offset->data(), _offset->size()));
1937 std::optional<PropertyArrayView<NormalizedType>>
scale() const noexcept {
1939 return std::nullopt;
1943 std::span<const std::byte>(_scale->data(), _scale->size()));
1949 std::optional<PropertyArrayView<NormalizedType>>
max() const noexcept {
1951 return std::nullopt;
1955 std::span<const std::byte>(_max->data(), _max->size()));
1961 std::optional<PropertyArrayView<NormalizedType>>
min() const noexcept {
1963 return std::nullopt;
1967 std::span<const std::byte>(_min->data(), _min->size()));
1978 std::optional<PropertyArrayView<ElementType>>
noData() const noexcept {
1980 return std::nullopt;
1984 std::span<const std::byte>(_noData->data(), _noData->size()));
1990 std::optional<PropertyArrayView<NormalizedType>>
1992 if (!_defaultValue) {
1993 return std::nullopt;
1997 _defaultValue->data(),
1998 _defaultValue->size()));
2006 std::optional<std::string> _name;
2007 std::optional<std::string> _semantic;
2008 std::optional<std::string> _description;
2012 std::optional<std::vector<std::byte>> _offset;
2013 std::optional<std::vector<std::byte>> _scale;
2014 std::optional<std::vector<std::byte>> _max;
2015 std::optional<std::vector<std::byte>> _min;
2018 std::optional<std::vector<std::byte>> _noData;
2019 std::optional<std::vector<std::byte>> _defaultValue;
2021 using PropertyDefinitionType = std::
2022 variant<ClassProperty, PropertyTableProperty, PropertyTextureProperty>;
2023 void getNumericPropertyValues(
const PropertyDefinitionType& inProperty) {
2025 [
this](
auto property) {
2026 if (property.offset) {
2028 _offset = getArrayValue<NormalizedType>(*property.offset);
2030 if (!_offset || getCount<NormalizedType>(_offset) != _count) {
2032 _status = PropertyViewStatus::ErrorInvalidOffset;
2037 if (property.scale) {
2039 _scale = getArrayValue<NormalizedType>(*property.scale);
2041 if (!_scale || getCount<NormalizedType>(_scale) != _count) {
2043 _status = PropertyViewStatus::ErrorInvalidScale;
2050 _max = getArrayValue<NormalizedType>(*property.max);
2052 if (!_max || getCount<NormalizedType>(_max) != _count) {
2054 _status = PropertyViewStatus::ErrorInvalidMax;
2061 _min = getArrayValue<NormalizedType>(*property.min);
2063 if (!_min || getCount<NormalizedType>(_min) != _count) {
2065 _status = PropertyViewStatus::ErrorInvalidMin;
2073 template <
typename T>
2074 static std::optional<std::vector<std::byte>>
2077 return std::nullopt;
2081 std::vector<T> values;
2082 values.reserve(array.size());
2084 if constexpr (IsMetadataScalar<T>::value) {
2085 for (
size_t i = 0; i < array.size(); i++) {
2086 std::optional<T> element = getScalar<T>(array[i]);
2088 return std::nullopt;
2091 values.push_back(*element);
2095 if constexpr (IsMetadataVecN<T>::value) {
2096 for (
size_t i = 0; i < array.size(); i++) {
2097 std::optional<T> element = getVecN<T>(array[i]);
2099 return std::nullopt;
2102 values.push_back(*element);
2106 if constexpr (IsMetadataMatN<T>::value) {
2107 for (
size_t i = 0; i < array.size(); i++) {
2108 std::optional<T> element = getMatN<T>(array[i]);
2110 return std::nullopt;
2113 values.push_back(*element);
2117 std::vector<std::byte> result(values.size() *
sizeof(T));
2118 std::memcpy(result.data(), values.data(), result.size());
2135 _name(
std::nullopt),
2136 _semantic(
std::nullopt),
2137 _description(
std::nullopt),
2149 _name(classProperty.name),
2150 _semantic(classProperty.semantic),
2151 _description(classProperty.description),
2152 _count(classProperty.count ? *classProperty.count : 0),
2153 _required(classProperty.required),
2156 if (_status != PropertyViewStatus::Valid) {
2163 getBooleanArrayValue(*classProperty.defaultProperty, _size);
2166 if (_size == 0 || (_count > 0 && _size != _count)) {
2167 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
2181 _name(
std::nullopt),
2182 _semantic(
std::nullopt),
2183 _description(
std::nullopt),
2207 const std::optional<std::string>&
name() const noexcept {
return _name; }
2212 const std::optional<std::string>&
semantic() const noexcept {
2220 return _description;
2236 std::optional<PropertyArrayView<bool>>
offset() const noexcept {
2237 return std::nullopt;
2243 std::optional<PropertyArrayView<bool>>
scale() const noexcept {
2244 return std::nullopt;
2250 std::optional<PropertyArrayView<bool>>
max() const noexcept {
2251 return std::nullopt;
2257 std::optional<PropertyArrayView<bool>>
min() const noexcept {
2258 return std::nullopt;
2269 std::optional<PropertyArrayView<bool>>
noData() const noexcept {
2270 return std::nullopt;
2279 std::span<const std::byte>(
2280 _defaultValue.data(),
2281 _defaultValue.size()),
2286 return std::nullopt;
2294 std::optional<std::string> _name;
2295 std::optional<std::string> _semantic;
2296 std::optional<std::string> _description;
2301 std::vector<std::byte> _defaultValue;
2304 static std::vector<std::byte> getBooleanArrayValue(
2308 return std::vector<std::byte>();
2312 std::vector<std::byte> values;
2313 values.reserve((array.size() / 8) + 1);
2315 size_t byteIndex = 0;
2316 uint8_t bitIndex = 0;
2318 for (
size_t i = 0; i < array.size(); i++, size++) {
2319 if (!array[i].isBool()) {
2324 if (values.size() < byteIndex - 1) {
2325 values.push_back(std::byte(0));
2328 std::byte value = std::byte(array[i].getBool() ? 1 : 0);
2329 value = value << bitIndex;
2331 values[byteIndex] |= value;
2355 _name(
std::nullopt),
2356 _semantic(
std::nullopt),
2357 _description(
std::nullopt),
2369 _name(classProperty.name),
2370 _semantic(classProperty.semantic),
2371 _description(classProperty.description),
2372 _count(classProperty.count ? *classProperty.count : 0),
2373 _required(classProperty.required),
2376 if (_status != PropertyViewStatus::Valid) {
2380 if (classProperty.
noData) {
2382 _noData = getStringArrayValue(*classProperty.noData);
2385 if (_noData.size == 0 || (_count > 0 && _noData.size != _count)) {
2386 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
2391 if (classProperty.defaultProperty) {
2393 _defaultValue = getStringArrayValue(*classProperty.defaultProperty);
2396 if (_defaultValue.size == 0 ||
2397 (_count > 0 && _defaultValue.size != _count)) {
2399 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
2413 _name(
std::nullopt),
2414 _semantic(
std::nullopt),
2415 _description(
std::nullopt),
2439 const std::optional<std::string>&
name() const noexcept {
return _name; }
2444 const std::optional<std::string>&
semantic() const noexcept {
2452 return _description;
2468 std::optional<PropertyArrayView<std::string_view>>
offset() const noexcept {
2469 return std::nullopt;
2475 std::optional<PropertyArrayView<std::string_view>>
scale() const noexcept {
2476 return std::nullopt;
2482 std::optional<PropertyArrayView<std::string_view>>
max() const noexcept {
2483 return std::nullopt;
2489 std::optional<PropertyArrayView<std::string_view>>
min() const noexcept {
2490 return std::nullopt;
2501 std::optional<PropertyArrayView<std::string_view>>
noData() const noexcept {
2502 if (_noData.size > 0) {
2504 std::span<const std::byte>(_noData.data.data(), _noData.data.size()),
2505 std::span<const std::byte>(
2506 _noData.offsets.data(),
2507 _noData.offsets.size()),
2512 return std::nullopt;
2518 std::optional<PropertyArrayView<std::string_view>>
2520 if (_defaultValue.size > 0) {
2522 std::span<const std::byte>(
2523 _defaultValue.data.data(),
2524 _defaultValue.data.size()),
2525 std::span<const std::byte>(
2526 _defaultValue.offsets.data(),
2527 _defaultValue.offsets.size()),
2528 _defaultValue.offsetType,
2529 _defaultValue.size);
2532 return std::nullopt;
2540 std::optional<std::string> _name;
2541 std::optional<std::string> _semantic;
2542 std::optional<std::string> _description;
2547 struct StringArrayValue {
2548 std::vector<std::byte> data;
2549 std::vector<std::byte> offsets;
2554 StringArrayValue _noData;
2555 StringArrayValue _defaultValue;
2557 static StringArrayValue
2559 StringArrayValue result;
2564 std::vector<std::string> strings;
2565 std::vector<uint64_t> stringOffsets;
2567 const auto array = jsonValue.
getArray();
2568 strings.reserve(array.size());
2569 stringOffsets.reserve(array.size() + 1);
2570 stringOffsets.push_back(
static_cast<uint64_t
>(0));
2572 for (
size_t i = 0; i < array.size(); i++) {
2573 if (!array[i].isString()) {
2578 const std::string&
string = array[i].getString();
2579 strings.push_back(
string);
2580 stringOffsets.push_back(stringOffsets[i] +
string.size());
2583 uint64_t totalLength = stringOffsets.back();
2584 result.data.resize(totalLength);
2585 for (
size_t i = 0; i < strings.size(); ++i) {
2587 result.data.data() + stringOffsets[i],
2592 if (totalLength <= std::numeric_limits<uint8_t>::max()) {
2593 result.offsets = narrowOffsetsBuffer<uint8_t>(stringOffsets);
2594 result.offsetType = PropertyComponentType::Uint8;
2595 }
else if (totalLength <= std::numeric_limits<uint16_t>::max()) {
2596 result.offsets = narrowOffsetsBuffer<uint16_t>(stringOffsets);
2597 result.offsetType = PropertyComponentType::Uint16;
2598 }
else if (totalLength <= std::numeric_limits<uint32_t>::max()) {
2599 result.offsets = narrowOffsetsBuffer<uint32_t>(stringOffsets);
2600 result.offsetType = PropertyComponentType::Uint32;
2602 result.offsets.resize(stringOffsets.size() *
sizeof(uint64_t));
2604 result.offsets.data(),
2605 stringOffsets.data(),
2606 result.offsets.size());
2607 result.offsetType = PropertyComponentType::Uint64;
2610 result.size =
static_cast<int64_t
>(strings.size());
2615 template <
typename T>
2616 static std::vector<std::byte>
2617 narrowOffsetsBuffer(std::vector<uint64_t> offsets) {
2618 std::vector<std::byte> result(offsets.size() *
sizeof(T));
2619 size_t bufferOffset = 0;
2620 for (
size_t i = 0; i < offsets.size(); i++, bufferOffset +=
sizeof(T)) {
2621 T offset =
static_cast<T
>(offsets[i]);
2622 std::memcpy(result.data() + bufferOffset, &offset,
sizeof(T));
A view on an array element of a PropertyTableProperty or PropertyTextureProperty.
Indicates the status of a property view.
static const PropertyViewStatusType ErrorTypeMismatch
This property view's type does not match what is specified in ClassProperty::type.
static const PropertyViewStatusType ErrorInvalidDefaultValue
The property provided an invalid default value.
static const PropertyViewStatusType ErrorInvalidMin
The property provided an invalid minimum value.
static const PropertyViewStatusType ErrorInvalidMax
The property provided an invalid maximum value.
static const PropertyViewStatusType ErrorInvalidOffset
The property provided an invalid offset value.
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 ErrorInvalidNormalization
This property says it is normalized, but it does not have an integer component type.
static const PropertyViewStatusType ErrorArrayTypeMismatch
This property view differs from what is specified in ClassProperty::array.
static const PropertyViewStatusType ErrorInvalidNoDataValue
The property provided an invalid "no data" value.
static const PropertyViewStatusType ErrorNormalizationMismatch
This property view's normalization differs from what is specified in ClassProperty::normalized.
static const PropertyViewStatusType EmptyPropertyWithDefault
This property view does not contain any data, but specifies a default value. This happens when a clas...
static const PropertyViewStatusType ErrorInvalidScale
The property provided an invalid scale value.
static const PropertyViewStatusType ErrorComponentTypeMismatch
This property view's component type does not match what is specified in ClassProperty::componentType.
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 ...
bool required() const noexcept
Whether the property must be present in every entity conforming to the class. If not required,...
std::optional< ElementType > defaultValue() const noexcept
Gets the default value to use when encountering a "no data" value or an omitted property....
const std::optional< std::string > & name() const noexcept
Gets the name of the property being viewed. Returns std::nullopt if no name was specified.
PropertyViewStatusType _status
Indicates the status of a property view.
const std::optional< std::string > & semantic() const noexcept
Gets the semantic of the property being viewed. The semantic is an identifier that describes how this...
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property)
Constructs a property instance from a property table property and its class definition.
bool normalized() const noexcept
Whether this property has a normalized integer type.
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
PropertyView(const ClassProperty &classProperty, const PropertyTextureProperty &property)
Constructs a property instance from a property texture property and its class definition.
int64_t arrayCount() const noexcept
Get the element count of the fixed-length arrays in this property. Only applicable when the property ...
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...
std::optional< ElementType > min() const noexcept
Gets the minimum allowed value for the property. Only applicable to SCALAR, VECN, and MATN types....
PropertyView(const ClassProperty &classProperty, const PropertyAttributeProperty &property)
Constructs a property instance from a property attribute property and its class definition.
std::optional< ElementType > max() const noexcept
Gets the maximum allowed value for the property. Only applicable to SCALAR, VECN, and MATN types....
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
const std::optional< std::string > & description() const noexcept
Gets the description of the property being viewed. Returns std::nullopt if no description was specifi...
PropertyView()
Constructs an empty property instance.
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property)
Constructs a property instance from a property table property and its class definition.
std::optional< ElementType > noData() const noexcept
Constructs an empty property instance. false>noData
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
std::optional< NormalizedType > max() const noexcept
Constructs an empty property instance. false>max
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
PropertyView(const ClassProperty &classProperty, const PropertyTextureProperty &property)
Constructs a property instance from a property texture property and its class definition.
PropertyView(const ClassProperty &classProperty, const PropertyAttributeProperty &property)
Constructs a property instance from a property attribute property and its class definition.
PropertyViewStatusType _status
Indicates the status of a property view.
std::optional< NormalizedType > scale() const noexcept
Constructs an empty property instance. false>scale
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
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
bool required() const noexcept
Constructs an empty property instance. false>required
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
std::optional< NormalizedType > offset() const noexcept
Constructs an empty property instance. false>offset
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
std::optional< NormalizedType > min() const noexcept
Constructs an empty property instance. false>min
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
std::optional< PropertyArrayView< ElementType > > noData() const noexcept
Constructs an empty property instance. false>noData
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
std::optional< PropertyArrayView< ElementType > > offset() const noexcept
Constructs an empty property instance. false>offset
std::optional< PropertyArrayView< ElementType > > max() const noexcept
Constructs an empty property instance. false>max
std::optional< PropertyArrayView< ElementType > > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
std::optional< PropertyArrayView< ElementType > > min() const noexcept
Constructs an empty property instance. false>min
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
PropertyView()
Constructs an empty property instance.
PropertyView(const ClassProperty &classProperty, const PropertyTextureProperty &property)
Constructs a property instance from a property texture property and its class definition.
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
bool required() const noexcept
Constructs an empty property instance. false>required
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property)
Constructs a property instance from a property table property and its class definition.
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
std::optional< PropertyArrayView< ElementType > > scale() const noexcept
Constructs an empty property instance. false>scale
PropertyViewStatusType _status
Indicates the status of a property view.
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
std::optional< PropertyArrayView< NormalizedType > > max() const noexcept
Constructs an empty property instance. false>max
PropertyViewStatusType _status
Indicates the status of a property view.
std::optional< PropertyArrayView< NormalizedType > > scale() const noexcept
Constructs an empty property instance. false>scale
std::optional< PropertyArrayView< ElementType > > noData() const noexcept
Constructs an empty property instance. false>noData
PropertyView()
Constructs an empty property instance.
std::optional< PropertyArrayView< NormalizedType > > min() const noexcept
Constructs an empty property instance. false>min
PropertyView(const ClassProperty &classProperty, const PropertyTextureProperty &property)
Constructs a property instance from a property texture property and its class definition.
std::optional< PropertyArrayView< NormalizedType > > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property)
Constructs a property instance from a property table property and its class definition.
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
std::optional< PropertyArrayView< NormalizedType > > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
bool required() const noexcept
Constructs an empty property instance. false>required
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
std::optional< PropertyArrayView< bool > > min() const noexcept
Constructs an empty property instance. false>min
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
std::optional< PropertyArrayView< bool > > max() const noexcept
Constructs an empty property instance. false>max
std::optional< PropertyArrayView< bool > > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
PropertyView()
Constructs an empty property instance.
PropertyViewStatusType _status
Indicates the status of a property view.
bool required() const noexcept
Constructs an empty property instance. false>required
std::optional< PropertyArrayView< bool > > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< PropertyArrayView< bool > > scale() const noexcept
Constructs an empty property instance. false>scale
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &)
Constructs a property instance from a property table property and its class definition.
std::optional< PropertyArrayView< bool > > noData() const noexcept
Constructs an empty property instance. false>noData
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
std::optional< PropertyArrayView< std::string_view > > max() const noexcept
Constructs an empty property instance. false>max
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &)
Constructs a property instance from a property table property and its class definition.
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
PropertyView()
Constructs an empty property instance.
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
std::optional< PropertyArrayView< std::string_view > > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyViewStatusType _status
Indicates the status of a property view.
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
std::optional< PropertyArrayView< std::string_view > > min() const noexcept
Constructs an empty property instance. false>min
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
std::optional< PropertyArrayView< std::string_view > > noData() const noexcept
Constructs an empty property instance. false>noData
bool required() const noexcept
Constructs an empty property instance. false>required
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< PropertyArrayView< std::string_view > > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
std::optional< PropertyArrayView< std::string_view > > scale() const noexcept
Constructs an empty property instance. false>scale
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
std::optional< bool > min() const noexcept
Constructs an empty property instance. false>min
std::optional< bool > noData() const noexcept
Constructs an empty property instance. false>noData
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
bool required() const noexcept
Constructs an empty property instance. false>required
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
std::optional< bool > scale() const noexcept
Constructs an empty property instance. false>scale
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &)
Constructs a property instance from a property table property and its class definition.
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyViewStatusType _status
Indicates the status of a property view.
PropertyView()
Constructs an empty property instance.
std::optional< bool > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
std::optional< bool > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< bool > max() const noexcept
Constructs an empty property instance. false>max
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &)
Constructs a property instance from a property table property and its class definition.
bool required() const noexcept
Constructs an empty property instance. false>required
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
PropertyView()
Constructs an empty property instance.
std::optional< std::string_view > min() const noexcept
Constructs an empty property instance. false>min
std::optional< std::string_view > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyViewStatusType _status
Indicates the status of a property view.
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
std::optional< std::string_view > scale() const noexcept
Constructs an empty property instance. false>scale
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
std::optional< std::string_view > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< std::string_view > noData() const noexcept
Constructs an empty property instance. false>noData
std::optional< std::string_view > max() const noexcept
Constructs an empty property instance. false>max
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
Represents a metadata property in EXT_structural_metadata.
A generic implementation of a value in a JSON structure.
bool getBool() const
Gets the bool from the value.
const JsonValue::String & getString() const
Gets the string from the value.
std::vector< JsonValue > Array
The type to represent an Array JSON value.
bool isBool() const noexcept
Returns whether this value is a Bool value.
bool isArray() const noexcept
Returns whether this value is an Array value.
bool isString() const noexcept
Returns whether this value is a String value.
std::optional< To > getSafeNumber() const
Gets the numerical quantity from the value casted to the To type. This function should be used over g...
const JsonValue::Array & getArray() const
Gets the array from the value.
Classes for working with glTF models.
PropertyComponentType
The possible types of a property component.
PropertyComponentType convertStringToPropertyComponentType(const std::string &str)
Converts a string into a PropertyComponentType.
int64_t getCount(std::optional< std::vector< std::byte > > &buffer)
Obtains the number of values of type ElementType that could fit in the buffer.
PropertyViewStatusType validatePropertyType(const ClassProperty &classProperty)
Validates a ClassProperty, checking for any type mismatches.
PropertyType convertStringToPropertyType(const std::string &str)
Converts a string into a PropertyType.
int32_t PropertyViewStatusType
The type used for fields of PropertyViewStatus.
PropertyViewStatusType validateArrayPropertyType(const ClassProperty &classProperty)
Validates a ClassProperty representing an array, checking for any type mismatches.
bool normalized
Specifies whether integer values are normalized. Only applicable to SCALAR, VECN, and MATN types with...
std::optional< std::string > componentType
The datatype of the element's components. Only applicable to SCALAR, VECN, and MATN types.
bool array
Whether the property is an array. When count is defined the property is a fixed-length array....
std::optional< CesiumUtility::JsonValue > noData
A noData value represents missing data — also known as a sentinel value — wherever it appears....
std::string type
The element type.
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 attribute containing property values.
An array of binary property values.
A texture containing property values.
Convert an integer numeric type to the corresponding representation as a double type....
Convert a C++ type to PropertyType and PropertyComponentType.