cesium-native 0.43.0
Loading...
Searching...
No Matches
PropertyAttributeView.h
1#pragma once
2
3#include "CesiumGltf/Class.h"
4#include "CesiumGltf/ClassProperty.h"
5#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h"
6#include "CesiumGltf/PropertyAttribute.h"
7#include "CesiumGltf/PropertyAttributePropertyView.h"
8#include "Model.h"
9
10namespace CesiumGltf {
40
51
63
73public:
82 const Model& model,
83 const PropertyAttribute& propertyAttribute) noexcept;
84
91 PropertyAttributeViewStatus status() const noexcept { return this->_status; }
92
97 const std::optional<std::string>& name() const noexcept {
98 return _pPropertyAttribute->name;
99 }
100
107 const Class* getClass() const noexcept { return _pClass; }
108
117 const ClassProperty* getClassProperty(const std::string& propertyId) const;
118
143 template <typename T, bool Normalized = false>
145 const MeshPrimitive& primitive,
146 const std::string& propertyId) const {
147 if (this->_status != PropertyAttributeViewStatus::Valid) {
150 }
151 const ClassProperty* pClassProperty = getClassProperty(propertyId);
152 if (!pClassProperty) {
155 }
156
157 if constexpr (
162 }
163
164 return getPropertyViewImpl<T, Normalized>(
165 primitive,
166 propertyId,
167 *pClassProperty);
168 }
169
191 template <typename Callback>
193 const MeshPrimitive& primitive,
194 const std::string& propertyId,
195 Callback&& callback) const {
196 if (this->_status != PropertyAttributeViewStatus::Valid) {
197 callback(
198 propertyId,
201 ErrorInvalidPropertyAttribute));
202 return;
203 }
204
205 const ClassProperty* pClassProperty = getClassProperty(propertyId);
206 if (!pClassProperty) {
207 callback(
208 propertyId,
211 return;
212 }
213
214 if (pClassProperty->array) {
215 callback(
216 propertyId,
219 return;
220 }
221
222 PropertyType type = convertStringToPropertyType(pClassProperty->type);
224 if (pClassProperty->componentType) {
225 componentType =
227 }
228
229 bool normalized = pClassProperty->normalized;
230 if (normalized && !isPropertyComponentTypeInteger(componentType)) {
231 callback(
232 propertyId,
235 return;
236 }
237
238 if (type == PropertyType::Scalar) {
239 if (normalized) {
240 getScalarPropertyViewImpl<Callback, true>(
241 primitive,
242 propertyId,
243 *pClassProperty,
244 componentType,
245 std::forward<Callback>(callback));
246 } else {
247 getScalarPropertyViewImpl<Callback, false>(
248 primitive,
249 propertyId,
250 *pClassProperty,
251 componentType,
252 std::forward<Callback>(callback));
253 }
254 return;
255 }
256
257 if (isPropertyTypeVecN(type)) {
258 if (normalized) {
259 getVecNPropertyViewImpl<Callback, true>(
260 primitive,
261 propertyId,
262 *pClassProperty,
263 type,
264 componentType,
265 std::forward<Callback>(callback));
266 } else {
267 getVecNPropertyViewImpl<Callback, false>(
268 primitive,
269 propertyId,
270 *pClassProperty,
271 type,
272 componentType,
273 std::forward<Callback>(callback));
274 }
275 return;
276 }
277
278 if (isPropertyTypeMatN(type)) {
279 if (normalized) {
280 getMatNPropertyViewImpl<Callback, true>(
281 primitive,
282 propertyId,
283 *pClassProperty,
284 type,
285 componentType,
286 std::forward<Callback>(callback));
287 } else {
288 getMatNPropertyViewImpl<Callback, false>(
289 primitive,
290 propertyId,
291 *pClassProperty,
292 type,
293 componentType,
294 std::forward<Callback>(callback));
295 }
296 return;
297 }
298
299 callback(
300 propertyId,
303 return;
304 }
305
326 template <typename Callback>
327 void
328 forEachProperty(const MeshPrimitive& primitive, Callback&& callback) const {
329 for (const auto& property : this->_pClass->properties) {
331 primitive,
332 property.first,
333 std::forward<Callback>(callback));
334 }
335 }
336
337private:
338 template <typename T, bool Normalized>
339 PropertyAttributePropertyView<T, Normalized> getEmptyPropertyViewWithDefault(
340 const MeshPrimitive& primitive,
341 const ClassProperty& classProperty) const {
342 // To make the view have a nonzero size, find the POSITION attribute and get
343 // its accessor count. If it doesn't exist or is somehow erroneous, just
344 // mark the property as nonexistent.
345 if (primitive.attributes.find("POSITION") == primitive.attributes.end()) {
348 }
349
350 const Accessor* pAccessor = _pModel->getSafe<Accessor>(
351 &_pModel->accessors,
352 primitive.attributes.at("POSITION"));
353 if (!pAccessor) {
354 return PropertyAttributePropertyView<T, Normalized>(
356 }
357
358 return PropertyAttributePropertyView<T, Normalized>(
359 classProperty,
360 pAccessor->count);
361 }
362
363 template <typename T, bool Normalized>
364 PropertyAttributePropertyView<T, Normalized> getPropertyViewImpl(
365 const MeshPrimitive& primitive,
366 const std::string& propertyId,
367 const ClassProperty& classProperty) const {
368 auto propertyAttributePropertyIter =
369 _pPropertyAttribute->properties.find(propertyId);
370 if (propertyAttributePropertyIter ==
371 _pPropertyAttribute->properties.end()) {
372 if (!classProperty.required && classProperty.defaultProperty) {
373 // If the property was omitted from the property attribute, it is still
374 // technically valid if it specifies a default value. Try to create a
375 // view that just returns the default value.
376 return getEmptyPropertyViewWithDefault<T, Normalized>(
377 primitive,
378 classProperty);
379 }
380
381 // Otherwise, the property is erroneously nonexistent.
382 return PropertyAttributePropertyView<T, Normalized>(
384 }
385
386 const PropertyAttributeProperty& propertyAttributeProperty =
387 propertyAttributePropertyIter->second;
388
389 return createPropertyView<T, Normalized>(
390 primitive,
391 classProperty,
392 propertyAttributeProperty);
393 }
394
395 template <typename Callback, bool Normalized>
396 void getScalarPropertyViewImpl(
397 const MeshPrimitive& primitive,
398 const std::string& propertyId,
399 const ClassProperty& classProperty,
400 PropertyComponentType componentType,
401 Callback&& callback) const {
402 switch (componentType) {
404 callback(
405 propertyId,
406 getPropertyViewImpl<int8_t, Normalized>(
407 primitive,
408 propertyId,
409 classProperty));
410 return;
412 callback(
413 propertyId,
414 getPropertyViewImpl<uint8_t, Normalized>(
415 primitive,
416 propertyId,
417 classProperty));
418 return;
420 callback(
421 propertyId,
422 getPropertyViewImpl<int16_t, Normalized>(
423 primitive,
424 propertyId,
425 classProperty));
426 return;
428 callback(
429 propertyId,
430 getPropertyViewImpl<uint16_t, Normalized>(
431 primitive,
432 propertyId,
433 classProperty));
434 break;
436 callback(
437 propertyId,
438 getPropertyViewImpl<float, false>(
439 primitive,
440 propertyId,
441 classProperty));
442 break;
443 default:
444 callback(
445 propertyId,
446 PropertyAttributePropertyView<uint8_t>(
448 break;
449 }
450 }
451
452 template <typename Callback, glm::length_t N, bool Normalized>
453 void getVecNPropertyViewImpl(
454 const MeshPrimitive& primitive,
455 const std::string& propertyId,
456 const ClassProperty& classProperty,
457 PropertyComponentType componentType,
458 Callback&& callback) const {
459 switch (componentType) {
461 callback(
462 propertyId,
463 getPropertyViewImpl<glm::vec<N, int8_t>, Normalized>(
464 primitive,
465 propertyId,
466 classProperty));
467 break;
469 callback(
470 propertyId,
471 getPropertyViewImpl<glm::vec<N, uint8_t>, Normalized>(
472 primitive,
473 propertyId,
474 classProperty));
475 break;
477 callback(
478 propertyId,
479 getPropertyViewImpl<glm::vec<N, int16_t>, Normalized>(
480 primitive,
481 propertyId,
482 classProperty));
483 break;
485 callback(
486 propertyId,
487 getPropertyViewImpl<glm::vec<N, uint16_t>, Normalized>(
488 primitive,
489 propertyId,
490 classProperty));
491 break;
493 callback(
494 propertyId,
495 getPropertyViewImpl<glm::vec<N, float>, false>(
496 primitive,
497 propertyId,
498 classProperty));
499 break;
500 default:
501 callback(
502 propertyId,
503 PropertyAttributePropertyView<uint8_t>(
505 break;
506 }
507 }
508
509 template <typename Callback, bool Normalized>
510 void getVecNPropertyViewImpl(
511 const MeshPrimitive& primitive,
512 const std::string& propertyId,
513 const ClassProperty& classProperty,
514 PropertyType type,
515 PropertyComponentType componentType,
516 Callback&& callback) const {
517 const glm::length_t N = getDimensionsFromPropertyType(type);
518 switch (N) {
519 case 2:
520 getVecNPropertyViewImpl<Callback, 2, Normalized>(
521 primitive,
522 propertyId,
523 classProperty,
524 componentType,
525 std::forward<Callback>(callback));
526 break;
527 case 3:
528 getVecNPropertyViewImpl<Callback, 3, Normalized>(
529 primitive,
530 propertyId,
531 classProperty,
532 componentType,
533 std::forward<Callback>(callback));
534 break;
535 case 4:
536 getVecNPropertyViewImpl<Callback, 4, Normalized>(
537 primitive,
538 propertyId,
539 classProperty,
540 componentType,
541 std::forward<Callback>(callback));
542 break;
543 default:
544 callback(
545 propertyId,
546 PropertyAttributePropertyView<uint8_t>(
548 break;
549 }
550 }
551
552 template <typename Callback, glm::length_t N, bool Normalized>
553 void getMatNPropertyViewImpl(
554 const MeshPrimitive& primitive,
555 const std::string& propertyId,
556 const ClassProperty& classProperty,
557 PropertyComponentType componentType,
558 Callback&& callback) const {
559 switch (componentType) {
561 callback(
562 propertyId,
563 getPropertyViewImpl<glm::mat<N, N, int8_t>, Normalized>(
564 primitive,
565 propertyId,
566 classProperty));
567 break;
569 callback(
570 propertyId,
571 getPropertyViewImpl<glm::mat<N, N, uint8_t>, Normalized>(
572 primitive,
573 propertyId,
574 classProperty));
575 break;
577 callback(
578 propertyId,
579 getPropertyViewImpl<glm::mat<N, N, int16_t>, Normalized>(
580 primitive,
581 propertyId,
582 classProperty));
583 break;
585 callback(
586 propertyId,
587 getPropertyViewImpl<glm::mat<N, N, uint16_t>, Normalized>(
588 primitive,
589 propertyId,
590 classProperty));
591 break;
593 callback(
594 propertyId,
595 getPropertyViewImpl<glm::mat<N, N, float>, false>(
596 primitive,
597 propertyId,
598 classProperty));
599 break;
600 default:
601 callback(
602 propertyId,
603 PropertyAttributePropertyView<uint8_t>(
605 break;
606 }
607 }
608
609 template <typename Callback, bool Normalized>
610 void getMatNPropertyViewImpl(
611 const MeshPrimitive& primitive,
612 const std::string& propertyId,
613 const ClassProperty& classProperty,
614 PropertyType type,
615 PropertyComponentType componentType,
616 Callback&& callback) const {
617 glm::length_t N = getDimensionsFromPropertyType(type);
618 switch (N) {
619 case 2:
620 getMatNPropertyViewImpl<Callback, 2, Normalized>(
621 primitive,
622 propertyId,
623 classProperty,
624 componentType,
625 std::forward<Callback>(callback));
626 break;
627 case 3:
628 getMatNPropertyViewImpl<Callback, 3, Normalized>(
629 primitive,
630 propertyId,
631 classProperty,
632 componentType,
633 std::forward<Callback>(callback));
634 break;
635 case 4:
636 getMatNPropertyViewImpl<Callback, 4, Normalized>(
637 primitive,
638 propertyId,
639 classProperty,
640 componentType,
641 std::forward<Callback>(callback));
642 break;
643 default:
644 callback(
645 propertyId,
646 PropertyAttributePropertyView<uint8_t>(
648 break;
649 }
650 }
651
652 template <typename T, bool Normalized>
653 PropertyAttributePropertyView<T, Normalized> createPropertyView(
654 const MeshPrimitive& primitive,
655 const ClassProperty& classProperty,
656 const PropertyAttributeProperty& propertyAttributeProperty) const {
657 const PropertyType type = convertStringToPropertyType(classProperty.type);
658 if (TypeToPropertyType<T>::value != type) {
659 return PropertyAttributePropertyView<T, Normalized>(
661 }
662
663 const PropertyComponentType componentType =
665 classProperty.componentType.value_or(""));
666 if (TypeToPropertyType<T>::component != componentType) {
667 return PropertyAttributePropertyView<T, Normalized>(
669 }
670
671 if (classProperty.normalized != Normalized) {
672 return PropertyAttributePropertyView<T, Normalized>(
674 }
675
676 if (primitive.attributes.find(propertyAttributeProperty.attribute) ==
677 primitive.attributes.end()) {
678 return PropertyAttributePropertyView<T, Normalized>(
680 }
681
682 const Accessor* pAccessor = _pModel->getSafe<Accessor>(
683 &_pModel->accessors,
684 primitive.attributes.at(propertyAttributeProperty.attribute));
685 if (!pAccessor) {
686 return PropertyAttributePropertyView<T, Normalized>(
688 }
689
690 if (getAccessorTypeAsPropertyType(*pAccessor) != type) {
691 return PropertyAttributePropertyView<T, Normalized>(
693 }
694
696 componentType) {
697 return PropertyAttributePropertyView<T, Normalized>(
698 PropertyAttributePropertyViewStatus::
699 ErrorAccessorComponentTypeMismatch);
700 }
701
702 if (pAccessor->normalized != Normalized) {
703 return PropertyAttributePropertyView<T, Normalized>(
704 PropertyAttributePropertyViewStatus::
705 ErrorAccessorNormalizationMismatch);
706 }
707
708 AccessorView<T> accessorView = AccessorView<T>(*_pModel, *pAccessor);
709 if (accessorView.status() != AccessorViewStatus::Valid) {
710 switch (accessorView.status()) {
712 return PropertyAttributePropertyView<T, Normalized>(
715 return PropertyAttributePropertyView<T, Normalized>(
718 return PropertyAttributePropertyView<T, Normalized>(
721 return PropertyAttributePropertyView<T, Normalized>(
723 default:
724 return PropertyAttributePropertyView<T, Normalized>(
726 }
727 }
728
729 return PropertyAttributePropertyView<T, Normalized>(
730 propertyAttributeProperty,
731 classProperty,
732 accessorView);
733 }
734
735 const Model* _pModel;
736 const PropertyAttribute* _pPropertyAttribute;
737 const Class* _pClass;
738
740};
741
742} // namespace CesiumGltf
Indicates the status of a property attribute property view.
static const int ErrorInvalidBufferView
This property view uses an accessor that does not have a valid buffer view index.
static const int ErrorInvalidBuffer
This property view uses a buffer view that does not have a valid buffer index.
static const int ErrorInvalidAccessor
This property view's attribute does not have a valid accessor index.
static const int ErrorMissingAttribute
This property view was initialized with a primitive that does not contain the specified attribute.
static const int ErrorUnsupportedProperty
This property view is associated with a ClassProperty of an unsupported type.
static const int ErrorAccessorTypeMismatch
This property view's type does not match the type of the accessor it uses.
static const int ErrorInvalidPropertyAttribute
This property view was initialized from an invalid PropertyAttribute.
static const PropertyViewStatusType ErrorAccessorOutOfBounds
This property view uses an accessor that points outside the bounds of its target buffer view.
static const PropertyViewStatusType ErrorBufferViewOutOfBounds
This property view uses a buffer view that points outside the bounds of its target buffer.
A view of the data specified by a PropertyAttributeProperty.
A view on a PropertyAttribute.
PropertyAttributeView(const Model &model, const PropertyAttribute &propertyAttribute) noexcept
Construct a PropertyAttributeView.
const ClassProperty * getClassProperty(const std::string &propertyId) const
Finds the ClassProperty that describes the type information of the property with the specified id.
PropertyAttributeViewStatus status() const noexcept
Gets the status of this property attribute view.
PropertyAttributePropertyView< T, Normalized > getPropertyView(const MeshPrimitive &primitive, const std::string &propertyId) const
Gets a PropertyAttributePropertyView that views the data of a property stored in the PropertyAttribut...
const std::optional< std::string > & name() const noexcept
Gets the name of the property attribute being viewed. Returns std::nullopt if no name was specified.
void getPropertyView(const MeshPrimitive &primitive, const std::string &propertyId, Callback &&callback) const
Gets a PropertyAttributePropertyView through a callback that accepts a property id and a PropertyAttr...
void forEachProperty(const MeshPrimitive &primitive, Callback &&callback) const
Iterates over each property in the PropertyAttribute with a callback that accepts a property id and a...
const Class * getClass() const noexcept
Gets the Class that this property attribute conforms to.
static const PropertyViewStatusType ErrorTypeMismatch
This property view's type does not match what is specified in ClassProperty::type.
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 ErrorNormalizationMismatch
This property view's normalization differs from what is specified in ClassProperty::normalized.
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.
@ 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.
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.
PropertyAttributeViewStatus
Indicates the status of a property attribute view.
@ Valid
This property attribute view is valid and ready to use.
@ 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.
PropertyType getAccessorTypeAsPropertyType(const Accessor &accessor)
Attempts to obtain a PropertyType from the type field of the accessor.
@ BufferViewTooSmall
The accessor is too large to fit in its bufferView.
@ Valid
This accessor is valid and ready to use.
@ InvalidBufferViewIndex
The accessor's bufferView index does not refer to a valid bufferView.
@ InvalidBufferIndex
The accessor's bufferView's buffer index does not refer to a valid buffer.
@ BufferTooSmall
The accessor's bufferView is too large to fit in its buffer.
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.
PropertyComponentType getAccessorComponentTypeAsPropertyComponentType(const Accessor &accessor)
Attempts to obtain a PropertyComponentType from the componentType field of the accessor.
This class is not meant to be instantiated directly. Use Accessor instead.
Definition Accessor.h:12
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.
A class containing a set of properties.
Definition Class.h:17
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:38
Check if a C++ type can be represented as an array.
Check if a C++ type can be represented as a boolean property type.
Check if a C++ type can be represented as a string property type.
Geometry to be rendered with the given material.
std::unordered_map< std::string, int32_t > attributes
A plain JSON object, where each key corresponds to a mesh attribute semantic and each value is the in...
std::vector< CesiumGltf::Accessor > accessors
An array of accessors.
Definition ModelSpec.h:51
This class is not meant to be instantiated directly. Use Model instead.
Definition Model.h:14
static const T & getSafe(const std::vector< T > &items, int32_t index)
Safely gets the element with a given index, returning a default instance if the index is outside the ...
Definition Model.h:181
Properties conforming to a class, organized as property values stored in attributes.
std::optional< std::string > name
The name of the property attribute, e.g. for display purposes.
std::unordered_map< std::string, CesiumGltf::PropertyAttributeProperty > properties
A dictionary, where each key corresponds to a property ID in the class' properties dictionary and eac...