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"
14 typedef int32_t PropertyViewStatusType;
32 static const PropertyViewStatusType
Valid = 0;
110 template <
typename T>
111 PropertyViewStatusType
114 convertStringToPropertyType(classProperty.
type)) {
118 PropertyComponentType expectedComponentType =
119 TypeToPropertyType<T>::component;
122 expectedComponentType != PropertyComponentType::None) {
127 expectedComponentType !=
128 convertStringToPropertyComponentType(*classProperty.
componentType)) {
132 if (classProperty.
array) {
139 template <
typename T>
140 PropertyViewStatusType
141 validateArrayPropertyType(
const ClassProperty& classProperty) {
142 using ElementType =
typename MetadataArrayType<T>::type;
143 if (TypeToPropertyType<ElementType>::value !=
144 convertStringToPropertyType(classProperty.type)) {
148 PropertyComponentType expectedComponentType =
149 TypeToPropertyType<ElementType>::component;
151 if (!classProperty.componentType &&
152 expectedComponentType != PropertyComponentType::None) {
156 if (classProperty.componentType &&
157 expectedComponentType !=
158 convertStringToPropertyComponentType(*classProperty.componentType)) {
162 if (!classProperty.array) {
169 template <
typename T>
175 }
catch (
const gsl::narrowing_error& ) {
180 template <
typename VecType>
181 static std::optional<VecType>
188 constexpr glm::length_t N = VecType::length();
189 if (array.size() != N) {
193 using T =
typename VecType::value_type;
196 for (glm::length_t i = 0; i < N; i++) {
197 std::optional<T> value = getScalar<T>(array[i]);
208 template <
typename MatType>
209 static std::optional<MatType>
216 constexpr glm::length_t N = MatType::length();
217 if (array.size() != N * N) {
221 using T =
typename MatType::value_type;
224 for (glm::length_t i = 0; i < N; i++) {
226 for (glm::length_t j = 0; j < N; j++) {
227 std::optional<T> value = getScalar<T>(array[i * N + j]);
232 result[i][j] = *value;
239 template <
typename ElementType>
240 int64_t getCount(std::optional<std::vector<std::byte>>& buffer) {
245 return static_cast<int64_t
>(buffer->size() /
sizeof(ElementType));
251 template <
typename ElementType,
bool Normalized = false>
class PropertyView;
265 template <
typename ElementType>
class PropertyView<ElementType, false> {
273 _semantic(std::nullopt),
274 _description(std::nullopt),
275 _offset(std::nullopt),
276 _scale(std::nullopt),
280 _noData(std::nullopt),
281 _defaultValue(std::nullopt) {}
287 : _status(validatePropertyType<ElementType>(classProperty)),
288 _name(classProperty.name),
289 _semantic(classProperty.semantic),
290 _description(classProperty.description),
291 _offset(std::nullopt),
292 _scale(std::nullopt),
295 _required(classProperty.required),
296 _noData(std::nullopt),
297 _defaultValue(std::nullopt) {
307 getNumericPropertyValues(classProperty);
312 if (classProperty.
noData) {
315 _noData = getValue(*classProperty.
noData);
331 if (!_defaultValue) {
349 _semantic(std::nullopt),
350 _description(std::nullopt),
351 _offset(std::nullopt),
352 _scale(std::nullopt),
356 _noData(std::nullopt),
357 _defaultValue(std::nullopt) {}
372 getNumericPropertyValues(property);
388 getNumericPropertyValues(property);
404 getNumericPropertyValues(property);
414 PropertyViewStatusType
status() const noexcept {
return _status; }
420 const std::optional<std::string>&
name() const noexcept {
return _name; }
428 const std::optional<std::string>&
semantic() const noexcept {
460 std::optional<ElementType>
offset() const noexcept {
return _offset; }
469 std::optional<ElementType>
scale() const noexcept {
return _scale; }
480 std::optional<ElementType>
max() const noexcept {
return _max; }
491 std::optional<ElementType>
min() const noexcept {
return _min; }
498 bool required() const noexcept {
return _required; }
509 std::optional<ElementType>
noData() const noexcept {
return _noData; }
520 return _defaultValue;
524 PropertyViewStatusType _status;
527 std::optional<std::string> _name;
528 std::optional<std::string> _semantic;
529 std::optional<std::string> _description;
531 std::optional<ElementType> _offset;
532 std::optional<ElementType> _scale;
533 std::optional<ElementType> _max;
534 std::optional<ElementType> _min;
537 std::optional<ElementType> _noData;
538 std::optional<ElementType> _defaultValue;
550 static std::optional<ElementType>
553 return getScalar<ElementType>(jsonValue);
556 if constexpr (IsMetadataVecN<ElementType>::value) {
557 return getVecN<ElementType>(jsonValue);
560 if constexpr (IsMetadataMatN<ElementType>::value) {
561 return getMatN<ElementType>(jsonValue);
565 using PropertyDefinitionType = std::variant<
567 PropertyTableProperty,
568 PropertyTextureProperty,
569 PropertyAttributeProperty>;
575 void getNumericPropertyValues(
const PropertyDefinitionType& inProperty) {
577 [
this](
auto property) {
578 if (property.offset) {
580 switch (TypeToPropertyType<ElementType>::component) {
581 case PropertyComponentType::Float32:
582 case PropertyComponentType::Float64:
583 this->_offset = getValue(*property.offset);
590 this->_status = PropertyViewStatus::ErrorInvalidOffset;
595 if (property.scale) {
597 switch (TypeToPropertyType<ElementType>::component) {
598 case PropertyComponentType::Float32:
599 case PropertyComponentType::Float64:
600 this->_scale = getValue(*property.scale);
607 this->_status = PropertyViewStatus::ErrorInvalidScale;
613 this->_max = getValue(*property.max);
616 this->_status = PropertyViewStatus::ErrorInvalidMax;
622 this->_min = getValue(*property.min);
625 this->_status = PropertyViewStatus::ErrorInvalidMin;
647 template <
typename ElementType>
class PropertyView<ElementType, true> {
658 _semantic(std::nullopt),
659 _description(std::nullopt),
660 _offset(std::nullopt),
661 _scale(std::nullopt),
665 _noData(std::nullopt),
666 _defaultValue(std::nullopt) {}
672 : _status(validatePropertyType<ElementType>(classProperty)),
673 _name(classProperty.name),
674 _semantic(classProperty.semantic),
675 _description(classProperty.description),
676 _offset(std::nullopt),
677 _scale(std::nullopt),
680 _required(classProperty.required),
681 _noData(std::nullopt),
682 _defaultValue(std::nullopt) {
683 if (_status != PropertyViewStatus::Valid) {
688 _status = PropertyViewStatus::ErrorNormalizationMismatch;
691 getNumericPropertyValues(classProperty);
692 if (_status != PropertyViewStatus::Valid) {
696 if (classProperty.
noData) {
699 _noData = getValue<ElementType>(*classProperty.
noData);
703 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
714 if (!_defaultValue) {
716 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
731 _semantic(std::nullopt),
732 _description(std::nullopt),
733 _offset(std::nullopt),
734 _scale(std::nullopt),
738 _noData(std::nullopt),
739 _defaultValue(std::nullopt) {}
749 if (_status != PropertyViewStatus::Valid) {
754 getNumericPropertyValues(property);
765 if (_status != PropertyViewStatus::Valid) {
770 getNumericPropertyValues(property);
781 if (_status != PropertyViewStatus::Valid) {
786 getNumericPropertyValues(property);
793 PropertyViewStatusType
status() const noexcept {
return _status; }
798 const std::optional<std::string>&
name() const noexcept {
return _name; }
803 const std::optional<std::string>&
semantic() const noexcept {
827 std::optional<NormalizedType>
offset() const noexcept {
return _offset; }
832 std::optional<NormalizedType>
scale() const noexcept {
return _scale; }
837 std::optional<NormalizedType>
max() const noexcept {
return _max; }
842 std::optional<NormalizedType>
min() const noexcept {
return _min; }
847 bool required() const noexcept {
return _required; }
852 std::optional<ElementType>
noData() const noexcept {
return _noData; }
858 return _defaultValue;
862 PropertyViewStatusType _status;
865 std::optional<std::string> _name;
866 std::optional<std::string> _semantic;
867 std::optional<std::string> _description;
869 std::optional<NormalizedType> _offset;
870 std::optional<NormalizedType> _scale;
871 std::optional<NormalizedType> _max;
872 std::optional<NormalizedType> _min;
875 std::optional<ElementType> _noData;
876 std::optional<NormalizedType> _defaultValue;
887 template <
typename T>
890 return getScalar<T>(jsonValue);
893 if constexpr (IsMetadataVecN<T>::value) {
894 return getVecN<T>(jsonValue);
897 if constexpr (IsMetadataMatN<T>::value) {
898 return getMatN<T>(jsonValue);
902 using PropertyDefinitionType = std::variant<
904 PropertyTableProperty,
905 PropertyTextureProperty,
906 PropertyAttributeProperty>;
912 void getNumericPropertyValues(
const PropertyDefinitionType& inProperty) {
914 [
this](
auto property) {
915 if (property.offset) {
916 _offset = getValue<NormalizedType>(*property.offset);
919 _status = PropertyViewStatus::ErrorInvalidOffset;
924 if (property.scale) {
925 _scale = getValue<NormalizedType>(*property.scale);
928 _status = PropertyViewStatus::ErrorInvalidScale;
934 _max = getValue<NormalizedType>(*property.max);
937 _status = PropertyViewStatus::ErrorInvalidMax;
943 _min = getValue<NormalizedType>(*property.min);
946 _status = PropertyViewStatus::ErrorInvalidMin;
967 _semantic(std::nullopt),
968 _description(std::nullopt),
970 _defaultValue(std::nullopt) {}
976 : _status(validatePropertyType<bool>(classProperty)),
977 _name(classProperty.name),
978 _semantic(classProperty.semantic),
979 _description(classProperty.description),
980 _required(classProperty.required),
981 _defaultValue(std::nullopt) {
982 if (_status != PropertyViewStatus::Valid) {
991 if (!_defaultValue) {
993 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1007 _name(std::nullopt),
1008 _semantic(std::nullopt),
1009 _description(std::nullopt),
1011 _defaultValue(std::nullopt) {}
1026 PropertyViewStatusType
status() const noexcept {
return _status; }
1031 const std::optional<std::string>&
name() const noexcept {
return _name; }
1036 const std::optional<std::string>&
semantic() const noexcept {
1044 return _description;
1060 std::optional<bool>
offset() const noexcept {
return std::nullopt; }
1065 std::optional<bool>
scale() const noexcept {
return std::nullopt; }
1070 std::optional<bool>
max() const noexcept {
return std::nullopt; }
1075 std::optional<bool>
min() const noexcept {
return std::nullopt; }
1085 std::optional<bool>
noData() const noexcept {
return std::nullopt; }
1090 std::optional<bool>
defaultValue() const noexcept {
return _defaultValue; }
1093 PropertyViewStatusType _status;
1096 std::optional<std::string> _name;
1097 std::optional<std::string> _semantic;
1098 std::optional<std::string> _description;
1101 std::optional<bool> _defaultValue;
1103 static std::optional<bool>
1106 return std::nullopt;
1124 _name(std::nullopt),
1125 _semantic(std::nullopt),
1126 _description(std::nullopt),
1128 _noData(std::nullopt),
1129 _defaultValue(std::nullopt) {}
1135 : _status(validatePropertyType<std::string_view>(classProperty)),
1136 _name(classProperty.name),
1137 _semantic(classProperty.semantic),
1138 _description(classProperty.description),
1139 _required(classProperty.required),
1140 _noData(std::nullopt),
1141 _defaultValue(std::nullopt) {
1142 if (_status != PropertyViewStatus::Valid) {
1146 if (classProperty.
noData) {
1148 _noData = getStringValue(*classProperty.
noData);
1153 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
1163 if (!_defaultValue) {
1165 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1179 _name(std::nullopt),
1180 _semantic(std::nullopt),
1181 _description(std::nullopt),
1183 _noData(std::nullopt),
1184 _defaultValue(std::nullopt) {}
1199 PropertyViewStatusType
status() const noexcept {
return _status; }
1204 const std::optional<std::string>&
name() const noexcept {
return _name; }
1209 const std::optional<std::string>&
semantic() const noexcept {
1217 return _description;
1233 std::optional<std::string_view>
offset() const noexcept {
1234 return std::nullopt;
1240 std::optional<std::string_view>
scale() const noexcept {
1241 return std::nullopt;
1247 std::optional<std::string_view>
max() const noexcept {
return std::nullopt; }
1252 std::optional<std::string_view>
min() const noexcept {
return std::nullopt; }
1262 std::optional<std::string_view>
noData() const noexcept {
1264 return std::string_view(*_noData);
1266 return std::nullopt;
1274 return std::string_view(*_defaultValue);
1276 return std::nullopt;
1280 PropertyViewStatusType _status;
1283 std::optional<std::string> _name;
1284 std::optional<std::string> _semantic;
1285 std::optional<std::string> _description;
1288 std::optional<std::string> _noData;
1289 std::optional<std::string> _defaultValue;
1291 static std::optional<std::string>
1294 return std::nullopt;
1297 return std::string(value.
getString().c_str());
1314 template <
typename ElementType>
1322 _name(std::nullopt),
1323 _semantic(std::nullopt),
1324 _description(std::nullopt),
1326 _offset(std::nullopt),
1327 _scale(std::nullopt),
1331 _noData(std::nullopt),
1332 _defaultValue(std::nullopt) {}
1340 _name(classProperty.name),
1341 _semantic(classProperty.semantic),
1342 _description(classProperty.description),
1343 _count(_count = classProperty.count ? *classProperty.count : 0),
1344 _offset(std::nullopt),
1345 _scale(std::nullopt),
1348 _required(classProperty.required),
1349 _noData(std::nullopt),
1350 _defaultValue(std::nullopt) {
1351 if (_status != PropertyViewStatus::Valid) {
1356 _status = PropertyViewStatus::ErrorNormalizationMismatch;
1360 getNumericPropertyValues(classProperty);
1361 if (_status != PropertyViewStatus::Valid) {
1365 if (classProperty.
noData) {
1367 _noData = getArrayValue(*classProperty.
noData);
1371 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
1381 if (!_defaultValue) {
1383 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1397 _name(std::nullopt),
1398 _semantic(std::nullopt),
1399 _description(std::nullopt),
1401 _offset(std::nullopt),
1402 _scale(std::nullopt),
1406 _noData(std::nullopt),
1407 _defaultValue(std::nullopt) {}
1417 if (_status != PropertyViewStatus::Valid) {
1422 getNumericPropertyValues(property);
1433 if (_status != PropertyViewStatus::Valid) {
1438 getNumericPropertyValues(property);
1445 PropertyViewStatusType
status() const noexcept {
return _status; }
1450 const std::optional<std::string>&
name() const noexcept {
return _name; }
1455 const std::optional<std::string>&
semantic() const noexcept {
1463 return _description;
1479 std::optional<PropertyArrayView<ElementType>>
offset() const noexcept {
1481 return std::nullopt;
1485 gsl::span<const std::byte>(_offset->data(), _offset->size()));
1491 std::optional<PropertyArrayView<ElementType>>
scale() const noexcept {
1493 return std::nullopt;
1497 gsl::span<const std::byte>(_scale->data(), _scale->size()));
1503 std::optional<PropertyArrayView<ElementType>>
max() const noexcept {
1505 return std::nullopt;
1509 gsl::span<const std::byte>(_max->data(), _max->size()));
1515 std::optional<PropertyArrayView<ElementType>>
min() const noexcept {
1517 return std::nullopt;
1521 gsl::span<const std::byte>(_min->data(), _min->size()));
1532 std::optional<PropertyArrayView<ElementType>>
noData() const noexcept {
1534 return std::nullopt;
1538 gsl::span<const std::byte>(_noData->data(), _noData->size()));
1544 std::optional<PropertyArrayView<ElementType>>
defaultValue() const noexcept {
1545 if (!_defaultValue) {
1546 return std::nullopt;
1550 _defaultValue->data(),
1551 _defaultValue->size()));
1555 PropertyViewStatusType _status;
1558 std::optional<std::string> _name;
1559 std::optional<std::string> _semantic;
1560 std::optional<std::string> _description;
1564 std::optional<std::vector<std::byte>> _offset;
1565 std::optional<std::vector<std::byte>> _scale;
1566 std::optional<std::vector<std::byte>> _max;
1567 std::optional<std::vector<std::byte>> _min;
1570 std::optional<std::vector<std::byte>> _noData;
1571 std::optional<std::vector<std::byte>> _defaultValue;
1573 using PropertyDefinitionType = std::
1574 variant<ClassProperty, PropertyTableProperty, PropertyTextureProperty>;
1575 void getNumericPropertyValues(
const PropertyDefinitionType& inProperty) {
1577 [
this](
auto property) {
1578 if (property.offset) {
1580 switch (TypeToPropertyType<ElementType>::component) {
1581 case PropertyComponentType::Float32:
1582 case PropertyComponentType::Float64:
1583 if (this->_count > 0) {
1584 this->_offset = getArrayValue(*property.offset);
1586 if (this->_offset &&
1587 getCount<ElementType>(this->_offset) == this->_count) {
1593 this->_status = PropertyViewStatus::ErrorInvalidOffset;
1598 if (property.scale) {
1600 switch (TypeToPropertyType<ElementType>::component) {
1601 case PropertyComponentType::Float32:
1602 case PropertyComponentType::Float64:
1604 this->_scale = getArrayValue(*property.scale);
1607 getCount<ElementType>(this->_scale) == this->_count) {
1613 this->_status = PropertyViewStatus::ErrorInvalidScale;
1619 if (this->_count > 0) {
1620 this->_max = getArrayValue(*property.max);
1623 getCount<ElementType>(this->_max) != this->_count) {
1625 this->_status = PropertyViewStatus::ErrorInvalidMax;
1631 if (this->_count > 0) {
1632 this->_min = getArrayValue(*property.min);
1635 getCount<ElementType>(this->_min) != this->_count) {
1637 this->_status = PropertyViewStatus::ErrorInvalidMin;
1645 static std::optional<std::vector<std::byte>>
1648 return std::nullopt;
1652 std::vector<ElementType> values;
1653 values.reserve(array.size());
1655 if constexpr (IsMetadataScalar<ElementType>::value) {
1656 for (
size_t i = 0; i < array.size(); i++) {
1657 std::optional<ElementType> element = getScalar<ElementType>(array[i]);
1659 return std::nullopt;
1662 values.push_back(*element);
1665 if constexpr (IsMetadataVecN<ElementType>::value) {
1666 for (
size_t i = 0; i < array.size(); i++) {
1667 std::optional<ElementType> element = getVecN<ElementType>(array[i]);
1669 return std::nullopt;
1672 values.push_back(*element);
1676 if constexpr (IsMetadataMatN<ElementType>::value) {
1677 for (
size_t i = 0; i < array.size(); i++) {
1678 std::optional<ElementType> element = getMatN<ElementType>(array[i]);
1680 return std::nullopt;
1683 values.push_back(*element);
1687 std::vector<std::byte> result(values.size() *
sizeof(ElementType));
1688 std::memcpy(result.data(), values.data(), result.size());
1707 template <
typename ElementType>
1718 _name(std::nullopt),
1719 _semantic(std::nullopt),
1720 _description(std::nullopt),
1722 _offset(std::nullopt),
1723 _scale(std::nullopt),
1727 _noData(std::nullopt),
1728 _defaultValue(std::nullopt) {}
1736 _name(classProperty.name),
1737 _semantic(classProperty.semantic),
1738 _description(classProperty.description),
1739 _count(_count = classProperty.count ? *classProperty.count : 0),
1740 _offset(std::nullopt),
1741 _scale(std::nullopt),
1744 _required(classProperty.required),
1745 _noData(std::nullopt),
1746 _defaultValue(std::nullopt) {
1747 if (_status != PropertyViewStatus::Valid) {
1752 _status = PropertyViewStatus::ErrorNormalizationMismatch;
1756 getNumericPropertyValues(classProperty);
1757 if (_status != PropertyViewStatus::Valid) {
1761 if (classProperty.
noData) {
1763 _noData = getArrayValue<ElementType>(*classProperty.
noData);
1767 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
1778 if (!_defaultValue) {
1779 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1793 _name(std::nullopt),
1794 _semantic(std::nullopt),
1795 _description(std::nullopt),
1797 _offset(std::nullopt),
1798 _scale(std::nullopt),
1802 _noData(std::nullopt),
1803 _defaultValue(std::nullopt) {}
1813 if (_status != PropertyViewStatus::Valid) {
1818 getNumericPropertyValues(property);
1829 if (_status != PropertyViewStatus::Valid) {
1834 getNumericPropertyValues(property);
1841 PropertyViewStatusType
status() const noexcept {
return _status; }
1846 const std::optional<std::string>&
name() const noexcept {
return _name; }
1851 const std::optional<std::string>&
semantic() const noexcept {
1859 return _description;
1875 std::optional<PropertyArrayView<NormalizedType>>
offset() const noexcept {
1877 return std::nullopt;
1881 gsl::span<const std::byte>(_offset->data(), _offset->size()));
1887 std::optional<PropertyArrayView<NormalizedType>>
scale() const noexcept {
1889 return std::nullopt;
1893 gsl::span<const std::byte>(_scale->data(), _scale->size()));
1899 std::optional<PropertyArrayView<NormalizedType>>
max() const noexcept {
1901 return std::nullopt;
1905 gsl::span<const std::byte>(_max->data(), _max->size()));
1911 std::optional<PropertyArrayView<NormalizedType>>
min() const noexcept {
1913 return std::nullopt;
1917 gsl::span<const std::byte>(_min->data(), _min->size()));
1928 std::optional<PropertyArrayView<ElementType>>
noData() const noexcept {
1930 return std::nullopt;
1934 gsl::span<const std::byte>(_noData->data(), _noData->size()));
1940 std::optional<PropertyArrayView<NormalizedType>>
1942 if (!_defaultValue) {
1943 return std::nullopt;
1947 _defaultValue->data(),
1948 _defaultValue->size()));
1952 PropertyViewStatusType _status;
1955 std::optional<std::string> _name;
1956 std::optional<std::string> _semantic;
1957 std::optional<std::string> _description;
1961 std::optional<std::vector<std::byte>> _offset;
1962 std::optional<std::vector<std::byte>> _scale;
1963 std::optional<std::vector<std::byte>> _max;
1964 std::optional<std::vector<std::byte>> _min;
1967 std::optional<std::vector<std::byte>> _noData;
1968 std::optional<std::vector<std::byte>> _defaultValue;
1970 using PropertyDefinitionType = std::
1971 variant<ClassProperty, PropertyTableProperty, PropertyTextureProperty>;
1972 void getNumericPropertyValues(
const PropertyDefinitionType& inProperty) {
1974 [
this](
auto property) {
1975 if (property.offset) {
1977 _offset = getArrayValue<NormalizedType>(*property.offset);
1979 if (!_offset || getCount<NormalizedType>(_offset) != _count) {
1981 _status = PropertyViewStatus::ErrorInvalidOffset;
1986 if (property.scale) {
1988 _scale = getArrayValue<NormalizedType>(*property.scale);
1990 if (!_scale || getCount<NormalizedType>(_scale) != _count) {
1992 _status = PropertyViewStatus::ErrorInvalidScale;
1999 _max = getArrayValue<NormalizedType>(*property.max);
2001 if (!_max || getCount<NormalizedType>(_max) != _count) {
2003 _status = PropertyViewStatus::ErrorInvalidMax;
2010 _min = getArrayValue<NormalizedType>(*property.min);
2012 if (!_min || getCount<NormalizedType>(_min) != _count) {
2014 _status = PropertyViewStatus::ErrorInvalidMin;
2022 template <
typename T>
2023 static std::optional<std::vector<std::byte>>
2026 return std::nullopt;
2030 std::vector<T> values;
2031 values.reserve(array.size());
2033 if constexpr (IsMetadataScalar<T>::value) {
2034 for (
size_t i = 0; i < array.size(); i++) {
2035 std::optional<T> element = getScalar<T>(array[i]);
2037 return std::nullopt;
2040 values.push_back(*element);
2044 if constexpr (IsMetadataVecN<T>::value) {
2045 for (
size_t i = 0; i < array.size(); i++) {
2046 std::optional<T> element = getVecN<T>(array[i]);
2048 return std::nullopt;
2051 values.push_back(*element);
2055 if constexpr (IsMetadataMatN<T>::value) {
2056 for (
size_t i = 0; i < array.size(); i++) {
2057 std::optional<T> element = getMatN<T>(array[i]);
2059 return std::nullopt;
2062 values.push_back(*element);
2066 std::vector<std::byte> result(values.size() *
sizeof(T));
2067 std::memcpy(result.data(), values.data(), result.size());
2084 _name(std::nullopt),
2085 _semantic(std::nullopt),
2086 _description(std::nullopt),
2098 _name(classProperty.name),
2099 _semantic(classProperty.semantic),
2100 _description(classProperty.description),
2101 _count(classProperty.count ? *classProperty.count : 0),
2102 _required(classProperty.required),
2105 if (_status != PropertyViewStatus::Valid) {
2115 if (_size == 0 || (_count > 0 && _size != _count)) {
2116 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
2130 _name(std::nullopt),
2131 _semantic(std::nullopt),
2132 _description(std::nullopt),
2151 PropertyViewStatusType
status() const noexcept {
return _status; }
2156 const std::optional<std::string>&
name() const noexcept {
return _name; }
2161 const std::optional<std::string>&
semantic() const noexcept {
2169 return _description;
2185 std::optional<PropertyArrayView<bool>>
offset() const noexcept {
2186 return std::nullopt;
2192 std::optional<PropertyArrayView<bool>>
scale() const noexcept {
2193 return std::nullopt;
2199 std::optional<PropertyArrayView<bool>>
max() const noexcept {
2200 return std::nullopt;
2206 std::optional<PropertyArrayView<bool>>
min() const noexcept {
2207 return std::nullopt;
2218 std::optional<PropertyArrayView<bool>>
noData() const noexcept {
2219 return std::nullopt;
2228 gsl::span<const std::byte>(
2229 _defaultValue.data(),
2230 _defaultValue.size()),
2235 return std::nullopt;
2239 PropertyViewStatusType _status;
2242 std::optional<std::string> _name;
2243 std::optional<std::string> _semantic;
2244 std::optional<std::string> _description;
2249 std::vector<std::byte> _defaultValue;
2252 static std::vector<std::byte> getBooleanArrayValue(
2256 return std::vector<std::byte>();
2260 std::vector<std::byte> values;
2261 values.reserve((array.size() / 8) + 1);
2263 size_t byteIndex = 0;
2264 uint8_t bitIndex = 0;
2266 for (
size_t i = 0; i < array.size(); i++, size++) {
2267 if (!array[i].isBool()) {
2272 if (values.size() < byteIndex - 1) {
2273 values.push_back(std::byte(0));
2276 std::byte value = std::byte(array[i].getBool() ? 1 : 0);
2277 value = value << bitIndex;
2279 values[byteIndex] |= value;
2303 _name(std::nullopt),
2304 _semantic(std::nullopt),
2305 _description(std::nullopt),
2317 _name(classProperty.name),
2318 _semantic(classProperty.semantic),
2319 _description(classProperty.description),
2320 _count(classProperty.count ? *classProperty.count : 0),
2321 _required(classProperty.required),
2324 if (_status != PropertyViewStatus::Valid) {
2328 if (classProperty.
noData) {
2330 _noData = getStringArrayValue(*classProperty.
noData);
2333 if (_noData.size == 0 || (_count > 0 && _noData.size != _count)) {
2334 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
2344 if (_defaultValue.size == 0 ||
2345 (_count > 0 && _defaultValue.size != _count)) {
2347 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
2361 _name(std::nullopt),
2362 _semantic(std::nullopt),
2363 _description(std::nullopt),
2382 PropertyViewStatusType
status() const noexcept {
return _status; }
2387 const std::optional<std::string>&
name() const noexcept {
return _name; }
2392 const std::optional<std::string>&
semantic() const noexcept {
2400 return _description;
2416 std::optional<PropertyArrayView<std::string_view>>
offset() const noexcept {
2417 return std::nullopt;
2423 std::optional<PropertyArrayView<std::string_view>>
scale() const noexcept {
2424 return std::nullopt;
2430 std::optional<PropertyArrayView<std::string_view>>
max() const noexcept {
2431 return std::nullopt;
2437 std::optional<PropertyArrayView<std::string_view>>
min() const noexcept {
2438 return std::nullopt;
2449 std::optional<PropertyArrayView<std::string_view>>
noData() const noexcept {
2450 if (_noData.size > 0) {
2452 gsl::span<const std::byte>(_noData.data.data(), _noData.data.size()),
2453 gsl::span<const std::byte>(
2454 _noData.offsets.data(),
2455 _noData.offsets.size()),
2460 return std::nullopt;
2466 std::optional<PropertyArrayView<std::string_view>>
2468 if (_defaultValue.size > 0) {
2470 gsl::span<const std::byte>(
2471 _defaultValue.data.data(),
2472 _defaultValue.data.size()),
2473 gsl::span<const std::byte>(
2474 _defaultValue.offsets.data(),
2475 _defaultValue.offsets.size()),
2476 _defaultValue.offsetType,
2477 _defaultValue.size);
2480 return std::nullopt;
2484 PropertyViewStatusType _status;
2487 std::optional<std::string> _name;
2488 std::optional<std::string> _semantic;
2489 std::optional<std::string> _description;
2494 struct StringArrayValue {
2495 std::vector<std::byte> data;
2496 std::vector<std::byte> offsets;
2497 PropertyComponentType offsetType = PropertyComponentType::None;
2501 StringArrayValue _noData;
2502 StringArrayValue _defaultValue;
2504 static StringArrayValue
2506 StringArrayValue result;
2511 std::vector<std::string> strings;
2512 std::vector<uint64_t> stringOffsets;
2514 const auto array = jsonValue.
getArray();
2515 strings.reserve(array.size());
2516 stringOffsets.reserve(array.size() + 1);
2517 stringOffsets.push_back(
static_cast<uint64_t
>(0));
2519 for (
size_t i = 0; i < array.size(); i++) {
2520 if (!array[i].isString()) {
2525 const std::string&
string = array[i].getString();
2526 strings.push_back(
string);
2527 stringOffsets.push_back(stringOffsets[i] +
string.size());
2530 uint64_t totalLength = stringOffsets.back();
2531 result.data.resize(totalLength);
2532 for (
size_t i = 0; i < strings.size(); ++i) {
2534 result.data.data() + stringOffsets[i],
2539 if (totalLength <= std::numeric_limits<uint8_t>::max()) {
2540 result.offsets = narrowOffsetsBuffer<uint8_t>(stringOffsets);
2541 result.offsetType = PropertyComponentType::Uint8;
2542 }
else if (totalLength <= std::numeric_limits<uint16_t>::max()) {
2543 result.offsets = narrowOffsetsBuffer<uint16_t>(stringOffsets);
2544 result.offsetType = PropertyComponentType::Uint16;
2545 }
else if (totalLength <= std::numeric_limits<uint32_t>::max()) {
2546 result.offsets = narrowOffsetsBuffer<uint32_t>(stringOffsets);
2547 result.offsetType = PropertyComponentType::Uint32;
2549 result.offsets.resize(stringOffsets.size() *
sizeof(uint64_t));
2551 result.offsets.data(),
2552 stringOffsets.data(),
2553 result.offsets.size());
2554 result.offsetType = PropertyComponentType::Uint64;
2557 result.size =
static_cast<int64_t
>(strings.size());
2562 template <
typename T>
2563 static std::vector<std::byte>
2564 narrowOffsetsBuffer(std::vector<uint64_t> offsets) {
2565 std::vector<std::byte> result(offsets.size() *
sizeof(T));
2566 size_t bufferOffset = 0;
2567 for (
size_t i = 0; i < offsets.size(); i++, bufferOffset +=
sizeof(T)) {
2568 T offset =
static_cast<T
>(offsets[i]);
2569 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...
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...
bool required() const noexcept
Whether the property must be present in every entity conforming to the class. If not required,...
std::optional< ElementType > noData() const noexcept
Gets the "no data" value, i.e., the value representing missing data in the property wherever it appea...
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(const ClassProperty &classProperty, const PropertyTableProperty &property)
Constructs a property instance from a property table property and its class definition.
std::optional< ElementType > defaultValue() const noexcept
Gets the default value to use when encountering a "no data" value or an omitted property....
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 normalized() const noexcept
Whether this property has a normalized integer type.
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)
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.
const std::optional< std::string > & name() const noexcept
Gets the name of the property being viewed. Returns std::nullopt if no name was specified.
PropertyView(const ClassProperty &classProperty, const PropertyAttributeProperty &property)
Constructs a property instance from a property attribute property and its class definition.
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< ElementType > max() const noexcept
Gets the maximum allowed value for the property. Only applicable to SCALAR, VECN, and MATN types....
PropertyView()
Constructs an empty property instance.
const std::optional< std::string > & description() const noexcept
std::optional< NormalizedType > scale() const noexcept
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 > & semantic() const noexcept
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.
std::optional< NormalizedType > defaultValue() const noexcept
std::optional< NormalizedType > min() const noexcept
bool normalized() const noexcept
PropertyView()
Constructs an empty property instance.
std::optional< NormalizedType > offset() const noexcept
std::optional< NormalizedType > max() const noexcept
PropertyViewStatusType status() const noexcept
const std::optional< std::string > & name() const noexcept
bool required() const noexcept
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
int64_t arrayCount() const noexcept
std::optional< ElementType > noData() const noexcept
const std::optional< std::string > & semantic() const noexcept
PropertyViewStatusType status() const noexcept
const std::optional< std::string > & description() const noexcept
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
std::optional< PropertyArrayView< ElementType > > offset() const noexcept
int64_t arrayCount() const noexcept
std::optional< PropertyArrayView< ElementType > > max() const noexcept
std::optional< PropertyArrayView< ElementType > > scale() const noexcept
std::optional< PropertyArrayView< ElementType > > min() const noexcept
bool normalized() const noexcept
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< PropertyArrayView< ElementType > > noData() const noexcept
PropertyView()
Constructs an empty property instance.
std::optional< PropertyArrayView< ElementType > > defaultValue() const noexcept
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
bool required() const noexcept
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property)
Constructs a property instance from a property table property and its class definition.
std::optional< PropertyArrayView< NormalizedType > > defaultValue() const noexcept
PropertyViewStatusType status() const noexcept
const std::optional< std::string > & semantic() const noexcept
std::optional< PropertyArrayView< NormalizedType > > min() const noexcept
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.
std::optional< PropertyArrayView< NormalizedType > > max() const noexcept
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.
std::optional< PropertyArrayView< NormalizedType > > scale() const noexcept
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
std::optional< PropertyArrayView< ElementType > > noData() const noexcept
const std::optional< std::string > & description() const noexcept
std::optional< PropertyArrayView< NormalizedType > > offset() const noexcept
int64_t arrayCount() const noexcept
bool required() const noexcept
bool normalized() const noexcept
const std::optional< std::string > & name() const noexcept
std::optional< PropertyArrayView< bool > > defaultValue() const noexcept
int64_t arrayCount() const noexcept
std::optional< PropertyArrayView< bool > > max() const noexcept
const std::optional< std::string > & description() const noexcept
const std::optional< std::string > & semantic() const noexcept
PropertyView()
Constructs an empty property instance.
std::optional< PropertyArrayView< bool > > noData() const noexcept
bool required() const noexcept
const std::optional< std::string > & name() const noexcept
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &)
Constructs a property instance from a property table property and its class definition.
std::optional< PropertyArrayView< bool > > offset() const noexcept
PropertyViewStatusType status() const noexcept
std::optional< PropertyArrayView< bool > > min() const noexcept
bool normalized() const noexcept
std::optional< PropertyArrayView< bool > > scale() const noexcept
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &)
Constructs a property instance from a property table property and its class definition.
const std::optional< std::string > & semantic() const noexcept
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
const std::optional< std::string > & name() const noexcept
const std::optional< std::string > & description() const noexcept
PropertyViewStatusType status() const noexcept
PropertyView()
Constructs an empty property instance.
std::optional< PropertyArrayView< std::string_view > > defaultValue() const noexcept
std::optional< PropertyArrayView< std::string_view > > min() const noexcept
std::optional< PropertyArrayView< std::string_view > > noData() const noexcept
int64_t arrayCount() const noexcept
std::optional< PropertyArrayView< std::string_view > > offset() const noexcept
bool required() const noexcept
std::optional< PropertyArrayView< std::string_view > > max() const noexcept
std::optional< PropertyArrayView< std::string_view > > scale() const noexcept
bool normalized() const noexcept
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
PropertyViewStatusType status() const noexcept
const std::optional< std::string > & semantic() const noexcept
bool required() const noexcept
int64_t arrayCount() const noexcept
std::optional< bool > defaultValue() const noexcept
std::optional< bool > max() const noexcept
const std::optional< std::string > & name() const noexcept
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &)
Constructs a property instance from a property table property and its class definition.
std::optional< bool > noData() const noexcept
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
const std::optional< std::string > & description() const noexcept
bool normalized() const noexcept
std::optional< bool > offset() const noexcept
PropertyView()
Constructs an empty property instance.
std::optional< bool > scale() const noexcept
std::optional< bool > min() const noexcept
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &)
Constructs a property instance from a property table property and its class definition.
const std::optional< std::string > & name() const noexcept
bool required() const noexcept
PropertyView()
Constructs an empty property instance.
std::optional< std::string_view > defaultValue() const noexcept
std::optional< std::string_view > noData() const noexcept
std::optional< std::string_view > max() const noexcept
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
const std::optional< std::string > & semantic() const noexcept
int64_t arrayCount() const noexcept
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< std::string_view > offset() const noexcept
bool normalized() const noexcept
const std::optional< std::string > & description() const noexcept
PropertyViewStatusType status() const noexcept
std::optional< std::string_view > min() const noexcept
std::optional< std::string_view > scale() const noexcept
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.
std::vector< JsonValue > Array
The type to represent an Array JSON value.
To getSafeNumber() const
Gets the numerical quantity from the value casted to the To type. This function should be used over g...
bool isBool() const noexcept
Returns whether this value is a Bool value.
const JsonValue::String & getString() const
Gets the string from the 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.
const JsonValue::Array & getArray() const
Gets the array from the value.
Classes for working with glTF models.
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.