cesium-native 0.64.0
Loading...
Searching...
No Matches
PropertyTableView.h
1#pragma once
2
3#include <CesiumGltf/ExtensionModelExtStructuralMetadata.h>
4#include <CesiumGltf/Model.h>
5#include <CesiumGltf/PropertyTablePropertyView.h>
6#include <CesiumGltf/PropertyType.h>
7#include <CesiumGltf/PropertyTypeTraits.h>
8
9#include <glm/common.hpp>
10
11#include <optional>
12
13namespace CesiumGltf {
14
47
56public:
63 PropertyTableView(const Model& model, const PropertyTable& propertyTable);
64
73 PropertyTableViewStatus status() const noexcept { return _status; }
74
79 const std::optional<std::string>& name() const noexcept {
80 return _pPropertyTable->name;
81 }
82
90 int64_t size() const noexcept {
91 return _status == PropertyTableViewStatus::Valid ? _pPropertyTable->count
92 : 0;
93 }
94
101 const Class* getClass() const noexcept { return _pClass; }
102
110 const ClassProperty* getClassProperty(const std::string& propertyId) const;
111
138 template <typename T, bool Normalized = false>
140 getPropertyView(const std::string& propertyId) const {
141 if (this->size() <= 0) {
144 }
145
146 const ClassProperty* pClassProperty = getClassProperty(propertyId);
147 if (!pClassProperty) {
150 }
151
152 return getPropertyViewImpl<T, Normalized>(propertyId, *pClassProperty);
153 }
154
177 template <typename Callback>
178 void
179 getPropertyView(const std::string& propertyId, Callback&& callback) const {
180 if (this->size() <= 0) {
181 callback(
182 propertyId,
185 return;
186 }
187
188 const ClassProperty* pClassProperty = getClassProperty(propertyId);
189 if (!pClassProperty) {
190 callback(
191 propertyId,
194 return;
195 }
196
197 PropertyType type = convertStringToPropertyType(pClassProperty->type);
199
200 // Handle enum component type indirection
201 if (type == PropertyType::Enum && pClassProperty->enumType) {
202 const auto& enumDefinitionIt =
203 this->_pEnumDefinitions->find(*pClassProperty->enumType);
204 if (enumDefinitionIt == this->_pEnumDefinitions->end()) {
205 callback(
206 propertyId,
209 return;
210 }
211
213 enumDefinitionIt->second.valueType);
214
215 if (componentType == PropertyComponentType::Float32 ||
216 componentType == PropertyComponentType::Float64) {
217 callback(
218 propertyId,
221 return;
222 }
223
224 } else if (type == PropertyType::Enum) {
225 callback(
226 propertyId,
229 return;
230 } else if (pClassProperty->componentType) {
231 componentType =
233 }
234
235 bool normalized = pClassProperty->normalized;
236 if (normalized && (!isPropertyComponentTypeInteger(componentType) ||
237 type == PropertyType::Enum)) {
238 // Only integer components may be normalized.
239 callback(
240 propertyId,
243 return;
244 }
245
246 if (pClassProperty->array) {
247 if (normalized) {
248 getArrayPropertyViewImpl<Callback, true>(
249 propertyId,
250 *pClassProperty,
251 type,
252 componentType,
253 std::forward<Callback>(callback));
254 } else {
255 getArrayPropertyViewImpl<Callback, false>(
256 propertyId,
257 *pClassProperty,
258 type,
259 componentType,
260 std::forward<Callback>(callback));
261 }
262 return;
263 }
264
265 if (type == PropertyType::Scalar || type == PropertyType::Enum) {
266 if (normalized) {
267 getScalarPropertyViewImpl<Callback, true>(
268 propertyId,
269 *pClassProperty,
270 componentType,
271 std::forward<Callback>(callback));
272 } else {
273 getScalarPropertyViewImpl<Callback, false>(
274 propertyId,
275 *pClassProperty,
276 componentType,
277 std::forward<Callback>(callback));
278 }
279 return;
280 }
281
282 if (isPropertyTypeVecN(type)) {
283 if (normalized) {
284 getVecNPropertyViewImpl<Callback, true>(
285 propertyId,
286 *pClassProperty,
287 type,
288 componentType,
289 std::forward<Callback>(callback));
290 } else {
291 getVecNPropertyViewImpl<Callback, false>(
292 propertyId,
293 *pClassProperty,
294 type,
295 componentType,
296 std::forward<Callback>(callback));
297 }
298 return;
299 }
300
301 if (isPropertyTypeMatN(type)) {
302 if (normalized) {
303 getMatNPropertyViewImpl<Callback, true>(
304 propertyId,
305 *pClassProperty,
306 type,
307 componentType,
308 std::forward<Callback>(callback));
309 } else {
310 getMatNPropertyViewImpl<Callback, false>(
311 propertyId,
312 *pClassProperty,
313 type,
314 componentType,
315 std::forward<Callback>(callback));
316 }
317 return;
318 }
319
320 if (type == PropertyType::String) {
321 callback(
322 propertyId,
323 getPropertyViewImpl<std::string_view, false>(
324 propertyId,
325 *pClassProperty));
326 return;
327 }
328
329 if (type == PropertyType::Boolean) {
330 callback(
331 propertyId,
332 getPropertyViewImpl<bool, false>(propertyId, *pClassProperty));
333 return;
334 }
335
336 callback(
337 propertyId,
340 }
341
363 template <typename Callback> void forEachProperty(Callback&& callback) const {
364 for (const auto& property : this->_pClass->properties) {
365 getPropertyView(property.first, std::forward<Callback>(callback));
366 }
367 }
368
369private:
370 template <typename Callback, bool Normalized>
371 void getScalarArrayPropertyViewImpl(
372 const std::string& propertyId,
373 const ClassProperty& classProperty,
374 PropertyComponentType componentType,
375 Callback&& callback) const {
376 switch (componentType) {
378 callback(
379 propertyId,
380 getPropertyViewImpl<PropertyArrayView<int8_t>, Normalized>(
381 propertyId,
382 classProperty));
383 break;
385 callback(
386 propertyId,
387 getPropertyViewImpl<PropertyArrayView<uint8_t>, Normalized>(
388 propertyId,
389 classProperty));
390 break;
392 callback(
393 propertyId,
394 getPropertyViewImpl<PropertyArrayView<int16_t>, Normalized>(
395 propertyId,
396 classProperty));
397 break;
399 callback(
400 propertyId,
401 getPropertyViewImpl<PropertyArrayView<uint16_t>, Normalized>(
402 propertyId,
403 classProperty));
404 break;
406 callback(
407 propertyId,
408 getPropertyViewImpl<PropertyArrayView<int32_t>, Normalized>(
409 propertyId,
410 classProperty));
411 break;
413 callback(
414 propertyId,
415 getPropertyViewImpl<PropertyArrayView<uint32_t>, Normalized>(
416 propertyId,
417 classProperty));
418 break;
420 callback(
421 propertyId,
422 getPropertyViewImpl<PropertyArrayView<int64_t>, Normalized>(
423 propertyId,
424 classProperty));
425 break;
427 callback(
428 propertyId,
429 getPropertyViewImpl<PropertyArrayView<uint64_t>, Normalized>(
430 propertyId,
431 classProperty));
432 break;
434 callback(
435 propertyId,
436 getPropertyViewImpl<PropertyArrayView<float>, false>(
437 propertyId,
438 classProperty));
439 break;
441 callback(
442 propertyId,
443 getPropertyViewImpl<PropertyArrayView<double>, false>(
444 propertyId,
445 classProperty));
446 break;
447 default:
448 callback(
449 propertyId,
452 break;
453 }
454 }
455
456 template <typename Callback, glm::length_t N, bool Normalized>
457 void getVecNArrayPropertyViewImpl(
458 const std::string& propertyId,
459 const ClassProperty& classProperty,
460 PropertyComponentType componentType,
461 Callback&& callback) const {
462 switch (componentType) {
464 callback(
465 propertyId,
466 getPropertyViewImpl<
467 PropertyArrayView<glm::vec<N, int8_t>>,
468 Normalized>(propertyId, classProperty));
469 break;
471 callback(
472 propertyId,
473 getPropertyViewImpl<
474 PropertyArrayView<glm::vec<N, uint8_t>>,
475 Normalized>(propertyId, classProperty));
476 break;
478 callback(
479 propertyId,
480 getPropertyViewImpl<
481 PropertyArrayView<glm::vec<N, int16_t>>,
482 Normalized>(propertyId, classProperty));
483 break;
485 callback(
486 propertyId,
487 getPropertyViewImpl<
488 PropertyArrayView<glm::vec<N, uint16_t>>,
489 Normalized>(propertyId, classProperty));
490 break;
492 callback(
493 propertyId,
494 getPropertyViewImpl<
495 PropertyArrayView<glm::vec<N, int32_t>>,
496 Normalized>(propertyId, classProperty));
497 break;
499 callback(
500 propertyId,
501 getPropertyViewImpl<
502 PropertyArrayView<glm::vec<N, uint32_t>>,
503 Normalized>(propertyId, classProperty));
504 break;
506 callback(
507 propertyId,
508 getPropertyViewImpl<
509 PropertyArrayView<glm::vec<N, int64_t>>,
510 Normalized>(propertyId, classProperty));
511 break;
513 callback(
514 propertyId,
515 getPropertyViewImpl<
516 PropertyArrayView<glm::vec<N, uint64_t>>,
517 Normalized>(propertyId, classProperty));
518 break;
520 callback(
521 propertyId,
522 getPropertyViewImpl<PropertyArrayView<glm::vec<N, float>>, false>(
523 propertyId,
524 classProperty));
525 break;
527 callback(
528 propertyId,
529 getPropertyViewImpl<PropertyArrayView<glm::vec<N, double>>, false>(
530 propertyId,
531 classProperty));
532 break;
533 default:
534 callback(
535 propertyId,
536 PropertyTablePropertyView<uint8_t>(
538 break;
539 }
540 }
541
542 template <typename Callback, bool Normalized>
543 void getVecNArrayPropertyViewImpl(
544 const std::string& propertyId,
545 const ClassProperty& classProperty,
546 PropertyType type,
547 PropertyComponentType componentType,
548 Callback&& callback) const {
549 glm::length_t N = getDimensionsFromPropertyType(type);
550 switch (N) {
551 case 2:
552 getVecNArrayPropertyViewImpl<Callback, 2, Normalized>(
553 propertyId,
554 classProperty,
555 componentType,
556 std::forward<Callback>(callback));
557 break;
558 case 3:
559 getVecNArrayPropertyViewImpl<Callback, 3, Normalized>(
560 propertyId,
561 classProperty,
562 componentType,
563 std::forward<Callback>(callback));
564 break;
565 case 4:
566 getVecNArrayPropertyViewImpl<Callback, 4, Normalized>(
567 propertyId,
568 classProperty,
569 componentType,
570 std::forward<Callback>(callback));
571 break;
572 default:
573 callback(
574 propertyId,
575 PropertyTablePropertyView<uint8_t>(
577 break;
578 }
579 }
580
581 template <typename Callback, glm::length_t N, bool Normalized>
582 void getMatNArrayPropertyViewImpl(
583 const std::string& propertyId,
584 const ClassProperty& classProperty,
585 PropertyComponentType componentType,
586 Callback&& callback) const {
587 switch (componentType) {
589 callback(
590 propertyId,
591 getPropertyViewImpl<
592 PropertyArrayView<glm::mat<N, N, int8_t>>,
593 Normalized>(propertyId, classProperty));
594 break;
596 callback(
597 propertyId,
598 getPropertyViewImpl<
599 PropertyArrayView<glm::mat<N, N, uint8_t>>,
600 Normalized>(propertyId, classProperty));
601 break;
603 callback(
604 propertyId,
605 getPropertyViewImpl<
606 PropertyArrayView<glm::mat<N, N, int16_t>>,
607 Normalized>(propertyId, classProperty));
608 break;
610 callback(
611 propertyId,
612 getPropertyViewImpl<
613 PropertyArrayView<glm::mat<N, N, uint16_t>>,
614 Normalized>(propertyId, classProperty));
615 break;
617 callback(
618 propertyId,
619 getPropertyViewImpl<
620 PropertyArrayView<glm::mat<N, N, int32_t>>,
621 Normalized>(propertyId, classProperty));
622 break;
624 callback(
625 propertyId,
626 getPropertyViewImpl<
627 PropertyArrayView<glm::mat<N, N, uint32_t>>,
628 Normalized>(propertyId, classProperty));
629 break;
631 callback(
632 propertyId,
633 getPropertyViewImpl<
634 PropertyArrayView<glm::mat<N, N, int64_t>>,
635 Normalized>(propertyId, classProperty));
636 break;
638 callback(
639 propertyId,
640 getPropertyViewImpl<
641 PropertyArrayView<glm::mat<N, N, uint64_t>>,
642 Normalized>(propertyId, classProperty));
643 break;
645 callback(
646 propertyId,
647 getPropertyViewImpl<PropertyArrayView<glm::mat<N, N, float>>, false>(
648 propertyId,
649 classProperty));
650 break;
652 callback(
653 propertyId,
654 getPropertyViewImpl<PropertyArrayView<glm::mat<N, N, double>>, false>(
655 propertyId,
656 classProperty));
657 break;
658 default:
659 callback(
660 propertyId,
661 PropertyTablePropertyView<uint8_t>(
663 break;
664 }
665 }
666
667 template <typename Callback, bool Normalized>
668 void getMatNArrayPropertyViewImpl(
669 const std::string& propertyId,
670 const ClassProperty& classProperty,
671 PropertyType type,
672 PropertyComponentType componentType,
673 Callback&& callback) const {
674 const glm::length_t N = getDimensionsFromPropertyType(type);
675 switch (N) {
676 case 2:
677 getMatNArrayPropertyViewImpl<Callback, 2, Normalized>(
678 propertyId,
679 classProperty,
680 componentType,
681 std::forward<Callback>(callback));
682 break;
683 case 3:
684 getMatNArrayPropertyViewImpl<Callback, 3, Normalized>(
685 propertyId,
686 classProperty,
687 componentType,
688 std::forward<Callback>(callback));
689 break;
690 case 4:
691 getMatNArrayPropertyViewImpl<Callback, 4, Normalized>(
692 propertyId,
693 classProperty,
694 componentType,
695 std::forward<Callback>(callback));
696 break;
697 default:
698 callback(
699 propertyId,
700 PropertyTablePropertyView<uint8_t>(
702 break;
703 }
704 }
705
706 template <typename Callback, bool Normalized>
707 void getArrayPropertyViewImpl(
708 const std::string& propertyId,
709 const ClassProperty& classProperty,
710 PropertyType type,
711 PropertyComponentType componentType,
712 Callback&& callback) const {
713 if (type == PropertyType::Scalar || type == PropertyType::Enum) {
714 getScalarArrayPropertyViewImpl<Callback, Normalized>(
715 propertyId,
716 classProperty,
717 componentType,
718 std::forward<Callback>(callback));
719 } else if (isPropertyTypeVecN(type)) {
720 getVecNArrayPropertyViewImpl<Callback, Normalized>(
721 propertyId,
722 classProperty,
723 type,
724 componentType,
725 std::forward<Callback>(callback));
726 } else if (isPropertyTypeMatN(type)) {
727 getMatNArrayPropertyViewImpl<Callback, Normalized>(
728 propertyId,
729 classProperty,
730 type,
731 componentType,
732 std::forward<Callback>(callback));
733 } else if (type == PropertyType::Boolean) {
734 callback(
735 propertyId,
736 getPropertyViewImpl<PropertyArrayView<bool>, false>(
737 propertyId,
738 classProperty));
739
740 } else if (type == PropertyType::String) {
741 callback(
742 propertyId,
743 getPropertyViewImpl<PropertyArrayView<std::string_view>, false>(
744 propertyId,
745 classProperty));
746 } else {
747 callback(
748 propertyId,
749 PropertyTablePropertyView<uint8_t>(
751 }
752 }
753
754 template <typename Callback, glm::length_t N, bool Normalized>
755 void getVecNPropertyViewImpl(
756 const std::string& propertyId,
757 const ClassProperty& classProperty,
758 PropertyComponentType componentType,
759 Callback&& callback) const {
760
761 switch (componentType) {
763 callback(
764 propertyId,
765 getPropertyViewImpl<glm::vec<N, int8_t>, Normalized>(
766 propertyId,
767 classProperty));
768 break;
770 callback(
771 propertyId,
772 getPropertyViewImpl<glm::vec<N, uint8_t>, Normalized>(
773 propertyId,
774 classProperty));
775 break;
777 callback(
778 propertyId,
779 getPropertyViewImpl<glm::vec<N, int16_t>, Normalized>(
780 propertyId,
781 classProperty));
782 break;
784 callback(
785 propertyId,
786 getPropertyViewImpl<glm::vec<N, uint16_t>, Normalized>(
787 propertyId,
788 classProperty));
789 break;
791 callback(
792 propertyId,
793 getPropertyViewImpl<glm::vec<N, int32_t>, Normalized>(
794 propertyId,
795 classProperty));
796 break;
798 callback(
799 propertyId,
800 getPropertyViewImpl<glm::vec<N, uint32_t>, Normalized>(
801 propertyId,
802 classProperty));
803 break;
805 callback(
806 propertyId,
807 getPropertyViewImpl<glm::vec<N, int64_t>, Normalized>(
808 propertyId,
809 classProperty));
810 break;
812 callback(
813 propertyId,
814 getPropertyViewImpl<glm::vec<N, uint64_t>, Normalized>(
815 propertyId,
816 classProperty));
817 break;
819 callback(
820 propertyId,
821 getPropertyViewImpl<glm::vec<N, float>, false>(
822 propertyId,
823 classProperty));
824 break;
826 callback(
827 propertyId,
828 getPropertyViewImpl<glm::vec<N, double>, false>(
829 propertyId,
830 classProperty));
831 break;
832 default:
833 callback(
834 propertyId,
835 PropertyTablePropertyView<uint8_t>(
837 break;
838 }
839 }
840
841 template <typename Callback, bool Normalized>
842 void getVecNPropertyViewImpl(
843 const std::string& propertyId,
844 const ClassProperty& classProperty,
845 PropertyType type,
846 PropertyComponentType componentType,
847 Callback&& callback) const {
848 const glm::length_t N = getDimensionsFromPropertyType(type);
849 switch (N) {
850 case 2:
851 getVecNPropertyViewImpl<Callback, 2, Normalized>(
852 propertyId,
853 classProperty,
854 componentType,
855 std::forward<Callback>(callback));
856 break;
857 case 3:
858 getVecNPropertyViewImpl<Callback, 3, Normalized>(
859 propertyId,
860 classProperty,
861 componentType,
862 std::forward<Callback>(callback));
863 break;
864 case 4:
865 getVecNPropertyViewImpl<Callback, 4, Normalized>(
866 propertyId,
867 classProperty,
868 componentType,
869 std::forward<Callback>(callback));
870 break;
871 default:
872 callback(
873 propertyId,
874 PropertyTablePropertyView<uint8_t>(
876 break;
877 }
878 }
879
880 template <typename Callback, glm::length_t N, bool Normalized>
881 void getMatNPropertyViewImpl(
882 const std::string& propertyId,
883 const ClassProperty& classProperty,
884 PropertyComponentType componentType,
885 Callback&& callback) const {
886 switch (componentType) {
888 callback(
889 propertyId,
890 getPropertyViewImpl<glm::mat<N, N, int8_t>, Normalized>(
891 propertyId,
892 classProperty));
893 break;
895 callback(
896 propertyId,
897 getPropertyViewImpl<glm::mat<N, N, uint8_t>, Normalized>(
898 propertyId,
899 classProperty));
900 break;
902 callback(
903 propertyId,
904 getPropertyViewImpl<glm::mat<N, N, int16_t>, Normalized>(
905 propertyId,
906 classProperty));
907 break;
909 callback(
910 propertyId,
911 getPropertyViewImpl<glm::mat<N, N, uint16_t>, Normalized>(
912 propertyId,
913 classProperty));
914 break;
916 callback(
917 propertyId,
918 getPropertyViewImpl<glm::mat<N, N, int32_t>, Normalized>(
919 propertyId,
920 classProperty));
921 break;
923 callback(
924 propertyId,
925 getPropertyViewImpl<glm::mat<N, N, uint32_t>, Normalized>(
926 propertyId,
927 classProperty));
928 break;
930 callback(
931 propertyId,
932 getPropertyViewImpl<glm::mat<N, N, int64_t>, Normalized>(
933 propertyId,
934 classProperty));
935 break;
937 callback(
938 propertyId,
939 getPropertyViewImpl<glm::mat<N, N, uint64_t>, Normalized>(
940 propertyId,
941 classProperty));
942 break;
944 callback(
945 propertyId,
946 getPropertyViewImpl<glm::mat<N, N, float>, false>(
947 propertyId,
948 classProperty));
949 break;
951 callback(
952 propertyId,
953 getPropertyViewImpl<glm::mat<N, N, double>, false>(
954 propertyId,
955 classProperty));
956 break;
957 default:
958 callback(
959 propertyId,
960 PropertyTablePropertyView<uint8_t>(
962 break;
963 }
964 }
965
966 template <typename Callback, bool Normalized>
967 void getMatNPropertyViewImpl(
968 const std::string& propertyId,
969 const ClassProperty& classProperty,
970 PropertyType type,
971 PropertyComponentType componentType,
972 Callback&& callback) const {
973 glm::length_t N = getDimensionsFromPropertyType(type);
974 switch (N) {
975 case 2:
976 getMatNPropertyViewImpl<Callback, 2, Normalized>(
977 propertyId,
978 classProperty,
979 componentType,
980 std::forward<Callback>(callback));
981 break;
982 case 3:
983 getMatNPropertyViewImpl<Callback, 3, Normalized>(
984 propertyId,
985 classProperty,
986 componentType,
987 std::forward<Callback>(callback));
988 break;
989 case 4:
990 getMatNPropertyViewImpl<Callback, 4, Normalized>(
991 propertyId,
992 classProperty,
993 componentType,
994 std::forward<Callback>(callback));
995 break;
996 default:
997 callback(
998 propertyId,
999 PropertyTablePropertyView<uint8_t>(
1001 break;
1002 }
1003 }
1004
1005 template <typename Callback, bool Normalized>
1006 void getScalarPropertyViewImpl(
1007 const std::string& propertyId,
1008 const ClassProperty& classProperty,
1009 PropertyComponentType componentType,
1010 Callback&& callback) const {
1011 switch (componentType) {
1013 callback(
1014 propertyId,
1015 getPropertyViewImpl<int8_t, Normalized>(propertyId, classProperty));
1016 return;
1018 callback(
1019 propertyId,
1020 getPropertyViewImpl<uint8_t, Normalized>(propertyId, classProperty));
1021 return;
1023 callback(
1024 propertyId,
1025 getPropertyViewImpl<int16_t, Normalized>(propertyId, classProperty));
1026 return;
1028 callback(
1029 propertyId,
1030 getPropertyViewImpl<uint16_t, Normalized>(propertyId, classProperty));
1031 break;
1033 callback(
1034 propertyId,
1035 getPropertyViewImpl<int32_t, Normalized>(propertyId, classProperty));
1036 break;
1038 callback(
1039 propertyId,
1040 getPropertyViewImpl<uint32_t, Normalized>(propertyId, classProperty));
1041 break;
1043 callback(
1044 propertyId,
1045 getPropertyViewImpl<int64_t, Normalized>(propertyId, classProperty));
1046 break;
1048 callback(
1049 propertyId,
1050 getPropertyViewImpl<uint64_t, Normalized>(propertyId, classProperty));
1051 break;
1053 callback(
1054 propertyId,
1055 getPropertyViewImpl<float, false>(propertyId, classProperty));
1056 break;
1058 callback(
1059 propertyId,
1060 getPropertyViewImpl<double, false>(propertyId, classProperty));
1061 break;
1062 default:
1063 callback(
1064 propertyId,
1065 PropertyTablePropertyView<uint8_t>(
1067 break;
1068 }
1069 }
1070
1071 template <typename T, bool Normalized>
1072 PropertyTablePropertyView<T, Normalized> getPropertyViewImpl(
1073 const std::string& propertyId,
1074 const ClassProperty& classProperty) const {
1075 auto propertyTablePropertyIter =
1076 _pPropertyTable->properties.find(propertyId);
1077 if (propertyTablePropertyIter == _pPropertyTable->properties.end()) {
1078 if (!classProperty.required && classProperty.defaultProperty) {
1079 // If the property was omitted from the property table, it is still
1080 // technically valid if it specifies a default value. Create a view that
1081 // just returns the default value.
1082 return PropertyTablePropertyView<T, Normalized>(
1083 classProperty,
1084 _pPropertyTable->count);
1085 }
1086
1087 // Otherwise, the property is erroneously nonexistent.
1088 return PropertyTablePropertyView<T, Normalized>(
1090 }
1091
1092 const PropertyTableProperty& propertyTableProperty =
1093 propertyTablePropertyIter->second;
1094
1095 if constexpr (IsMetadataNumeric<T>::value || IsMetadataBoolean<T>::value) {
1096 return getNumericOrBooleanPropertyValues<T, Normalized>(
1097 classProperty,
1098 propertyTableProperty);
1099 }
1100
1101 if constexpr (IsMetadataString<T>::value) {
1102 return getStringPropertyValues(classProperty, propertyTableProperty);
1103 }
1104
1105 if constexpr (IsMetadataBooleanArray<T>::value) {
1106 return getBooleanArrayPropertyValues(
1107 classProperty,
1108 propertyTableProperty);
1109 }
1110
1111 if constexpr (IsMetadataNumericArray<T>::value) {
1112 return getNumericArrayPropertyValues<
1114 Normalized>(classProperty, propertyTableProperty);
1115 }
1116
1117 if constexpr (IsMetadataStringArray<T>::value) {
1118 return getStringArrayPropertyValues(classProperty, propertyTableProperty);
1119 }
1120 }
1121
1122 template <typename T, bool Normalized>
1123 PropertyTablePropertyView<T, Normalized> getNumericOrBooleanPropertyValues(
1124 const ClassProperty& classProperty,
1125 const PropertyTableProperty& propertyTableProperty) const {
1126 if (classProperty.array) {
1127 return PropertyTablePropertyView<T, Normalized>(
1129 }
1130
1131 const PropertyType type = convertStringToPropertyType(classProperty.type);
1132 if (!canRepresentPropertyType<T>(type)) {
1133 return PropertyTablePropertyView<T, Normalized>(
1135 }
1136
1138 classProperty.componentType.value_or(""));
1139 const CesiumGltf::Enum* pEnumDefinition = nullptr;
1140 if (type == PropertyType::Enum && classProperty.enumType) {
1141 const auto& enumDefinitionIt =
1142 this->_pEnumDefinitions->find(*classProperty.enumType);
1143 if (enumDefinitionIt == this->_pEnumDefinitions->end()) {
1144 return PropertyTablePropertyView<T, Normalized>(
1146 }
1147
1149 enumDefinitionIt->second.valueType);
1150 if (componentType == PropertyComponentType::Float32 ||
1151 componentType == PropertyComponentType::Float64) {
1152 return PropertyTablePropertyView<T, Normalized>(
1154 }
1155 pEnumDefinition = &enumDefinitionIt->second;
1156 } else if (type == PropertyType::Enum) {
1157 return PropertyTablePropertyView<T, Normalized>(
1159 }
1160
1161 if (TypeToPropertyType<T>::component != componentType) {
1162 return PropertyTablePropertyView<T, Normalized>(
1164 }
1165
1166 if (classProperty.normalized != Normalized ||
1167 (classProperty.normalized && type == PropertyType::Enum)) {
1168 return PropertyTablePropertyView<T, Normalized>(
1170 }
1171
1172 std::span<const std::byte> values;
1173 const auto status = getBufferSafe(propertyTableProperty.values, values);
1175 return PropertyTablePropertyView<T, Normalized>(status);
1176 }
1177
1178 if (values.size() % sizeof(T) != 0) {
1179 return PropertyTablePropertyView<T, Normalized>(
1180 PropertyTablePropertyViewStatus::
1181 ErrorBufferViewSizeNotDivisibleByTypeSize);
1182 }
1183
1184 size_t maxRequiredBytes = 0;
1185 if (IsMetadataBoolean<T>::value) {
1186 maxRequiredBytes = static_cast<size_t>(
1187 glm::ceil(static_cast<double>(_pPropertyTable->count) / 8.0));
1188 } else {
1189 maxRequiredBytes =
1190 static_cast<size_t>(_pPropertyTable->count) * sizeof(T);
1191 }
1192
1193 if (values.size() < maxRequiredBytes) {
1194 return PropertyTablePropertyView<T, Normalized>(
1195 PropertyTablePropertyViewStatus::
1196 ErrorBufferViewSizeDoesNotMatchPropertyTableCount);
1197 }
1198
1199 if constexpr (!Normalized) {
1200 return PropertyTablePropertyView<T, Normalized>(
1201 propertyTableProperty,
1202 classProperty,
1203 pEnumDefinition,
1204 _pPropertyTable->count,
1205 values);
1206 } else {
1207 return PropertyTablePropertyView<T, Normalized>(
1208 propertyTableProperty,
1209 classProperty,
1210 _pPropertyTable->count,
1211 values);
1212 }
1213 }
1214
1215 PropertyTablePropertyView<std::string_view> getStringPropertyValues(
1216 const ClassProperty& classProperty,
1217 const PropertyTableProperty& propertyTableProperty) const;
1218
1219 PropertyTablePropertyView<PropertyArrayView<bool>>
1220 getBooleanArrayPropertyValues(
1221 const ClassProperty& classProperty,
1222 const PropertyTableProperty& propertyTableProperty) const;
1223
1224 template <typename T, bool Normalized>
1225 PropertyTablePropertyView<PropertyArrayView<T>, Normalized>
1226 getNumericArrayPropertyValues(
1227 const ClassProperty& classProperty,
1228 const PropertyTableProperty& propertyTableProperty) const {
1229 if (!classProperty.array) {
1230 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1232 }
1233
1234 const PropertyType type = convertStringToPropertyType(classProperty.type);
1235 if (!canRepresentPropertyType<T>(type)) {
1236 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1238 }
1239
1241 classProperty.componentType.value_or(""));
1242 const CesiumGltf::Enum* pEnumDefinition = nullptr;
1243 if (type == PropertyType::Enum && classProperty.enumType) {
1244 const auto& enumDefinitionIt =
1245 this->_pEnumDefinitions->find(*classProperty.enumType);
1246 if (enumDefinitionIt == this->_pEnumDefinitions->end()) {
1247 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1249 }
1250
1252 enumDefinitionIt->second.valueType);
1253
1254 if (componentType == PropertyComponentType::Float32 ||
1255 componentType == PropertyComponentType::Float64) {
1256 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1258 }
1259 pEnumDefinition = &enumDefinitionIt->second;
1260 } else if (type == PropertyType::Enum) {
1261 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1263 }
1264
1265 if (TypeToPropertyType<T>::component != componentType) {
1266 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1268 }
1269
1270 if (classProperty.normalized != Normalized) {
1271 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1273 }
1274
1275 std::span<const std::byte> values;
1276 auto status = getBufferSafe(propertyTableProperty.values, values);
1278 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1279 status);
1280 }
1281
1282 if (values.size() % sizeof(T) != 0) {
1283 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1284 PropertyTablePropertyViewStatus::
1285 ErrorBufferViewSizeNotDivisibleByTypeSize);
1286 }
1287
1288 const int64_t fixedLengthArrayCount = classProperty.count.value_or(0);
1289 if (fixedLengthArrayCount > 0 && propertyTableProperty.arrayOffsets >= 0) {
1290 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1291 PropertyTablePropertyViewStatus::
1292 ErrorArrayCountAndOffsetBufferCoexist);
1293 }
1294
1295 if (fixedLengthArrayCount <= 0 && propertyTableProperty.arrayOffsets < 0) {
1296 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1297 PropertyTablePropertyViewStatus::
1298 ErrorArrayCountAndOffsetBufferDontExist);
1299 }
1300
1301 // Handle fixed-length arrays
1302 if (fixedLengthArrayCount > 0) {
1303 size_t maxRequiredBytes =
1304 static_cast<size_t>(_pPropertyTable->count * fixedLengthArrayCount) *
1305 sizeof(T);
1306
1307 if (values.size() < maxRequiredBytes) {
1308 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1309 PropertyTablePropertyViewStatus::
1310 ErrorBufferViewSizeDoesNotMatchPropertyTableCount);
1311 }
1312
1313 if constexpr (!Normalized) {
1314 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1315 propertyTableProperty,
1316 classProperty,
1317 pEnumDefinition,
1318 _pPropertyTable->count,
1319 values);
1320 } else {
1321 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1322 propertyTableProperty,
1323 classProperty,
1324 _pPropertyTable->count,
1325 values);
1326 }
1327 }
1328
1329 // Handle variable-length arrays
1330 const PropertyComponentType arrayOffsetType =
1332 propertyTableProperty.arrayOffsetType);
1333 if (arrayOffsetType == PropertyComponentType::None) {
1334 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1336 }
1337
1338 constexpr bool checkBitsSize = false;
1339 std::span<const std::byte> arrayOffsets;
1340 status = getArrayOffsetsBufferSafe(
1341 propertyTableProperty.arrayOffsets,
1342 arrayOffsetType,
1343 values.size(),
1344 static_cast<size_t>(_pPropertyTable->count),
1345 checkBitsSize,
1346 arrayOffsets);
1348 return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1349 status);
1350 }
1351
1352 if constexpr (Normalized) {
1353 return PropertyTablePropertyView<PropertyArrayView<T>, true>(
1354 propertyTableProperty,
1355 classProperty,
1356 _pPropertyTable->count,
1357 values,
1358 arrayOffsets,
1359 arrayOffsetType);
1360 } else {
1361 return PropertyTablePropertyView<PropertyArrayView<T>, false>(
1362 propertyTableProperty,
1363 classProperty,
1364 pEnumDefinition,
1365 _pPropertyTable->count,
1366 values,
1367 arrayOffsets,
1368 std::span<const std::byte>(),
1369 arrayOffsetType,
1371 }
1372 }
1373
1374 PropertyTablePropertyView<PropertyArrayView<std::string_view>>
1375 getStringArrayPropertyValues(
1376 const ClassProperty& classProperty,
1377 const PropertyTableProperty& propertyTableProperty) const;
1378
1379 PropertyViewStatusType getBufferSafe(
1380 int32_t bufferView,
1381 std::span<const std::byte>& buffer) const noexcept;
1382
1383 PropertyViewStatusType getArrayOffsetsBufferSafe(
1384 int32_t arrayOffsetsBufferView,
1385 PropertyComponentType arrayOffsetType,
1386 size_t valuesBufferSize,
1387 size_t propertyTableCount,
1388 bool checkBitsSize,
1389 std::span<const std::byte>& arrayOffsetsBuffer) const noexcept;
1390
1391 PropertyViewStatusType getStringOffsetsBufferSafe(
1392 int32_t stringOffsetsBufferView,
1393 PropertyComponentType stringOffsetType,
1394 size_t valuesBufferSize,
1395 size_t propertyTableCount,
1396 std::span<const std::byte>& stringOffsetsBuffer) const noexcept;
1397
1398 const Model* _pModel;
1399 const PropertyTable* _pPropertyTable;
1400 const Class* _pClass;
1401 const std::unordered_map<std::string, CesiumGltf::Enum>* _pEnumDefinitions;
1403};
1404} // namespace CesiumGltf
A view on an array element of a PropertyTableProperty or PropertyTextureProperty.
static const PropertyViewStatusType ErrorInvalidPropertyTable
This property view was initialized from an invalid PropertyTable.
static const PropertyViewStatusType ErrorInvalidArrayOffsetType
This property view has an unknown array offset type.
A view on the data of the PropertyTableProperty that is created by a PropertyTableView.
PropertyTableViewStatus status() const noexcept
Gets the status of this property table view.
void getPropertyView(const std::string &propertyId, Callback &&callback) const
Gets a PropertyTablePropertyView through a callback that accepts a property id and a PropertyTablePro...
const Class * getClass() const noexcept
Gets the Class that this property table conforms to.
PropertyTablePropertyView< T, Normalized > getPropertyView(const std::string &propertyId) const
Gets a PropertyTablePropertyView that views the data of a property stored in the PropertyTable.
int64_t size() const noexcept
Get the number of elements in this PropertyTableView. If the view is valid, this returns PropertyTabl...
const std::optional< std::string > & name() const noexcept
Gets the name of the property table being viewed. Returns std::nullopt if no name was specified.
void forEachProperty(Callback &&callback) const
Iterates over each property in the PropertyTable with a callback that accepts a property id and a Pro...
const ClassProperty * getClassProperty(const std::string &propertyId) const
Finds the ClassProperty that describes the type information of the property with the specified id.
PropertyTableView(const Model &model, const PropertyTable &propertyTable)
Creates an instance of PropertyTableView.
static const PropertyViewStatusType ErrorTypeMismatch
This property view's type does not match what is specified in ClassProperty::type.
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 ErrorNormalizationMismatch
This property view's normalization differs from what is specified in ClassProperty::normalized.
static const PropertyViewStatusType ErrorInvalidEnum
The property provided an invalid enum value.
static const PropertyViewStatusType ErrorComponentTypeMismatch
This property view's component type does not match what is specified in ClassProperty::componentType.
Classes for working with glTF models.
PropertyComponentType
The possible types of a property component.
@ Float32
A property component equivalent to a float.
@ Uint32
A property component equivalent to a uint32_t.
@ Uint16
A property component equivalent to a uint16_t.
@ Int16
A property component equivalent to an int16_t.
@ Uint8
A property component equivalent to a uint8_t.
@ Int8
A property component equivalent to an int8_t.
@ Int32
A property component equivalent to an int32_t.
@ Uint64
A property component equivalent to a uint32_t.
@ Float64
A property component equivalent to a double.
@ Int64
A property component equivalent to an int64_t.
PropertyComponentType convertArrayOffsetTypeStringToPropertyComponentType(const std::string &str)
Converts a string listed in PropertyTableProperty::ArrayOffsetType to its corresponding PropertyCompo...
bool isPropertyTypeVecN(PropertyType type)
Checks if the given PropertyType represents a vector with any number of components.
bool isPropertyComponentTypeInteger(PropertyComponentType componentType)
Checks if the given PropertyComponentType represents an integer value.
PropertyComponentType convertStringToPropertyComponentType(const std::string &str)
Converts a string into a PropertyComponentType.
@ ErrorClassNotFound
The property attribute's specified class could not be found in the extension.
@ ErrorMissingMetadataExtension
The glTF is missing the EXT_structural_metadata extension.
@ ErrorMissingSchema
The glTF EXT_structural_metadata extension doesn't contain a schema.
bool isPropertyTypeMatN(PropertyType type)
Checks if the given PropertyType represents a matrix with any number of components.
bool canRepresentPropertyType(PropertyType type)
Returns whether the type T can represent the given PropertyType.
@ Valid
This accessor is valid and ready to use.
PropertyType convertStringToPropertyType(const std::string &str)
Converts a string into a PropertyType.
PropertyType
The possible types of a property in a PropertyTableView.
@ Scalar
A scalar property, i.e. an integer or floating point value.
glm::length_t getDimensionsFromPropertyType(PropertyType type)
Obtains the number of dimensions in the given PropertyType.
PropertyTableViewStatus
Indicates the status of a property table view.
@ Valid
This property table view is valid and ready to use.
int32_t PropertyViewStatusType
The type used for fields of PropertyViewStatus.
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::string type
The element type.
std::optional< std::string > enumType
Enum ID as declared in the enums dictionary. Required when type is ENUM.
A class containing a set of properties.
Definition Class.h:17
static constexpr bool value
Whether the given metadata type is a scalar, a vector, or a matrix.
void type
The component type of this metadata array.
This class is not meant to be instantiated directly. Use Model instead.
Definition Model.h:14
Properties conforming to a class, organized as property values stored in binary columnar arrays.