cesium-native 0.43.0
Loading...
Searching...
No Matches
PropertyTextureView.h
1#pragma once
2
3#include "CesiumGltf/Class.h"
4#include "CesiumGltf/ClassProperty.h"
5#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h"
6#include "CesiumGltf/Model.h"
7#include "CesiumGltf/PropertyTexture.h"
8#include "CesiumGltf/PropertyTexturePropertyView.h"
9#include "CesiumGltf/TextureView.h"
10
11namespace CesiumGltf {
41
51public:
60 const Model& model,
61 const PropertyTexture& propertyTexture) noexcept;
62
69 PropertyTextureViewStatus status() const noexcept { return this->_status; }
70
75 const std::optional<std::string>& name() const noexcept {
76 return _pPropertyTexture->name;
77 }
78
85 const Class* getClass() const noexcept { return _pClass; }
86
95 const ClassProperty* getClassProperty(const std::string& propertyId) const;
96
121 template <typename T, bool Normalized = false>
123 const std::string& propertyId,
124 const TextureViewOptions& propertyOptions = TextureViewOptions()) const {
125 if (this->_status != PropertyTextureViewStatus::Valid) {
128 }
129
130 const ClassProperty* pClassProperty = getClassProperty(propertyId);
131 if (!pClassProperty) {
134 }
135
136 return getPropertyViewImpl<T, Normalized>(
137 propertyId,
138 *pClassProperty,
139 propertyOptions);
140 }
141
163 template <typename Callback>
165 const std::string& propertyId,
166 Callback&& callback,
167 const TextureViewOptions& propertyOptions = TextureViewOptions()) const {
168 if (this->_status != PropertyTextureViewStatus::Valid) {
169 callback(
170 propertyId,
173 return;
174 }
175
176 const ClassProperty* pClassProperty = getClassProperty(propertyId);
177 if (!pClassProperty) {
178 callback(
179 propertyId,
182 return;
183 }
184
185 PropertyType type = convertStringToPropertyType(pClassProperty->type);
187 if (pClassProperty->componentType) {
188 componentType =
190 }
191
192 bool normalized = pClassProperty->normalized;
193 if (normalized && !isPropertyComponentTypeInteger(componentType)) {
194 // Only integer components may be normalized.
195 callback(
196 propertyId,
199 return;
200 }
201
202 if (pClassProperty->array) {
203 if (normalized) {
204 getArrayPropertyViewImpl<Callback, true>(
205 propertyId,
206 *pClassProperty,
207 type,
208 componentType,
209 std::forward<Callback>(callback),
210 propertyOptions);
211 } else {
212 getArrayPropertyViewImpl<Callback, false>(
213 propertyId,
214 *pClassProperty,
215 type,
216 componentType,
217 std::forward<Callback>(callback),
218 propertyOptions);
219 }
220 return;
221 }
222
223 if (type == PropertyType::Scalar) {
224 if (normalized) {
225 getScalarPropertyViewImpl<Callback, true>(
226 propertyId,
227 *pClassProperty,
228 componentType,
229 std::forward<Callback>(callback),
230 propertyOptions);
231 } else {
232 getScalarPropertyViewImpl<Callback, false>(
233 propertyId,
234 *pClassProperty,
235 componentType,
236 std::forward<Callback>(callback),
237 propertyOptions);
238 }
239 return;
240 }
241
242 if (isPropertyTypeVecN(type)) {
243 if (normalized) {
244 getVecNPropertyViewImpl<Callback, true>(
245 propertyId,
246 *pClassProperty,
247 type,
248 componentType,
249 std::forward<Callback>(callback),
250 propertyOptions);
251 } else {
252 getVecNPropertyViewImpl<Callback, false>(
253 propertyId,
254 *pClassProperty,
255 type,
256 componentType,
257 std::forward<Callback>(callback),
258 propertyOptions);
259 }
260 return;
261 }
262
263 callback(
264 propertyId,
267 return;
268 }
269
292 template <typename Callback>
294 Callback&& callback,
295 const TextureViewOptions& propertyOptions = TextureViewOptions()) const {
296 for (const auto& property : this->_pClass->properties) {
298 property.first,
299 std::forward<Callback>(callback),
300 propertyOptions);
301 }
302 }
303
304private:
305 template <typename T, bool Normalized>
307 const std::string& propertyId,
308 const ClassProperty& classProperty,
309 const TextureViewOptions& propertyOptions) const {
310 auto propertyTexturePropertyIter =
311 _pPropertyTexture->properties.find(propertyId);
312 if (propertyTexturePropertyIter == _pPropertyTexture->properties.end()) {
313 if (!classProperty.required && classProperty.defaultProperty) {
314 // If the property was omitted from the property texture, it is still
315 // technically valid if it specifies a default value. Create a view that
316 // just returns the default value.
317 return PropertyTexturePropertyView<T, Normalized>(classProperty);
318 }
319
320 return PropertyTexturePropertyView<T, Normalized>(
322 }
323
324 const PropertyTextureProperty& propertyTextureProperty =
325 propertyTexturePropertyIter->second;
326
327 if constexpr (IsMetadataScalar<T>::value) {
328 return createScalarPropertyView<T, Normalized>(
329 classProperty,
330 propertyTextureProperty,
331 propertyOptions);
332 }
333
334 if constexpr (IsMetadataVecN<T>::value) {
335 return createVecNPropertyView<T, Normalized>(
336 classProperty,
337 propertyTextureProperty,
338 propertyOptions);
339 }
340
341 if constexpr (IsMetadataArray<T>::value) {
342 return createArrayPropertyView<
344 Normalized>(classProperty, propertyTextureProperty, propertyOptions);
345 }
346 }
347
348 template <typename Callback, bool Normalized>
349 void getArrayPropertyViewImpl(
350 const std::string& propertyId,
351 const ClassProperty& classProperty,
352 PropertyType type,
353 PropertyComponentType componentType,
354 Callback&& callback,
355 const TextureViewOptions& propertyOptions) const {
356 // Only scalar arrays are supported.
357 if (type != PropertyType::Scalar) {
358 callback(
359 propertyId,
360 PropertyTexturePropertyView<uint8_t>(
362 return;
363 }
364
365 int64_t count = classProperty.count.value_or(0);
366 if (count <= 0 || count > 4) {
367 callback(
368 propertyId,
369 PropertyTexturePropertyView<uint8_t>(
371 return;
372 }
373
374 switch (componentType) {
376 callback(
377 propertyId,
378 getPropertyViewImpl<PropertyArrayView<int8_t>, Normalized>(
379 propertyId,
380 classProperty,
381 propertyOptions));
382 break;
384 callback(
385 propertyId,
386 getPropertyViewImpl<PropertyArrayView<uint8_t>, Normalized>(
387 propertyId,
388 classProperty,
389 propertyOptions));
390 break;
392 callback(
393 propertyId,
394 getPropertyViewImpl<PropertyArrayView<int16_t>, Normalized>(
395 propertyId,
396 classProperty,
397 propertyOptions));
398 break;
400 callback(
401 propertyId,
402 getPropertyViewImpl<PropertyArrayView<uint16_t>, Normalized>(
403 propertyId,
404 classProperty,
405 propertyOptions));
406 break;
407 default:
408 callback(
409 propertyId,
410 PropertyTexturePropertyView<uint8_t>(
412 break;
413 }
414 }
415
416 template <typename Callback, bool Normalized>
417 void getScalarPropertyViewImpl(
418 const std::string& propertyId,
419 const ClassProperty& classProperty,
420 PropertyComponentType componentType,
421 Callback&& callback,
422 const TextureViewOptions& propertyOptions) const {
423 switch (componentType) {
425 callback(
426 propertyId,
427 getPropertyViewImpl<int8_t, Normalized>(
428 propertyId,
429 classProperty,
430 propertyOptions));
431 return;
433 callback(
434 propertyId,
435 getPropertyViewImpl<uint8_t, Normalized>(
436 propertyId,
437 classProperty,
438 propertyOptions));
439 return;
441 callback(
442 propertyId,
443 getPropertyViewImpl<int16_t, Normalized>(
444 propertyId,
445 classProperty,
446 propertyOptions));
447 return;
449 callback(
450 propertyId,
451 getPropertyViewImpl<uint16_t, Normalized>(
452 propertyId,
453 classProperty,
454 propertyOptions));
455 break;
457 callback(
458 propertyId,
459 getPropertyViewImpl<int32_t, Normalized>(
460 propertyId,
461 classProperty,
462 propertyOptions));
463 break;
465 callback(
466 propertyId,
467 getPropertyViewImpl<uint32_t, Normalized>(
468 propertyId,
469 classProperty,
470 propertyOptions));
471 break;
473 callback(
474 propertyId,
475 getPropertyViewImpl<float, false>(
476 propertyId,
477 classProperty,
478 propertyOptions));
479 break;
480 default:
481 callback(
482 propertyId,
483 PropertyTexturePropertyView<uint8_t>(
485 break;
486 }
487 }
488
489 template <typename Callback, glm::length_t N, bool Normalized>
490 void getVecNPropertyViewImpl(
491 const std::string& propertyId,
492 const ClassProperty& classProperty,
493 PropertyComponentType componentType,
494 Callback&& callback,
495 const TextureViewOptions& propertyOptions) const {
496 switch (componentType) {
498 callback(
499 propertyId,
500 getPropertyViewImpl<glm::vec<N, int8_t>, Normalized>(
501 propertyId,
502 classProperty,
503 propertyOptions));
504 break;
506 callback(
507 propertyId,
508 getPropertyViewImpl<glm::vec<N, uint8_t>, Normalized>(
509 propertyId,
510 classProperty,
511 propertyOptions));
512 break;
514 if constexpr (N == 2) {
515 callback(
516 propertyId,
517 getPropertyViewImpl<glm::vec<N, int16_t>, Normalized>(
518 propertyId,
519 classProperty,
520 propertyOptions));
521 break;
522 }
523 [[fallthrough]];
525 if constexpr (N == 2) {
526 callback(
527 propertyId,
528 getPropertyViewImpl<glm::vec<N, uint16_t>, Normalized>(
529 propertyId,
530 classProperty,
531 propertyOptions));
532 break;
533 }
534 [[fallthrough]];
535 default:
536 callback(
537 propertyId,
538 PropertyTexturePropertyView<uint8_t>(
540 break;
541 }
542 }
543
544 template <typename Callback, bool Normalized>
545 void getVecNPropertyViewImpl(
546 const std::string& propertyId,
547 const ClassProperty& classProperty,
548 PropertyType type,
549 PropertyComponentType componentType,
550 Callback&& callback,
551 const TextureViewOptions& propertyOptions) const {
552 const glm::length_t N = getDimensionsFromPropertyType(type);
553 switch (N) {
554 case 2:
555 getVecNPropertyViewImpl<Callback, 2, Normalized>(
556 propertyId,
557 classProperty,
558 componentType,
559 std::forward<Callback>(callback),
560 propertyOptions);
561 break;
562 case 3:
563 getVecNPropertyViewImpl<Callback, 3, Normalized>(
564 propertyId,
565 classProperty,
566 componentType,
567 std::forward<Callback>(callback),
568 propertyOptions);
569 break;
570 case 4:
571 getVecNPropertyViewImpl<Callback, 4, Normalized>(
572 propertyId,
573 classProperty,
574 componentType,
575 std::forward<Callback>(callback),
576 propertyOptions);
577 break;
578 default:
579 callback(
580 propertyId,
581 PropertyTexturePropertyView<uint8_t>(
583 break;
584 }
585 }
586
587 template <typename T, bool Normalized>
588 PropertyTexturePropertyView<T, Normalized> createScalarPropertyView(
589 const ClassProperty& classProperty,
590 [[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty,
591 const TextureViewOptions& propertyOptions) const {
592 if (classProperty.array) {
593 return PropertyTexturePropertyView<T, Normalized>(
595 }
596
597 const PropertyType type = convertStringToPropertyType(classProperty.type);
598 if (TypeToPropertyType<T>::value != type) {
599 return PropertyTexturePropertyView<T, Normalized>(
601 }
602
603 const PropertyComponentType componentType =
605 classProperty.componentType.value_or(""));
606 if (TypeToPropertyType<T>::component != componentType) {
607 return PropertyTexturePropertyView<T, Normalized>(
609 }
610
611 if (classProperty.normalized != Normalized) {
612 return PropertyTexturePropertyView<T, Normalized>(
614 }
615
616 // Only up to four bytes of image data are supported.
617 if constexpr (sizeof(T) <= 4) {
618 return createPropertyViewImpl<T, Normalized>(
619 classProperty,
620 propertyTextureProperty,
621 sizeof(T),
622 propertyOptions);
623 } else {
624 return PropertyTexturePropertyView<T, Normalized>(
626 }
627 }
628
629 template <typename T, bool Normalized>
630 PropertyTexturePropertyView<T, Normalized> createVecNPropertyView(
631 const ClassProperty& classProperty,
632 [[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty,
633 [[maybe_unused]] const TextureViewOptions& propertyOptions) const {
634 if (classProperty.array) {
635 return PropertyTexturePropertyView<T, Normalized>(
637 }
638
639 const PropertyType type = convertStringToPropertyType(classProperty.type);
640 if (TypeToPropertyType<T>::value != type) {
641 return PropertyTexturePropertyView<T, Normalized>(
643 }
644
645 const PropertyComponentType componentType =
647 classProperty.componentType.value_or(""));
648 if (TypeToPropertyType<T>::component != componentType) {
649 return PropertyTexturePropertyView<T, Normalized>(
651 }
652
653 if (classProperty.normalized != Normalized) {
654 return PropertyTexturePropertyView<T, Normalized>(
656 }
657
658 // Only up to four bytes of image data are supported.
659 if constexpr (sizeof(T) <= 4) {
660 return createPropertyViewImpl<T, Normalized>(
661 classProperty,
662 propertyTextureProperty,
663 sizeof(T),
664 propertyOptions);
665 } else {
666 return PropertyTexturePropertyView<T, Normalized>(
668 }
669 }
670
671 template <typename T, bool Normalized>
672 PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>
673 createArrayPropertyView(
674 const ClassProperty& classProperty,
675 [[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty,
676 [[maybe_unused]] const TextureViewOptions& propertyOptions) const {
677 if (!classProperty.array) {
678 return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
680 }
681
682 const PropertyType type = convertStringToPropertyType(classProperty.type);
683 if (TypeToPropertyType<T>::value != type) {
684 return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
686 }
687
688 const PropertyComponentType componentType =
690 classProperty.componentType.value_or(""));
691 if (TypeToPropertyType<T>::component != componentType) {
692 return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
694 }
695
696 if (classProperty.normalized != Normalized) {
697 return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
699 }
700
701 // Only scalar arrays are supported. The scalar component type must not
702 // exceed two bytes.
703 if constexpr (IsMetadataScalar<T>::value && sizeof(T) <= 4) {
704 // Only up to four elements are supported.
705 int64_t count = classProperty.count.value_or(0);
706 if (count <= 0 || count > 4) {
707 return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
709 }
710
711 if (count * sizeof(T) > 4) {
712 return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
714 }
715
716 return createPropertyViewImpl<PropertyArrayView<T>, Normalized>(
717 classProperty,
718 propertyTextureProperty,
719 count * sizeof(T),
720 propertyOptions);
721 } else {
722 return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
724 }
725 }
726
727 template <typename T, bool Normalized>
728 PropertyTexturePropertyView<T, Normalized> createPropertyViewImpl(
729 const ClassProperty& classProperty,
730 const PropertyTextureProperty& propertyTextureProperty,
731 size_t elementSize,
732 const TextureViewOptions& propertyOptions) const {
733 int32_t samplerIndex;
734 int32_t imageIndex;
735
736 auto status =
737 getTextureSafe(propertyTextureProperty.index, samplerIndex, imageIndex);
738
740 return PropertyTexturePropertyView<T, Normalized>(status);
741 }
742
743 status = checkSampler(samplerIndex);
745 return PropertyTexturePropertyView<T, Normalized>(status);
746 }
747
748 status = checkImage(imageIndex);
750 return PropertyTexturePropertyView<T, Normalized>(status);
751 }
752
754 _pModel->images[imageIndex].pAsset;
755 const std::vector<int64_t>& channels = propertyTextureProperty.channels;
756
757 status = checkChannels(channels, *pImage);
759 return PropertyTexturePropertyView<T, Normalized>(status);
760 }
761
762 if (channels.size() * pImage->bytesPerChannel != elementSize) {
764 }
765
766 return PropertyTexturePropertyView<T, Normalized>(
767 propertyTextureProperty,
768 classProperty,
769 _pModel->samplers[samplerIndex],
770 *pImage,
771 propertyOptions);
772 }
773
774 PropertyViewStatusType getTextureSafe(
775 const int32_t textureIndex,
776 int32_t& samplerIndex,
777 int32_t& imageIndex) const noexcept;
778
780 checkSampler(const int32_t samplerIndex) const noexcept;
781
782 PropertyViewStatusType checkImage(const int32_t imageIndex) const noexcept;
783
784 PropertyViewStatusType checkChannels(
785 const std::vector<int64_t>& channels,
786 const ImageAsset& image) const noexcept;
787
788 const Model* _pModel;
789 const PropertyTexture* _pPropertyTexture;
790 const Class* _pClass;
791
793};
794} // namespace CesiumGltf
static const int ErrorUnsupportedProperty
This property view is associated with a ClassProperty of an unsupported type.
static const int ErrorChannelsAndTypeMismatch
The channels of this property texture property do not provide the exact number of bytes required by t...
static const int ErrorInvalidPropertyTexture
This property view was initialized from an invalid PropertyTexture.
A view of the data specified by a PropertyTextureProperty.
A view on a PropertyTexture.
PropertyTextureView(const Model &model, const PropertyTexture &propertyTexture) noexcept
Construct a PropertyTextureView.
PropertyTexturePropertyView< T, Normalized > getPropertyView(const std::string &propertyId, const TextureViewOptions &propertyOptions=TextureViewOptions()) const
Gets a PropertyTexturePropertyView that views the data of a property stored in the PropertyTexture.
PropertyTextureViewStatus status() const noexcept
Gets the status of this property texture view.
void forEachProperty(Callback &&callback, const TextureViewOptions &propertyOptions=TextureViewOptions()) const
Iterates over each property in the PropertyTexture with a callback that accepts a property id and a P...
void getPropertyView(const std::string &propertyId, Callback &&callback, const TextureViewOptions &propertyOptions=TextureViewOptions()) const
Gets a PropertyTexturePropertyView through a callback that accepts a property id and a PropertyTextur...
const ClassProperty * getClassProperty(const std::string &propertyId) const
Finds the ClassProperty that describes the type information of the property with the specified id.
const std::optional< std::string > & name() const noexcept
Gets the name of the property texture being viewed. Returns std::nullopt if no name was specified.
const Class * getClass() const noexcept
Gets the Class that this property texture conforms to.
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 ErrorComponentTypeMismatch
This property view's component type does not match what is specified in ClassProperty::componentType.
A smart pointer that calls addReference and releaseReference on the controlled object.
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.
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.
@ 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.
int32_t PropertyViewStatusType
The type used for fields of PropertyViewStatus.
PropertyTextureViewStatus
Indicates the status of a property texture view.
@ Valid
This property texture view is valid and ready to use.
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.
bool required
If required, the property must be present in every entity conforming to the class....
std::optional< CesiumUtility::JsonValue > defaultProperty
A default value to use when encountering a noData value or an omitted property. The value is given in...
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
void type
The component type of this metadata array.
std::vector< CesiumGltf::Sampler > samplers
An array of samplers.
Definition ModelSpec.h:116
std::vector< CesiumGltf::Image > images
An array of images.
Definition ModelSpec.h:90
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 textures.
std::optional< std::string > name
The name of the property texture, e.g. for display purposes.
std::unordered_map< std::string, CesiumGltf::PropertyTextureProperty > properties
A dictionary, where each key corresponds to a property ID in the class' properties dictionary and eac...
Describes options for constructing a view on a glTF texture.
Definition TextureView.h:18