cesium-native  0.41.0
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 
8 #include <glm/common.hpp>
9 
10 #include <optional>
11 
12 namespace CesiumGltf {
13 
26  Valid,
27 
33 
39 
45 };
46 
55 public:
62  PropertyTableView(const Model& model, const PropertyTable& propertyTable);
63 
72  PropertyTableViewStatus status() const noexcept { return _status; }
73 
78  const std::optional<std::string>& name() const noexcept {
79  return _pPropertyTable->name;
80  }
81 
88  int64_t size() const noexcept {
89  return _status == PropertyTableViewStatus::Valid ? _pPropertyTable->count
90  : 0;
91  }
92 
99  const Class* getClass() const noexcept { return _pClass; }
100 
108  const ClassProperty* getClassProperty(const std::string& propertyId) const;
109 
136  template <typename T, bool Normalized = false>
138  getPropertyView(const std::string& propertyId) const {
139  if (this->size() <= 0) {
142  }
143 
144  const ClassProperty* pClassProperty = getClassProperty(propertyId);
145  if (!pClassProperty) {
148  }
149 
150  return getPropertyViewImpl<T, Normalized>(propertyId, *pClassProperty);
151  }
152 
174  template <typename Callback>
175  void
176  getPropertyView(const std::string& propertyId, Callback&& callback) const {
177  if (this->size() <= 0) {
178  callback(
179  propertyId,
182  return;
183  }
184 
185  const ClassProperty* pClassProperty = getClassProperty(propertyId);
186  if (!pClassProperty) {
187  callback(
188  propertyId,
191  return;
192  }
193 
194  PropertyType type = convertStringToPropertyType(pClassProperty->type);
195  PropertyComponentType componentType = PropertyComponentType::None;
196  if (pClassProperty->componentType) {
197  componentType =
198  convertStringToPropertyComponentType(*pClassProperty->componentType);
199  }
200 
201  bool normalized = pClassProperty->normalized;
202  if (normalized && !isPropertyComponentTypeInteger(componentType)) {
203  // Only integer components may be normalized.
204  callback(
205  propertyId,
208  return;
209  }
210 
211  if (pClassProperty->array) {
212  if (normalized) {
213  getArrayPropertyViewImpl<Callback, true>(
214  propertyId,
215  *pClassProperty,
216  type,
217  componentType,
218  std::forward<Callback>(callback));
219  } else {
220  getArrayPropertyViewImpl<Callback, false>(
221  propertyId,
222  *pClassProperty,
223  type,
224  componentType,
225  std::forward<Callback>(callback));
226  }
227  return;
228  }
229 
230  if (type == PropertyType::Scalar) {
231  if (normalized) {
232  getScalarPropertyViewImpl<Callback, true>(
233  propertyId,
234  *pClassProperty,
235  componentType,
236  std::forward<Callback>(callback));
237  } else {
238  getScalarPropertyViewImpl<Callback, false>(
239  propertyId,
240  *pClassProperty,
241  componentType,
242  std::forward<Callback>(callback));
243  }
244  return;
245  }
246 
247  if (isPropertyTypeVecN(type)) {
248  if (normalized) {
249  getVecNPropertyViewImpl<Callback, true>(
250  propertyId,
251  *pClassProperty,
252  type,
253  componentType,
254  std::forward<Callback>(callback));
255  } else {
256  getVecNPropertyViewImpl<Callback, false>(
257  propertyId,
258  *pClassProperty,
259  type,
260  componentType,
261  std::forward<Callback>(callback));
262  }
263  return;
264  }
265 
266  if (isPropertyTypeMatN(type)) {
267  if (normalized) {
268  getMatNPropertyViewImpl<Callback, true>(
269  propertyId,
270  *pClassProperty,
271  type,
272  componentType,
273  std::forward<Callback>(callback));
274  } else {
275  getMatNPropertyViewImpl<Callback, false>(
276  propertyId,
277  *pClassProperty,
278  type,
279  componentType,
280  std::forward<Callback>(callback));
281  }
282  return;
283  }
284 
285  if (type == PropertyType::String) {
286  callback(
287  propertyId,
288  getPropertyViewImpl<std::string_view, false>(
289  propertyId,
290  *pClassProperty));
291  return;
292  }
293 
294  if (type == PropertyType::Boolean) {
295  callback(
296  propertyId,
297  getPropertyViewImpl<bool, false>(propertyId, *pClassProperty));
298  return;
299  }
300 
301  callback(
302  propertyId,
305  }
306 
328  template <typename Callback> void forEachProperty(Callback&& callback) const {
329  for (const auto& property : this->_pClass->properties) {
330  getPropertyView(property.first, std::forward<Callback>(callback));
331  }
332  }
333 
334 private:
335  template <typename Callback, bool Normalized>
336  void getScalarArrayPropertyViewImpl(
337  const std::string& propertyId,
338  const ClassProperty& classProperty,
339  PropertyComponentType componentType,
340  Callback&& callback) const {
341  switch (componentType) {
342  case PropertyComponentType::Int8:
343  callback(
344  propertyId,
345  getPropertyViewImpl<PropertyArrayView<int8_t>, Normalized>(
346  propertyId,
347  classProperty));
348  break;
349  case PropertyComponentType::Uint8:
350  callback(
351  propertyId,
352  getPropertyViewImpl<PropertyArrayView<uint8_t>, Normalized>(
353  propertyId,
354  classProperty));
355  break;
356  case PropertyComponentType::Int16:
357  callback(
358  propertyId,
359  getPropertyViewImpl<PropertyArrayView<int16_t>, Normalized>(
360  propertyId,
361  classProperty));
362  break;
363  case PropertyComponentType::Uint16:
364  callback(
365  propertyId,
366  getPropertyViewImpl<PropertyArrayView<uint16_t>, Normalized>(
367  propertyId,
368  classProperty));
369  break;
370  case PropertyComponentType::Int32:
371  callback(
372  propertyId,
373  getPropertyViewImpl<PropertyArrayView<int32_t>, Normalized>(
374  propertyId,
375  classProperty));
376  break;
377  case PropertyComponentType::Uint32:
378  callback(
379  propertyId,
380  getPropertyViewImpl<PropertyArrayView<uint32_t>, Normalized>(
381  propertyId,
382  classProperty));
383  break;
384  case PropertyComponentType::Int64:
385  callback(
386  propertyId,
387  getPropertyViewImpl<PropertyArrayView<int64_t>, Normalized>(
388  propertyId,
389  classProperty));
390  break;
391  case PropertyComponentType::Uint64:
392  callback(
393  propertyId,
394  getPropertyViewImpl<PropertyArrayView<uint64_t>, Normalized>(
395  propertyId,
396  classProperty));
397  break;
398  case PropertyComponentType::Float32:
399  callback(
400  propertyId,
401  getPropertyViewImpl<PropertyArrayView<float>, false>(
402  propertyId,
403  classProperty));
404  break;
405  case PropertyComponentType::Float64:
406  callback(
407  propertyId,
408  getPropertyViewImpl<PropertyArrayView<double>, false>(
409  propertyId,
410  classProperty));
411  break;
412  default:
413  callback(
414  propertyId,
417  break;
418  }
419  }
420 
421  template <typename Callback, glm::length_t N, bool Normalized>
422  void getVecNArrayPropertyViewImpl(
423  const std::string& propertyId,
424  const ClassProperty& classProperty,
425  PropertyComponentType componentType,
426  Callback&& callback) const {
427  switch (componentType) {
428  case PropertyComponentType::Int8:
429  callback(
430  propertyId,
431  getPropertyViewImpl<
432  PropertyArrayView<glm::vec<N, int8_t>>,
433  Normalized>(propertyId, classProperty));
434  break;
435  case PropertyComponentType::Uint8:
436  callback(
437  propertyId,
438  getPropertyViewImpl<
439  PropertyArrayView<glm::vec<N, uint8_t>>,
440  Normalized>(propertyId, classProperty));
441  break;
442  case PropertyComponentType::Int16:
443  callback(
444  propertyId,
445  getPropertyViewImpl<
446  PropertyArrayView<glm::vec<N, int16_t>>,
447  Normalized>(propertyId, classProperty));
448  break;
449  case PropertyComponentType::Uint16:
450  callback(
451  propertyId,
452  getPropertyViewImpl<
453  PropertyArrayView<glm::vec<N, uint16_t>>,
454  Normalized>(propertyId, classProperty));
455  break;
456  case PropertyComponentType::Int32:
457  callback(
458  propertyId,
459  getPropertyViewImpl<
460  PropertyArrayView<glm::vec<N, int32_t>>,
461  Normalized>(propertyId, classProperty));
462  break;
463  case PropertyComponentType::Uint32:
464  callback(
465  propertyId,
466  getPropertyViewImpl<
467  PropertyArrayView<glm::vec<N, uint32_t>>,
468  Normalized>(propertyId, classProperty));
469  break;
470  case PropertyComponentType::Int64:
471  callback(
472  propertyId,
473  getPropertyViewImpl<
474  PropertyArrayView<glm::vec<N, int64_t>>,
475  Normalized>(propertyId, classProperty));
476  break;
477  case PropertyComponentType::Uint64:
478  callback(
479  propertyId,
480  getPropertyViewImpl<
481  PropertyArrayView<glm::vec<N, uint64_t>>,
482  Normalized>(propertyId, classProperty));
483  break;
484  case PropertyComponentType::Float32:
485  callback(
486  propertyId,
487  getPropertyViewImpl<PropertyArrayView<glm::vec<N, float>>, false>(
488  propertyId,
489  classProperty));
490  break;
491  case PropertyComponentType::Float64:
492  callback(
493  propertyId,
494  getPropertyViewImpl<PropertyArrayView<glm::vec<N, double>>, false>(
495  propertyId,
496  classProperty));
497  break;
498  default:
499  callback(
500  propertyId,
501  PropertyTablePropertyView<uint8_t>(
503  break;
504  }
505  }
506 
507  template <typename Callback, bool Normalized>
508  void getVecNArrayPropertyViewImpl(
509  const std::string& propertyId,
510  const ClassProperty& classProperty,
511  PropertyType type,
512  PropertyComponentType componentType,
513  Callback&& callback) const {
514  glm::length_t N = getDimensionsFromPropertyType(type);
515  switch (N) {
516  case 2:
517  getVecNArrayPropertyViewImpl<Callback, 2, Normalized>(
518  propertyId,
519  classProperty,
520  componentType,
521  std::forward<Callback>(callback));
522  break;
523  case 3:
524  getVecNArrayPropertyViewImpl<Callback, 3, Normalized>(
525  propertyId,
526  classProperty,
527  componentType,
528  std::forward<Callback>(callback));
529  break;
530  case 4:
531  getVecNArrayPropertyViewImpl<Callback, 4, Normalized>(
532  propertyId,
533  classProperty,
534  componentType,
535  std::forward<Callback>(callback));
536  break;
537  default:
538  callback(
539  propertyId,
540  PropertyTablePropertyView<uint8_t>(
542  break;
543  }
544  }
545 
546  template <typename Callback, glm::length_t N, bool Normalized>
547  void getMatNArrayPropertyViewImpl(
548  const std::string& propertyId,
549  const ClassProperty& classProperty,
550  PropertyComponentType componentType,
551  Callback&& callback) const {
552  switch (componentType) {
553  case PropertyComponentType::Int8:
554  callback(
555  propertyId,
556  getPropertyViewImpl<
557  PropertyArrayView<glm::mat<N, N, int8_t>>,
558  Normalized>(propertyId, classProperty));
559  break;
560  case PropertyComponentType::Uint8:
561  callback(
562  propertyId,
563  getPropertyViewImpl<
564  PropertyArrayView<glm::mat<N, N, uint8_t>>,
565  Normalized>(propertyId, classProperty));
566  break;
567  case PropertyComponentType::Int16:
568  callback(
569  propertyId,
570  getPropertyViewImpl<
571  PropertyArrayView<glm::mat<N, N, int16_t>>,
572  Normalized>(propertyId, classProperty));
573  break;
574  case PropertyComponentType::Uint16:
575  callback(
576  propertyId,
577  getPropertyViewImpl<
578  PropertyArrayView<glm::mat<N, N, uint16_t>>,
579  Normalized>(propertyId, classProperty));
580  break;
581  case PropertyComponentType::Int32:
582  callback(
583  propertyId,
584  getPropertyViewImpl<
585  PropertyArrayView<glm::mat<N, N, int32_t>>,
586  Normalized>(propertyId, classProperty));
587  break;
588  case PropertyComponentType::Uint32:
589  callback(
590  propertyId,
591  getPropertyViewImpl<
592  PropertyArrayView<glm::mat<N, N, uint32_t>>,
593  Normalized>(propertyId, classProperty));
594  break;
595  case PropertyComponentType::Int64:
596  callback(
597  propertyId,
598  getPropertyViewImpl<
599  PropertyArrayView<glm::mat<N, N, int64_t>>,
600  Normalized>(propertyId, classProperty));
601  break;
602  case PropertyComponentType::Uint64:
603  callback(
604  propertyId,
605  getPropertyViewImpl<
606  PropertyArrayView<glm::mat<N, N, uint64_t>>,
607  Normalized>(propertyId, classProperty));
608  break;
609  case PropertyComponentType::Float32:
610  callback(
611  propertyId,
612  getPropertyViewImpl<PropertyArrayView<glm::mat<N, N, float>>, false>(
613  propertyId,
614  classProperty));
615  break;
616  case PropertyComponentType::Float64:
617  callback(
618  propertyId,
619  getPropertyViewImpl<PropertyArrayView<glm::mat<N, N, double>>, false>(
620  propertyId,
621  classProperty));
622  break;
623  default:
624  callback(
625  propertyId,
626  PropertyTablePropertyView<uint8_t>(
628  break;
629  }
630  }
631 
632  template <typename Callback, bool Normalized>
633  void getMatNArrayPropertyViewImpl(
634  const std::string& propertyId,
635  const ClassProperty& classProperty,
636  PropertyType type,
637  PropertyComponentType componentType,
638  Callback&& callback) const {
639  const glm::length_t N = getDimensionsFromPropertyType(type);
640  switch (N) {
641  case 2:
642  getMatNArrayPropertyViewImpl<Callback, 2, Normalized>(
643  propertyId,
644  classProperty,
645  componentType,
646  std::forward<Callback>(callback));
647  break;
648  case 3:
649  getMatNArrayPropertyViewImpl<Callback, 3, Normalized>(
650  propertyId,
651  classProperty,
652  componentType,
653  std::forward<Callback>(callback));
654  break;
655  case 4:
656  getMatNArrayPropertyViewImpl<Callback, 4, Normalized>(
657  propertyId,
658  classProperty,
659  componentType,
660  std::forward<Callback>(callback));
661  break;
662  default:
663  callback(
664  propertyId,
665  PropertyTablePropertyView<uint8_t>(
667  break;
668  }
669  }
670 
671  template <typename Callback, bool Normalized>
672  void getArrayPropertyViewImpl(
673  const std::string& propertyId,
674  const ClassProperty& classProperty,
675  PropertyType type,
676  PropertyComponentType componentType,
677  Callback&& callback) const {
678  if (type == PropertyType::Scalar) {
679  getScalarArrayPropertyViewImpl<Callback, Normalized>(
680  propertyId,
681  classProperty,
682  componentType,
683  std::forward<Callback>(callback));
684  } else if (isPropertyTypeVecN(type)) {
685  getVecNArrayPropertyViewImpl<Callback, Normalized>(
686  propertyId,
687  classProperty,
688  type,
689  componentType,
690  std::forward<Callback>(callback));
691  } else if (isPropertyTypeMatN(type)) {
692  getMatNArrayPropertyViewImpl<Callback, Normalized>(
693  propertyId,
694  classProperty,
695  type,
696  componentType,
697  std::forward<Callback>(callback));
698  } else if (type == PropertyType::Boolean) {
699  callback(
700  propertyId,
701  getPropertyViewImpl<PropertyArrayView<bool>, false>(
702  propertyId,
703  classProperty));
704 
705  } else if (type == PropertyType::String) {
706  callback(
707  propertyId,
708  getPropertyViewImpl<PropertyArrayView<std::string_view>, false>(
709  propertyId,
710  classProperty));
711  } else {
712  callback(
713  propertyId,
714  PropertyTablePropertyView<uint8_t>(
716  }
717  }
718 
719  template <typename Callback, glm::length_t N, bool Normalized>
720  void getVecNPropertyViewImpl(
721  const std::string& propertyId,
722  const ClassProperty& classProperty,
723  PropertyComponentType componentType,
724  Callback&& callback) const {
725 
726  switch (componentType) {
727  case PropertyComponentType::Int8:
728  callback(
729  propertyId,
730  getPropertyViewImpl<glm::vec<N, int8_t>, Normalized>(
731  propertyId,
732  classProperty));
733  break;
734  case PropertyComponentType::Uint8:
735  callback(
736  propertyId,
737  getPropertyViewImpl<glm::vec<N, uint8_t>, Normalized>(
738  propertyId,
739  classProperty));
740  break;
741  case PropertyComponentType::Int16:
742  callback(
743  propertyId,
744  getPropertyViewImpl<glm::vec<N, int16_t>, Normalized>(
745  propertyId,
746  classProperty));
747  break;
748  case PropertyComponentType::Uint16:
749  callback(
750  propertyId,
751  getPropertyViewImpl<glm::vec<N, uint16_t>, Normalized>(
752  propertyId,
753  classProperty));
754  break;
755  case PropertyComponentType::Int32:
756  callback(
757  propertyId,
758  getPropertyViewImpl<glm::vec<N, int32_t>, Normalized>(
759  propertyId,
760  classProperty));
761  break;
762  case PropertyComponentType::Uint32:
763  callback(
764  propertyId,
765  getPropertyViewImpl<glm::vec<N, uint32_t>, Normalized>(
766  propertyId,
767  classProperty));
768  break;
769  case PropertyComponentType::Int64:
770  callback(
771  propertyId,
772  getPropertyViewImpl<glm::vec<N, int64_t>, Normalized>(
773  propertyId,
774  classProperty));
775  break;
776  case PropertyComponentType::Uint64:
777  callback(
778  propertyId,
779  getPropertyViewImpl<glm::vec<N, uint64_t>, Normalized>(
780  propertyId,
781  classProperty));
782  break;
783  case PropertyComponentType::Float32:
784  callback(
785  propertyId,
786  getPropertyViewImpl<glm::vec<N, float>, false>(
787  propertyId,
788  classProperty));
789  break;
790  case PropertyComponentType::Float64:
791  callback(
792  propertyId,
793  getPropertyViewImpl<glm::vec<N, double>, false>(
794  propertyId,
795  classProperty));
796  break;
797  default:
798  callback(
799  propertyId,
800  PropertyTablePropertyView<uint8_t>(
802  break;
803  }
804  }
805 
806  template <typename Callback, bool Normalized>
807  void getVecNPropertyViewImpl(
808  const std::string& propertyId,
809  const ClassProperty& classProperty,
810  PropertyType type,
811  PropertyComponentType componentType,
812  Callback&& callback) const {
813  const glm::length_t N = getDimensionsFromPropertyType(type);
814  switch (N) {
815  case 2:
816  getVecNPropertyViewImpl<Callback, 2, Normalized>(
817  propertyId,
818  classProperty,
819  componentType,
820  std::forward<Callback>(callback));
821  break;
822  case 3:
823  getVecNPropertyViewImpl<Callback, 3, Normalized>(
824  propertyId,
825  classProperty,
826  componentType,
827  std::forward<Callback>(callback));
828  break;
829  case 4:
830  getVecNPropertyViewImpl<Callback, 4, Normalized>(
831  propertyId,
832  classProperty,
833  componentType,
834  std::forward<Callback>(callback));
835  break;
836  default:
837  callback(
838  propertyId,
839  PropertyTablePropertyView<uint8_t>(
841  break;
842  }
843  }
844 
845  template <typename Callback, glm::length_t N, bool Normalized>
846  void getMatNPropertyViewImpl(
847  const std::string& propertyId,
848  const ClassProperty& classProperty,
849  PropertyComponentType componentType,
850  Callback&& callback) const {
851  switch (componentType) {
852  case PropertyComponentType::Int8:
853  callback(
854  propertyId,
855  getPropertyViewImpl<glm::mat<N, N, int8_t>, Normalized>(
856  propertyId,
857  classProperty));
858  break;
859  case PropertyComponentType::Uint8:
860  callback(
861  propertyId,
862  getPropertyViewImpl<glm::mat<N, N, uint8_t>, Normalized>(
863  propertyId,
864  classProperty));
865  break;
866  case PropertyComponentType::Int16:
867  callback(
868  propertyId,
869  getPropertyViewImpl<glm::mat<N, N, int16_t>, Normalized>(
870  propertyId,
871  classProperty));
872  break;
873  case PropertyComponentType::Uint16:
874  callback(
875  propertyId,
876  getPropertyViewImpl<glm::mat<N, N, uint16_t>, Normalized>(
877  propertyId,
878  classProperty));
879  break;
880  case PropertyComponentType::Int32:
881  callback(
882  propertyId,
883  getPropertyViewImpl<glm::mat<N, N, int32_t>, Normalized>(
884  propertyId,
885  classProperty));
886  break;
887  case PropertyComponentType::Uint32:
888  callback(
889  propertyId,
890  getPropertyViewImpl<glm::mat<N, N, uint32_t>, Normalized>(
891  propertyId,
892  classProperty));
893  break;
894  case PropertyComponentType::Int64:
895  callback(
896  propertyId,
897  getPropertyViewImpl<glm::mat<N, N, int64_t>, Normalized>(
898  propertyId,
899  classProperty));
900  break;
901  case PropertyComponentType::Uint64:
902  callback(
903  propertyId,
904  getPropertyViewImpl<glm::mat<N, N, uint64_t>, Normalized>(
905  propertyId,
906  classProperty));
907  break;
908  case PropertyComponentType::Float32:
909  callback(
910  propertyId,
911  getPropertyViewImpl<glm::mat<N, N, float>, false>(
912  propertyId,
913  classProperty));
914  break;
915  case PropertyComponentType::Float64:
916  callback(
917  propertyId,
918  getPropertyViewImpl<glm::mat<N, N, double>, false>(
919  propertyId,
920  classProperty));
921  break;
922  default:
923  callback(
924  propertyId,
925  PropertyTablePropertyView<uint8_t>(
927  break;
928  }
929  }
930 
931  template <typename Callback, bool Normalized>
932  void getMatNPropertyViewImpl(
933  const std::string& propertyId,
934  const ClassProperty& classProperty,
935  PropertyType type,
936  PropertyComponentType componentType,
937  Callback&& callback) const {
938  glm::length_t N = getDimensionsFromPropertyType(type);
939  switch (N) {
940  case 2:
941  getMatNPropertyViewImpl<Callback, 2, Normalized>(
942  propertyId,
943  classProperty,
944  componentType,
945  std::forward<Callback>(callback));
946  break;
947  case 3:
948  getMatNPropertyViewImpl<Callback, 3, Normalized>(
949  propertyId,
950  classProperty,
951  componentType,
952  std::forward<Callback>(callback));
953  break;
954  case 4:
955  getMatNPropertyViewImpl<Callback, 4, Normalized>(
956  propertyId,
957  classProperty,
958  componentType,
959  std::forward<Callback>(callback));
960  break;
961  default:
962  callback(
963  propertyId,
964  PropertyTablePropertyView<uint8_t>(
966  break;
967  }
968  }
969 
970  template <typename Callback, bool Normalized>
971  void getScalarPropertyViewImpl(
972  const std::string& propertyId,
973  const ClassProperty& classProperty,
974  PropertyComponentType componentType,
975  Callback&& callback) const {
976  switch (componentType) {
977  case PropertyComponentType::Int8:
978  callback(
979  propertyId,
980  getPropertyViewImpl<int8_t, Normalized>(propertyId, classProperty));
981  return;
982  case PropertyComponentType::Uint8:
983  callback(
984  propertyId,
985  getPropertyViewImpl<uint8_t, Normalized>(propertyId, classProperty));
986  return;
987  case PropertyComponentType::Int16:
988  callback(
989  propertyId,
990  getPropertyViewImpl<int16_t, Normalized>(propertyId, classProperty));
991  return;
992  case PropertyComponentType::Uint16:
993  callback(
994  propertyId,
995  getPropertyViewImpl<uint16_t, Normalized>(propertyId, classProperty));
996  break;
997  case PropertyComponentType::Int32:
998  callback(
999  propertyId,
1000  getPropertyViewImpl<int32_t, Normalized>(propertyId, classProperty));
1001  break;
1002  case PropertyComponentType::Uint32:
1003  callback(
1004  propertyId,
1005  getPropertyViewImpl<uint32_t, Normalized>(propertyId, classProperty));
1006  break;
1007  case PropertyComponentType::Int64:
1008  callback(
1009  propertyId,
1010  getPropertyViewImpl<int64_t, Normalized>(propertyId, classProperty));
1011  break;
1012  case PropertyComponentType::Uint64:
1013  callback(
1014  propertyId,
1015  getPropertyViewImpl<uint64_t, Normalized>(propertyId, classProperty));
1016  break;
1017  case PropertyComponentType::Float32:
1018  callback(
1019  propertyId,
1020  getPropertyViewImpl<float, false>(propertyId, classProperty));
1021  break;
1022  case PropertyComponentType::Float64:
1023  callback(
1024  propertyId,
1025  getPropertyViewImpl<double, false>(propertyId, classProperty));
1026  break;
1027  default:
1028  callback(
1029  propertyId,
1030  PropertyTablePropertyView<uint8_t>(
1032  break;
1033  }
1034  }
1035 
1036  template <typename T, bool Normalized>
1037  PropertyTablePropertyView<T, Normalized> getPropertyViewImpl(
1038  const std::string& propertyId,
1039  const ClassProperty& classProperty) const {
1040  auto propertyTablePropertyIter =
1041  _pPropertyTable->properties.find(propertyId);
1042  if (propertyTablePropertyIter == _pPropertyTable->properties.end()) {
1043  if (!classProperty.required && classProperty.defaultProperty) {
1044  // If the property was omitted from the property table, it is still
1045  // technically valid if it specifies a default value. Create a view that
1046  // just returns the default value.
1047  return PropertyTablePropertyView<T, Normalized>(
1048  classProperty,
1049  _pPropertyTable->count);
1050  }
1051 
1052  // Otherwise, the property is erroneously nonexistent.
1053  return PropertyTablePropertyView<T, Normalized>(
1055  }
1056 
1057  const PropertyTableProperty& propertyTableProperty =
1058  propertyTablePropertyIter->second;
1059 
1060  if constexpr (IsMetadataNumeric<T>::value || IsMetadataBoolean<T>::value) {
1061  return getNumericOrBooleanPropertyValues<T, Normalized>(
1062  classProperty,
1063  propertyTableProperty);
1064  }
1065 
1066  if constexpr (IsMetadataString<T>::value) {
1067  return getStringPropertyValues(classProperty, propertyTableProperty);
1068  }
1069 
1070  if constexpr (IsMetadataBooleanArray<T>::value) {
1071  return getBooleanArrayPropertyValues(
1072  classProperty,
1073  propertyTableProperty);
1074  }
1075 
1076  if constexpr (IsMetadataNumericArray<T>::value) {
1077  return getNumericArrayPropertyValues<
1078  typename MetadataArrayType<T>::type,
1079  Normalized>(classProperty, propertyTableProperty);
1080  }
1081 
1082  if constexpr (IsMetadataStringArray<T>::value) {
1083  return getStringArrayPropertyValues(classProperty, propertyTableProperty);
1084  }
1085  }
1086 
1087  template <typename T, bool Normalized>
1088  PropertyTablePropertyView<T, Normalized> getNumericOrBooleanPropertyValues(
1089  const ClassProperty& classProperty,
1090  const PropertyTableProperty& propertyTableProperty) const {
1091  if (classProperty.array) {
1092  return PropertyTablePropertyView<T, Normalized>(
1094  }
1095 
1096  const PropertyType type = convertStringToPropertyType(classProperty.type);
1097  if (TypeToPropertyType<T>::value != type) {
1098  return PropertyTablePropertyView<T, Normalized>(
1100  }
1101  const PropertyComponentType componentType =
1102  convertStringToPropertyComponentType(
1103  classProperty.componentType.value_or(""));
1104  if (TypeToPropertyType<T>::component != componentType) {
1105  return PropertyTablePropertyView<T, Normalized>(
1107  }
1108 
1109  if (classProperty.normalized != Normalized) {
1110  return PropertyTablePropertyView<T, Normalized>(
1112  }
1113 
1114  gsl::span<const std::byte> values;
1115  const auto status = getBufferSafe(propertyTableProperty.values, values);
1117  return PropertyTablePropertyView<T, Normalized>(status);
1118  }
1119 
1120  if (values.size() % sizeof(T) != 0) {
1121  return PropertyTablePropertyView<T, Normalized>(
1122  PropertyTablePropertyViewStatus::
1123  ErrorBufferViewSizeNotDivisibleByTypeSize);
1124  }
1125 
1126  size_t maxRequiredBytes = 0;
1127  if (IsMetadataBoolean<T>::value) {
1128  maxRequiredBytes = static_cast<size_t>(
1129  glm::ceil(static_cast<double>(_pPropertyTable->count) / 8.0));
1130  } else {
1131  maxRequiredBytes = _pPropertyTable->count * sizeof(T);
1132  }
1133 
1134  if (values.size() < maxRequiredBytes) {
1135  return PropertyTablePropertyView<T, Normalized>(
1136  PropertyTablePropertyViewStatus::
1137  ErrorBufferViewSizeDoesNotMatchPropertyTableCount);
1138  }
1139 
1140  return PropertyTablePropertyView<T, Normalized>(
1141  propertyTableProperty,
1142  classProperty,
1143  _pPropertyTable->count,
1144  values);
1145  }
1146 
1147  PropertyTablePropertyView<std::string_view> getStringPropertyValues(
1148  const ClassProperty& classProperty,
1149  const PropertyTableProperty& propertyTableProperty) const;
1150 
1151  PropertyTablePropertyView<PropertyArrayView<bool>>
1152  getBooleanArrayPropertyValues(
1153  const ClassProperty& classProperty,
1154  const PropertyTableProperty& propertyTableProperty) const;
1155 
1156  template <typename T, bool Normalized>
1157  PropertyTablePropertyView<PropertyArrayView<T>, Normalized>
1158  getNumericArrayPropertyValues(
1159  const ClassProperty& classProperty,
1160  const PropertyTableProperty& propertyTableProperty) const {
1161  if (!classProperty.array) {
1162  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1164  }
1165 
1166  const PropertyType type = convertStringToPropertyType(classProperty.type);
1167  if (TypeToPropertyType<T>::value != type) {
1168  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1170  }
1171 
1172  const PropertyComponentType componentType =
1173  convertStringToPropertyComponentType(
1174  classProperty.componentType.value_or(""));
1175  if (TypeToPropertyType<T>::component != componentType) {
1176  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1178  }
1179 
1180  if (classProperty.normalized != Normalized) {
1181  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1183  }
1184 
1185  gsl::span<const std::byte> values;
1186  auto status = getBufferSafe(propertyTableProperty.values, values);
1188  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1189  status);
1190  }
1191 
1192  if (values.size() % sizeof(T) != 0) {
1193  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1196  }
1197 
1198  const int64_t fixedLengthArrayCount = classProperty.count.value_or(0);
1199  if (fixedLengthArrayCount > 0 && propertyTableProperty.arrayOffsets >= 0) {
1200  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1203  }
1204 
1205  if (fixedLengthArrayCount <= 0 && propertyTableProperty.arrayOffsets < 0) {
1206  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1209  }
1210 
1211  // Handle fixed-length arrays
1212  if (fixedLengthArrayCount > 0) {
1213  size_t maxRequiredBytes = maxRequiredBytes = static_cast<size_t>(
1214  _pPropertyTable->count * fixedLengthArrayCount * sizeof(T));
1215 
1216  if (values.size() < maxRequiredBytes) {
1217  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1220  }
1221 
1222  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1223  propertyTableProperty,
1224  classProperty,
1225  _pPropertyTable->count,
1226  values);
1227  }
1228 
1229  // Handle variable-length arrays
1230  const PropertyComponentType arrayOffsetType =
1231  convertArrayOffsetTypeStringToPropertyComponentType(
1232  propertyTableProperty.arrayOffsetType);
1233  if (arrayOffsetType == PropertyComponentType::None) {
1234  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1236  }
1237 
1238  constexpr bool checkBitsSize = false;
1239  gsl::span<const std::byte> arrayOffsets;
1240  status = getArrayOffsetsBufferSafe(
1241  propertyTableProperty.arrayOffsets,
1242  arrayOffsetType,
1243  values.size(),
1244  static_cast<size_t>(_pPropertyTable->count),
1245  checkBitsSize,
1246  arrayOffsets);
1248  return PropertyTablePropertyView<PropertyArrayView<T>, Normalized>(
1249  status);
1250  }
1251 
1252  if constexpr (Normalized) {
1253  return PropertyTablePropertyView<PropertyArrayView<T>, true>(
1254  propertyTableProperty,
1255  classProperty,
1256  _pPropertyTable->count,
1257  values,
1258  arrayOffsets,
1259  arrayOffsetType);
1260  } else {
1261  return PropertyTablePropertyView<PropertyArrayView<T>, false>(
1262  propertyTableProperty,
1263  classProperty,
1264  _pPropertyTable->count,
1265  values,
1266  arrayOffsets,
1267  gsl::span<const std::byte>(),
1268  arrayOffsetType,
1269  PropertyComponentType::None);
1270  }
1271  }
1272 
1273  PropertyTablePropertyView<PropertyArrayView<std::string_view>>
1274  getStringArrayPropertyValues(
1275  const ClassProperty& classProperty,
1276  const PropertyTableProperty& propertyTableProperty) const;
1277 
1278  PropertyViewStatusType getBufferSafe(
1279  int32_t bufferView,
1280  gsl::span<const std::byte>& buffer) const noexcept;
1281 
1282  PropertyViewStatusType getArrayOffsetsBufferSafe(
1283  int32_t arrayOffsetsBufferView,
1284  PropertyComponentType arrayOffsetType,
1285  size_t valuesBufferSize,
1286  size_t propertyTableCount,
1287  bool checkBitsSize,
1288  gsl::span<const std::byte>& arrayOffsetsBuffer) const noexcept;
1289 
1290  PropertyViewStatusType getStringOffsetsBufferSafe(
1291  int32_t stringOffsetsBufferView,
1292  PropertyComponentType stringOffsetType,
1293  size_t valuesBufferSize,
1294  size_t propertyTableCount,
1295  gsl::span<const std::byte>& stringOffsetsBuffer) const noexcept;
1296 
1297  const Model* _pModel;
1298  const PropertyTable* _pPropertyTable;
1299  const Class* _pClass;
1300  PropertyTableViewStatus _status;
1301 };
1302 } // namespace CesiumGltf
A view on an array element of a PropertyTableProperty or PropertyTextureProperty.
static const PropertyViewStatusType ErrorBufferViewSizeDoesNotMatchPropertyTableCount
This property view has an invalid buffer view; its length does not match the size of the property tab...
static const PropertyViewStatusType ErrorArrayCountAndOffsetBufferCoexist
This array property view has both a fixed length and an offset buffer view defined.
static const PropertyViewStatusType ErrorArrayCountAndOffsetBufferDontExist
This array property view has neither a fixed length nor an offset buffer view defined.
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.
static const PropertyViewStatusType ErrorBufferViewSizeNotDivisibleByTypeSize
This property view has an invalid buffer view; its length is not a multiple of the size of its type /...
A view on the data of the PropertyTableProperty that is created by a PropertyTableView.
Utility to retrieve the data of PropertyTable.
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...
int64_t size() const noexcept
Get the number of elements in this PropertyTableView. If the view is valid, this returns PropertyTabl...
const ClassProperty * getClassProperty(const std::string &propertyId) const
Finds the ClassProperty that describes the type information of the property with the specified id.
void forEachProperty(Callback &&callback) const
Iterates over each property in the PropertyTable with a callback that accepts a property id and a Pro...
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.
PropertyTableView(const Model &model, const PropertyTable &propertyTable)
Creates an instance of PropertyTableView.
PropertyTablePropertyView< T, Normalized > getPropertyView(const std::string &propertyId) const
Gets a PropertyTablePropertyView that views the data of a property stored in the PropertyTable.
const Class * getClass() const noexcept
Gets the Class that this property table conforms to.
static const PropertyViewStatusType ErrorTypeMismatch
This property view's type does not match what is specified in ClassProperty::type.
Definition: PropertyView.h:53
static const PropertyViewStatusType Valid
This property view is valid and ready to use.
Definition: PropertyView.h:32
static const PropertyViewStatusType ErrorNonexistentProperty
This property view is trying to view a property that does not exist.
Definition: PropertyView.h:47
static const PropertyViewStatusType ErrorInvalidNormalization
This property says it is normalized, but it does not have an integer component type.
Definition: PropertyView.h:71
static const PropertyViewStatusType ErrorArrayTypeMismatch
This property view differs from what is specified in ClassProperty::array.
Definition: PropertyView.h:65
static const PropertyViewStatusType ErrorNormalizationMismatch
This property view's normalization differs from what is specified in ClassProperty::normalized.
Definition: PropertyView.h:77
static const PropertyViewStatusType ErrorComponentTypeMismatch
This property view's component type does not match what is specified in ClassProperty::componentType.
Definition: PropertyView.h:59
Classes for working with glTF models.
PropertyTableViewStatus
Indicates the status of a property table view.
@ Valid
This property table view is valid and ready to use.
@ ErrorClassNotFound
The property table's specified class could not be found in the extension.
@ ErrorMissingMetadataExtension
The property table view's model does not contain an EXT_structural_metadata extension.
@ ErrorMissingSchema
The property table view's model does not have a schema in its EXT_structural_metadata extension.
A class property.
Definition: ClassProperty.h:19
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.
Definition: ClassProperty.h:98
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.
Definition: ClassProperty.h:89
A class containing a set of properties.
Definition: Class.h:18
std::unordered_map< std::string, CesiumGltf::ClassProperty > properties
A dictionary, where each key is a property ID and each value is an object defining the property....
Definition: Class.h:36
The root object for a glTF asset.
Definition: Model.h:14
Properties conforming to a class, organized as property values stored in binary columnar arrays.
Definition: PropertyTable.h:21
std::unordered_map< std::string, CesiumGltf::PropertyTableProperty > properties
A dictionary, where each key corresponds to a property ID in the class' properties dictionary and eac...
Definition: PropertyTable.h:46
std::optional< std::string > name
The name of the property table, e.g. for display purposes.
Definition: PropertyTable.h:27
int64_t count
The number of elements in each property array.
Definition: PropertyTable.h:38