初始提交: UE5.3项目基础框架

This commit is contained in:
2025-10-14 11:14:54 +08:00
commit 721d9fd98e
5334 changed files with 316782 additions and 0 deletions

View File

@ -0,0 +1,97 @@
#pragma once
#include "CesiumGltf/AccessorSpec.h"
#include "CesiumGltf/Library.h"
#include <cstdint>
namespace CesiumGltf {
struct Model;
/** @copydoc AccessorSpec */
struct CESIUMGLTF_API Accessor final : public AccessorSpec {
/**
* @brief Computes the number of components for a given accessor type.
*
* For example `CesiumGltf::Accessor::Type::SCALAR` has 1 component while
* `CesiumGltf::Accessor::Type::VEC4` has 4 components.
*
* @param type The accessor type.
* @return The number of components. Returns 0 if {@link Accessor::type} is
* not a valid enumeration value.
*/
static int8_t computeNumberOfComponents(const std::string& type) noexcept;
/**
* @brief Computes the number of bytes for a given accessor component type.
*
* For example `CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT` is 2
* bytes while `CesiumGltf::Accessor::ComponentType::FLOAT` is 4 bytes.
*
* @param componentType The accessor component type.
* @return The number of bytes for the component type. Returns 0 if
* {@link Accessor::componentType} is not a valid enumeration value.
*/
static int8_t computeByteSizeOfComponent(int32_t componentType) noexcept;
Accessor() = default;
/**
* @brief Computes the number of components for this accessor.
*
* For example if this accessor's {@link Accessor::type} is
* `CesiumGltf::Accessor::Type::SCALAR`, then it has 1 component, while if
* it's `CesiumGltf::Accessor::Type::VEC4` it has 4 components.
*
* @return The number of components in this accessor. Returns 0 if this
* accessor's {@link Accessor::type} does not have a valid enumeration value.
*/
int8_t computeNumberOfComponents() const noexcept;
/**
* @brief Computes the number of bytes for this accessor's component type.
*
* For example if this accessor's {@link Accessor::componentType} is
* `CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT`, then the component
* type is 2 bytes, while if it's `CesiumGltf::Accessor::ComponentType::FLOAT`
* then it is 4 bytes.
*
* @return The number of bytes for this accessor's component type. Returns 0
* if this accessor's {@link Accessor::componentType} does not have a valid
* enumeration value.
*/
int8_t computeByteSizeOfComponent() const noexcept;
/**
* @brief Computes the total number of bytes for this accessor in each vertex.
*
* This is computed by multiplying
* {@link Accessor::computeByteSizeOfComponent} by
* {@link Accessor::computeNumberOfComponents}.
*
* @return The total number of bytes for this accessor in each vertex. Returns
* 0 if this accessor's {@link Accessor::type} or
* {@link Accessor::componentType} does not have a valid enumeration
* value.
*/
int64_t computeBytesPerVertex() const noexcept;
/**
* @brief Computes this accessor's stride.
*
* The stride is the number of bytes between the same elements of successive
* vertices. The returned value will be at least as large as
* {@link Accessor::computeBytesPerVertex}, but maybe be larger if this
* accessor's data is interleaved with other accessors.
*
* The behavior is undefined if this accessor is not part of the given model.
*
* @param model The model that this accessor is a part of.
* @return The stride in bytes. Returns 0 if this accessor's
* {@link Accessor::type} or {@link Accessor::componentType} does not have
* a valid enumeration value, or if {@link Accessor::bufferView} does not
* refer to a valid {@link BufferView}.
*/
int64_t computeByteStride(const CesiumGltf::Model& model) const noexcept;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,60 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/AccessorSparseIndices.h>
#include <CesiumGltf/AccessorSparseValues.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief Sparse storage of accessor values that deviate from their
* initialization value.
*/
struct CESIUMGLTF_API AccessorSparse final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "AccessorSparse";
/**
* @brief Number of deviating accessor values stored in the sparse array.
*/
int64_t count = int64_t();
/**
* @brief An object pointing to a buffer view containing the indices of
* deviating accessor values. The number of indices is equal to `count`.
* Indices **MUST** strictly increase.
*/
CesiumGltf::AccessorSparseIndices indices;
/**
* @brief An object pointing to a buffer view containing the deviating
* accessor values.
*/
CesiumGltf::AccessorSparseValues values;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(AccessorSparse));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += this->indices.getSizeBytes() -
int64_t(sizeof(CesiumGltf::AccessorSparseIndices));
accum += this->values.getSizeBytes() -
int64_t(sizeof(CesiumGltf::AccessorSparseValues));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,73 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief An object pointing to a buffer view containing the indices of
* deviating accessor values. The number of indices is equal to
* `accessor.sparse.count`. Indices **MUST** strictly increase.
*/
struct CESIUMGLTF_API AccessorSparseIndices final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "AccessorSparseIndices";
/**
* @brief Known values for The indices data type.
*/
struct ComponentType {
/** @brief UNSIGNED_BYTE (`5121`) */
static constexpr int32_t UNSIGNED_BYTE = 5121;
/** @brief UNSIGNED_SHORT (`5123`) */
static constexpr int32_t UNSIGNED_SHORT = 5123;
/** @brief UNSIGNED_INT (`5125`) */
static constexpr int32_t UNSIGNED_INT = 5125;
};
/**
* @brief The index of the buffer view with sparse indices. The referenced
* buffer view **MUST NOT** have its `target` or `byteStride` properties
* defined. The buffer view and the optional `byteOffset` **MUST** be aligned
* to the `componentType` byte length.
*/
int32_t bufferView = -1;
/**
* @brief The offset relative to the start of the buffer view in bytes.
*/
int64_t byteOffset = 0;
/**
* @brief The indices data type.
*
* Known values are defined in {@link ComponentType}.
*
*/
int32_t componentType = ComponentType::UNSIGNED_BYTE;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(AccessorSparseIndices));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,52 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief An object pointing to a buffer view containing the deviating accessor
* values. The number of elements is equal to `accessor.sparse.count` times
* number of components. The elements have the same component type as the base
* accessor. The elements are tightly packed. Data **MUST** be aligned following
* the same rules as the base accessor.
*/
struct CESIUMGLTF_API AccessorSparseValues final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "AccessorSparseValues";
/**
* @brief The index of the bufferView with sparse values. The referenced
* buffer view **MUST NOT** have its `target` or `byteStride` properties
* defined.
*/
int32_t bufferView = -1;
/**
* @brief The offset relative to the start of the bufferView in bytes.
*/
int64_t byteOffset = 0;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(AccessorSparseValues));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,204 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/AccessorSparse.h>
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace CesiumGltf {
/**
* @brief A typed view into a buffer view that contains raw binary data.
*/
struct CESIUMGLTF_API AccessorSpec : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Accessor";
/**
* @brief Known values for The datatype of the accessor's components.
*/
struct ComponentType {
/** @brief BYTE (`5120`) */
static constexpr int32_t BYTE = 5120;
/** @brief UNSIGNED_BYTE (`5121`) */
static constexpr int32_t UNSIGNED_BYTE = 5121;
/** @brief SHORT (`5122`) */
static constexpr int32_t SHORT = 5122;
/** @brief UNSIGNED_SHORT (`5123`) */
static constexpr int32_t UNSIGNED_SHORT = 5123;
/** @brief INT (`5124`) */
static constexpr int32_t INT = 5124;
/** @brief UNSIGNED_INT (`5125`) */
static constexpr int32_t UNSIGNED_INT = 5125;
/** @brief INT64 (`5134`) */
static constexpr int32_t INT64 = 5134;
/** @brief UNSIGNED_INT64 (`5135`) */
static constexpr int32_t UNSIGNED_INT64 = 5135;
/** @brief FLOAT (`5126`) */
static constexpr int32_t FLOAT = 5126;
/** @brief DOUBLE (`5130`) */
static constexpr int32_t DOUBLE = 5130;
};
/**
* @brief Known values for Specifies if the accessor's elements are scalars,
* vectors, or matrices.
*/
struct Type {
/** @brief `SCALAR` */
inline static const std::string SCALAR = "SCALAR";
/** @brief `VEC2` */
inline static const std::string VEC2 = "VEC2";
/** @brief `VEC3` */
inline static const std::string VEC3 = "VEC3";
/** @brief `VEC4` */
inline static const std::string VEC4 = "VEC4";
/** @brief `MAT2` */
inline static const std::string MAT2 = "MAT2";
/** @brief `MAT3` */
inline static const std::string MAT3 = "MAT3";
/** @brief `MAT4` */
inline static const std::string MAT4 = "MAT4";
};
/**
* @brief The index of the bufferView.
*
* The index of the buffer view. When undefined, the accessor **MUST** be
* initialized with zeros; `sparse` property or extensions **MAY** override
* zeros with actual values.
*/
int32_t bufferView = -1;
/**
* @brief The offset relative to the start of the buffer view in bytes.
*
* This **MUST** be a multiple of the size of the component datatype. This
* property **MUST NOT** be defined when `bufferView` is undefined.
*/
int64_t byteOffset = 0;
/**
* @brief The datatype of the accessor's components.
*
* Known values are defined in {@link ComponentType}.
*
*
* UNSIGNED_INT type **MUST NOT** be used for any accessor that is not
* referenced by `mesh.primitive.indices`.
*/
int32_t componentType = ComponentType::BYTE;
/**
* @brief Specifies whether integer data values are normalized before usage.
*
* Specifies whether integer data values are normalized (`true`) to [0, 1]
* (for unsigned types) or to [-1, 1] (for signed types) when they are
* accessed. This property **MUST NOT** be set to `true` for accessors with
* `FLOAT` or `UNSIGNED_INT` component type.
*/
bool normalized = false;
/**
* @brief The number of elements referenced by this accessor.
*
* The number of elements referenced by this accessor, not to be confused with
* the number of bytes or number of components.
*/
int64_t count = int64_t();
/**
* @brief Specifies if the accessor's elements are scalars, vectors, or
* matrices.
*
* Known values are defined in {@link Type}.
*
*/
std::string type = Type::SCALAR;
/**
* @brief Maximum value of each component in this accessor.
*
* Array elements **MUST** be treated as having the same data type as
* accessor's `componentType`. Both `min` and `max` arrays have the same
* length. The length is determined by the value of the `type` property; it
* can be 1, 2, 3, 4, 9, or 16.
*
* `normalized` property has no effect on array values: they always correspond
* to the actual values stored in the buffer. When the accessor is sparse,
* this property **MUST** contain maximum values of accessor data with sparse
* substitution applied.
*/
std::vector<double> max;
/**
* @brief Minimum value of each component in this accessor.
*
* Array elements **MUST** be treated as having the same data type as
* accessor's `componentType`. Both `min` and `max` arrays have the same
* length. The length is determined by the value of the `type` property; it
* can be 1, 2, 3, 4, 9, or 16.
*
* `normalized` property has no effect on array values: they always correspond
* to the actual values stored in the buffer. When the accessor is sparse,
* this property **MUST** contain minimum values of accessor data with sparse
* substitution applied.
*/
std::vector<double> min;
/**
* @brief Sparse storage of elements that deviate from their initialization
* value.
*/
std::optional<CesiumGltf::AccessorSparse> sparse;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(AccessorSpec));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
accum += int64_t(sizeof(double) * this->max.capacity());
accum += int64_t(sizeof(double) * this->min.capacity());
if (this->sparse) {
accum += this->sparse->getSizeBytes() -
int64_t(sizeof(CesiumGltf::AccessorSparse));
}
return accum;
}
protected:
/**
* @brief This class is not meant to be instantiated directly. Use {@link Accessor} instead.
*/
AccessorSpec() = default;
friend struct Accessor;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,399 @@
#pragma once
#include "AccessorView.h"
#include <CesiumGltf/MeshPrimitive.h>
#include <glm/common.hpp>
#include <array>
#include <variant>
namespace CesiumGltf {
/**
* @brief Visitor that retrieves the count of elements in the given accessor
* type as an int64_t.
*/
struct CountFromAccessor {
/** @brief Attempts to obtain an element count from an empty accessor variant,
* resulting in 0. */
int64_t operator()(std::monostate) { return 0; }
/** @brief Attempts to obtain an element count from an \ref AccessorView. */
template <typename T> int64_t operator()(const AccessorView<T>& value) {
return value.size();
}
};
/**
* @brief Visitor that retrieves the status from the given accessor. Returns an
* invalid status for a std::monostate (interpreted as a nonexistent accessor).
*/
struct StatusFromAccessor {
/** @brief Attempts to obtain an \ref AccessorViewStatus from an empty
* accessor variant, resulting in \ref
* AccessorViewStatus::InvalidAccessorIndex. */
AccessorViewStatus operator()(std::monostate) {
return AccessorViewStatus::InvalidAccessorIndex;
}
/** @brief Attempts to obtain an \ref AccessorViewStatus from an \ref
* AccessorView. */
template <typename T>
AccessorViewStatus operator()(const AccessorView<T>& value) {
return value.status();
}
};
/**
* Type definition for position accessor.
*/
typedef AccessorView<AccessorTypes::VEC3<float>> PositionAccessorType;
/**
* Retrieves an accessor view for the position attribute from the given glTF
* primitive and model. This verifies that the accessor is of a valid type. If
* not, the returned accessor view will be invalid.
*/
PositionAccessorType
getPositionAccessorView(const Model& model, const MeshPrimitive& primitive);
/**
* Type definition for normal accessor.
*/
typedef AccessorView<AccessorTypes::VEC3<float>> NormalAccessorType;
/**
* Retrieves an accessor view for the normal attribute from the given glTF
* primitive and model. This verifies that the accessor is of a valid type. If
* not, the returned accessor view will be invalid.
*/
NormalAccessorType
getNormalAccessorView(const Model& model, const MeshPrimitive& primitive);
/**
* Type definition for all kinds of feature ID attribute accessors.
*/
typedef std::variant<
AccessorView<int8_t>,
AccessorView<uint8_t>,
AccessorView<int16_t>,
AccessorView<uint16_t>,
AccessorView<uint32_t>,
AccessorView<float>>
FeatureIdAccessorType;
/**
* Retrieves an accessor view for the specified feature ID attribute from the
* given glTF primitive and model. This verifies that the accessor is of a valid
* type. If not, the returned accessor view will be invalid.
*/
FeatureIdAccessorType getFeatureIdAccessorView(
const Model& model,
const MeshPrimitive& primitive,
int32_t featureIdAttributeIndex);
/**
* Retrieves an accessor view for the specified feature ID attribute from the
* given glTF node and model, if the node contains an EXT_mesh_gpu_instancing
* property. This verifies that the accessor is of a valid type. If not, the
* returned accessor view will be invalid.
*/
FeatureIdAccessorType getFeatureIdAccessorView(
const Model& model,
const Node& node,
int32_t featureIdAttributeIndex);
/**
* Visitor that retrieves the feature ID from the given accessor type as an
* int64_t. This should be initialized with the index of the vertex whose
* feature ID is being queried.
*
* -1 is used to indicate errors retrieving the feature ID, e.g., if the given
* index was out-of-bounds.
*/
struct FeatureIdFromAccessor {
/** @brief Attempts to obtain a feature ID from an \ref AccessorView over
* float values, returning the float value rounded to the nearest `int64_t`.
*/
int64_t operator()(const AccessorView<float>& value) {
if (index < 0 || index >= value.size()) {
return -1;
}
return static_cast<int64_t>(glm::round(value[index]));
}
/** @brief Attempts to obtain a feature ID from an \ref AccessorView. */
template <typename T> int64_t operator()(const AccessorView<T>& value) {
if (index < 0 || index >= value.size()) {
return -1;
}
return static_cast<int64_t>(value[index]);
}
/** @brief The index of the vertex whose feature ID is being queried. */
int64_t index;
};
/**
* Type definition for all kinds of index accessors. std::monostate
* indicates a nonexistent accessor, which can happen (and is valid) if the
* primitive vertices are defined without an index buffer.
*/
typedef std::variant<
std::monostate,
AccessorView<uint8_t>,
AccessorView<uint16_t>,
AccessorView<uint32_t>>
IndexAccessorType;
/**
* Retrieves an accessor view for the indices of the given glTF primitive from
* the model. The primitive may not specify any indices; if so, std::monostate
* is returned.
*/
IndexAccessorType
getIndexAccessorView(const Model& model, const MeshPrimitive& primitive);
/**
* Visitor that retrieves the vertex indices from the given accessor type
* corresponding to a given face index. These indices are returned as an array
* of int64_ts. This should be initialized with the index of the face, the
* total number of vertices in the primitive, and the
* `CesiumGltf::MeshPrimitive::Mode` of the primitive.
*
* -1 is used to indicate errors retrieving the index, e.g., if the given
* index was out-of-bounds.
*/
struct IndicesForFaceFromAccessor {
/** @brief Attempts to obtain the indices for the given face from an empty
* accessor variant, using the \ref vertexCount property. */
std::array<int64_t, 3> operator()(std::monostate) {
int64_t firstVertex = faceIndex;
int64_t numFaces = 0;
switch (primitiveMode) {
case MeshPrimitive::Mode::TRIANGLE_STRIP:
numFaces = vertexCount - 2;
break;
case MeshPrimitive::Mode::TRIANGLE_FAN:
numFaces = vertexCount - 2;
firstVertex++;
break;
case MeshPrimitive::Mode::TRIANGLES:
numFaces = vertexCount / 3;
firstVertex *= 3;
break;
default:
// Unsupported primitive mode.
return {-1, -1, -1};
}
if (faceIndex < 0 || faceIndex >= numFaces) {
return {-1, -1, -1};
}
std::array<int64_t, 3> result;
if (primitiveMode == MeshPrimitive::Mode::TRIANGLE_FAN) {
result[0] = 0;
result[1] = firstVertex < vertexCount ? firstVertex : -1;
result[2] = firstVertex + 1 < vertexCount ? firstVertex + 1 : -1;
} else {
for (int64_t i = 0; i < 3; i++) {
int64_t vertexIndex = firstVertex + i;
result[i] = vertexIndex < vertexCount ? vertexIndex : -1;
}
}
return result;
}
/** @brief Attempts to obtain the indices for the given face from an \ref
* AccessorView, using the view's size and contents rather than the \ref
* vertexCount property. */
template <typename T>
std::array<int64_t, 3> operator()(const AccessorView<T>& value) {
int64_t firstIndex = faceIndex;
int64_t numFaces = 0;
switch (primitiveMode) {
case MeshPrimitive::Mode::TRIANGLE_STRIP:
numFaces = value.size() - 2;
break;
case MeshPrimitive::Mode::TRIANGLE_FAN:
numFaces = value.size() - 2;
firstIndex++;
break;
case MeshPrimitive::Mode::TRIANGLES:
numFaces = value.size() / 3;
firstIndex *= 3;
break;
default:
// Unsupported primitive mode.
return {-1, -1, -1};
}
if (faceIndex < 0 || faceIndex >= numFaces) {
return {-1, -1, -1};
}
std::array<int64_t, 3> result;
if (primitiveMode == MeshPrimitive::Mode::TRIANGLE_FAN) {
result[0] = value[0];
result[1] = firstIndex < value.size() ? value[firstIndex] : -1;
result[2] = firstIndex + 1 < value.size() ? value[firstIndex + 1] : -1;
} else {
for (int64_t i = 0; i < 3; i++) {
int64_t index = firstIndex + i;
result[i] = index < value.size() ? value[index] : -1;
}
}
return result;
}
/** @brief The index of the face to obtain indices for. */
int64_t faceIndex;
/** @brief The total number of vertices in the data being accessed. */
int64_t vertexCount;
/** @brief The \ref MeshPrimitive::Mode of the data being accessed. */
int32_t primitiveMode;
}; // namespace CesiumGltf
/**
* Visitor that retrieves the vertex index from the given accessor type as an
* int64_t. This should be initialized with the index (within the
* accessor itself) of the vertex index.
*
* -1 is used to indicate errors retrieving the index, e.g., if the given
* index was out-of-bounds.
*/
struct IndexFromAccessor {
/** @brief Attempts to obtain a vertex index from an empty \ref
* IndexAccessorType, resulting in -1. */
int64_t operator()(std::monostate) { return -1; }
/** @brief Attempts to obtain a vertex index from an \ref
* CesiumGltf::AccessorView. */
template <typename T>
int64_t operator()(const CesiumGltf::AccessorView<T>& value) {
if (index < 0 || index >= value.size()) {
return -1;
}
return value[index];
}
/** @brief The index of the vertex index within the accessor itself. */
int64_t index;
};
/**
* Type definition for all kinds of texture coordinate (TEXCOORD_n) accessors.
*/
typedef std::variant<
AccessorView<AccessorTypes::VEC2<uint8_t>>,
AccessorView<AccessorTypes::VEC2<uint16_t>>,
AccessorView<AccessorTypes::VEC2<float>>>
TexCoordAccessorType;
/**
* Retrieves an accessor view for the specified texture coordinate set from
* the given glTF primitive and model. This verifies that the accessor is of a
* valid type. If not, the returned accessor view will be invalid.,
*/
TexCoordAccessorType getTexCoordAccessorView(
const Model& model,
const MeshPrimitive& primitive,
int32_t textureCoordinateSetIndex);
/**
* Visitor that retrieves the texture coordinates from the given accessor type
* as a glm::dvec2. This should be initialized with the target index.
*
* There are technically no invalid UV values because of clamp / wrap
* behavior, so we use std::nullopt to denote an erroneous value.
*/
struct TexCoordFromAccessor {
/**
* @brief Attempts to obtain a `glm::dvec2` at the given index from an
* accessor over a vec2 of floats. If the index is invalid, `std::nullopt` is
* returned instead.
*/
std::optional<glm::dvec2>
operator()(const AccessorView<AccessorTypes::VEC2<float>>& value) {
if (index < 0 || index >= value.size()) {
return std::nullopt;
}
return glm::dvec2(value[index].value[0], value[index].value[1]);
}
/**
* @brief Attempts to obtain a `glm::dvec2` at the given index from an
* accessor over a vec2. The values will be cast to `double` and normalized
* based on `std::numeric_limits<T>::max()`. If the index is invalid,
* `std::nullopt` is returned instead.
*/
template <typename T>
std::optional<glm::dvec2>
operator()(const AccessorView<AccessorTypes::VEC2<T>>& value) {
if (index < 0 || index >= value.size()) {
return std::nullopt;
}
double u = static_cast<double>(value[index].value[0]);
double v = static_cast<double>(value[index].value[1]);
// TODO: do normalization logic in accessor view?
u /= std::numeric_limits<T>::max();
v /= std::numeric_limits<T>::max();
return glm::dvec2(u, v);
}
/** @brief The index of texcoords to obtain. */
int64_t index;
};
/**
* @brief Type definition for quaternion accessors, as used in
* ExtMeshGpuInstancing rotations and animation samplers.
*/
typedef std::variant<
AccessorView<AccessorTypes::VEC4<uint8_t>>,
AccessorView<AccessorTypes::VEC4<int8_t>>,
AccessorView<AccessorTypes::VEC4<uint16_t>>,
AccessorView<AccessorTypes::VEC4<int16_t>>,
AccessorView<AccessorTypes::VEC4<float>>>
QuaternionAccessorType;
/**
* @brief Obtains a \ref QuaternionAccessorType from the given \ref Accessor on
* the given \ref Model.
*
* @param model The model containing the quaternion.
* @param accessor An accessor from which the quaternion will be obtained.
* @returns A quaternion from the data in `accessor`. If no quaternion could be
* obtained, the default value for \ref QuaternionAccessorType will be returned
* instead.
*/
QuaternionAccessorType
getQuaternionAccessorView(const Model& model, const Accessor* accessor);
/**
* @brief Obtains a \ref QuaternionAccessorType from the given \ref Accessor on
* the given \ref Model.
*
* @param model The model containing the quaternion.
* @param accessorIndex An index to the accessor from which the quaternion will
* be obtained.
* @returns A quaternion from the data in the accessor at `accessorIndex`. If no
* quaternion could be obtained, the default value for \ref
* QuaternionAccessorType will be returned instead.
*/
QuaternionAccessorType
getQuaternionAccessorView(const Model& model, int32_t accessorIndex);
} // namespace CesiumGltf

View File

@ -0,0 +1,538 @@
#pragma once
#include "CesiumGltf/Accessor.h"
#include "CesiumGltf/Model.h"
#include <cstddef>
#include <stdexcept>
namespace CesiumGltf {
/**
* @brief Indicates the status of an accessor view.
*
* The {@link AccessorView} constructor always completes successfully. However,
* it may not always reflect the actual content of the {@link Accessor}, but
* instead indicate that its {@link AccessorView::size} is 0. This enumeration
* provides the reason.
*/
enum class AccessorViewStatus {
/**
* @brief This accessor is valid and ready to use.
*/
Valid,
/**
* @brief The accessor index does not refer to a valid accessor.
*/
InvalidAccessorIndex,
/**
* @brief The accessor's bufferView index does not refer to a valid
* bufferView.
*/
InvalidBufferViewIndex,
/**
* @brief The accessor's bufferView's buffer index does not refer to a valid
* buffer.
*/
InvalidBufferIndex,
/**
* @brief The accessor is too large to fit in its bufferView.
*/
BufferViewTooSmall,
/**
* @brief The accessor's bufferView is too large to fit in its buffer.
*/
BufferTooSmall,
/**
* @brief The `sizeof(T)` does not match the accessor's
* {@link Accessor::computeBytesPerVertex}.
*/
WrongSizeT,
/**
* @brief The `AccessorSpec:type` is invalid.
*/
InvalidType,
/**
* @brief The {@link AccessorSpec::componentType} is invalid.
*/
InvalidComponentType,
/**
* @brief The {@link BufferView::byteStride} is negative, which is invalid.
*
*/
InvalidByteStride,
};
/**
* @brief A view on the data of one accessor of a glTF asset.
*
* It provides the actual accessor data like an array of elements.
* The type of the accessor elements is determined by the template
* parameter. Instances are usually from an {@link Accessor},
* and the {@link operator[]()} can be used to access the elements:
*
* @snippet TestAccessorView.cpp createFromAccessorAndRead
*
* @tparam T The type of the elements in the accessor.
*/
template <class T> class AccessorView final {
private:
const std::byte* _pData;
int64_t _stride;
int64_t _offset;
int64_t _size;
AccessorViewStatus _status;
public:
/**
* @brief The type of the elements in the accessor.
*/
typedef T value_type;
/**
* @brief Construct a new instance not pointing to any data.
*
* The new instance will have a {@link size} of 0 and a {@link status} of
* `AccessorViewStatus::InvalidAccessorIndex`.
*
* @param status The status of the new accessor. Defaults to
* {@link AccessorViewStatus::InvalidAccessorIndex}.
*/
AccessorView(
AccessorViewStatus status = AccessorViewStatus::InvalidAccessorIndex)
: _pData(nullptr), _stride(0), _offset(0), _size(0), _status(status) {}
/**
* @brief Creates a new instance from low-level parameters.
*
* The provided parameters are not validated in any way, and so this overload
* can easily be used to access invalid memory.
*
* @param pData The raw data buffer from which to read.
* @param stride The stride, in bytes, between successive elements.
* @param offset The offset from the start of the buffer to the first element.
* @param size The total number of elements.
*/
AccessorView(
const std::byte* pData,
int64_t stride,
int64_t offset,
int64_t size)
: _pData(pData),
_stride(stride),
_offset(offset),
_size(size),
_status(AccessorViewStatus::Valid) {}
/**
* @brief Creates a new instance from a given model and {@link Accessor}.
*
* If the accessor cannot be viewed, the construct will still complete
* successfully without throwing an exception. However, {@link size} will
* return 0 and
* {@link status} will indicate what went wrong.
*
* @param model The model to access.
* @param accessor The accessor to view.
*/
AccessorView(const Model& model, const Accessor& accessor) noexcept
: AccessorView() {
this->create(model, accessor);
}
/**
* @brief Creates a new instance from a given model and accessor index.
*
* If the accessor cannot be viewed, the construct will still complete
* successfully without throwing an exception. However, {@link size} will
* return 0 and
* {@link status} will indicate what went wrong.
*
* @param model The model to access.
* @param accessorIndex The index of the accessor to view in the model's
* {@link Model::accessors} list.
*/
AccessorView(const Model& model, int32_t accessorIndex) noexcept
: AccessorView() {
const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex);
if (!pAccessor) {
this->_status = AccessorViewStatus::InvalidAccessorIndex;
return;
}
this->create(model, *pAccessor);
}
/**
* @brief Provides the specified accessor element.
*
* @param i The index of the element.
* @returns The constant reference to the accessor element.
* @throws A `std::range_error` if the given index is negative
* or not smaller than the {@link size} of this accessor.
*/
const T& operator[](int64_t i) const {
if (i < 0 || i >= this->_size) {
throw std::range_error("index out of range");
}
return *reinterpret_cast<const T*>(
this->_pData + i * this->_stride + this->_offset);
}
/**
* @brief Returns the size (number of elements) of this accessor.
*
* This is the number of elements of type `T` that this accessor contains.
*
* @returns The size.
*/
int64_t size() const noexcept { return this->_size; }
/**
* @brief Gets the status of this accessor view.
*
* Indicates whether the view accurately reflects the accessor's data, or
* whether an error occurred.
*/
AccessorViewStatus status() const noexcept { return this->_status; }
/**
* @brief Returns the stride of this accessor, which is the number of bytes
* from the start of one element to the start of the next.
*
* @returns The stride.
*/
int64_t stride() const noexcept { return this->_stride; }
/**
* @brief Returns the offset of this accessor, which is the number of bytes
* from the start of the buffer to the first element.
*
* @returns The offset.
*/
int64_t offset() const noexcept { return this->_offset; }
/**
* @brief Returns a pointer to the first byte of this accessor view's data.
* The elements are stored contiguously, so the next one starts {@link stride} bytes later.
*
* @returns The start of this view.
*/
const std::byte* data() const noexcept {
return this->_pData + this->_offset;
}
private:
void create(const Model& model, const Accessor& accessor) noexcept {
const CesiumGltf::BufferView* pBufferView =
Model::getSafe(&model.bufferViews, accessor.bufferView);
if (!pBufferView) {
this->_status = AccessorViewStatus::InvalidBufferViewIndex;
return;
}
const CesiumGltf::Buffer* pBuffer =
Model::getSafe(&model.buffers, pBufferView->buffer);
if (!pBuffer) {
this->_status = AccessorViewStatus::InvalidBufferIndex;
return;
}
const std::vector<std::byte>& data = pBuffer->cesium.data;
const int64_t bufferBytes = int64_t(data.size());
if (pBufferView->byteOffset + pBufferView->byteLength > bufferBytes) {
this->_status = AccessorViewStatus::BufferTooSmall;
return;
}
const int64_t accessorByteStride = accessor.computeByteStride(model);
if (accessorByteStride < 0) {
this->_status = AccessorViewStatus::InvalidByteStride;
return;
}
const int64_t accessorComponentElements =
accessor.computeNumberOfComponents();
const int64_t accessorComponentBytes =
accessor.computeByteSizeOfComponent();
const int64_t accessorBytesPerStride =
accessorComponentElements * accessorComponentBytes;
if (sizeof(T) != accessorBytesPerStride) {
this->_status = AccessorViewStatus::WrongSizeT;
return;
}
const int64_t accessorBytes = accessorByteStride * accessor.count;
const int64_t bytesRemainingInBufferView =
pBufferView->byteLength -
(accessor.byteOffset + accessorByteStride * (accessor.count - 1) +
accessorBytesPerStride);
if (accessorBytes > pBufferView->byteLength ||
bytesRemainingInBufferView < 0) {
this->_status = AccessorViewStatus::BufferViewTooSmall;
return;
}
this->_pData = pBuffer->cesium.data.data();
this->_stride = accessorByteStride;
this->_offset = accessor.byteOffset + pBufferView->byteOffset;
this->_size = accessor.count;
this->_status = AccessorViewStatus::Valid;
}
};
/**
* @brief Contains types that may optionally be used with {@link AccessorView}
* for various {@link Accessor::componentType} values.
*/
struct AccessorTypes {
#pragma pack(push, 1)
/**
* @brief A scalar element for an {@link AccessorView}.
*
* @tparam T The component type.
*/
template <typename T> struct SCALAR {
/**
* @brief The component values of this element.
*/
T value[1];
};
/**
* @brief A 2D vector element for an {@link AccessorView}.
*
* @tparam T The component type.
*/
template <typename T> struct VEC2 {
/**
* @brief The component values of this element.
*/
T value[2];
};
/**
* @brief A 3D vector element for an {@link AccessorView}.
*
* @tparam T The component type.
*/
template <typename T> struct VEC3 {
/**
* @brief The component values of this element.
*/
T value[3];
};
/**
* @brief A 4D vector element for an {@link AccessorView}.
*
* @tparam T The component type.
*/
template <typename T> struct VEC4 {
/**
* @brief The component values of this element.
*/
T value[4];
};
/**
* @brief A 2x2 matrix element for an {@link AccessorView}.
*
* @tparam T The component type.
*/
template <typename T> struct MAT2 {
/**
* @brief The component values of this element.
*/
T value[4];
};
/**
* @brief A 3x3 matrix element for an {@link AccessorView}.
*
* @tparam T The component type.
*/
template <typename T> struct MAT3 {
/**
* @brief The component values of this element.
*/
T value[9];
};
/**
* @brief A 4x4 matrix element for an {@link AccessorView}.
*
* @tparam T The component type.
*/
template <typename T> struct MAT4 {
/**
* @brief The component values of this element.
*/
T value[16];
};
#pragma pack(pop)
};
namespace CesiumImpl {
template <typename TCallback, typename TElement>
std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<TElement>>>
createAccessorView(
const Model& model,
const Accessor& accessor,
TCallback&& callback) {
if (accessor.type == Accessor::Type::SCALAR) {
return callback(
AccessorView<AccessorTypes::SCALAR<TElement>>(model, accessor));
}
if (accessor.type == Accessor::Type::VEC2) {
return callback(
AccessorView<AccessorTypes::VEC2<TElement>>(model, accessor));
}
if (accessor.type == Accessor::Type::VEC3) {
return callback(
AccessorView<AccessorTypes::VEC3<TElement>>(model, accessor));
}
if (accessor.type == Accessor::Type::VEC4) {
return callback(
AccessorView<AccessorTypes::VEC4<TElement>>(model, accessor));
}
if (accessor.type == Accessor::Type::MAT2) {
return callback(
AccessorView<AccessorTypes::MAT2<TElement>>(model, accessor));
}
if (accessor.type == Accessor::Type::MAT3) {
return callback(
AccessorView<AccessorTypes::MAT3<TElement>>(model, accessor));
}
if (accessor.type == Accessor::Type::MAT4) {
return callback(
AccessorView<AccessorTypes::MAT4<TElement>>(model, accessor));
}
// TODO Print a warning here???
return callback(AccessorView<AccessorTypes::SCALAR<TElement>>(
AccessorViewStatus::InvalidType));
}
} // namespace CesiumImpl
/**
* @brief Creates an appropriate {@link AccessorView} for a given accessor.
*
* The created accessor is provided via a callback, which is a function that can
* be invoked with all possible {@link AccessorView} types. If an accessor
* cannot be created, the callback will be invoked with
* `AccessorView<AccessorTypes::SCALAR<float>>` and the
* {@link AccessorView::status} will indicate the reason.
*
* @tparam TCallback The callback.
* @param model The model to access.
* @param accessor The accessor to view.
* @param callback The callback that receives the created accessor.
* @return The value returned by the callback.
*/
template <typename TCallback>
std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>>
createAccessorView(
const Model& model,
const Accessor& accessor,
TCallback&& callback) {
switch (accessor.componentType) {
case Accessor::ComponentType::BYTE:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int8_t>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::UNSIGNED_BYTE:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint8_t>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::SHORT:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int16_t>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::UNSIGNED_SHORT:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint16_t>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::INT:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int32_t>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::UNSIGNED_INT:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint32_t>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::INT64:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int64_t>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::UNSIGNED_INT64:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint64_t>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::FLOAT:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, float>(
model,
accessor,
std::forward<TCallback>(callback));
case Accessor::ComponentType::DOUBLE:
return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, double>(
model,
accessor,
std::forward<TCallback>(callback));
default:
return callback(AccessorView<AccessorTypes::SCALAR<float>>(
AccessorViewStatus::InvalidComponentType));
}
}
/**
* @brief Creates an appropriate {@link AccessorView} for a given accessor.
*
* The created accessor is provided via a callback, which is a function that can
* be invoked with all possible {@link AccessorView} types. If an accessor
* cannot be created, the callback will be invoked with
* `AccessorView<AccessorTypes::SCALAR<float>>` and the
* {@link AccessorView::status} will indicate the reason.
*
* @tparam TCallback The callback.
* @param model The model to access.
* @param accessorIndex The index of the accessor to view in
* {@link Model::accessors}.
* @param callback The callback that receives the created accessor.
* @return The value returned by the callback.
*/
template <typename TCallback>
std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>>
createAccessorView(
const Model& model,
int32_t accessorIndex,
TCallback&& callback) {
const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex);
if (!pAccessor) {
return callback(AccessorView<AccessorTypes::SCALAR<float>>(
AccessorViewStatus::InvalidComponentType));
}
return createAccessorView(model, *pAccessor, callback);
}
} // namespace CesiumGltf

View File

@ -0,0 +1,72 @@
#pragma once
#include "CesiumGltf/AccessorView.h"
namespace CesiumGltf {
/**
* @brief Provides write access to an {@link AccessorView}.
*/
template <class T> class AccessorWriter final {
private:
AccessorView<T> _accessor;
public:
/**
* @brief The type of the elements in the accessor.
*/
typedef T value_type;
AccessorWriter() : _accessor() {}
/**
* @brief Constructs a new instance from an {@link AccessorView}.
*/
AccessorWriter(const AccessorView<T>& accessorView)
: _accessor(accessorView) {}
/** @copydoc AccessorView::AccessorView(const std::byte*, int64_t, int64_t,
* int64_t) */
AccessorWriter(std::byte* pData, int64_t stride, int64_t offset, int64_t size)
: _accessor(pData, stride, offset, size) {}
/** @copydoc AccessorView::AccessorView(const Model&,const Accessor&) */
AccessorWriter(Model& model, const Accessor& accessor)
: _accessor(model, accessor) {}
/** @copydoc AccessorView::AccessorView(const Model&,int32_t) */
AccessorWriter(Model& model, int32_t accessorIndex) noexcept
: _accessor(model, accessorIndex) {}
/** @copydoc AccessorView::operator[]() */
const T& operator[](int64_t i) const { return this->_accessor[i]; }
/** @copydoc AccessorView::operator[]() */
T& operator[](int64_t i) { return const_cast<T&>(this->_accessor[i]); }
/** @copydoc AccessorView::size */
int64_t size() const noexcept { return this->_accessor.size(); }
/**
* @brief Gets the status of this accessor writer.
*
* Indicates whether the writer accurately reflects the accessor's data, or
* whether an error occurred.
*/
AccessorViewStatus status() const noexcept {
return this->_accessor.status();
}
/** @copydoc AccessorView::stride */
int64_t stride() const noexcept { return this->_accessor.stride(); }
/** @copydoc AccessorView::offset */
int64_t offset() const noexcept { return this->_accessor.offset(); }
/** @copydoc AccessorView::data */
std::byte* data() noexcept {
return const_cast<std::byte*>(this->_accessor.data());
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,62 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/AnimationChannel.h>
#include <CesiumGltf/AnimationSampler.h>
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <vector>
namespace CesiumGltf {
/**
* @brief A keyframe animation.
*/
struct CESIUMGLTF_API Animation final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Animation";
/**
* @brief An array of animation channels. An animation channel combines an
* animation sampler with a target property being animated. Different channels
* of the same animation **MUST NOT** have the same targets.
*/
std::vector<CesiumGltf::AnimationChannel> channels;
/**
* @brief An array of animation samplers. An animation sampler combines
* timestamps with a sequence of output values and defines an interpolation
* algorithm.
*/
std::vector<CesiumGltf::AnimationSampler> samplers;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Animation));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
accum += int64_t(
sizeof(CesiumGltf::AnimationChannel) * this->channels.capacity());
for (const CesiumGltf::AnimationChannel& value : this->channels) {
accum +=
value.getSizeBytes() - int64_t(sizeof(CesiumGltf::AnimationChannel));
}
accum += int64_t(
sizeof(CesiumGltf::AnimationSampler) * this->samplers.capacity());
for (const CesiumGltf::AnimationSampler& value : this->samplers) {
accum +=
value.getSizeBytes() - int64_t(sizeof(CesiumGltf::AnimationSampler));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,53 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/AnimationChannelTarget.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief An animation channel combines an animation sampler with a target
* property being animated.
*/
struct CESIUMGLTF_API AnimationChannel final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "AnimationChannel";
/**
* @brief The index of a sampler in this animation used to compute the value
* for the target.
*
* The index of a sampler in this animation used to compute the value for the
* target, e.g., a node's translation, rotation, or scale (TRS).
*/
int32_t sampler = -1;
/**
* @brief The descriptor of the animated property.
*/
CesiumGltf::AnimationChannelTarget target;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(AnimationChannel));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += this->target.getSizeBytes() -
int64_t(sizeof(CesiumGltf::AnimationChannelTarget));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,79 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <string>
namespace CesiumGltf {
/**
* @brief The descriptor of the animated property.
*/
struct CESIUMGLTF_API AnimationChannelTarget final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "AnimationChannelTarget";
/**
* @brief Known values for The name of the node's TRS property to animate, or
* the `"weights"` of the Morph Targets it instantiates. For the
* `"translation"` property, the values that are provided by the sampler are
* the translation along the X, Y, and Z axes. For the `"rotation"` property,
* the values are a quaternion in the order (x, y, z, w), where w is the
* scalar. For the `"scale"` property, the values are the scaling factors
* along the X, Y, and Z axes.
*/
struct Path {
/** @brief `translation` */
inline static const std::string translation = "translation";
/** @brief `rotation` */
inline static const std::string rotation = "rotation";
/** @brief `scale` */
inline static const std::string scale = "scale";
/** @brief `weights` */
inline static const std::string weights = "weights";
};
/**
* @brief The index of the node to animate. When undefined, the animated
* object **MAY** be defined by an extension.
*/
int32_t node = -1;
/**
* @brief The name of the node's TRS property to animate, or the `"weights"`
* of the Morph Targets it instantiates. For the `"translation"` property, the
* values that are provided by the sampler are the translation along the X, Y,
* and Z axes. For the `"rotation"` property, the values are a quaternion in
* the order (x, y, z, w), where w is the scalar. For the `"scale"` property,
* the values are the scaling factors along the X, Y, and Z axes.
*
* Known values are defined in {@link Path}.
*
*/
std::string path = Path::translation;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(AnimationChannelTarget));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,84 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <string>
namespace CesiumGltf {
/**
* @brief An animation sampler combines timestamps with a sequence of output
* values and defines an interpolation algorithm.
*/
struct CESIUMGLTF_API AnimationSampler final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "AnimationSampler";
/**
* @brief Known values for Interpolation algorithm.
*/
struct Interpolation {
/** @brief The animated values are linearly interpolated between keyframes.
* When targeting a rotation, spherical linear interpolation (slerp)
* **SHOULD** be used to interpolate quaternions. The number of output
* elements **MUST** equal the number of input elements. */
inline static const std::string LINEAR = "LINEAR";
/** @brief The animated values remain constant to the output of the first
* keyframe, until the next keyframe. The number of output elements **MUST**
* equal the number of input elements. */
inline static const std::string STEP = "STEP";
/** @brief The animation's interpolation is computed using a cubic spline
* with specified tangents. The number of output elements **MUST** equal
* three times the number of input elements. For each input element, the
* output stores three elements, an in-tangent, a spline vertex, and an
* out-tangent. There **MUST** be at least two keyframes when using this
* interpolation. */
inline static const std::string CUBICSPLINE = "CUBICSPLINE";
};
/**
* @brief The index of an accessor containing keyframe timestamps.
*
* The accessor **MUST** be of scalar type with floating-point components. The
* values represent time in seconds with `time[0] >= 0.0`, and strictly
* increasing values, i.e., `time[n + 1] > time[n]`.
*/
int32_t input = -1;
/**
* @brief Interpolation algorithm.
*
* Known values are defined in {@link Interpolation}.
*
*/
std::string interpolation = Interpolation::LINEAR;
/**
* @brief The index of an accessor, containing keyframe output values.
*/
int32_t output = -1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(AnimationSampler));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,69 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief Metadata about the glTF asset.
*/
struct CESIUMGLTF_API Asset final : public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Asset";
/**
* @brief A copyright message suitable for display to credit the content
* creator.
*/
std::optional<std::string> copyright;
/**
* @brief Tool that generated this glTF model. Useful for debugging.
*/
std::optional<std::string> generator;
/**
* @brief The glTF version in the form of `<major>.<minor>` that this asset
* targets.
*/
std::string version;
/**
* @brief The minimum glTF version in the form of `<major>.<minor>` that this
* asset targets. This property **MUST NOT** be greater than the asset
* version.
*/
std::optional<std::string> minVersion;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Asset));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->copyright) {
accum += int64_t(this->copyright->capacity() * sizeof(char));
}
if (this->generator) {
accum += int64_t(this->generator->capacity() * sizeof(char));
}
accum += int64_t(this->version.capacity() * sizeof(char));
if (this->minVersion) {
accum += int64_t(this->minVersion->capacity() * sizeof(char));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,18 @@
#pragma once
#include "CesiumGltf/BufferCesium.h"
#include "CesiumGltf/BufferSpec.h"
#include "CesiumGltf/Library.h"
namespace CesiumGltf {
/** @copydoc BufferSpec */
struct CESIUMGLTF_API Buffer final : public BufferSpec {
Buffer() = default;
/**
* @brief Holds properties that are specific to the glTF loader rather than
* part of the glTF spec.
*/
BufferCesium cesium;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,19 @@
#pragma once
#include "CesiumGltf/Library.h"
#include <cstddef>
#include <vector>
namespace CesiumGltf {
/**
* @brief Holds {@link Buffer} properties that are specific to the glTF loader
* rather than part of the glTF spec.
*/
struct CESIUMGLTF_API BufferCesium final {
/**
* @brief The buffer's data.
*/
std::vector<std::byte> data;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,59 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <cstdint>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief A buffer points to binary geometry, animation, or skins.
*/
struct CESIUMGLTF_API BufferSpec : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Buffer";
/**
* @brief The URI (or IRI) of the buffer.
*
* Relative paths are relative to the current glTF asset. Instead of
* referencing an external file, this field **MAY** contain a `data:`-URI.
*/
std::optional<std::string> uri;
/**
* @brief The length of the buffer in bytes.
*/
int64_t byteLength = int64_t();
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(BufferSpec));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
if (this->uri) {
accum += int64_t(this->uri->capacity() * sizeof(char));
}
return accum;
}
protected:
/**
* @brief This class is not meant to be instantiated directly. Use {@link Buffer} instead.
*/
BufferSpec() = default;
friend struct Buffer;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,81 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <cstdint>
#include <optional>
namespace CesiumGltf {
/**
* @brief A view into a buffer generally representing a subset of the buffer.
*/
struct CESIUMGLTF_API BufferView final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "BufferView";
/**
* @brief Known values for The hint representing the intended GPU buffer type
* to use with this buffer view.
*/
struct Target {
/** @brief ARRAY_BUFFER (`34962`) */
static constexpr int32_t ARRAY_BUFFER = 34962;
/** @brief ELEMENT_ARRAY_BUFFER (`34963`) */
static constexpr int32_t ELEMENT_ARRAY_BUFFER = 34963;
};
/**
* @brief The index of the buffer.
*/
int32_t buffer = -1;
/**
* @brief The offset into the buffer in bytes.
*/
int64_t byteOffset = 0;
/**
* @brief The length of the bufferView in bytes.
*/
int64_t byteLength = int64_t();
/**
* @brief The stride, in bytes.
*
* The stride, in bytes, between vertex attributes. When this is not defined,
* data is tightly packed. When two or more accessors use the same buffer
* view, this field **MUST** be defined.
*/
std::optional<int64_t> byteStride;
/**
* @brief The hint representing the intended GPU buffer type to use with this
* buffer view.
*
* Known values are defined in {@link Target}.
*
*/
std::optional<int32_t> target;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(BufferView));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,84 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/CameraOrthographic.h>
#include <CesiumGltf/CameraPerspective.h>
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief A camera's projection. A node **MAY** reference a camera to apply a
* transform to place the camera in the scene.
*/
struct CESIUMGLTF_API Camera final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Camera";
/**
* @brief Known values for Specifies if the camera uses a perspective or
* orthographic projection.
*/
struct Type {
/** @brief `perspective` */
inline static const std::string perspective = "perspective";
/** @brief `orthographic` */
inline static const std::string orthographic = "orthographic";
};
/**
* @brief An orthographic camera containing properties to create an
* orthographic projection matrix. This property **MUST NOT** be defined when
* `perspective` is defined.
*/
std::optional<CesiumGltf::CameraOrthographic> orthographic;
/**
* @brief A perspective camera containing properties to create a perspective
* projection matrix. This property **MUST NOT** be defined when
* `orthographic` is defined.
*/
std::optional<CesiumGltf::CameraPerspective> perspective;
/**
* @brief Specifies if the camera uses a perspective or orthographic
* projection.
*
* Known values are defined in {@link Type}.
*
*
* Based on this, either the camera's `perspective` or `orthographic` property
* **MUST** be defined.
*/
std::string type = Type::perspective;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Camera));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
if (this->orthographic) {
accum += this->orthographic->getSizeBytes() -
int64_t(sizeof(CesiumGltf::CameraOrthographic));
}
if (this->perspective) {
accum += this->perspective->getSizeBytes() -
int64_t(sizeof(CesiumGltf::CameraPerspective));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,58 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
namespace CesiumGltf {
/**
* @brief An orthographic camera containing properties to create an orthographic
* projection matrix.
*/
struct CESIUMGLTF_API CameraOrthographic final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "CameraOrthographic";
/**
* @brief The floating-point horizontal magnification of the view. This value
* **MUST NOT** be equal to zero. This value **SHOULD NOT** be negative.
*/
double xmag = double();
/**
* @brief The floating-point vertical magnification of the view. This value
* **MUST NOT** be equal to zero. This value **SHOULD NOT** be negative.
*/
double ymag = double();
/**
* @brief The floating-point distance to the far clipping plane. This value
* **MUST NOT** be equal to zero. `zfar` **MUST** be greater than `znear`.
*/
double zfar = double();
/**
* @brief The floating-point distance to the near clipping plane.
*/
double znear = double();
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(CameraOrthographic));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,65 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <optional>
namespace CesiumGltf {
/**
* @brief A perspective camera containing properties to create a perspective
* projection matrix.
*/
struct CESIUMGLTF_API CameraPerspective final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "CameraPerspective";
/**
* @brief The floating-point aspect ratio of the field of view.
*
* When undefined, the aspect ratio of the rendering viewport **MUST** be
* used.
*/
std::optional<double> aspectRatio;
/**
* @brief The floating-point vertical field of view in radians. This value
* **SHOULD** be less than π.
*/
double yfov = double();
/**
* @brief The floating-point distance to the far clipping plane.
*
* When defined, `zfar` **MUST** be greater than `znear`. If `zfar` is
* undefined, client implementations **SHOULD** use infinite projection
* matrix.
*/
std::optional<double> zfar;
/**
* @brief The floating-point distance to the near clipping plane.
*/
double znear = double();
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(CameraPerspective));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,67 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/ClassProperty.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <optional>
#include <string>
#include <unordered_map>
namespace CesiumGltf {
/**
* @brief A class containing a set of properties.
*/
struct CESIUMGLTF_API Class final : public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Class";
/**
* @brief The name of the class, e.g. for display purposes.
*/
std::optional<std::string> name;
/**
* @brief The description of the class.
*/
std::optional<std::string> description;
/**
* @brief A dictionary, where each key is a property ID and each value is an
* object defining the property. Property IDs must be alphanumeric identifiers
* matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`.
*/
std::unordered_map<std::string, CesiumGltf::ClassProperty> properties;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Class));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
if (this->description) {
accum += int64_t(this->description->capacity() * sizeof(char));
}
accum += int64_t(
this->properties.bucket_count() *
(sizeof(std::string) + sizeof(CesiumGltf::ClassProperty)));
for (const auto& [k, v] : this->properties) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += v.getSizeBytes() - int64_t(sizeof(CesiumGltf::ClassProperty));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,239 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <CesiumUtility/JsonValue.h>
#include <cstdint>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief A class property.
*/
struct CESIUMGLTF_API ClassProperty final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ClassProperty";
/**
* @brief Known values for The element type.
*/
struct Type {
/** @brief `SCALAR` */
inline static const std::string SCALAR = "SCALAR";
/** @brief `VEC2` */
inline static const std::string VEC2 = "VEC2";
/** @brief `VEC3` */
inline static const std::string VEC3 = "VEC3";
/** @brief `VEC4` */
inline static const std::string VEC4 = "VEC4";
/** @brief `MAT2` */
inline static const std::string MAT2 = "MAT2";
/** @brief `MAT3` */
inline static const std::string MAT3 = "MAT3";
/** @brief `MAT4` */
inline static const std::string MAT4 = "MAT4";
/** @brief `STRING` */
inline static const std::string STRING = "STRING";
/** @brief `BOOLEAN` */
inline static const std::string BOOLEAN = "BOOLEAN";
/** @brief `ENUM` */
inline static const std::string ENUM = "ENUM";
};
/**
* @brief Known values for The datatype of the element's components. Only
* applicable to `SCALAR`, `VECN`, and `MATN` types.
*/
struct ComponentType {
/** @brief `INT8` */
inline static const std::string INT8 = "INT8";
/** @brief `UINT8` */
inline static const std::string UINT8 = "UINT8";
/** @brief `INT16` */
inline static const std::string INT16 = "INT16";
/** @brief `UINT16` */
inline static const std::string UINT16 = "UINT16";
/** @brief `INT32` */
inline static const std::string INT32 = "INT32";
/** @brief `UINT32` */
inline static const std::string UINT32 = "UINT32";
/** @brief `INT64` */
inline static const std::string INT64 = "INT64";
/** @brief `UINT64` */
inline static const std::string UINT64 = "UINT64";
/** @brief `FLOAT32` */
inline static const std::string FLOAT32 = "FLOAT32";
/** @brief `FLOAT64` */
inline static const std::string FLOAT64 = "FLOAT64";
};
/**
* @brief The name of the property, e.g. for display purposes.
*/
std::optional<std::string> name;
/**
* @brief The description of the property.
*/
std::optional<std::string> description;
/**
* @brief The element type.
*
* Known values are defined in {@link Type}.
*
*/
std::string type = Type::SCALAR;
/**
* @brief The datatype of the element's components. Only applicable to
* `SCALAR`, `VECN`, and `MATN` types.
*
* Known values are defined in {@link ComponentType}.
*
*/
std::optional<std::string> componentType;
/**
* @brief Enum ID as declared in the `enums` dictionary. Required when `type`
* is `ENUM`.
*/
std::optional<std::string> enumType;
/**
* @brief Whether the property is an array. When `count` is defined the
* property is a fixed-length array. Otherwise the property is a
* variable-length array.
*/
bool array = false;
/**
* @brief The number of array elements. May only be defined when `array` is
* true.
*/
std::optional<int64_t> count;
/**
* @brief Specifies whether integer values are normalized. Only applicable to
* `SCALAR`, `VECN`, and `MATN` types with integer component types. For
* unsigned integer component types, values are normalized between
* `[0.0, 1.0]`. For signed integer component types, values are normalized
* between `[-1.0, 1.0]`. For all other component types, this property must be
* false.
*/
bool normalized = false;
/**
* @brief An offset to apply to property values. Only applicable to `SCALAR`,
* `VECN`, and `MATN` types when the component type is `FLOAT32` or `FLOAT64`,
* or when the property is `normalized`.
*/
std::optional<CesiumUtility::JsonValue> offset;
/**
* @brief A scale to apply to property values. Only applicable to `SCALAR`,
* `VECN`, and `MATN` types when the component type is `FLOAT32` or `FLOAT64`,
* or when the property is `normalized`.
*/
std::optional<CesiumUtility::JsonValue> scale;
/**
* @brief Maximum allowed value for the property. Only applicable to `SCALAR`,
* `VECN`, and `MATN` types. This is the maximum of all property values, after
* the transforms based on the `normalized`, `offset`, and `scale` properties
* have been applied.
*/
std::optional<CesiumUtility::JsonValue> max;
/**
* @brief Minimum allowed value for the property. Only applicable to `SCALAR`,
* `VECN`, and `MATN` types. This is the minimum of all property values, after
* the transforms based on the `normalized`, `offset`, and `scale` properties
* have been applied.
*/
std::optional<CesiumUtility::JsonValue> min;
/**
* @brief If required, the property must be present in every entity conforming
* to the class. If not required, individual entities may include `noData`
* values, or the entire property may be omitted. As a result, `noData` has no
* effect on a required property. Client implementations may use required
* properties to make performance optimizations.
*/
bool required = false;
/**
* @brief A `noData` value represents missing data — also known as a sentinel
* value — wherever it appears. `BOOLEAN` properties may not specify `noData`
* values. This is given as the plain property value, without the transforms
* from the `normalized`, `offset`, and `scale` properties. Must not be
* defined if `required` is true.
*/
std::optional<CesiumUtility::JsonValue> noData;
/**
* @brief A default value to use when encountering a `noData` value or an
* omitted property. The value is given in its final form, taking the effect
* of `normalized`, `offset`, and `scale` properties into account. Must not be
* defined if `required` is true.
*/
std::optional<CesiumUtility::JsonValue> defaultProperty;
/**
* @brief An identifier that describes how this property should be
* interpreted. The semantic cannot be used by other properties in the class.
*/
std::optional<std::string> semantic;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ClassProperty));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
if (this->description) {
accum += int64_t(this->description->capacity() * sizeof(char));
}
if (this->enumType) {
accum += int64_t(this->enumType->capacity() * sizeof(char));
}
if (this->semantic) {
accum += int64_t(this->semantic->capacity() * sizeof(char));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,100 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/EnumValue.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <optional>
#include <string>
#include <vector>
namespace CesiumGltf {
/**
* @brief An object defining the values of an enum.
*/
struct CESIUMGLTF_API Enum final : public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Enum";
/**
* @brief Known values for The type of the integer enum value.
*/
struct ValueType {
/** @brief `INT8` */
inline static const std::string INT8 = "INT8";
/** @brief `UINT8` */
inline static const std::string UINT8 = "UINT8";
/** @brief `INT16` */
inline static const std::string INT16 = "INT16";
/** @brief `UINT16` */
inline static const std::string UINT16 = "UINT16";
/** @brief `INT32` */
inline static const std::string INT32 = "INT32";
/** @brief `UINT32` */
inline static const std::string UINT32 = "UINT32";
/** @brief `INT64` */
inline static const std::string INT64 = "INT64";
/** @brief `UINT64` */
inline static const std::string UINT64 = "UINT64";
};
/**
* @brief The name of the enum, e.g. for display purposes.
*/
std::optional<std::string> name;
/**
* @brief The description of the enum.
*/
std::optional<std::string> description;
/**
* @brief The type of the integer enum value.
*
* Known values are defined in {@link ValueType}.
*
*/
std::string valueType = ValueType::UINT16;
/**
* @brief An array of enum values. Duplicate names or duplicate integer values
* are not allowed.
*/
std::vector<CesiumGltf::EnumValue> values;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Enum));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
if (this->description) {
accum += int64_t(this->description->capacity() * sizeof(char));
}
accum += int64_t(sizeof(CesiumGltf::EnumValue) * this->values.capacity());
for (const CesiumGltf::EnumValue& value : this->values) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::EnumValue));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,55 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief An enum value.
*/
struct CESIUMGLTF_API EnumValue final : public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "EnumValue";
/**
* @brief The name of the enum value.
*/
std::string name;
/**
* @brief The description of the enum value.
*/
std::optional<std::string> description;
/**
* @brief The integer enum value.
*/
int64_t value = int64_t();
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(EnumValue));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(this->name.capacity() * sizeof(char));
if (this->description) {
accum += int64_t(this->description->capacity() * sizeof(char));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,45 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
namespace CesiumGltf {
/**
* @brief Compressed data for bufferView.
*/
struct CESIUMGLTF_API ExtensionBufferExtMeshoptCompression final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionBufferExtMeshoptCompression";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_meshopt_compression";
/**
* @brief Set to true to indicate that the buffer is only referenced by
* bufferViews that have EXT_meshopt_compression extension and as such doesn't
* need to be loaded.
*/
bool fallback = false;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionBufferExtMeshoptCompression));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,113 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <string>
namespace CesiumGltf {
/**
* @brief Compressed data for bufferView.
*/
struct CESIUMGLTF_API ExtensionBufferViewExtMeshoptCompression final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionBufferViewExtMeshoptCompression";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_meshopt_compression";
/**
* @brief Known values for The compression mode.
*/
struct Mode {
/** @brief `ATTRIBUTES` */
inline static const std::string ATTRIBUTES = "ATTRIBUTES";
/** @brief `TRIANGLES` */
inline static const std::string TRIANGLES = "TRIANGLES";
/** @brief `INDICES` */
inline static const std::string INDICES = "INDICES";
};
/**
* @brief Known values for The compression filter.
*/
struct Filter {
/** @brief `NONE` */
inline static const std::string NONE = "NONE";
/** @brief `OCTAHEDRAL` */
inline static const std::string OCTAHEDRAL = "OCTAHEDRAL";
/** @brief `QUATERNION` */
inline static const std::string QUATERNION = "QUATERNION";
/** @brief `EXPONENTIAL` */
inline static const std::string EXPONENTIAL = "EXPONENTIAL";
};
/**
* @brief The index of the buffer with compressed data.
*/
int32_t buffer = -1;
/**
* @brief The offset into the buffer in bytes.
*/
int64_t byteOffset = 0;
/**
* @brief The length of the compressed data in bytes.
*/
int64_t byteLength = int64_t();
/**
* @brief The stride, in bytes.
*/
int64_t byteStride = int64_t();
/**
* @brief The number of elements.
*/
int64_t count = int64_t();
/**
* @brief The compression mode.
*
* Known values are defined in {@link Mode}.
*
*/
std::string mode = Mode::ATTRIBUTES;
/**
* @brief The compression filter.
*
* Known values are defined in {@link Filter}.
*
*/
std::string filter = Filter::NONE;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionBufferViewExtMeshoptCompression));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,46 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief glTF extension for indicating that some edges of a primitive's
* triangles should be outlined.
*/
struct CESIUMGLTF_API ExtensionCesiumPrimitiveOutline final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionCesiumPrimitiveOutline";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "CESIUM_primitive_outline";
/**
* @brief The index of the accessor providing the list of highlighted lines at
* the edge of this primitive's triangles.
*/
int32_t indices = -1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionCesiumPrimitiveOutline));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,44 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <vector>
namespace CesiumGltf {
/**
* @brief glTF CESIUM_RTC extension.
*/
struct CESIUMGLTF_API ExtensionCesiumRTC final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionCesiumRTC";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "CESIUM_RTC";
/**
* @brief Center that vertex positions are relative to.
*/
std::vector<double> center;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionCesiumRTC));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(sizeof(double) * this->center.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,63 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief `CESIUM_tile_edges` extension for a primitive in a glTF model.
*/
struct CESIUMGLTF_API ExtensionCesiumTileEdges final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionCesiumTileEdges";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "CESIUM_tile_edges";
/**
* @brief The index of the accessor containing indices that make up the left
* edge.
*/
int32_t left = -1;
/**
* @brief The index of the accessor containing indices that make up the bottom
* edge.
*/
int32_t bottom = -1;
/**
* @brief The index of the accessor containing indices that make up the right
* edge.
*/
int32_t right = -1;
/**
* @brief The index of the accessor containing indices that make up the top
* edge.
*/
int32_t top = -1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionCesiumTileEdges));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,53 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/ExtensionExtInstanceFeaturesFeatureId.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <vector>
namespace CesiumGltf {
/**
* @brief An object describing per-instance feature IDs.
*/
struct CESIUMGLTF_API ExtensionExtInstanceFeatures final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionExtInstanceFeatures";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_instance_features";
/**
* @brief An array of feature ID sets.
*/
std::vector<CesiumGltf::ExtensionExtInstanceFeaturesFeatureId> featureIds;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionExtInstanceFeatures));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(
sizeof(CesiumGltf::ExtensionExtInstanceFeaturesFeatureId) *
this->featureIds.capacity());
for (const CesiumGltf::ExtensionExtInstanceFeaturesFeatureId& value :
this->featureIds) {
accum +=
value.getSizeBytes() -
int64_t(sizeof(CesiumGltf::ExtensionExtInstanceFeaturesFeatureId));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,72 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief Feature IDs stored in a GPU mesh instancing attribute
*/
struct CESIUMGLTF_API ExtensionExtInstanceFeaturesFeatureId final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionExtInstanceFeaturesFeatureId";
/**
* @brief The number of unique features in the attribute.
*/
int64_t featureCount = int64_t();
/**
* @brief A value that indicates that no feature is associated with this
* instance.
*/
std::optional<int64_t> nullFeatureId;
/**
* @brief A label assigned to this feature ID set. Labels must be alphanumeric
* identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`.
*/
std::optional<std::string> label;
/**
* @brief An integer value used to construct a string in the format
* `_FEATURE_ID_<set index>` which is a reference to a key in
* `EXT_mesh_gpu_instancing.attributes` dictionary (e.g. a value of `0`
* corresponds to `_FEATURE_ID_0`).
*/
std::optional<int64_t> attribute;
/**
* @brief The index of the property table containing per-feature property
* values. Only applicable when using the `EXT_structural_metadata` extension.
*/
std::optional<int64_t> propertyTable;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionExtInstanceFeaturesFeatureId));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->label) {
accum += int64_t(this->label->capacity() * sizeof(char));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,49 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/FeatureId.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <vector>
namespace CesiumGltf {
/**
* @brief An object describing feature IDs for a mesh primitive.
*/
struct CESIUMGLTF_API ExtensionExtMeshFeatures final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionExtMeshFeatures";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_mesh_features";
/**
* @brief An array of feature ID sets.
*/
std::vector<CesiumGltf::FeatureId> featureIds;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionExtMeshFeatures));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum +=
int64_t(sizeof(CesiumGltf::FeatureId) * this->featureIds.capacity());
for (const CesiumGltf::FeatureId& value : this->featureIds) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::FeatureId));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,60 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <string>
#include <unordered_map>
namespace CesiumGltf {
/**
* @brief glTF extension defines instance attributes for a node with a mesh.
*/
struct CESIUMGLTF_API ExtensionExtMeshGpuInstancing final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionExtMeshGpuInstancing";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_mesh_gpu_instancing";
/**
* @brief A dictionary object, where each key corresponds to instance
* attribute and each value is the index of the accessor containing
* attribute's data. Attributes TRANSLATION, ROTATION, SCALE define instance
* transformation. For "TRANSLATION" the values are FLOAT_VEC3's specifying
* translation along the x, y, and z axes. For "ROTATION" the values are
* VEC4's specifying rotation as a quaternion in the order (x, y, z, w), where
* w is the scalar, with component type `FLOAT` or normalized integer. For
* "SCALE" the values are FLOAT_VEC3's specifying scaling factors along the x,
* y, and z axes.
*/
std::unordered_map<std::string, int32_t> attributes;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionExtMeshGpuInstancing));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(
this->attributes.bucket_count() *
(sizeof(std::string) + sizeof(int32_t)));
for (const auto& [k, v] : this->attributes) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += int64_t(sizeof(int32_t));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,69 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <CesiumUtility/JsonValue.h>
#include <optional>
#include <string>
#include <unordered_map>
namespace CesiumGltf {
/**
* @brief Structural metadata about a glTF element.
*/
struct CESIUMGLTF_API ExtensionExtStructuralMetadata final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionExtStructuralMetadata";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_structural_metadata";
/**
* @brief The class that property values conform to. The value shall be a
* class ID declared in the `classes` dictionary of the metadata schema.
*/
std::optional<std::string> classProperty;
/**
* @brief A dictionary, where each key corresponds to a property ID in the
* class' `properties` dictionary and each value contains the property values.
* The type of the value shall match the property definition: For `BOOLEAN`
* use `true` or `false`. For `STRING` use a JSON string. For numeric types
* use a JSON number. For `ENUM` use a valid enum `name`, not an integer
* value. For `ARRAY`, `VECN`, and `MATN` types use a JSON array containing
* values matching the `componentType`. Required properties shall be included
* in this dictionary.
*/
std::unordered_map<std::string, CesiumUtility::JsonValue> properties;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionExtStructuralMetadata));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->classProperty) {
accum += int64_t(this->classProperty->capacity() * sizeof(char));
}
accum += int64_t(
this->properties.bucket_count() *
(sizeof(std::string) + sizeof(CesiumUtility::JsonValue)));
for (const auto& [k, v] : this->properties) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += int64_t(sizeof(CesiumUtility::JsonValue));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,58 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <string>
#include <unordered_map>
namespace CesiumGltf {
/**
* @brief KHR_draco_mesh_compression glTF Mesh Primitive Extension
*/
struct CESIUMGLTF_API ExtensionKhrDracoMeshCompression final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionKhrDracoMeshCompression";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "KHR_draco_mesh_compression";
/**
* @brief The index of the bufferView.
*/
int32_t bufferView = -1;
/**
* @brief A dictionary object, where each key corresponds to an attribute and
* its unique attribute id stored in the compressed geometry.
*/
std::unordered_map<std::string, int32_t> attributes;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionKhrDracoMeshCompression));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(
this->attributes.bucket_count() *
(sizeof(std::string) + sizeof(int32_t)));
for (const auto& [k, v] : this->attributes) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += int64_t(sizeof(int32_t));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,37 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
namespace CesiumGltf {
/**
* @brief glTF extension that defines the unlit material model.
*/
struct CESIUMGLTF_API ExtensionKhrMaterialsUnlit final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionKhrMaterialsUnlit";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "KHR_materials_unlit";
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionKhrMaterialsUnlit));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,46 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief glTF extension to specify textures using the KTX v2 images with Basis
* Universal supercompression.
*/
struct CESIUMGLTF_API ExtensionKhrTextureBasisu final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionKhrTextureBasisu";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "KHR_texture_basisu";
/**
* @brief The index of the image which points to a KTX v2 resource with Basis
* Universal supercompression.
*/
int32_t source = -1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionKhrTextureBasisu));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,66 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <optional>
#include <vector>
namespace CesiumGltf {
/**
* @brief glTF extension that enables shifting and scaling UV coordinates on a
* per-texture basis
*/
struct CESIUMGLTF_API ExtensionKhrTextureTransform final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionKhrTextureTransform";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "KHR_texture_transform";
/**
* @brief The offset of the UV coordinate origin as a factor of the texture
* dimensions.
*/
std::vector<double> offset = {0, 0};
/**
* @brief Rotate the UVs by this many radians counter-clockwise around the
* origin.
*/
double rotation = 0;
/**
* @brief The scale factor applied to the components of the UV coordinates.
*/
std::vector<double> scale = {1, 1};
/**
* @brief Overrides the textureInfo texCoord value if supplied, and if this
* extension is supported.
*/
std::optional<int64_t> texCoord;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionKhrTextureTransform));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(sizeof(double) * this->offset.capacity());
accum += int64_t(sizeof(double) * this->scale.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,54 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <vector>
namespace CesiumGltf {
/**
* @brief Structural metadata about a glTF primitive.
*/
struct CESIUMGLTF_API ExtensionMeshPrimitiveExtStructuralMetadata final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionMeshPrimitiveExtStructuralMetadata";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_structural_metadata";
/**
* @brief An array of indexes of property textures in the root
* `EXT_structural_metadata` object.
*/
std::vector<int32_t> propertyTextures;
/**
* @brief An array of indexes of property attributes in the root
* `EXT_structural_metadata` object.
*/
std::vector<int32_t> propertyAttributes;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionMeshPrimitiveExtStructuralMetadata));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(sizeof(int32_t) * this->propertyTextures.capacity());
accum += int64_t(sizeof(int32_t) * this->propertyAttributes.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,63 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <vector>
namespace CesiumGltf {
/**
* @brief KHR_materials_variants glTF Mesh Primitive Extension
*/
struct CESIUMGLTF_API ExtensionMeshPrimitiveKhrMaterialsVariants final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionMeshPrimitiveKhrMaterialsVariants";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "KHR_materials_variants";
/**
* @brief A list of material to variant mappings
*
* An array of object values that associate an indexed material to a set of
* variants.
*/
std::vector<
CesiumGltf::ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue>
mappings;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionMeshPrimitiveKhrMaterialsVariants));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(
sizeof(CesiumGltf::
ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue) *
this->mappings.capacity());
for (const CesiumGltf::
ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue& value :
this->mappings) {
accum +=
value.getSizeBytes() -
int64_t(sizeof(
CesiumGltf::
ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,67 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace CesiumGltf {
/**
* @brief ExtensionMeshPrimitiveKhrMaterialsVariants Mappings Value
*/
struct CESIUMGLTF_API ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue
final : public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue";
/**
* @brief An array of variant index values.
*
* An array of index values that reference variants defined in the glTF root's
* extension object.
*/
std::vector<int32_t> variants;
/**
* @brief The material associated with the set of variants.
*
* A reference to the material associated with the given array of variants.
*/
int32_t material = -1;
/**
* @brief The user-defined name of this variant material mapping.
*
* The optional user-defined name of this variant material mapping. This is
* not necessarily unique.
*/
std::optional<std::string> name;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(
sizeof(ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(sizeof(int32_t) * this->variants.capacity());
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,99 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/PropertyAttribute.h>
#include <CesiumGltf/PropertyTable.h>
#include <CesiumGltf/PropertyTexture.h>
#include <CesiumGltf/Schema.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <CesiumUtility/IntrusivePointer.h>
#include <optional>
#include <string>
#include <vector>
namespace CesiumGltf {
/**
* @brief glTF extension that provides structural metadata about vertices,
* texels, and features in a glTF asset.
*/
struct CESIUMGLTF_API ExtensionModelExtStructuralMetadata final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionModelExtStructuralMetadata";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_structural_metadata";
/**
* @brief An object defining classes and enums.
*/
CesiumUtility::IntrusivePointer<CesiumGltf::Schema> schema;
/**
* @brief The URI (or IRI) of the external schema file.
*/
std::optional<std::string> schemaUri;
/**
* @brief An array of property table definitions, which may be referenced by
* index.
*/
std::vector<CesiumGltf::PropertyTable> propertyTables;
/**
* @brief An array of property texture definitions, which may be referenced by
* index.
*/
std::vector<CesiumGltf::PropertyTexture> propertyTextures;
/**
* @brief An array of property attribute definitions, which may be referenced
* by index.
*/
std::vector<CesiumGltf::PropertyAttribute> propertyAttributes;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionModelExtStructuralMetadata));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += this->schema->getSizeBytes();
if (this->schemaUri) {
accum += int64_t(this->schemaUri->capacity() * sizeof(char));
}
accum += int64_t(
sizeof(CesiumGltf::PropertyTable) * this->propertyTables.capacity());
for (const CesiumGltf::PropertyTable& value : this->propertyTables) {
accum +=
value.getSizeBytes() - int64_t(sizeof(CesiumGltf::PropertyTable));
}
accum += int64_t(
sizeof(CesiumGltf::PropertyTexture) *
this->propertyTextures.capacity());
for (const CesiumGltf::PropertyTexture& value : this->propertyTextures) {
accum +=
value.getSizeBytes() - int64_t(sizeof(CesiumGltf::PropertyTexture));
}
accum += int64_t(
sizeof(CesiumGltf::PropertyAttribute) *
this->propertyAttributes.capacity());
for (const CesiumGltf::PropertyAttribute& value :
this->propertyAttributes) {
accum +=
value.getSizeBytes() - int64_t(sizeof(CesiumGltf::PropertyAttribute));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,53 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/ExtensionModelKhrMaterialsVariantsValue.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <vector>
namespace CesiumGltf {
/**
* @brief glTF extension that defines a material variations for mesh primitives
*/
struct CESIUMGLTF_API ExtensionModelKhrMaterialsVariants final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionModelKhrMaterialsVariants";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "KHR_materials_variants";
/**
* @brief variants
*/
std::vector<CesiumGltf::ExtensionModelKhrMaterialsVariantsValue> variants;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionModelKhrMaterialsVariants));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(
sizeof(CesiumGltf::ExtensionModelKhrMaterialsVariantsValue) *
this->variants.capacity());
for (const CesiumGltf::ExtensionModelKhrMaterialsVariantsValue& value :
this->variants) {
accum +=
value.getSizeBytes() -
int64_t(sizeof(CesiumGltf::ExtensionModelKhrMaterialsVariantsValue));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,42 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <string>
namespace CesiumGltf {
/**
* @brief An object defining a valid material variant
*/
struct CESIUMGLTF_API ExtensionModelKhrMaterialsVariantsValue final
: public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionModelKhrMaterialsVariantsValue";
/**
* @brief The name of the material variant.
*/
std::string name;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionModelKhrMaterialsVariantsValue));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
accum += int64_t(this->name.capacity() * sizeof(char));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,61 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/ExtensionModelMaxarMeshVariantsValue.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <vector>
namespace CesiumGltf {
/**
* @brief glTF extension that defines mesh variants for nodes
*/
struct CESIUMGLTF_API ExtensionModelMaxarMeshVariants final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionModelMaxarMeshVariants";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "MAXAR_mesh_variants";
/**
* @brief The index of the variant to load by default. The meshes that are
* mapped to the default variant must represent the set of meshes initially
* selected by the nodes for rendering, as per vanilla glTF behavior.
*/
int32_t defaultProperty = -1;
/**
* @brief variants
*/
std::vector<CesiumGltf::ExtensionModelMaxarMeshVariantsValue> variants;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionModelMaxarMeshVariants));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(
sizeof(CesiumGltf::ExtensionModelMaxarMeshVariantsValue) *
this->variants.capacity());
for (const CesiumGltf::ExtensionModelMaxarMeshVariantsValue& value :
this->variants) {
accum +=
value.getSizeBytes() -
int64_t(sizeof(CesiumGltf::ExtensionModelMaxarMeshVariantsValue));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,42 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <string>
namespace CesiumGltf {
/**
* @brief An object defining a valid mesh variant
*/
struct CESIUMGLTF_API ExtensionModelMaxarMeshVariantsValue final
: public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionModelMaxarMeshVariantsValue";
/**
* @brief The name of the mesh variant
*/
std::string name;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionModelMaxarMeshVariantsValue));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
accum += int64_t(this->name.capacity() * sizeof(char));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,53 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/ExtensionNodeMaxarMeshVariantsMappingsValue.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <vector>
namespace CesiumGltf {
/**
* @brief MAXAR_mesh_variants node extension
*/
struct CESIUMGLTF_API ExtensionNodeMaxarMeshVariants final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionNodeMaxarMeshVariants";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "MAXAR_mesh_variants";
/**
* @brief A list of mesh to variant mappings
*/
std::vector<CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue> mappings;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionNodeMaxarMeshVariants));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(
sizeof(CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue) *
this->mappings.capacity());
for (const CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue& value :
this->mappings) {
accum += value.getSizeBytes() -
int64_t(sizeof(
CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,58 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace CesiumGltf {
/**
* @brief ExtensionNodeMaxarMeshVariants Mappings Value
*/
struct CESIUMGLTF_API ExtensionNodeMaxarMeshVariantsMappingsValue final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName =
"ExtensionNodeMaxarMeshVariantsMappingsValue";
/**
* @brief An array of variant index values.
*/
std::vector<int32_t> variants;
/**
* @brief The mesh associated with the set of variants.
*/
int32_t mesh = -1;
/**
* @brief The user-defined name of this variant mesh mapping.
*/
std::optional<std::string> name;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionNodeMaxarMeshVariantsMappingsValue));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(sizeof(int32_t) * this->variants.capacity());
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,44 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief glTF extension to specify textures using the WebP image format.
*/
struct CESIUMGLTF_API ExtensionTextureWebp final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "ExtensionTextureWebp";
/** @brief The official name of the extension. This should be the same as its
* key in the `extensions` object. */
static constexpr const char* ExtensionName = "EXT_texture_webp";
/**
* @brief The index of the images node which points to a WebP image.
*/
int32_t source = -1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ExtensionTextureWebp));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,80 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/FeatureIdTexture.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief Feature IDs stored in an attribute or texture.
*/
struct CESIUMGLTF_API FeatureId final : public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "FeatureId";
/**
* @brief The number of unique features in the attribute or texture.
*/
int64_t featureCount = int64_t();
/**
* @brief A value that indicates that no feature is associated with this
* vertex or texel.
*/
std::optional<int64_t> nullFeatureId;
/**
* @brief A label assigned to this feature ID set. Labels must be alphanumeric
* identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`.
*/
std::optional<std::string> label;
/**
* @brief An integer value used to construct a string in the format
* `_FEATURE_ID_<set index>` which is a reference to a key in
* `mesh.primitives.attributes` (e.g. a value of `0` corresponds to
* `_FEATURE_ID_0`).
*/
std::optional<int64_t> attribute;
/**
* @brief A texture containing feature IDs.
*/
std::optional<CesiumGltf::FeatureIdTexture> texture;
/**
* @brief The index of the property table containing per-feature property
* values. Only applicable when using the `EXT_structural_metadata` extension.
*/
int32_t propertyTable = -1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(FeatureId));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->label) {
accum += int64_t(this->label->capacity() * sizeof(char));
}
if (this->texture) {
accum += this->texture->getSizeBytes() -
int64_t(sizeof(CesiumGltf::FeatureIdTexture));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,43 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/TextureInfo.h>
#include <cstdint>
#include <vector>
namespace CesiumGltf {
/**
* @brief A texture containing feature IDs
*/
struct CESIUMGLTF_API FeatureIdTexture final : public TextureInfo {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "FeatureIdTexture";
/**
* @brief Texture channels containing feature IDs, identified by index.
* Feature IDs may be packed into multiple channels if a single channel does
* not have sufficient bit depth to represent all feature ID values. The
* values are packed in little-endian order.
*/
std::vector<int64_t> channels = {0};
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(FeatureIdTexture));
accum += TextureInfo::getSizeBytes() - int64_t(sizeof(TextureInfo));
accum += int64_t(sizeof(int64_t) * this->channels.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,136 @@
#pragma once
#include "CesiumGltf/FeatureIdTexture.h"
#include "CesiumGltf/TextureView.h"
#include <cstdint>
namespace CesiumGltf {
struct Model;
/**
* @brief The status of a feature ID texture view.
*
* The {@link FeatureIdTextureView} constructor always completes successfully,
* but it may not always reflect the actual content of the
* {@link FeatureIdTexture}. This enumeration provides the reason.
*/
enum class FeatureIdTextureViewStatus {
/**
* @brief This view is valid and ready to use.
*/
Valid,
/**
* @brief This view has not yet been initialized.
*/
ErrorUninitialized,
/**
* @brief This feature ID texture has a texture index that doesn't exist in
* the glTF.
*/
ErrorInvalidTexture,
/**
* @brief This feature ID texture has an image index that doesn't exist in
* the glTF.
*/
ErrorInvalidImage,
/**
* @brief This feature ID texture has a sampler index that doesn't exist in
* the glTF.
*/
ErrorInvalidSampler,
/**
* @brief This feature ID texture has an empty image.
*/
ErrorEmptyImage,
/**
* @brief The image for this feature ID texture has channels that take up more
* than a byte. Only single-byte channels are supported.
*/
ErrorInvalidImageBytesPerChannel,
/**
* @brief The channels of this feature ID texture property are invalid.
* Channels must be in the range 0-3, with a minimum of one channel. Although
* more than four channels can be defined for specialized texture
* formats, this view only supports a maximum of four channels.
*/
ErrorInvalidChannels
};
/**
* @brief A view on the image data of {@link FeatureIdTexture}.
*
* It provides the ability to sample the feature IDs from the
* {@link FeatureIdTexture} using texture coordinates.
*/
class FeatureIdTextureView : public TextureView {
public:
/**
* @brief Constructs an uninitialized and invalid view.
*/
FeatureIdTextureView() noexcept;
/**
* @brief Construct a view of the data specified by a {@link FeatureIdTexture}.
*
* A feature ID texture may contain the `KHR_texture_transform` extension,
* which transforms the texture coordinates used to sample the texture. The
* extension may also override the TEXCOORD set index that was originally
* specified by the feature ID texture.
*
* If a view is constructed with applyKhrTextureTransformExtension set to
* true, the view will automatically apply the texture transform to any UV
* coordinates used to sample the texture. If the extension defines its own
* TEXCOORD set index, it will override the original value.
*
* Otherwise, if the flag is set to false, UVs will not be transformed and
* the original TEXCOORD set index will be preserved. The extension's values
* may still be retrieved using getTextureTransform, if desired.
*
* @param model The glTF in which to look for the feature ID texture's data.
* @param featureIdTexture The feature ID texture to create a view for.
* @param options The set of options to use for this `FeatureIdTextureView`.
*/
FeatureIdTextureView(
const Model& model,
const FeatureIdTexture& featureIdTexture,
const TextureViewOptions& options = TextureViewOptions()) noexcept;
/**
* @brief Get the feature ID from the texture at the given texture
* coordinates. If the texture is somehow invalid, this returns -1.
*
* @param u The u-component of the texture coordinates. Must be within
* [0.0, 1.0].
* @param v The v-component of the texture coordinates. Must be within
* [0.0, 1.0].
* @return The feature ID at the nearest pixel to the texture coordinates.
*/
int64_t getFeatureID(double u, double v) const noexcept;
/**
* @brief Get the status of this view.
*
* If invalid, it will not be safe to sample feature IDs from this view.
*/
FeatureIdTextureViewStatus status() const noexcept { return this->_status; }
/**
* @brief Get the channels of this feature ID texture. The channels represent
* the bytes of the actual feature ID, in little-endian order.
*/
std::vector<int64_t> getChannels() const noexcept { return this->_channels; }
private:
FeatureIdTextureViewStatus _status;
std::vector<int64_t> _channels;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,19 @@
#pragma once
#include "CesiumGltf/ImageAsset.h"
#include "CesiumGltf/ImageSpec.h"
#include "CesiumGltf/Library.h"
#include "CesiumUtility/IntrusivePointer.h"
namespace CesiumGltf {
/** @copydoc ImageSpec */
struct CESIUMGLTF_API Image final : public ImageSpec {
Image() = default;
/**
* @brief The loaded image asset. When an image is loaded from a URL, multiple
* `Image` instances may all point to the same `ImageAsset` instance.
*/
CesiumUtility::IntrusivePointer<ImageAsset> pAsset;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,132 @@
#pragma once
#include "CesiumGltf/Ktx2TranscodeTargets.h"
#include "CesiumGltf/Library.h"
#include "CesiumUtility/SharedAsset.h"
#include <cstddef>
#include <cstdint>
#include <optional>
#include <vector>
namespace CesiumGltf {
/**
* @brief The byte range within a buffer where this mip exists.
*/
struct CESIUMGLTF_API ImageAssetMipPosition {
/**
* @brief The byte index where this mip begins.
*/
size_t byteOffset;
/**
* @brief The size in bytes of this mip.
*/
size_t byteSize;
};
/**
* @brief A 2D image asset, including its pixel data. The image may have
* mipmaps, and it may be encoded in a GPU compression format.
*/
struct CESIUMGLTF_API ImageAsset final
: public CesiumUtility::SharedAsset<ImageAsset> {
/**
* @brief The width of the image in pixels.
*/
int32_t width = 0;
/**
* @brief The height of the image in pixels.
*/
int32_t height = 0;
/**
* @brief The number of channels per pixel.
*/
int32_t channels = 4;
/**
* @brief The number of bytes per channel.
*/
int32_t bytesPerChannel = 1;
/**
* @brief The gpu compressed pixel format for this image or NONE if it is not
* compressed.
*/
GpuCompressedPixelFormat compressedPixelFormat =
GpuCompressedPixelFormat::NONE;
/**
* @brief The offset of each mip in the pixel data.
*
* A list of the positions of each mip's data within the overall pixel buffer.
* The first element will be the full image, the second will be the second
* biggest and etc. If this is empty, assume the entire buffer is a single
* image, the mip map will need to be generated on the client in this case.
*/
std::vector<ImageAssetMipPosition> mipPositions;
/**
* @brief The pixel data.
*
* This will be the raw pixel data when compressedPixelFormat is std::nullopt.
* Otherwise, this buffer will store the compressed pixel data in the
* specified format.
*
* If mipPositions is not empty, this buffer will contains multiple mips
* back-to-back.
*
* When this is an uncompressed texture:
* -The pixel data is consistent with the
* [stb](https://github.com/nothings/stb) image library.
*
* -For a correctly-formed image, the size of the array will be
* `width * height * channels * bytesPerChannel` bytes. There is no
* padding between rows or columns of the image, regardless of format.
*
* -The channels and their meaning are as follows:
*
* | Number of Channels | Channel Order and Meaning |
* |--------------------|---------------------------|
* | 1 | grey |
* | 2 | grey, alpha |
* | 3 | red, green, blue |
* | 4 | red, green, blue, alpha |
*/
std::vector<std::byte> pixelData;
/**
* @brief The effective size of this image, in bytes, for estimating resource
* usage for caching purposes.
*
* When this value is less than zero (the default), the size of this image
* should be assumed to equal the size of the {@link pixelData} array. When
* it is greater than or equal to zero, the specified size should be used
* instead. For example, the overridden size may account for:
* * The `pixelData` being cleared during the load process in order to save
* memory.
* * The cost of any renderer resources (e.g., GPU textures) created for
* this image.
*/
int64_t sizeBytes = -1;
/**
* @brief Constructs an empty image asset.
*/
ImageAsset() = default;
/**
* @brief Gets the size of this asset, in bytes.
*
* If {@link sizeBytes} is greater than or equal to zero, it is returned.
* Otherwise, the size of the {@link pixelData} array is returned.
*/
int64_t getSizeBytes() const {
return this->sizeBytes >= 0 ? this->sizeBytes
: static_cast<int64_t>(this->pixelData.size());
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,83 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <cstdint>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief Image data used to create a texture. Image **MAY** be referenced by an
* URI (or IRI) or a buffer view index.
*/
struct CESIUMGLTF_API ImageSpec : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Image";
/**
* @brief Known values for The image's media type. This field **MUST** be
* defined when `bufferView` is defined.
*/
struct MimeType {
/** @brief `image/jpeg` */
inline static const std::string image_jpeg = "image/jpeg";
/** @brief `image/png` */
inline static const std::string image_png = "image/png";
};
/**
* @brief The URI (or IRI) of the image.
*
* Relative paths are relative to the current glTF asset. Instead of
* referencing an external file, this field **MAY** contain a `data:`-URI.
* This field **MUST NOT** be defined when `bufferView` is defined.
*/
std::optional<std::string> uri;
/**
* @brief The image's media type. This field **MUST** be defined when
* `bufferView` is defined.
*
* Known values are defined in {@link MimeType}.
*
*/
std::optional<std::string> mimeType;
/**
* @brief The index of the bufferView that contains the image. This field
* **MUST NOT** be defined when `uri` is defined.
*/
int32_t bufferView = -1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ImageSpec));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
if (this->uri) {
accum += int64_t(this->uri->capacity() * sizeof(char));
}
return accum;
}
protected:
/**
* @brief This class is not meant to be instantiated directly. Use {@link Image} instead.
*/
ImageSpec() = default;
friend struct Image;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,35 @@
#pragma once
#include <array>
#include <string>
namespace CesiumGltf {
/**
* @brief The standard glTF instance attribute semantics from
* `EXT_mesh_gpu_instancing` plus additional instance attribute semantics from
* extensions.
*/
struct InstanceAttributeSemantics {
/**
* @brief XYZ translation vector.
*/
static const std::string TRANSLATION;
/**
* @brief XYZW rotation quaternion.
*/
static const std::string ROTATION;
/**
* @brief XYZ scale vector.
*/
static const std::string SCALE;
/**
* @brief Feature IDs used by `EXT_instance_features`.
*/
static const std::array<std::string, 8> FEATURE_ID_n;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,91 @@
#pragma once
#include "CesiumGltf/ExtensionKhrTextureTransform.h"
#include <glm/glm.hpp>
namespace CesiumGltf {
/**
* @brief The status of a parsed KHR_texture_transform.
*
* The {@link KhrTextureTransform} constructor always completes successfully,
* but it may not always reflect the actual transform if errors occur. This
* enumeration provides the reason.
*/
enum class KhrTextureTransformStatus {
Valid,
ErrorInvalidOffset,
ErrorInvalidScale
};
/**
* @brief A utility class that parses KHR_texture_transform parameters and
* transforms input texture coordinates.
*/
class KhrTextureTransform {
public:
/**
* @brief Constructs a texture transformation with identity values.
*/
KhrTextureTransform() noexcept;
/**
* @brief Constructs a texture transformation from the given extension.
*/
KhrTextureTransform(const ExtensionKhrTextureTransform& extension) noexcept;
/**
* @brief The current \ref KhrTextureTransformStatus of the transform
* operation.
*/
KhrTextureTransformStatus status() const noexcept { return this->_status; }
/**
* @brief Gets the offset of the texture transform.
*/
glm::dvec2 offset() const noexcept { return this->_offset; }
/**
* @brief Gets the rotation (in radians) of the texture transform.
*/
double rotation() const noexcept { return this->_rotation; }
/**
* @brief Gets the sine and cosine of the rotation in the texture transform.
* This is cached to avoid re-computing the values in the future.
*/
glm::dvec2 rotationSineCosine() const noexcept {
return this->_rotationSineCosine;
}
/**
* @brief Gets the scale of the texture transform.
*/
glm::dvec2 scale() const noexcept { return this->_scale; }
/**
* @brief Applies this texture transformation to the input coordinates.
*/
glm::dvec2 applyTransform(double u, double v) const noexcept;
/**
* @brief Gets the texture coordinate set index used by this texture
* transform. If defined, this should override the set index of the texture's
* original textureInfo.
*/
std::optional<int64_t> getTexCoordSetIndex() const noexcept {
return this->_texCoordSetIndex;
}
private:
KhrTextureTransformStatus _status;
glm::dvec2 _offset;
double _rotation;
glm::dvec2 _scale;
std::optional<int64_t> _texCoordSetIndex;
// Cached values of sin(rotation) and cos(rotation).
glm::dvec2 _rotationSineCosine;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,214 @@
#pragma once
#include "CesiumGltf/Library.h"
namespace CesiumGltf {
/**
* @brief Supported GPU compressed pixel formats.
*/
enum class CESIUMGLTF_API GpuCompressedPixelFormat {
/**
* @brief The data is uncompressed.
*/
NONE,
/**
* @brief The data is an <a
* href="https://registry.khronos.org/OpenGL/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt">ETC1-compressed</a>
* RGB888 texture.
*/
ETC1_RGB,
/**
* @brief The data is an ETC2-compressed RGBA8888 texture.
*/
ETC2_RGBA,
/**
* @brief The data is a <a
* href="https://learn.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc1">BC1-compressed</a>
* RGB565 texture.
*/
BC1_RGB,
/**
* @brief The data is a <a
* href="https://learn.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc3">BC3-compressed</a>
* RGBA5658 texture.
*/
BC3_RGBA,
/**
* @brief The data is a <a
* href="https://learn.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc4">BC4-compressed</a>
* R8 texture.
*/
BC4_R,
/**
* @brief The data is a <a
* href="https://learn.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc5">BC5-compressed</a>
* RG88 texture.
*/
BC5_RG,
/**
* @brief The data is a <a
* href="https://learn.microsoft.com/en-us/windows/win32/direct3d11/bc7-format">BC7-compressed</a>
* RGBA8888 texture.
*/
BC7_RGBA,
/**
* @brief The data is a <a
* href="https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#_format_pvrtc1_4bpp">PVRTC1-compressed</a>
* RGB444 texture.
*/
PVRTC1_4_RGB,
/**
* @brief The data is a <a
* href="https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#_format_pvrtc1_4bpp">PVRTC1-compressed</a>
* RGBA4444 texture.
*/
PVRTC1_4_RGBA,
/**
* @brief The data is a <a
* href="https://registry.khronos.org/DataFormat/specs/1.1/dataformat.1.1.html#ASTC">ASTC-compressed</a>
* RGBA texture with a 4x4 block footprint.
*/
ASTC_4x4_RGBA,
/**
* @brief The data is a <a
* href="https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#_format_pvrtc2_4bpp">PVRTC2-compressed</a>
* RGB444 texture.
*/
PVRTC2_4_RGB,
/**
* @brief The data is a <a
* href="https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#_format_pvrtc2_4bpp">PVRTC2-compressed</a>
* RGBA4444 texture.
*/
PVRTC2_4_RGBA,
/**
* @brief The data is a <a
* href="https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#Section-r11eac">ETC2
* R11 EAC-compressed</a> texture with a single channel.
*/
ETC2_EAC_R11,
/**
* @brief The data is a <a
* href="https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#Section-rg11eac">ETC2
* RG11 EAC-compressed</a> texture with two channels.
*/
ETC2_EAC_RG11
};
/**
* @brief Represents the status of support for all
* {@link GpuCompressedPixelFormat}s on a client platform.
*
* Clients can use this struct to convey which gpu compressed pixel formats are
* supported. This can be used to construct a {@link Ktx2TranscodeTargets}.
*
* Each entry in the struct is a bool that represents whether the gpu
* compressed pixel format with the corresponding name is supported.
*/
struct CESIUMGLTF_API SupportedGpuCompressedPixelFormats {
/** @copydoc GpuCompressedPixelFormat::ETC1_RGB */
bool ETC1_RGB{};
/** @copydoc GpuCompressedPixelFormat::ETC2_RGBA */
bool ETC2_RGBA{};
/** @copydoc GpuCompressedPixelFormat::BC1_RGB */
bool BC1_RGB{};
/** @copydoc GpuCompressedPixelFormat::BC3_RGBA */
bool BC3_RGBA{};
/** @copydoc GpuCompressedPixelFormat::BC4_R */
bool BC4_R{};
/** @copydoc GpuCompressedPixelFormat::BC5_RG */
bool BC5_RG{};
/** @copydoc GpuCompressedPixelFormat::BC7_RGBA */
bool BC7_RGBA{};
/** @copydoc GpuCompressedPixelFormat::PVRTC1_4_RGB */
bool PVRTC1_4_RGB{};
/** @copydoc GpuCompressedPixelFormat::PVRTC1_4_RGBA */
bool PVRTC1_4_RGBA{};
/** @copydoc GpuCompressedPixelFormat::ASTC_4x4_RGBA */
bool ASTC_4x4_RGBA{};
/** @copydoc GpuCompressedPixelFormat::PVRTC2_4_RGB */
bool PVRTC2_4_RGB{};
/** @copydoc GpuCompressedPixelFormat::PVRTC2_4_RGBA */
bool PVRTC2_4_RGBA{};
/** @copydoc GpuCompressedPixelFormat::ETC2_EAC_R11 */
bool ETC2_EAC_R11{};
/** @copydoc GpuCompressedPixelFormat::ETC2_EAC_RG11 */
bool ETC2_EAC_RG11{};
};
/**
* @brief For each possible input transmission format, this struct names
* the ideal target gpu-compressed pixel format to transcode to.
*
* When built with the constructor, these targets can take into account
* platform-specific support for target formats as reported by the client.
*/
struct CESIUMGLTF_API Ktx2TranscodeTargets {
/**
* @brief The gpu pixel compression format to transcode Red ETC1S textures
* into. If NONE, it will be decompressed into raw pixels.
*/
GpuCompressedPixelFormat ETC1S_R = GpuCompressedPixelFormat::NONE;
/**
* @brief The gpu pixel compression format to transcode Red-Green ETC1S
* textures into, if one exists. Otherwise it will be decompressed into raw
* pixels.
*/
GpuCompressedPixelFormat ETC1S_RG = GpuCompressedPixelFormat::NONE;
/**
* @brief The gpu pixel compression format to transcode RGB ETC1S textures
* into. If NONE, it will be decompressed into raw pixels.
*/
GpuCompressedPixelFormat ETC1S_RGB = GpuCompressedPixelFormat::NONE;
/**
* @brief The gpu pixel compression format to transcode RGBA ETC1S textures
* into. If NONE, it will be decompressed into raw pixels.
*/
GpuCompressedPixelFormat ETC1S_RGBA = GpuCompressedPixelFormat::NONE;
/**
* @brief The gpu pixel compression format to transcode Red UASTC textures
* into. If NONE, it will be decompressed into raw pixels.
*/
GpuCompressedPixelFormat UASTC_R = GpuCompressedPixelFormat::NONE;
/**
* @brief The gpu pixel compression format to transcode Red-Green UASTC
* textures into. If NONE, it will be decompressed into raw pixels.
*/
GpuCompressedPixelFormat UASTC_RG = GpuCompressedPixelFormat::NONE;
/**
* @brief The gpu pixel compression format to transcode RGB UASTC textures
* into. If NONE, it will be decompressed into raw pixels.
*/
GpuCompressedPixelFormat UASTC_RGB = GpuCompressedPixelFormat::NONE;
/**
* @brief The gpu pixel compression format to transcode RGBA UASTC textures
* into. If NONE, it will be decompressed into raw pixels.
*/
GpuCompressedPixelFormat UASTC_RGBA = GpuCompressedPixelFormat::NONE;
Ktx2TranscodeTargets() = default;
/**
* @brief Determine ideal transcode targets based on a list of supported gpu
* compressed formats.
*
* @param supportedFormats The supported gpu compressed pixel formats.
* @param preserveHighQuality Whether to preserve texture quality when
* transcoding KTXv2 textures. If this is true, the texture may be fully
* decompressed instead of picking a lossy target gpu compressed pixel format.
*/
Ktx2TranscodeTargets(
const SupportedGpuCompressedPixelFormats& supportedFormats,
bool preserveHighQuality);
};
} // namespace CesiumGltf

View File

@ -0,0 +1,18 @@
#pragma once
/**
* @brief Classes for working with [glTF](https://www.khronos.org/gltf/) models.
*
* @mermaid-interactive{dependencies/CesiumGltf}
*/
namespace CesiumGltf {}
#if defined(_WIN32) && defined(CESIUM_SHARED)
#ifdef CESIUMGLTF_BUILDING
#define CESIUMGLTF_API __declspec(dllexport)
#else
#define CESIUMGLTF_API __declspec(dllimport)
#endif
#else
#define CESIUMGLTF_API
#endif

View File

@ -0,0 +1,160 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/MaterialNormalTextureInfo.h>
#include <CesiumGltf/MaterialOcclusionTextureInfo.h>
#include <CesiumGltf/MaterialPBRMetallicRoughness.h>
#include <CesiumGltf/NamedObject.h>
#include <CesiumGltf/TextureInfo.h>
#include <optional>
#include <string>
#include <vector>
namespace CesiumGltf {
/**
* @brief The material appearance of a primitive.
*/
struct CESIUMGLTF_API Material final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Material";
/**
* @brief Known values for The alpha rendering mode of the material.
*/
struct AlphaMode {
/** @brief The alpha value is ignored, and the rendered output is fully
* opaque. */
inline static const std::string OPAQUE = "OPAQUE";
/** @brief The rendered output is either fully opaque or fully transparent
* depending on the alpha value and the specified `alphaCutoff` value; the
* exact appearance of the edges **MAY** be subject to
* implementation-specific techniques such as "`Alpha-to-Coverage`". */
inline static const std::string MASK = "MASK";
/** @brief The alpha value is used to composite the source and destination
* areas. The rendered output is combined with the background using the
* normal painting operation (i.e. the Porter and Duff over operator). */
inline static const std::string BLEND = "BLEND";
};
/**
* @brief A set of parameter values that are used to define the
* metallic-roughness material model from Physically Based Rendering (PBR)
* methodology. When undefined, all the default values of
* `pbrMetallicRoughness` **MUST** apply.
*/
std::optional<CesiumGltf::MaterialPBRMetallicRoughness> pbrMetallicRoughness;
/**
* @brief The tangent space normal texture.
*
* The texture encodes RGB components with linear transfer function. Each
* texel represents the XYZ components of a normal vector in tangent space.
* The normal vectors use the convention +X is right and +Y is up. +Z points
* toward the viewer. If a fourth component (A) is present, it **MUST** be
* ignored. When undefined, the material does not have a tangent space normal
* texture.
*/
std::optional<CesiumGltf::MaterialNormalTextureInfo> normalTexture;
/**
* @brief The occlusion texture.
*
* The occlusion values are linearly sampled from the R channel. Higher values
* indicate areas that receive full indirect lighting and lower values
* indicate no indirect lighting. If other channels are present (GBA), they
* **MUST** be ignored for occlusion calculations. When undefined, the
* material does not have an occlusion texture.
*/
std::optional<CesiumGltf::MaterialOcclusionTextureInfo> occlusionTexture;
/**
* @brief The emissive texture.
*
* It controls the color and intensity of the light being emitted by the
* material. This texture contains RGB components encoded with the sRGB
* transfer function. If a fourth component (A) is present, it **MUST** be
* ignored. When undefined, the texture **MUST** be sampled as having `1.0` in
* RGB components.
*/
std::optional<CesiumGltf::TextureInfo> emissiveTexture;
/**
* @brief The factors for the emissive color of the material.
*
* This value defines linear multipliers for the sampled texels of the
* emissive texture.
*/
std::vector<double> emissiveFactor = {0, 0, 0};
/**
* @brief The alpha rendering mode of the material.
*
* Known values are defined in {@link AlphaMode}.
*
*
* The material's alpha rendering mode enumeration specifying the
* interpretation of the alpha value of the base color.
*/
std::string alphaMode = AlphaMode::OPAQUE;
/**
* @brief The alpha cutoff value of the material.
*
* Specifies the cutoff threshold when in `MASK` alpha mode. If the alpha
* value is greater than or equal to this value then it is rendered as fully
* opaque, otherwise, it is rendered as fully transparent. A value greater
* than `1.0` will render the entire material as fully transparent. This value
* **MUST** be ignored for other alpha modes. When `alphaMode` is not defined,
* this value **MUST NOT** be defined.
*/
double alphaCutoff = 0.5;
/**
* @brief Specifies whether the material is double sided.
*
* When this value is false, back-face culling is enabled. When this value is
* true, back-face culling is disabled and double-sided lighting is enabled.
* The back-face **MUST** have its normals reversed before the lighting
* equation is evaluated.
*/
bool doubleSided = false;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Material));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
if (this->pbrMetallicRoughness) {
accum += this->pbrMetallicRoughness->getSizeBytes() -
int64_t(sizeof(CesiumGltf::MaterialPBRMetallicRoughness));
}
if (this->normalTexture) {
accum += this->normalTexture->getSizeBytes() -
int64_t(sizeof(CesiumGltf::MaterialNormalTextureInfo));
}
if (this->occlusionTexture) {
accum += this->occlusionTexture->getSizeBytes() -
int64_t(sizeof(CesiumGltf::MaterialOcclusionTextureInfo));
}
if (this->emissiveTexture) {
accum += this->emissiveTexture->getSizeBytes() -
int64_t(sizeof(CesiumGltf::TextureInfo));
}
accum += int64_t(sizeof(double) * this->emissiveFactor.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,43 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/TextureInfo.h>
namespace CesiumGltf {
/**
* @brief Material Normal Texture Info
*/
struct CESIUMGLTF_API MaterialNormalTextureInfo final : public TextureInfo {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "MaterialNormalTextureInfo";
/**
* @brief The scalar parameter applied to each normal vector of the normal
* texture.
*
* The scalar parameter applied to each normal vector of the texture. This
* value scales the normal vector in X and Y directions using the formula:
* `scaledNormal = normalize((<sampled normal texture value> * 2.0 - 1.0) *
* vec3(<normal scale>, <normal scale>, 1.0))`.
*/
double scale = 1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(MaterialNormalTextureInfo));
accum += TextureInfo::getSizeBytes() - int64_t(sizeof(TextureInfo));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,42 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/TextureInfo.h>
namespace CesiumGltf {
/**
* @brief Material Occlusion Texture Info
*/
struct CESIUMGLTF_API MaterialOcclusionTextureInfo final : public TextureInfo {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "MaterialOcclusionTextureInfo";
/**
* @brief A scalar multiplier controlling the amount of occlusion applied.
*
* A scalar parameter controlling the amount of occlusion applied. A value of
* `0.0` means no occlusion. A value of `1.0` means full occlusion. This value
* affects the final occlusion value as: `1.0 + strength * (<sampled occlusion
* texture value> - 1.0)`.
*/
double strength = 1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(MaterialOcclusionTextureInfo));
accum += TextureInfo::getSizeBytes() - int64_t(sizeof(TextureInfo));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,96 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/TextureInfo.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <optional>
#include <vector>
namespace CesiumGltf {
/**
* @brief A set of parameter values that are used to define the
* metallic-roughness material model from Physically-Based Rendering (PBR)
* methodology.
*/
struct CESIUMGLTF_API MaterialPBRMetallicRoughness final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "MaterialPBRMetallicRoughness";
/**
* @brief The factors for the base color of the material.
*
* This value defines linear multipliers for the sampled texels of the base
* color texture.
*/
std::vector<double> baseColorFactor = {1, 1, 1, 1};
/**
* @brief The base color texture.
*
* The first three components (RGB) **MUST** be encoded with the sRGB transfer
* function. They specify the base color of the material. If the fourth
* component (A) is present, it represents the linear alpha coverage of the
* material. Otherwise, the alpha coverage is equal to `1.0`. The
* `material.alphaMode` property specifies how alpha is interpreted. The
* stored texels **MUST NOT** be premultiplied. When undefined, the texture
* **MUST** be sampled as having `1.0` in all components.
*/
std::optional<CesiumGltf::TextureInfo> baseColorTexture;
/**
* @brief The factor for the metalness of the material.
*
* This value defines a linear multiplier for the sampled metalness values of
* the metallic-roughness texture.
*/
double metallicFactor = 1;
/**
* @brief The factor for the roughness of the material.
*
* This value defines a linear multiplier for the sampled roughness values of
* the metallic-roughness texture.
*/
double roughnessFactor = 1;
/**
* @brief The metallic-roughness texture.
*
* The metalness values are sampled from the B channel. The roughness values
* are sampled from the G channel. These values **MUST** be encoded with a
* linear transfer function. If other channels are present (R or A), they
* **MUST** be ignored for metallic-roughness calculations. When undefined,
* the texture **MUST** be sampled as having `1.0` in G and B components.
*/
std::optional<CesiumGltf::TextureInfo> metallicRoughnessTexture;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(MaterialPBRMetallicRoughness));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(sizeof(double) * this->baseColorFactor.capacity());
if (this->baseColorTexture) {
accum += this->baseColorTexture->getSizeBytes() -
int64_t(sizeof(CesiumGltf::TextureInfo));
}
if (this->metallicRoughnessTexture) {
accum += this->metallicRoughnessTexture->getSizeBytes() -
int64_t(sizeof(CesiumGltf::TextureInfo));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,54 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/MeshPrimitive.h>
#include <CesiumGltf/NamedObject.h>
#include <vector>
namespace CesiumGltf {
/**
* @brief A set of primitives to be rendered. Its global transform is defined
* by a node that references it.
*/
struct CESIUMGLTF_API Mesh final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Mesh";
/**
* @brief An array of primitives, each defining geometry to be rendered.
*/
std::vector<CesiumGltf::MeshPrimitive> primitives;
/**
* @brief Array of weights to be applied to the morph targets. The number of
* array elements **MUST** match the number of morph targets.
*/
std::vector<double> weights;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Mesh));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
accum += int64_t(
sizeof(CesiumGltf::MeshPrimitive) * this->primitives.capacity());
for (const CesiumGltf::MeshPrimitive& value : this->primitives) {
accum +=
value.getSizeBytes() - int64_t(sizeof(CesiumGltf::MeshPrimitive));
}
accum += int64_t(sizeof(double) * this->weights.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,108 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
namespace CesiumGltf {
/**
* @brief Geometry to be rendered with the given material.
*/
struct CESIUMGLTF_API MeshPrimitive final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "MeshPrimitive";
/**
* @brief Known values for The topology type of primitives to render.
*/
struct Mode {
/** @brief POINTS (`0`) */
static constexpr int32_t POINTS = 0;
/** @brief LINES (`1`) */
static constexpr int32_t LINES = 1;
/** @brief LINE_LOOP (`2`) */
static constexpr int32_t LINE_LOOP = 2;
/** @brief LINE_STRIP (`3`) */
static constexpr int32_t LINE_STRIP = 3;
/** @brief TRIANGLES (`4`) */
static constexpr int32_t TRIANGLES = 4;
/** @brief TRIANGLE_STRIP (`5`) */
static constexpr int32_t TRIANGLE_STRIP = 5;
/** @brief TRIANGLE_FAN (`6`) */
static constexpr int32_t TRIANGLE_FAN = 6;
};
/**
* @brief A plain JSON object, where each key corresponds to a mesh attribute
* semantic and each value is the index of the accessor containing attribute's
* data.
*/
std::unordered_map<std::string, int32_t> attributes;
/**
* @brief The index of the accessor that contains the vertex indices.
*
* When this is undefined, the primitive defines non-indexed geometry. When
* defined, the accessor **MUST** have `SCALAR` type and an unsigned integer
* component type.
*/
int32_t indices = -1;
/**
* @brief The index of the material to apply to this primitive when rendering.
*/
int32_t material = -1;
/**
* @brief The topology type of primitives to render.
*
* Known values are defined in {@link Mode}.
*
*/
int32_t mode = Mode::TRIANGLES;
/**
* @brief An array of morph targets.
*/
std::vector<std::unordered_map<std::string, int32_t>> targets;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(MeshPrimitive));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(
this->attributes.bucket_count() *
(sizeof(std::string) + sizeof(int32_t)));
for (const auto& [k, v] : this->attributes) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += int64_t(sizeof(int32_t));
}
accum += int64_t(
sizeof(std::unordered_map<std::string, int32_t>) *
this->targets.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,865 @@
#pragma once
#include "PropertyTypeTraits.h"
#include <CesiumUtility/JsonValue.h>
#include <glm/common.hpp>
#include <cerrno>
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#ifndef GLM_ENABLE_EXPERIMENTAL
// If we define GLM_ENABLE_EXPERIMENTAL here, we undefine it at the end of this
// header file.
#define GLM_ENABLE_EXPERIMENTAL
#define GLM_ENABLE_EXPERIMENTAL_defined_locally
#endif
#include <glm/gtx/string_cast.hpp>
namespace CesiumGltf {
/**
* @brief Default conversion between two types. No actual conversion is defined.
* This returns std::nullopt to indicate the conversion was not successful.
*/
template <typename TTo, typename TFrom, typename Enable = void>
struct MetadataConversions {
/**
* @brief Converts between `TFrom` and `TTo` where no actual conversion is
* defined, returning `std::nullopt`.
*/
static std::optional<TTo> convert(TFrom /*from*/) { return std::nullopt; }
};
/**
* @brief Trivially converts any type to itself.
*/
template <typename T> struct MetadataConversions<T, T> {
/**
* @brief Converts an instance of `T` to an instance of `T`, always returning
* the same value that was passed in.
*/
static std::optional<T> convert(T from) { return from; }
};
#pragma region Conversions to boolean
/**
* @brief Converts from a scalar to a bool.
*/
template <typename TFrom>
struct MetadataConversions<
bool,
TFrom,
std::enable_if_t<CesiumGltf::IsMetadataScalar<TFrom>::value>> {
/**
* @brief Converts a scalar to a boolean. Zero is converted to false, while
* nonzero values are converted to true.
*
* @param from The scalar to convert from.
*/
static std::optional<bool> convert(TFrom from) {
return from != static_cast<TFrom>(0);
}
};
/**
* @brief Converts from std::string_view to a bool.
*/
template <> struct MetadataConversions<bool, std::string_view> {
private:
static bool
isEqualCaseInsensitive(const std::string_view& a, const std::string_view& b) {
if (a.size() != b.size()) {
return false;
}
for (size_t i = 0; i < a.size(); i++) {
if (std::tolower(a[i]) != std::tolower(b[i])) {
return false;
}
}
return true;
}
public:
/**
* @brief Converts the contents of a std::string_view to a boolean.
*
* "0", "false", and "no" (case-insensitive) are converted to false, while
* "1", "true", and "yes" are converted to true. All other strings will return
* std::nullopt.
*
* @param from The std::string_view to convert from.
*/
static std::optional<bool> convert(const std::string_view& from) {
if (isEqualCaseInsensitive(from, "1") ||
isEqualCaseInsensitive(from, "true") ||
isEqualCaseInsensitive(from, "yes")) {
return true;
}
if (isEqualCaseInsensitive(from, "0") ||
isEqualCaseInsensitive(from, "false") ||
isEqualCaseInsensitive(from, "no")) {
return false;
}
return std::nullopt;
}
};
/**
* @brief Converts from std::string to a bool.
*/
template <> struct MetadataConversions<bool, std::string> {
public:
/**
* @brief Converts the contents of a std::string to a boolean.
*
* "0", "false", and "no" (case-insensitive) are converted to false, while
* "1", "true", and "yes" are converted to true. All other strings will return
* std::nullopt.
*
* @param from The std::string to convert from.
*/
static std::optional<bool> convert(const std::string& from) {
return MetadataConversions<bool, std::string_view>::convert(
std::string_view(from.data(), from.size()));
}
};
#pragma endregion
#pragma region Conversions to integer
/**
* @brief Converts from one integer type to another.
*/
template <typename TTo, typename TFrom>
struct MetadataConversions<
TTo,
TFrom,
std::enable_if_t<
CesiumGltf::IsMetadataInteger<TTo>::value &&
CesiumGltf::IsMetadataInteger<TFrom>::value &&
!std::is_same_v<TTo, TFrom>>> {
/**
* @brief Converts a value of the given integer to another integer type. If
* the integer cannot be losslessly converted to the desired type,
* std::nullopt is returned.
*
* @param from The integer value to convert from.
*/
static std::optional<TTo> convert(TFrom from) {
return CesiumUtility::losslessNarrow<TTo, TFrom>(from);
}
};
/**
* @brief Converts from a floating-point type to an integer.
*/
template <typename TTo, typename TFrom>
struct MetadataConversions<
TTo,
TFrom,
std::enable_if_t<
CesiumGltf::IsMetadataInteger<TTo>::value &&
CesiumGltf::IsMetadataFloating<TFrom>::value>> {
/**
* @brief Converts a floating-point value to an integer type. This truncates
* the floating-point value, rounding it towards zero.
*
* If the value is outside the range of the integer type, std::nullopt is
* returned.
*
* @param from The floating-point value to convert from.
*/
static std::optional<TTo> convert(TFrom from) {
if (double(std::numeric_limits<TTo>::max()) < from ||
double(std::numeric_limits<TTo>::lowest()) > from) {
// Floating-point number is outside the range of this integer type.
return std::nullopt;
}
return static_cast<TTo>(from);
}
};
/**
* @brief Converts from std::string to a signed integer.
*/
template <typename TTo>
struct MetadataConversions<
TTo,
std::string,
std::enable_if_t<
CesiumGltf::IsMetadataInteger<TTo>::value && std::is_signed_v<TTo>>> {
/**
* @brief Converts the contents of a std::string to a signed integer.
* This assumes that the entire std::string represents the number, not
* just a part of it.
*
* This returns std::nullopt if no number is parsed from the string.
*
* @param from The std::string to parse from.
*/
static std::optional<TTo> convert(const std::string& from) {
if (from.size() == 0) {
// Return early. Otherwise, empty strings will be parsed as 0, which is
// misleading.
return std::nullopt;
}
errno = 0;
char* pLastUsed;
int64_t parsedValue = std::strtoll(from.c_str(), &pLastUsed, 10);
if (errno == 0 && pLastUsed == from.c_str() + from.size()) {
// Successfully parsed the entire string as an integer of this type.
return CesiumUtility::losslessNarrow<TTo, int64_t>(parsedValue);
}
errno = 0;
// Failed to parse as an integer. Maybe we can parse as a double and
// truncate it?
double parsedDouble = std::strtod(from.c_str(), &pLastUsed);
if (errno == 0 && pLastUsed == from.c_str() + from.size()) {
// Successfully parsed the entire string as a double.
// Convert it to an integer if we can.
double truncated = glm::trunc(parsedDouble);
int64_t asInteger = static_cast<int64_t>(truncated);
double roundTrip = static_cast<double>(asInteger);
if (roundTrip == truncated) {
return CesiumUtility::losslessNarrow<TTo, int64_t>(asInteger);
}
}
return std::nullopt;
}
}; // namespace CesiumGltf
/**
* @brief Converts from std::string to an unsigned integer.
*/
template <typename TTo>
struct MetadataConversions<
TTo,
std::string,
std::enable_if_t<
CesiumGltf::IsMetadataInteger<TTo>::value && !std::is_signed_v<TTo>>> {
/**
* @brief Converts the contents of a std::string to an unsigned integer.
* This assumes that the entire std::string represents the number, not
* just a part of it.
*
* This returns std::nullopt if no number is parsed from the string.
*
* @param from The std::string to parse from.
*/
static std::optional<TTo> convert(const std::string& from) {
if (from.size() == 0) {
// Return early. Otherwise, empty strings will be parsed as 0, which is
// misleading.
return std::nullopt;
}
if (from.find('-') != std::string::npos) {
// The string must be manually checked for a negative sign because for
// std::strtoull accepts negative numbers and bitcasts them, which is not
// desired!
return std::nullopt;
}
errno = 0;
char* pLastUsed;
uint64_t parsedValue = std::strtoull(from.c_str(), &pLastUsed, 10);
if (errno == 0 && pLastUsed == from.c_str() + from.size()) {
// Successfully parsed the entire string as an integer of this type.
return CesiumUtility::losslessNarrow<TTo, uint64_t>(parsedValue);
}
// Failed to parse as an integer. Maybe we can parse as a double and
// truncate it?
errno = 0;
double parsedDouble = std::strtod(from.c_str(), &pLastUsed);
if (errno == 0 && pLastUsed == from.c_str() + from.size()) {
// Successfully parsed the entire string as a double.
// Convert it to an integer if we can.
double truncated = glm::trunc(parsedDouble);
uint64_t asInteger = static_cast<uint64_t>(truncated);
double roundTrip = static_cast<double>(asInteger);
if (roundTrip == truncated) {
return CesiumUtility::losslessNarrow<TTo, uint64_t>(asInteger);
}
}
return std::nullopt;
}
};
/**
* @brief Converts from std::string_view to an integer.
*/
template <typename TTo>
struct MetadataConversions<
TTo,
std::string_view,
std::enable_if_t<CesiumGltf::IsMetadataInteger<TTo>::value>> {
/**
* @brief Converts the contents of a std::string_view to an integer.
* This assumes that the entire std::string_view represents the number, not
* just a part of it.
*
* This returns std::nullopt if no number is parsed from the string.
*
* @param from The std::string_view to parse from.
*/
static std::optional<TTo> convert(const std::string_view& from) {
if (from.size() == 0) {
// Return early. Otherwise, empty strings will be parsed as 0, which is
// misleading.
return std::nullopt;
}
// Amazingly, C++ has no* string parsing functions that work with strings
// that might not be null-terminated. So we have to copy to a std::string
// (which _is_ guaranteed to be null terminated) before parsing.
// * except std::from_chars, but compiler/library support for the
// floating-point version of that method is spotty at best.
return MetadataConversions<TTo, std::string>::convert(std::string(from));
}
};
/**
* @brief Converts from a boolean to an integer type.
*/
template <typename TTo>
struct MetadataConversions<
TTo,
bool,
std::enable_if_t<CesiumGltf::IsMetadataInteger<TTo>::value>> {
/**
* @brief Converts a boolean to an integer. This returns 1 for true, 0 for
* false.
*
* @param from The boolean value to be converted.
*/
static std::optional<TTo> convert(bool from) { return from ? 1 : 0; }
};
#pragma endregion
#pragma region Conversions to float
/**
* @brief Converts from a boolean to a float.
*/
template <> struct MetadataConversions<float, bool> {
/**
* @brief Converts a boolean to a float. This returns 1.0f for true, 0.0f for
* false.
*
* @param from The boolean value to be converted.
*/
static std::optional<float> convert(bool from) { return from ? 1.0f : 0.0f; }
};
/**
* @brief Converts from an integer type to a float.
*/
template <typename TFrom>
struct MetadataConversions<
float,
TFrom,
std::enable_if_t<CesiumGltf::IsMetadataInteger<TFrom>::value>> {
/**
* @brief Converts an integer to a float. The value may lose precision during
* conversion.
*
* @param from The integer value to be converted.
*/
static std::optional<float> convert(TFrom from) {
return static_cast<float>(from);
}
};
/**
* @brief Converts from a double to a float.
*/
template <> struct MetadataConversions<float, double> {
/**
* @brief Converts a double to a float. The value may lose precision during
* conversion.
*
* If the value is outside the range of a float, std::nullopt is returned.
*
* @param from The double value to be converted.
*/
static std::optional<float> convert(double from) {
if (from > std::numeric_limits<float>::max() ||
from < std::numeric_limits<float>::lowest()) {
return std::nullopt;
}
return static_cast<float>(from);
}
};
/**
* @brief Converts from a std::string to a float.
*/
template <> struct MetadataConversions<float, std::string> {
/**
* @brief Converts a std::string to a float. This assumes that the entire
* std::string represents the number, not just a part of it.
*
* This returns std::nullopt if no number is parsed from the string.
*
* @param from The std::string to parse from.
*/
static std::optional<float> convert(const std::string& from) {
if (from.size() == 0) {
// Return early. Otherwise, empty strings will be parsed as 0, which is
// misleading.
return std::nullopt;
}
errno = 0;
char* pLastUsed;
float parsedValue = std::strtof(from.c_str(), &pLastUsed);
if (errno == 0 && pLastUsed == from.c_str() + from.size() &&
!std::isinf(parsedValue)) {
// Successfully parsed the entire string as a float.
return parsedValue;
}
return std::nullopt;
}
};
/**
* @brief Converts from a std::string_view to a float.
*/
template <> struct MetadataConversions<float, std::string_view> {
/**
* @brief Converts a std::string_view to a float. This assumes that the entire
* std::string_view represents the number, not just a part of it.
*
* This returns std::nullopt if no number is parsed from the string.
*
* @param from The std::string_view to parse from.
*/
static std::optional<float> convert(const std::string_view& from) {
if (from.size() == 0) {
// Return early. Otherwise, empty strings will be parsed as 0, which is
// misleading.
return std::nullopt;
}
// Amazingly, C++ has no* string parsing functions that work with strings
// that might not be null-terminated. So we have to copy to a std::string
// (which _is_ guaranteed to be null terminated) before parsing.
// * except std::from_chars, but compiler/library support for the
// floating-point version of that method is spotty at best.
return MetadataConversions<float, std::string>::convert(
std::string(from.data(), from.size()));
}
};
#pragma endregion
#pragma region Conversions to double
/**
* @brief Converts from a boolean to a double.
*/
template <> struct MetadataConversions<double, bool> {
/**
* @brief Converts a boolean to a double. This returns 1.0 for true, 0.0 for
* false.
*
* @param from The boolean value to be converted.
*/
static std::optional<double> convert(bool from) { return from ? 1.0 : 0.0; }
};
/**
* @brief Converts from any integer type to a double.
*/
template <typename TFrom>
struct MetadataConversions<
double,
TFrom,
std::enable_if_t<CesiumGltf::IsMetadataInteger<TFrom>::value>> {
/**
* @brief Converts any integer type to a double. The value may lose precision
* during conversion.
*
* @param from The boolean value to be converted.
*/
static std::optional<double> convert(TFrom from) {
return static_cast<double>(from);
}
};
/**
* @brief Converts from a float to a double.
*/
template <> struct MetadataConversions<double, float> {
/**
* @brief Converts from a float to a double.
*
* @param from The float value to be converted.
*/
static std::optional<double> convert(float from) {
return static_cast<double>(from);
}
};
/**
* @brief Converts from std::string to a double.
*/
template <> struct MetadataConversions<double, std::string> {
/**
* Converts a std::string to a double. This assumes that the entire
* std::string represents the number, not just a part of it.
*
* This returns std::nullopt if no number is parsed from the string.
*
* @param from The std::string to parse from.
*/
static std::optional<double> convert(const std::string& from) {
if (from.size() == 0) {
// Return early. Otherwise, empty strings will be parsed as 0, which is
// misleading.
return std::nullopt;
}
errno = 0;
char* pLastUsed;
double parsedValue = std::strtod(from.c_str(), &pLastUsed);
if (errno == 0 && pLastUsed == from.c_str() + from.size() &&
!std::isinf(parsedValue)) {
// Successfully parsed the entire string as a double.
return parsedValue;
}
return std::nullopt;
}
};
/**
* @brief Converts from std::string_view to a double.
*/
template <> struct MetadataConversions<double, std::string_view> {
/**
* Converts a std::string_view to a double. This assumes that the entire
* std::string_view represents the number, not just a part of it.
*
* This returns std::nullopt if no number is parsed from the string.
*
* @param from The std::string_view to parse from.
*/
static std::optional<double> convert(const std::string_view& from) {
if (from.size() == 0) {
// Return early. Otherwise, empty strings will be parsed as 0, which is
// misleading.
return std::nullopt;
}
// Amazingly, C++ has no* string parsing functions that work with strings
// that might not be null-terminated. So we have to copy to a std::string
// (which _is_ guaranteed to be null terminated) before parsing.
// * except std::from_chars, but compiler/library support for the
// floating-point version of that method is spotty at best.
return MetadataConversions<double, std::string>::convert(std::string(from));
}
};
#pragma endregion
#pragma region Conversions to string
/**
* @brief Converts from a boolean to a string.
*/
template <> struct MetadataConversions<std::string, bool> {
/**
* @brief Converts a boolean to a std::string. Returns "true" for true and
* "false" for false.
*
* @param from The boolean to be converted.
*/
static std::optional<std::string> convert(bool from) {
return from ? "true" : "false";
}
};
/**
* @brief Converts from a scalar to a string.
*/
template <typename TFrom>
struct MetadataConversions<
std::string,
TFrom,
std::enable_if_t<IsMetadataScalar<TFrom>::value>> {
/**
* @brief Converts a scalar to a std::string.
*
* @param from The scalar to be converted.
*/
static std::optional<std::string> convert(TFrom from) {
return std::to_string(from);
}
};
/**
* @brief Converts from a glm::vecN or glm::matN to a string.
*/
template <typename TFrom>
struct MetadataConversions<
std::string,
TFrom,
std::enable_if_t<
IsMetadataVecN<TFrom>::value || IsMetadataMatN<TFrom>::value>> {
/**
* @brief Converts a glm::vecN or glm::matN to a std::string. This uses the
* format that glm::to_string() outputs for vecNs or matNs respectively.
*
* @param from The glm::vecN or glm::matN to be converted.
*/
static std::optional<std::string> convert(const TFrom& from) {
return glm::to_string(from);
}
};
/**
* @brief Converts from a std::string_view to a std::string.
*/
template <> struct MetadataConversions<std::string, std::string_view> {
/**
* @brief Converts from a std::string_view to a std::string.
*/
static std::optional<std::string> convert(const std::string_view& from) {
return std::string(from.data(), from.size());
}
};
#pragma endregion
#pragma region Conversions to glm::vecN
/**
* @brief Converts from a boolean to a vecN.
*/
template <typename TTo>
struct MetadataConversions<
TTo,
bool,
std::enable_if_t<IsMetadataVecN<TTo>::value>> {
/**
* @brief Converts a boolean to a vecN. The boolean is converted to an integer
* value of 1 for true or 0 for false. The returned vector is initialized with
* this value in both of its components.
*
* @param from The boolean to be converted.
*/
static std::optional<TTo> convert(bool from) {
return from ? TTo(1) : TTo(0);
}
};
/**
* @brief Converts from a scalar type to a vecN.
*/
template <typename TTo, typename TFrom>
struct MetadataConversions<
TTo,
TFrom,
std::enable_if_t<
CesiumGltf::IsMetadataVecN<TTo>::value &&
CesiumGltf::IsMetadataScalar<TFrom>::value>> {
/**
* @brief Converts a scalar to a vecN. The returned vector is initialized
* with the value in all of its components. The value may lose precision
* during conversion depending on the type of the scalar and the component
* type of the matrix.
*
* If the scalar cannot be reasonably converted to the component type of the
* vecN, std::nullopt is returned.
*
* @param from The scalar value to be converted.
*/
static std::optional<TTo> convert(TFrom from) {
using ToValueType = typename TTo::value_type;
std::optional<ToValueType> maybeValue =
MetadataConversions<ToValueType, TFrom>::convert(from);
if (maybeValue) {
ToValueType value = *maybeValue;
return TTo(value);
}
return std::nullopt;
}
};
/**
* @brief Converts from a vecN type to another vecN type.
*/
template <typename TTo, typename TFrom>
struct MetadataConversions<
TTo,
TFrom,
std::enable_if_t<
CesiumGltf::IsMetadataVecN<TTo>::value &&
CesiumGltf::IsMetadataVecN<TFrom>::value &&
!std::is_same_v<TTo, TFrom>>> {
/**
* @brief Converts a value of the given vecN to another vecN type.
*
* If the given vector has more components than the target vecN type, then
* only its first N components will be used, where N is the dimension of the
* target vecN type. Otherwise, if the target vecN type has more components,
* its extra components will be initialized to zero.
*
* If any of the relevant components cannot be converted to the target vecN
* component type, std::nullopt is returned.
*
* @param from The vecN value to convert from.
*/
static std::optional<TTo> convert(TFrom from) {
TTo result = TTo(0);
constexpr glm::length_t validLength =
glm::min(TTo::length(), TFrom::length());
using ToValueType = typename TTo::value_type;
using FromValueType = typename TFrom::value_type;
for (glm::length_t i = 0; i < validLength; i++) {
auto maybeValue =
MetadataConversions<ToValueType, FromValueType>::convert(from[i]);
if (!maybeValue) {
return std::nullopt;
}
result[i] = *maybeValue;
}
return result;
}
};
#pragma endregion
#pragma region Conversions to glm::matN
/**
* @brief Converts from a boolean to a matN.
*/
template <typename TTo>
struct MetadataConversions<
TTo,
bool,
std::enable_if_t<IsMetadataMatN<TTo>::value>> {
/**
* @brief Converts a boolean to a matN. The boolean is converted to an integer
* value of 1 for true or 0 for false. The returned matrix is initialized with
* this value in all of its components.
*
* @param from The boolean to be converted.
*/
static std::optional<TTo> convert(bool from) {
return from ? TTo(1) : TTo(0);
}
};
/**
* Converts from a scalar type to a matN.
*/
template <typename TTo, typename TFrom>
struct MetadataConversions<
TTo,
TFrom,
std::enable_if_t<
CesiumGltf::IsMetadataMatN<TTo>::value &&
CesiumGltf::IsMetadataScalar<TFrom>::value>> {
/**
* Converts a scalar to a matN. The returned vector is initialized
* with the value in all components. The value may lose precision during
* conversion depending on the type of the scalar and the component type of
* the matrix.
*
* If the scalar cannot be reasonably converted to the component type of the
* matN, std::nullopt is returned.
*
* @param from The scalar value to be converted.
*/
static std::optional<TTo> convert(TFrom from) {
using ToValueType = typename TTo::value_type;
std::optional<ToValueType> maybeValue =
MetadataConversions<ToValueType, TFrom>::convert(from);
if (!maybeValue) {
return std::nullopt;
}
ToValueType value = *maybeValue;
return TTo(value);
}
};
/**
* @brief Converts from a matN type to another matN type.
*/
template <typename TTo, typename TFrom>
struct MetadataConversions<
TTo,
TFrom,
std::enable_if_t<
CesiumGltf::IsMetadataMatN<TTo>::value &&
CesiumGltf::IsMetadataMatN<TFrom>::value &&
!std::is_same_v<TTo, TFrom>>> {
/**
* @brief Converts a value of the given matN to another matN type.
*
* Let M be the length of the given matN, and N be the length of the target
* matN. If M > N, then only the first N components of the first N columns
* will be used. Otherwise, if M < N, all other elements in the N x N matrix
* will be initialized to zero.
*
* If any of the relevant components cannot be converted to the target matN
* component type, std::nullopt is returned.
*
* @param from The matN value to convert from.
*/
static std::optional<TTo> convert(TFrom from) {
TTo result = TTo(0);
constexpr glm::length_t validLength =
glm::min(TTo::length(), TFrom::length());
using ToValueType = typename TTo::value_type;
using FromValueType = typename TFrom::value_type;
for (glm::length_t c = 0; c < validLength; c++) {
for (glm::length_t r = 0; r < validLength; r++) {
auto maybeValue =
MetadataConversions<ToValueType, FromValueType>::convert(
from[c][r]);
if (!maybeValue) {
return std::nullopt;
}
result[c][r] = *maybeValue;
}
}
return result;
}
};
#pragma endregion
} // namespace CesiumGltf
#ifdef GLM_ENABLE_EXPERIMENTAL_defined_locally
#undef GLM_ENABLE_EXPERIMENTAL
#undef GLM_ENABLE_EXPERIMENTAL_defined_locally
#endif

View File

@ -0,0 +1,287 @@
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/ModelSpec.h>
#include <CesiumUtility/ErrorList.h>
#include <glm/mat4x4.hpp>
#include <functional>
namespace CesiumGltf {
/** @copydoc ModelSpec */
struct CESIUMGLTF_API Model : public ModelSpec {
Model() = default;
/**
* @brief Merges another model into this one.
*
* After this method returns, this `Model` contains all of the
* elements that were originally in it _plus_ all of the elements
* that were in `rhs`. Element indices are updated accordingly.
* However, element indices in {@link CesiumUtility::ExtensibleObject::extras}, if any,
* are _not_ updated.
*
* @param rhs The model to merge into this one.
*/
CesiumUtility::ErrorList merge(Model&& rhs);
/**
* @brief A callback function for {@link forEachRootNodeInScene}.
*/
typedef void ForEachRootNodeInSceneCallback(Model& gltf, Node& node);
/**
* @brief A callback function for {@link forEachRootNodeInScene}.
*/
typedef void
ForEachRootNodeInSceneConstCallback(const Model& gltf, const Node& node);
/**
* @brief Apply the given callback to the root nodes of the scene.
*
* If the given `sceneID` is non-negative and exists in the given glTF,
* then the given callback will be applied to all root nodes of this scene.
*
* If the given `sceneId` is negative, then the nodes that the callback
* will be applied to depends on the structure of the glTF model:
*
* * If the glTF model has a default scene, then it will
* be applied to all root nodes of the default scene.
* * Otherwise, it will be applied to all root nodes of the first scene.
* * Otherwise (if the glTF model does not contain any scenes), it will
* be applied to the first node.
* * Otherwise (if there are no scenes and no nodes), then this method will do
* nothing.
*
* @param sceneID The scene ID (index)
* @param callback The callback to apply
*/
void forEachRootNodeInScene(
int32_t sceneID,
std::function<ForEachRootNodeInSceneCallback>&& callback);
/** @copydoc Model::forEachRootNodeInScene */
void forEachRootNodeInScene(
int32_t sceneID,
std::function<ForEachRootNodeInSceneConstCallback>&& callback) const;
/**
* @brief A callback function for {@link forEachNodeInScene}.
*/
typedef void ForEachNodeInSceneCallback(
Model& gltf,
Node& node,
const glm::dmat4& transform);
/**
* @brief Apply the given callback to all nodes in the scene.
*
* If the given `sceneID` is non-negative and exists in the given glTF,
* then the given callback will be applied to all nodes in this scene.
*
* If the given `sceneId` is negative, then the nodes that the callback
* will be applied to depends on the structure of the glTF model:
*
* * If the glTF model has a default scene, then it will
* be applied to all nodes in the default scene.
* * Otherwise, it will be applied to all nodes in the first scene.
* * Otherwise (if the glTF model does not contain any scenes), it will
* be applied to the first node.
* * Otherwise (if there are no scenes and no nodes), then this method will do
* nothing.
*
* @param sceneID The scene ID (index)
* @param callback The callback to apply
*/
void forEachNodeInScene(
int32_t sceneID,
std::function<ForEachNodeInSceneCallback>&& callback);
/**
* @brief A callback function for {@link forEachNodeInScene}.
*/
typedef void ForEachNodeInSceneConstCallback(
const Model& gltf,
const Node& node,
const glm::dmat4& transform);
/** @copydoc Model::forEachNodeInScene */
void forEachNodeInScene(
int32_t sceneID,
std::function<ForEachNodeInSceneConstCallback>&& callback) const;
/**
* @brief A callback function for {@link forEachPrimitiveInScene}.
*/
typedef void ForEachPrimitiveInSceneCallback(
Model& gltf,
Node& node,
Mesh& mesh,
MeshPrimitive& primitive,
const glm::dmat4& transform);
/**
* @brief Apply the given callback to all relevant primitives.
*
* If the given `sceneID` is non-negative and exists in the given glTF,
* then the given callback will be applied to all meshes of this scene.
*
* If the given `sceneId` is negative, then the meshes that the callback
* will be applied to depends on the structure of the glTF model:
*
* * If the glTF model has a default scene, then it will
* be applied to all meshes of the default scene.
* * Otherwise, it will be applied to all meshes of the the first scene.
* * Otherwise (if the glTF model does not contain any scenes), it will
* be applied to all meshes that can be found by starting a traversal
* at the root node.
* * Otherwise (if there are no scenes and no nodes), then all meshes
* will be traversed.
*
* @param sceneID The scene ID (index)
* @param callback The callback to apply
*/
void forEachPrimitiveInScene(
int32_t sceneID,
std::function<ForEachPrimitiveInSceneCallback>&& callback);
/**
* @brief A callback function for {@link forEachPrimitiveInScene}.
*/
typedef void ForEachPrimitiveInSceneConstCallback(
const Model& gltf,
const Node& node,
const Mesh& mesh,
const MeshPrimitive& primitive,
const glm::dmat4& transform);
/** @copydoc Model::forEachPrimitiveInScene */
void forEachPrimitiveInScene(
int32_t sceneID,
std::function<ForEachPrimitiveInSceneConstCallback>&& callback) const;
/**
* @brief Fills in smooth normals for any primitives with missing normals.
*/
void generateMissingNormalsSmooth();
/**
* @brief Safely gets the element with a given index, returning a default
* instance if the index is outside the range.
*
* @tparam T The type of the array.
* @param items The array.
* @param index The index of the array element to retrieve.
* @return The requested element, or a default instance if the index is
* invalid.
*/
template <typename T>
static const T& getSafe(const std::vector<T>& items, int32_t index) {
static T defaultObject;
if (index < 0 || size_t(index) >= items.size()) {
return defaultObject;
} else {
return items[size_t(index)];
}
}
/**
* @brief Safely gets a pointer to the element with a given index, returning
* `nullptr` if the index is outside the range.
*
* @tparam T The type of the array.
* @param pItems The array.
* @param index The index of the array element to retrieve.
* @return A pointer to the requested element, or `nullptr` if the index is
* invalid.
*/
template <typename T>
static const T*
getSafe(const std::vector<T>* pItems, int32_t index) noexcept {
if (index < 0 || size_t(index) >= pItems->size()) {
return nullptr;
} else {
return &(*pItems)[size_t(index)];
}
}
/**
* @brief Safely gets a pointer to the element with a given index, returning
* `nullptr` if the index is outside the range.
*
* @tparam T The type of the array.
* @param pItems The array.
* @param index The index of the array element to retrieve.
* @return A pointer to the requested element, or `nullptr` if the index is
* invalid.
*/
template <typename T>
static T* getSafe(std::vector<T>* pItems, int32_t index) noexcept {
if (index < 0 || size_t(index) >= pItems->size()) {
return nullptr;
} else {
return &(*pItems)[size_t(index)];
}
}
/**
* @brief Adds an extension to the {@link ModelSpec::extensionsUsed}
* property, if it is not already present.
*
* @param extensionName The name of the used extension.
*/
void addExtensionUsed(const std::string& extensionName);
/**
* @brief Adds an extension to the {@link ModelSpec::extensionsRequired}
* property, if it is not already present.
*
* Calling this function also adds the extension to `extensionsUsed`, if it's
* not already present.
*
* @param extensionName The name of the required extension.
*/
void addExtensionRequired(const std::string& extensionName);
/**
* @brief Removes an extension from the {@link ModelSpec::extensionsUsed}
* property.
*
* @param extensionName The name of the used extension.
*/
void removeExtensionUsed(const std::string& extensionName);
/**
* @brief Removes an extension from the {@link ModelSpec::extensionsRequired}
* property.
*
* Calling this function also removes the extension from `extensionsUsed`.
*
* @param extensionName The name of the required extension.
*/
void removeExtensionRequired(const std::string& extensionName);
/**
* @brief Determines whether a given extension name is listed in the model's
* {@link ModelSpec::extensionsUsed} property.
*
* @param extensionName The extension name to check.
* @returns True if the extension is found in `extensionsUsed`; otherwise,
* false.
*/
bool isExtensionUsed(const std::string& extensionName) const noexcept;
/**
* @brief Determines whether a given extension name is listed in the model's
* {@link ModelSpec::extensionsRequired} property.
*
* @param extensionName The extension name to check.
* @returns True if the extension is found in `extensionsRequired`; otherwise,
* false.
*/
bool isExtensionRequired(const std::string& extensionName) const noexcept;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,220 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Accessor.h>
#include <CesiumGltf/Animation.h>
#include <CesiumGltf/Asset.h>
#include <CesiumGltf/Buffer.h>
#include <CesiumGltf/BufferView.h>
#include <CesiumGltf/Camera.h>
#include <CesiumGltf/Image.h>
#include <CesiumGltf/Library.h>
#include <CesiumGltf/Material.h>
#include <CesiumGltf/Mesh.h>
#include <CesiumGltf/Node.h>
#include <CesiumGltf/Sampler.h>
#include <CesiumGltf/Scene.h>
#include <CesiumGltf/Skin.h>
#include <CesiumGltf/Texture.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <string>
#include <vector>
namespace CesiumGltf {
/**
* @brief The root object for a glTF asset.
*/
struct CESIUMGLTF_API ModelSpec : public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Model";
/**
* @brief Names of glTF extensions used in this asset.
*/
std::vector<std::string> extensionsUsed;
/**
* @brief Names of glTF extensions required to properly load this asset.
*/
std::vector<std::string> extensionsRequired;
/**
* @brief An array of accessors.
*
* An accessor is a typed view into a bufferView.
*/
std::vector<CesiumGltf::Accessor> accessors;
/**
* @brief An array of keyframe animations.
*/
std::vector<CesiumGltf::Animation> animations;
/**
* @brief Metadata about the glTF asset.
*/
CesiumGltf::Asset asset;
/**
* @brief An array of buffers.
*
* A buffer points to binary geometry, animation, or skins.
*/
std::vector<CesiumGltf::Buffer> buffers;
/**
* @brief An array of bufferViews.
*
* A bufferView is a view into a buffer generally representing a subset of the
* buffer.
*/
std::vector<CesiumGltf::BufferView> bufferViews;
/**
* @brief An array of cameras.
*
* A camera defines a projection matrix.
*/
std::vector<CesiumGltf::Camera> cameras;
/**
* @brief An array of images.
*
* An image defines data used to create a texture.
*/
std::vector<CesiumGltf::Image> images;
/**
* @brief An array of materials.
*
* A material defines the appearance of a primitive.
*/
std::vector<CesiumGltf::Material> materials;
/**
* @brief An array of meshes.
*
* A mesh is a set of primitives to be rendered.
*/
std::vector<CesiumGltf::Mesh> meshes;
/**
* @brief An array of nodes.
*/
std::vector<CesiumGltf::Node> nodes;
/**
* @brief An array of samplers.
*
* A sampler contains properties for texture filtering and wrapping modes.
*/
std::vector<CesiumGltf::Sampler> samplers;
/**
* @brief The index of the default scene.
*
* This property **MUST NOT** be defined, when `scenes` is undefined.
*/
int32_t scene = -1;
/**
* @brief An array of scenes.
*/
std::vector<CesiumGltf::Scene> scenes;
/**
* @brief An array of skins.
*
* A skin is defined by joints and matrices.
*/
std::vector<CesiumGltf::Skin> skins;
/**
* @brief An array of textures.
*/
std::vector<CesiumGltf::Texture> textures;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(ModelSpec));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(sizeof(std::string) * this->extensionsUsed.capacity());
accum += int64_t(sizeof(std::string) * this->extensionsRequired.capacity());
accum += int64_t(sizeof(CesiumGltf::Accessor) * this->accessors.capacity());
for (const CesiumGltf::Accessor& value : this->accessors) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Accessor));
}
accum +=
int64_t(sizeof(CesiumGltf::Animation) * this->animations.capacity());
for (const CesiumGltf::Animation& value : this->animations) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Animation));
}
accum += this->asset.getSizeBytes() - int64_t(sizeof(CesiumGltf::Asset));
accum += int64_t(sizeof(CesiumGltf::Buffer) * this->buffers.capacity());
for (const CesiumGltf::Buffer& value : this->buffers) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Buffer));
}
accum +=
int64_t(sizeof(CesiumGltf::BufferView) * this->bufferViews.capacity());
for (const CesiumGltf::BufferView& value : this->bufferViews) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::BufferView));
}
accum += int64_t(sizeof(CesiumGltf::Camera) * this->cameras.capacity());
for (const CesiumGltf::Camera& value : this->cameras) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Camera));
}
accum += int64_t(sizeof(CesiumGltf::Image) * this->images.capacity());
for (const CesiumGltf::Image& value : this->images) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Image));
}
accum += int64_t(sizeof(CesiumGltf::Material) * this->materials.capacity());
for (const CesiumGltf::Material& value : this->materials) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Material));
}
accum += int64_t(sizeof(CesiumGltf::Mesh) * this->meshes.capacity());
for (const CesiumGltf::Mesh& value : this->meshes) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Mesh));
}
accum += int64_t(sizeof(CesiumGltf::Node) * this->nodes.capacity());
for (const CesiumGltf::Node& value : this->nodes) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Node));
}
accum += int64_t(sizeof(CesiumGltf::Sampler) * this->samplers.capacity());
for (const CesiumGltf::Sampler& value : this->samplers) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Sampler));
}
accum += int64_t(sizeof(CesiumGltf::Scene) * this->scenes.capacity());
for (const CesiumGltf::Scene& value : this->scenes) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Scene));
}
accum += int64_t(sizeof(CesiumGltf::Skin) * this->skins.capacity());
for (const CesiumGltf::Skin& value : this->skins) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Skin));
}
accum += int64_t(sizeof(CesiumGltf::Texture) * this->textures.capacity());
for (const CesiumGltf::Texture& value : this->textures) {
accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Texture));
}
return accum;
}
protected:
/**
* @brief This class is not meant to be instantiated directly. Use {@link Model} instead.
*/
ModelSpec() = default;
friend struct Model;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,38 @@
#pragma once
#include "CesiumGltf/Library.h"
#include <CesiumUtility/ExtensibleObject.h>
#include <string>
namespace CesiumGltf {
/**
* @brief The base class for objects in a glTF that have a name.
*
* A named object is also an {@link CesiumUtility::ExtensibleObject}.
*/
struct CESIUMGLTF_API NamedObject : public CesiumUtility::ExtensibleObject {
/**
* @brief The user-defined name of this object.
*
* This is not necessarily unique, e.g., an accessor and a buffer could have
* the same name, or two accessors could even have the same name.
*/
std::string name;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += sizeof(NamedObject);
accum +=
ExtensibleObject::getSizeBytes() - int64_t(sizeof(ExtensibleObject));
accum += this->name.capacity() * sizeof(char);
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,103 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <cstdint>
#include <vector>
namespace CesiumGltf {
/**
* @brief A node in the node hierarchy. When the node contains `skin`, all
* `mesh.primitives` **MUST** contain `JOINTS_0` and `WEIGHTS_0` attributes. A
* node **MAY** have either a `matrix` or any combination of
* `translation`/`rotation`/`scale` (TRS) properties. TRS properties are
* converted to matrices and postmultiplied in the `T * R * S` order to compose
* the transformation matrix; first the scale is applied to the vertices, then
* the rotation, and then the translation. If none are provided, the transform
* is the identity. When a node is targeted for animation (referenced by an
* animation.channel.target), `matrix` **MUST NOT** be present.
*/
struct CESIUMGLTF_API Node final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Node";
/**
* @brief The index of the camera referenced by this node.
*/
int32_t camera = -1;
/**
* @brief The indices of this node's children.
*/
std::vector<int32_t> children;
/**
* @brief The index of the skin referenced by this node.
*
* When a skin is referenced by a node within a scene, all joints used by the
* skin **MUST** belong to the same scene. When defined, `mesh` **MUST** also
* be defined.
*/
int32_t skin = -1;
/**
* @brief A floating-point 4x4 transformation matrix stored in column-major
* order.
*/
std::vector<double> matrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
/**
* @brief The index of the mesh in this node.
*/
int32_t mesh = -1;
/**
* @brief The node's unit quaternion rotation in the order (x, y, z, w), where
* w is the scalar.
*/
std::vector<double> rotation = {0, 0, 0, 1};
/**
* @brief The node's non-uniform scale, given as the scaling factors along the
* x, y, and z axes.
*/
std::vector<double> scale = {1, 1, 1};
/**
* @brief The node's translation along the x, y, and z axes.
*/
std::vector<double> translation = {0, 0, 0};
/**
* @brief The weights of the instantiated morph target. The number of array
* elements **MUST** match the number of morph targets of the referenced mesh.
* When defined, `mesh` **MUST** also be defined.
*/
std::vector<double> weights;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Node));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
accum += int64_t(sizeof(int32_t) * this->children.capacity());
accum += int64_t(sizeof(double) * this->matrix.capacity());
accum += int64_t(sizeof(double) * this->rotation.capacity());
accum += int64_t(sizeof(double) * this->scale.capacity());
accum += int64_t(sizeof(double) * this->translation.capacity());
accum += int64_t(sizeof(double) * this->weights.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,370 @@
#pragma once
#include "CesiumGltf/PropertyType.h"
#include "getOffsetFromOffsetsBuffer.h"
#include <CesiumUtility/SpanHelper.h>
#include <cstddef>
#include <cstring>
#include <span>
#include <variant>
#include <vector>
namespace CesiumGltf {
/**
* @brief A view on an array element of a {@link PropertyTableProperty}
* or {@link PropertyTextureProperty}.
*
* Provides utility to retrieve the data stored in the array of
* elements via the array index operator.
*/
template <typename ElementType> class PropertyArrayView {
public:
/**
* @brief Constructs an empty array view.
*/
PropertyArrayView() : _values{} {}
/**
* @brief Constructs an array view from a buffer.
*
* @param buffer The buffer containing the values.
*/
PropertyArrayView(const std::span<const std::byte>& buffer) noexcept
: _values{CesiumUtility::reintepretCastSpan<const ElementType>(buffer)} {}
/**
* @brief Accesses the element of this array at the given index.
*/
const ElementType& operator[](int64_t index) const noexcept {
return this->_values[index];
}
/**
* @brief The number of elements in this array.
*/
int64_t size() const noexcept { return this->_values.size(); }
/**
* @brief The `begin` iterator.
*/
auto begin() { return this->_values.begin(); }
/**
* @brief The `end` iterator.
*/
auto end() { return this->_values.end(); }
/** @copydoc begin */
auto begin() const { return this->_values.begin(); }
/** @copydoc end */
auto end() const { return this->_values.end(); }
private:
std::span<const ElementType> _values;
};
/**
* @brief A copy of an array element of a {@link PropertyTableProperty} or
* {@link PropertyTextureProperty}.
*
* Whereas {@link PropertyArrayView} is a pointer to data stored in a separate
* place, a PropertyArrayCopy owns the data that it's viewing.
*
* Provides utility to retrieve the data stored in the array of elements via the
* array index operator.
*/
template <typename ElementType> class PropertyArrayCopy {
public:
/**
* @brief Constructs an empty array view.
*/
PropertyArrayCopy() : _storage{}, _view() {}
/**
* @brief Constructs an array view from a buffer.
*
* @param values The buffer containing the values.
*/
PropertyArrayCopy(const std::vector<ElementType>& values) noexcept
: _storage(), _view() {
size_t numberOfElements = values.size();
size_t sizeInBytes = numberOfElements * sizeof(ElementType);
this->_storage.resize(sizeInBytes);
std::memcpy(
this->_storage.data(),
reinterpret_cast<const std::byte*>(values.data()),
sizeInBytes);
this->_view = PropertyArrayView<ElementType>(this->_storage);
}
/** @brief Default move constructor */
PropertyArrayCopy(PropertyArrayCopy&&) = default;
/** @brief Default move assignment operator */
PropertyArrayCopy& operator=(PropertyArrayCopy&&) = default;
/** @brief Creates a new \ref PropertyArrayCopy directly from a buffer of
* bytes, which will be moved into this copy. */
PropertyArrayCopy(std::vector<std::byte>&& buffer) noexcept
: _storage(std::move(buffer)), _view(this->_storage) {}
/** @brief Copy constructor */
PropertyArrayCopy(const PropertyArrayCopy& rhs)
: _storage(rhs._storage), _view(this->_storage) {}
/** @brief Copy assignment operator */
PropertyArrayCopy& operator=(const PropertyArrayCopy& rhs) {
this->_storage = rhs._storage;
this->_view = PropertyArrayView<ElementType>(this->_storage);
return *this;
}
/**
* @brief Returns the `ElementType` at the given index from this copy.
*
* @param index The index to obtain.
* @returns The `ElementType` at that index from the internal view.
*/
const ElementType& operator[](int64_t index) const noexcept {
return this->_view[index];
}
/** @copydoc PropertyArrayView::size */
int64_t size() const noexcept { return this->_view.size(); }
/** @copydoc PropertyArrayView::begin */
auto begin() { return this->_view.begin(); }
/** @copydoc PropertyArrayView::end */
auto end() { return this->_view.end(); }
/** @copydoc PropertyArrayView::begin */
auto begin() const { return this->_view.begin(); }
/** @copydoc PropertyArrayView::end */
auto end() const { return this->_view.end(); }
/**
* @brief Obtains a \ref PropertyArrayView over the contents of this copy.
*/
const PropertyArrayView<ElementType>& view() const { return this->_view; }
/**
* @brief Obtains a buffer and view from the copied data, leaving this \ref
* PropertyArrayCopy empty.
*
* @param outBuffer The destination where this copy's internal buffer will be
* moved to.
*/
PropertyArrayView<ElementType>
toViewAndExternalBuffer(std::vector<std::byte>& outBuffer) && {
outBuffer = std::move(this->_storage);
PropertyArrayView<ElementType> result = std::move(this->_view);
this->_view = PropertyArrayView<ElementType>();
return result;
}
private:
std::vector<std::byte> _storage;
PropertyArrayView<ElementType> _view;
};
/**
* @brief A view on a bool array element of a {@link PropertyTableProperty}
* or {@link PropertyTextureProperty}.
*
* Provides utility to retrieve the data stored in the array of
* elements via the array index operator.
*/
template <> class PropertyArrayView<bool> {
public:
/**
* @brief Constructs an empty array view.
*/
PropertyArrayView() : _values{}, _bitOffset{0}, _size{0} {}
/**
* @brief Constructs an array view from a buffer.
*
* @param buffer The buffer containing the values.
* @param bitOffset The offset into the buffer where the values actually
* begin.
* @param size The number of values in the array.
*/
PropertyArrayView(
const std::span<const std::byte>& buffer,
int64_t bitOffset,
int64_t size) noexcept
: _values{buffer}, _bitOffset{bitOffset}, _size{size} {}
/**
* @brief Obtains the element in the array at the given index.
*/
bool operator[](int64_t index) const noexcept {
index += _bitOffset;
const int64_t byteIndex = index / 8;
const int64_t bitIndex = index % 8;
const int bitValue = static_cast<int>(_values[byteIndex] >> bitIndex) & 1;
return bitValue == 1;
}
/**
* @brief The number of entries in the array.
*/
int64_t size() const noexcept { return _size; }
private:
std::span<const std::byte> _values;
int64_t _bitOffset;
int64_t _size;
};
/**
* @brief A view on a string array element of a {@link PropertyTableProperty}
* or {@link PropertyTextureProperty}.
*
* Provides utility to retrieve the data stored in the array of
* elements via the array index operator.
*/
template <> class PropertyArrayView<std::string_view> {
public:
/**
* @brief Constructs an empty array view.
*/
PropertyArrayView()
: _values{},
_stringOffsets{},
_stringOffsetType{PropertyComponentType::None},
_size{0} {}
/**
* @brief Constructs an array view from buffers and their information.
*
* @param values The buffer containing the values.
* @param stringOffsets The buffer containing the string offsets.
* @param stringOffsetType The component type of the string offsets.
* @param size The number of values in the array.
*/
PropertyArrayView(
const std::span<const std::byte>& values,
const std::span<const std::byte>& stringOffsets,
PropertyComponentType stringOffsetType,
int64_t size) noexcept
: _values{values},
_stringOffsets{stringOffsets},
_stringOffsetType{stringOffsetType},
_size{size} {}
/**
* @brief Obtains an `std::string_view` for the element at the given index.
*/
std::string_view operator[](int64_t index) const noexcept {
const size_t currentOffset =
getOffsetFromOffsetsBuffer(index, _stringOffsets, _stringOffsetType);
const size_t nextOffset = getOffsetFromOffsetsBuffer(
index + 1,
_stringOffsets,
_stringOffsetType);
return std::string_view(
reinterpret_cast<const char*>(_values.data() + currentOffset),
(nextOffset - currentOffset));
}
/**
* @brief The number of elements in this array.
*/
int64_t size() const noexcept { return _size; }
private:
std::span<const std::byte> _values;
std::span<const std::byte> _stringOffsets;
PropertyComponentType _stringOffsetType;
int64_t _size;
};
/** @brief Compares two \ref PropertyArrayView instances by comparing their
* values. If the two arrays aren't the same size, this comparison will return
* false. */
template <typename T>
bool operator==(
const PropertyArrayView<T>& lhs,
const PropertyArrayView<T>& rhs) {
int64_t size = lhs.size();
if (size != rhs.size()) {
return false;
}
for (int64_t i = 0; i < size; ++i) {
if (lhs[i] != rhs[i]) {
return false;
}
}
return true;
}
/** @brief Compares a \ref PropertyArrayView with a \ref
* PropertyArrayCopy by creating a view from the copy and comparing the two. */
template <typename T>
bool operator==(
const PropertyArrayView<T>& lhs,
const PropertyArrayCopy<T>& rhs) {
return lhs == PropertyArrayView(rhs);
}
/** @brief Compares a \ref PropertyArrayView with a \ref
* PropertyArrayCopy by creating a view from the copy and comparing the two. */
template <typename T>
bool operator==(
const PropertyArrayCopy<T>& lhs,
const PropertyArrayView<T>& rhs) {
return lhs.view() == rhs;
}
/** @brief Compares two \ref PropertyArrayCopy instances by creating
* views from each instance and comparing the two. */
template <typename T>
bool operator==(
const PropertyArrayCopy<T>& lhs,
const PropertyArrayCopy<T>& rhs) {
return lhs.view() == rhs.view();
}
/**
* @brief Compares two \ref PropertyArrayView instances and returns the inverse.
*/
template <typename T>
bool operator!=(
const PropertyArrayView<T>& lhs,
const PropertyArrayView<T>& rhs) {
return !(lhs == rhs);
}
/** @brief Compares a \ref PropertyArrayView with a \ref
* PropertyArrayCopy by creating a view from the copy and returning the inverse
* of comparing the two. */
template <typename T>
bool operator!=(
const PropertyArrayView<T>& lhs,
const PropertyArrayCopy<T>& rhs) {
return !(lhs == rhs);
}
/** @brief Compares a \ref PropertyArrayView with a \ref
* PropertyArrayCopy by creating a view from the copy and returning the inverse
* of comparing the two. */
template <typename T>
bool operator!=(
const PropertyArrayCopy<T>& lhs,
const PropertyArrayView<T>& rhs) {
return !(lhs == rhs);
}
/** @brief Compares two \ref
* PropertyArrayCopy instances by creating views from both instances and
* returning the inverse of comparing the two. */
template <typename T>
bool operator!=(
const PropertyArrayCopy<T>& lhs,
const PropertyArrayCopy<T>& rhs) {
return !(lhs == rhs);
}
} // namespace CesiumGltf

View File

@ -0,0 +1,71 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/PropertyAttributeProperty.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <optional>
#include <string>
#include <unordered_map>
namespace CesiumGltf {
/**
* @brief Properties conforming to a class, organized as property values stored
* in attributes.
*/
struct CESIUMGLTF_API PropertyAttribute final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "PropertyAttribute";
/**
* @brief The name of the property attribute, e.g. for display purposes.
*/
std::optional<std::string> name;
/**
* @brief The class that property values conform to. The value must be a class
* ID declared in the `classes` dictionary.
*/
std::string classProperty;
/**
* @brief A dictionary, where each key corresponds to a property ID in the
* class' `properties` dictionary and each value is an object describing where
* property values are stored. Required properties must be included in this
* dictionary.
*/
std::unordered_map<std::string, CesiumGltf::PropertyAttributeProperty>
properties;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(PropertyAttribute));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
accum += int64_t(this->classProperty.capacity() * sizeof(char));
accum += int64_t(
this->properties.bucket_count() *
(sizeof(std::string) + sizeof(CesiumGltf::PropertyAttributeProperty)));
for (const auto& [k, v] : this->properties) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += v.getSizeBytes() -
int64_t(sizeof(CesiumGltf::PropertyAttributeProperty));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,73 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <CesiumUtility/JsonValue.h>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief An attribute containing property values.
*/
struct CESIUMGLTF_API PropertyAttributeProperty final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "PropertyAttributeProperty";
/**
* @brief The name of the attribute containing property values.
*/
std::string attribute;
/**
* @brief An offset to apply to property values. Only applicable when the
* component type is `FLOAT32` or `FLOAT64`, or when the property is
* `normalized`. Overrides the class property's `offset` if both are defined.
*/
std::optional<CesiumUtility::JsonValue> offset;
/**
* @brief A scale to apply to property values. Only applicable when the
* component type is `FLOAT32` or `FLOAT64`, or when the property is
* `normalized`. Overrides the class property's `scale` if both are defined.
*/
std::optional<CesiumUtility::JsonValue> scale;
/**
* @brief Maximum value present in the property values. Only applicable to
* `SCALAR`, `VECN`, and `MATN` types. This is the maximum of all property
* values, after the transforms based on the `normalized`, `offset`, and
* `scale` properties have been applied.
*/
std::optional<CesiumUtility::JsonValue> max;
/**
* @brief Minimum value present in the property values. Only applicable to
* `SCALAR`, `VECN`, and `MATN` types. This is the minimum of all property
* values, after the transforms based on the `normalized`, `offset`, and
* `scale` properties have been applied.
*/
std::optional<CesiumUtility::JsonValue> min;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(PropertyAttributeProperty));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
accum += int64_t(this->attribute.capacity() * sizeof(char));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,440 @@
#pragma once
#include "CesiumGltf/AccessorView.h"
#include "CesiumGltf/PropertyAttributeProperty.h"
#include "CesiumGltf/PropertyTransformations.h"
#include "CesiumGltf/PropertyTypeTraits.h"
#include "CesiumGltf/PropertyView.h"
#include <CesiumUtility/Assert.h>
#include <cmath>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief Indicates the status of a property attribute property view.
*
* The {@link PropertyAttributePropertyView} constructor always completes
* successfully. However it may not always reflect the actual content of the
* corresponding property attribute property. This enumeration provides the
* reason.
*/
class PropertyAttributePropertyViewStatus : public PropertyViewStatus {
public:
/**
* @brief This property view was initialized from an invalid
* {@link PropertyAttribute}.
*/
static const int ErrorInvalidPropertyAttribute = 14;
/**
* @brief This property view is associated with a {@link ClassProperty} of an
* unsupported type.
*/
static const int ErrorUnsupportedProperty = 15;
/**
* @brief This property view was initialized with a primitive that does not
* contain the specified attribute.
*/
static const int ErrorMissingAttribute = 16;
/**
* @brief This property view's attribute does not have a valid accessor index.
*/
static const int ErrorInvalidAccessor = 17;
/**
* @brief This property view's type does not match the type of the accessor it
* uses.
*/
static const int ErrorAccessorTypeMismatch = 18;
/**
* @brief This property view's component type does not match the type of the
* accessor it uses.
*/
static const int ErrorAccessorComponentTypeMismatch = 19;
/**
* @brief This property view's normalization does not match the normalization
* of the accessor it uses.
*/
static const int ErrorAccessorNormalizationMismatch = 20;
/**
* @brief This property view uses an accessor that does not have a valid
* buffer view index.
*/
static const int ErrorInvalidBufferView = 21;
/**
* @brief This property view uses a buffer view that does not have a valid
* buffer index.
*/
static const int ErrorInvalidBuffer = 22;
/**
* @brief This property view uses an accessor that points outside the bounds
* of its target buffer view.
*/
static const PropertyViewStatusType ErrorAccessorOutOfBounds = 23;
/**
* @brief This property view uses a buffer view that points outside the bounds
* of its target buffer.
*/
static const PropertyViewStatusType ErrorBufferViewOutOfBounds = 24;
};
/**
* @brief A view of the data specified by a {@link PropertyAttributeProperty}.
*
* Ideally, property attribute properties can be initialized as vertex
* attributes in the target rendering context. However, some runtime engines do
* not allow custom vertex attributes. To compensate, this view can be used to
* sample the property attributes property via vertex index.
*
* @tparam ElementType The type of the elements represented in the property view
* @tparam Normalized Whether or not the property is normalized. If normalized,
* the elements can be retrieved as normalized floating-point numbers, as
* opposed to their integer values.
*/
template <typename ElementType, bool Normalized = false>
class PropertyAttributePropertyView;
/**
* @brief A view of the non-normalized data specified by a
* {@link PropertyAttributeProperty}.
*
* Ideally, property attribute properties can be initialized as vertex
* attributes in the target rendering context. However, some runtime engines do
* not allow custom vertex attributes. This view can be used instead to sample
* the property attributes property via vertex index.
*
* @tparam ElementType The type of the elements represented in the property view
*/
template <typename ElementType>
class PropertyAttributePropertyView<ElementType, false>
: public PropertyView<ElementType, false> {
public:
/**
* @brief Constructs an invalid instance for a non-existent property.
*/
PropertyAttributePropertyView() noexcept
: PropertyView<ElementType, false>(), _accessor{}, _size{0} {}
/**
* @brief Constructs an invalid instance for an erroneous property.
*
* @param status The code from {@link PropertyAttributePropertyViewStatus} indicating the error with the property.
*/
PropertyAttributePropertyView(PropertyViewStatusType status) noexcept
: PropertyView<ElementType, false>(status), _accessor{}, _size{0} {
CESIUM_ASSERT(
this->_status != PropertyAttributePropertyViewStatus::Valid &&
"An empty property view should not be constructed with a valid status");
}
/**
* @brief Constructs an instance of an empty property that specifies a default
* value. Although this property has no data, it can return the default value
* when {@link PropertyAttributePropertyView<ElementType, false>::get} is called. However,
* {@link PropertyAttributePropertyView<ElementType, false>::getRaw} cannot be used.
*
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param size The number of elements in the primitive's POSITION accessor.
* Used as a substitute since no actual accessor is defined.
*/
PropertyAttributePropertyView(
const ClassProperty& classProperty,
int64_t size) noexcept
: PropertyView<ElementType, false>(classProperty), _accessor{}, _size{0} {
if (this->_status != PropertyAttributePropertyViewStatus::Valid) {
// Don't override the status / size if something is wrong with the class
// property's definition.
return;
}
if (!classProperty.defaultProperty) {
// This constructor should only be called if the class property *has* a
// default value. But in the case that it does not, this property view
// becomes invalid.
this->_status =
PropertyAttributePropertyViewStatus::ErrorNonexistentProperty;
return;
}
this->_status =
PropertyAttributePropertyViewStatus::EmptyPropertyWithDefault;
this->_size = size;
}
/**
* @brief Construct a view of the data specified by a {@link PropertyAttributeProperty}.
*
* @param property The {@link PropertyAttributeProperty}
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param accessorView The {@link AccessorView} for the data that this property is
* associated with.
*/
PropertyAttributePropertyView(
const PropertyAttributeProperty& property,
const ClassProperty& classProperty,
const AccessorView<ElementType>& accessorView) noexcept
: PropertyView<ElementType, false>(classProperty, property),
_accessor{accessorView},
_size{
this->_status == PropertyAttributePropertyViewStatus::Valid
? accessorView.size()
: 0} {}
/**
* @brief Gets the value of the property for the given vertex index
* with all value transforms applied. That is, if the property specifies an
* offset and scale, they will be applied to the value before the value is
* returned.
*
* If this property has a specified "no data" value, this will return the
* property's default value for any elements that equal this "no data" value.
* If the property did not specify a default value, this returns std::nullopt.
*
* @param index The vertex index.
*
* @return The value of the property for the given vertex, or std::nullopt if
* it matches the "no data" value
*/
std::optional<ElementType> get(int64_t index) const noexcept {
if (this->_status ==
PropertyAttributePropertyViewStatus::EmptyPropertyWithDefault) {
return this->defaultValue();
}
ElementType value = getRaw(index);
if (value == this->noData()) {
return this->defaultValue();
}
return transformValue(value, this->offset(), this->scale());
}
/**
* @brief Gets the raw value of the property for the given vertex index.
*
* If this property has a specified "no data" value, the raw value will still
* be returned, even if it equals the "no data" value.
*
* @param index The vertex index.
*
* @return The value of the property for the given vertex.
*/
ElementType getRaw(int64_t index) const noexcept {
CESIUM_ASSERT(
this->_status == PropertyAttributePropertyViewStatus::Valid &&
"Check the status() first to make sure view is valid");
CESIUM_ASSERT(
size() > 0 &&
"Check the size() of the view to make sure it's not empty");
CESIUM_ASSERT(index >= 0 && "index must be non-negative");
CESIUM_ASSERT(index < size() && "index must be less than size");
return _accessor[index];
}
/**
* @brief Get the number of elements in this PropertyAttributePropertyView.
* If the view is valid, this returns the count of the elements in the
* attribute's accessor. Otherwise, this returns 0.
*
* @return The number of elements in this PropertyAttributePropertyView.
*/
int64_t size() const noexcept { return _size; }
private:
AccessorView<ElementType> _accessor;
int64_t _size;
};
/**
* @brief A view of the normalized data specified by a
* {@link PropertyAttributeProperty}.
*
* Ideally, property attribute properties can be initialized as vertex
* attributes in the target rendering context. However, some runtime engines do
* not allow custom vertex attributes. This view can be used instead to sample
* the property attributes property via vertex index.
*
* @tparam ElementType The type of the elements represented in the property view
*/
template <typename ElementType>
class PropertyAttributePropertyView<ElementType, true>
: public PropertyView<ElementType, true> {
private:
using NormalizedType = typename TypeToNormalizedType<ElementType>::type;
public:
/**
* @brief Constructs an invalid instance for a non-existent property.
*/
PropertyAttributePropertyView() noexcept
: PropertyView<ElementType, true>(), _accessor{}, _size{0} {}
/**
* @brief Constructs an invalid instance for an erroneous property.
*
* @param status The code from {@link PropertyAttributePropertyViewStatus} indicating the error with the property.
*/
PropertyAttributePropertyView(PropertyViewStatusType status) noexcept
: PropertyView<ElementType, true>(status), _accessor{}, _size{0} {
CESIUM_ASSERT(
this->_status != PropertyAttributePropertyViewStatus::Valid &&
"An empty property view should not be constructed with a valid status");
}
/**
* @brief Constructs an instance of an empty property that specifies a default
* value. Although this property has no data, it can return the default value
* when \ref get is called. However, \ref getRaw cannot be used.
*
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param size The number of elements in the primitive's POSITION accessor.
* Used as a substitute since no actual accessor is defined.
*/
PropertyAttributePropertyView(
const ClassProperty& classProperty,
int64_t size) noexcept
: PropertyView<ElementType, true>(classProperty), _accessor{}, _size{0} {
if (this->_status != PropertyAttributePropertyViewStatus::Valid) {
// Don't override the status / size if something is wrong with the class
// property's definition.
return;
}
if (!classProperty.defaultProperty) {
// This constructor should only be called if the class property *has* a
// default value. But in the case that it does not, this property view
// becomes invalid.
this->_status =
PropertyAttributePropertyViewStatus::ErrorNonexistentProperty;
return;
}
this->_status =
PropertyAttributePropertyViewStatus::EmptyPropertyWithDefault;
this->_size = size;
}
/**
* @brief Construct a view of the data specified by a {@link PropertyAttributeProperty}.
*
* @param property The {@link PropertyAttributeProperty}
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param accessorView The {@link AccessorView} for the data that this property is
* associated with.
*/
PropertyAttributePropertyView(
const PropertyAttributeProperty& property,
const ClassProperty& classProperty,
const AccessorView<ElementType>& accessorView) noexcept
: PropertyView<ElementType, true>(classProperty, property),
_accessor{accessorView},
_size{
this->_status == PropertyAttributePropertyViewStatus::Valid
? accessorView.size()
: 0} {}
/**
* @brief Gets the value of the property for the given vertex index
* with all value transforms applied. That is, if the property specifies an
* offset and scale, they will be applied to the value before the value is
* returned.
*
* If this property has a specified "no data" value, this will return the
* property's default value for any elements that equal this "no data" value.
* If the property did not specify a default value, this returns std::nullopt.
*
* @param index The vertex index.
*
* @return The value of the property for the given vertex, or std::nullopt if
* it matches the "no data" value
*/
std::optional<NormalizedType> get(int64_t index) const noexcept {
if (this->_status ==
PropertyAttributePropertyViewStatus::EmptyPropertyWithDefault) {
return this->defaultValue();
}
ElementType value = getRaw(index);
if (value == this->noData()) {
return this->defaultValue();
}
if constexpr (IsMetadataScalar<ElementType>::value) {
return transformValue<NormalizedType>(
normalize<ElementType>(value),
this->offset(),
this->scale());
}
if constexpr (IsMetadataVecN<ElementType>::value) {
constexpr glm::length_t N = ElementType::length();
using T = typename ElementType::value_type;
using NormalizedT = typename NormalizedType::value_type;
return transformValue<glm::vec<N, NormalizedT>>(
normalize<N, T>(value),
this->offset(),
this->scale());
}
if constexpr (IsMetadataMatN<ElementType>::value) {
constexpr glm::length_t N = ElementType::length();
using T = typename ElementType::value_type;
using NormalizedT = typename NormalizedType::value_type;
return transformValue<glm::mat<N, N, NormalizedT>>(
normalize<N, T>(value),
this->offset(),
this->scale());
}
}
/**
* @brief Gets the raw value of the property for the given vertex index.
*
* If this property has a specified "no data" value, the raw value will still
* be returned, even if it equals the "no data" value.
*
* @param index The vertex index.
*
* @return The value of the property for the given vertex.
*/
ElementType getRaw(int64_t index) const noexcept {
CESIUM_ASSERT(
this->_status == PropertyAttributePropertyViewStatus::Valid &&
"Check the status() first to make sure view is valid");
CESIUM_ASSERT(
size() > 0 &&
"Check the size() of the view to make sure it's not empty");
CESIUM_ASSERT(index >= 0 && "index must be non-negative");
CESIUM_ASSERT(index < size() && "index must be less than size");
return _accessor[index];
}
/**
* @brief Get the number of elements in this PropertyAttributePropertyView.
* If the view is valid, this returns the count of the elements in the
* attribute's accessor. Otherwise, this returns 0.
*
* @return The number of elements in this PropertyAttributePropertyView.
*/
int64_t size() const noexcept { return _size; }
private:
AccessorView<ElementType> _accessor;
int64_t _size;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,742 @@
#pragma once
#include "CesiumGltf/Class.h"
#include "CesiumGltf/ClassProperty.h"
#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h"
#include "CesiumGltf/PropertyAttribute.h"
#include "CesiumGltf/PropertyAttributePropertyView.h"
#include "Model.h"
namespace CesiumGltf {
/**
* @brief Indicates the status of a property attribute view.
*
* The {@link PropertyAttributeView} constructor always completes successfully.
* However it may not always reflect the actual content of the
* {@link PropertyAttribute}. This enumeration provides the reason.
*/
enum class PropertyAttributeViewStatus {
/**
* @brief This property attribute view is valid and ready to use.
*/
Valid,
/**
* @brief The glTF is missing the EXT_structural_metadata extension.
*/
ErrorMissingMetadataExtension,
/**
* @brief The glTF EXT_structural_metadata extension doesn't contain a schema.
*/
ErrorMissingSchema,
/**
* @brief The property attribute's specified class could not be found in the
* extension.
*/
ErrorClassNotFound
};
/**
* @brief Attempts to obtain a \ref PropertyType from the \ref Accessor::type
* "type" field of the accessor.
*
* @param accessor The accessor whose type will be obtained.
* @returns A \ref PropertyType equivalent to the accessor's \ref
* AccessorSpec::type, or \ref PropertyType::Invalid if no conversion could be
* made.
*/
PropertyType getAccessorTypeAsPropertyType(const Accessor& accessor);
/**
* @brief Attempts to obtain a \ref PropertyComponentType from the \ref
* Accessor::componentType "componentType" field of the accessor.
*
* @param accessor The accessor whose componentType will be obtained.
* @returns A \ref PropertyComponentType equivalent to the accessor's \ref
* AccessorSpec::componentType, or \ref PropertyComponentType::None if no
* conversion could be made.
*/
PropertyComponentType
getAccessorComponentTypeAsPropertyComponentType(const Accessor& accessor);
/**
* @brief A view on a {@link PropertyAttribute}.
*
* This should be used to get a {@link PropertyAttributePropertyView} of a property
* in the property attribute. It will validate the EXT_structural_metadata
* format and ensure {@link PropertyAttributePropertyView} does not access data out
* of bounds.
*/
class PropertyAttributeView {
public:
/**
* @brief Construct a PropertyAttributeView.
*
* @param model The glTF that contains the property attribute's data.
* @param propertyAttribute The {@link PropertyAttribute} from which
* the view will retrieve data.
*/
PropertyAttributeView(
const Model& model,
const PropertyAttribute& propertyAttribute) noexcept;
/**
* @brief Gets the status of this property attribute view.
*
* Indicates whether the view accurately reflects the property attribute's
* data, or whether an error occurred.
*/
PropertyAttributeViewStatus status() const noexcept { return this->_status; }
/**
* @brief Gets the name of the property attribute being viewed. Returns
* std::nullopt if no name was specified.
*/
const std::optional<std::string>& name() const noexcept {
return _pPropertyAttribute->name;
}
/**
* @brief Gets the {@link Class} that this property attribute conforms to.
*
* @return A pointer to the {@link Class}. Returns nullptr if the
* PropertyAttribute did not specify a valid class.
*/
const Class* getClass() const noexcept { return _pClass; }
/**
* @brief Finds the {@link ClassProperty} that
* describes the type information of the property with the specified id.
* @param propertyId The id of the property to retrieve the class for.
* @return A pointer to the {@link ClassProperty}.
* Return nullptr if the PropertyAttributeView is invalid or if no class
* property was found.
*/
const ClassProperty* getClassProperty(const std::string& propertyId) const;
/**
* @brief Gets a {@link PropertyAttributePropertyView} that views the data of a
* property stored in the {@link PropertyAttribute}.
*
* This method will validate the EXT_structural_metadata format to ensure
* {@link PropertyAttributePropertyView} retrieves the correct data. T must
* be a scalar with a supported component type (int8_t, uint8_t, int16_t,
* uint16_t, float), a glm vecN composed of one of the scalar types,
* or a glm matN containing one of the scalar types.
*
* If T does not match the type specified by the class property, this returns
* an invalid PropertyAttributePropertyView. Likewise, if the value of
* Normalized does not match the value of {@link ClassProperty::normalized} for that
* class property, this returns an invalid property view. Only types with
* integer components may be normalized.
*
* @tparam T The C++ type corresponding to the type of the data retrieved.
* @tparam Normalized Whether the property is normalized. Only applicable to
* types with integer components.
* @param primitive The target primitive
* @param propertyId The id of the property to retrieve data from
* @return A {@link PropertyAttributePropertyView} of the property. If no valid
* property is found, the property view will be invalid.
*/
template <typename T, bool Normalized = false>
PropertyAttributePropertyView<T, Normalized> getPropertyView(
const MeshPrimitive& primitive,
const std::string& propertyId) const {
if (this->_status != PropertyAttributeViewStatus::Valid) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorInvalidPropertyAttribute);
}
const ClassProperty* pClassProperty = getClassProperty(propertyId);
if (!pClassProperty) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorNonexistentProperty);
}
if constexpr (
IsMetadataArray<T>::value || IsMetadataBoolean<T>::value ||
IsMetadataString<T>::value) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty);
}
return getPropertyViewImpl<T, Normalized>(
primitive,
propertyId,
*pClassProperty);
}
/**
* @brief Gets a {@link PropertyAttributePropertyView} through a callback that accepts a
* property id and a {@link PropertyAttributePropertyView} that views the data
* of the property with the specified id.
*
* This method will validate the EXT_structural_metadata format to ensure
* {@link PropertyAttributePropertyView} retrieves the correct data. T must
* be a scalar with a supported component type (int8_t, uint8_t, int16_t,
* uint16_t, float), a glm vecN composed of one of the scalar types,
* or a glm matN containing one of the scalar types.
*
* If the property is somehow invalid, an empty {@link PropertyAttributePropertyView}
* with an error status will be passed to the callback. Otherwise, a valid
* property view will be passed to the callback.
*
* @param primitive The target primitive
* @param propertyId The id of the property to retrieve data from
* @param callback A callback function that accepts a property id and a
* {@link PropertyAttributePropertyView}
* @tparam Callback The type of the callback function.
*/
template <typename Callback>
void getPropertyView(
const MeshPrimitive& primitive,
const std::string& propertyId,
Callback&& callback) const {
if (this->_status != PropertyAttributeViewStatus::Valid) {
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::
ErrorInvalidPropertyAttribute));
return;
}
const ClassProperty* pClassProperty = getClassProperty(propertyId);
if (!pClassProperty) {
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorNonexistentProperty));
return;
}
if (pClassProperty->array) {
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty));
return;
}
PropertyType type = convertStringToPropertyType(pClassProperty->type);
PropertyComponentType componentType = PropertyComponentType::None;
if (pClassProperty->componentType) {
componentType =
convertStringToPropertyComponentType(*pClassProperty->componentType);
}
bool normalized = pClassProperty->normalized;
if (normalized && !isPropertyComponentTypeInteger(componentType)) {
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorInvalidNormalization));
return;
}
if (type == PropertyType::Scalar) {
if (normalized) {
getScalarPropertyViewImpl<Callback, true>(
primitive,
propertyId,
*pClassProperty,
componentType,
std::forward<Callback>(callback));
} else {
getScalarPropertyViewImpl<Callback, false>(
primitive,
propertyId,
*pClassProperty,
componentType,
std::forward<Callback>(callback));
}
return;
}
if (isPropertyTypeVecN(type)) {
if (normalized) {
getVecNPropertyViewImpl<Callback, true>(
primitive,
propertyId,
*pClassProperty,
type,
componentType,
std::forward<Callback>(callback));
} else {
getVecNPropertyViewImpl<Callback, false>(
primitive,
propertyId,
*pClassProperty,
type,
componentType,
std::forward<Callback>(callback));
}
return;
}
if (isPropertyTypeMatN(type)) {
if (normalized) {
getMatNPropertyViewImpl<Callback, true>(
primitive,
propertyId,
*pClassProperty,
type,
componentType,
std::forward<Callback>(callback));
} else {
getMatNPropertyViewImpl<Callback, false>(
primitive,
propertyId,
*pClassProperty,
type,
componentType,
std::forward<Callback>(callback));
}
return;
}
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty));
return;
}
/**
* @brief Iterates over each property in the {@link PropertyAttribute} with a callback
* that accepts a property id and a {@link PropertyAttributePropertyView} to view
* the data stored in the {@link PropertyAttributeProperty}.
*
* This method will validate the EXT_structural_metadata format to ensure
* {@link PropertyAttributePropertyView} retrieves the correct data. T must be
* a scalar with a supported component type (int8_t, uint8_t, int16_t,
* uint16_t, float), a glm vecN composed of one of the scalar types,
* or a PropertyArrayView containing one of the scalar types.
*
* If the property is invalid, an empty {@link PropertyAttributePropertyView} with an
* error status will be passed to the callback. Otherwise, a valid property
* view will be passed to the callback.
*
* @param primitive The id of the property to retrieve data from
* @param callback A callback function that accepts property id and
* {@link PropertyAttributePropertyView}
* @tparam Callback The type of the callback function.
*/
template <typename Callback>
void
forEachProperty(const MeshPrimitive& primitive, Callback&& callback) const {
for (const auto& property : this->_pClass->properties) {
getPropertyView(
primitive,
property.first,
std::forward<Callback>(callback));
}
}
private:
template <typename T, bool Normalized>
PropertyAttributePropertyView<T, Normalized> getEmptyPropertyViewWithDefault(
const MeshPrimitive& primitive,
const ClassProperty& classProperty) const {
// To make the view have a nonzero size, find the POSITION attribute and get
// its accessor count. If it doesn't exist or is somehow erroneous, just
// mark the property as nonexistent.
if (primitive.attributes.find("POSITION") == primitive.attributes.end()) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorNonexistentProperty);
}
const Accessor* pAccessor = _pModel->getSafe<Accessor>(
&_pModel->accessors,
primitive.attributes.at("POSITION"));
if (!pAccessor) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorNonexistentProperty);
}
return PropertyAttributePropertyView<T, Normalized>(
classProperty,
pAccessor->count);
}
template <typename T, bool Normalized>
PropertyAttributePropertyView<T, Normalized> getPropertyViewImpl(
const MeshPrimitive& primitive,
const std::string& propertyId,
const ClassProperty& classProperty) const {
auto propertyAttributePropertyIter =
_pPropertyAttribute->properties.find(propertyId);
if (propertyAttributePropertyIter ==
_pPropertyAttribute->properties.end()) {
if (!classProperty.required && classProperty.defaultProperty) {
// If the property was omitted from the property attribute, it is still
// technically valid if it specifies a default value. Try to create a
// view that just returns the default value.
return getEmptyPropertyViewWithDefault<T, Normalized>(
primitive,
classProperty);
}
// Otherwise, the property is erroneously nonexistent.
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorNonexistentProperty);
}
const PropertyAttributeProperty& propertyAttributeProperty =
propertyAttributePropertyIter->second;
return createPropertyView<T, Normalized>(
primitive,
classProperty,
propertyAttributeProperty);
}
template <typename Callback, bool Normalized>
void getScalarPropertyViewImpl(
const MeshPrimitive& primitive,
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyComponentType componentType,
Callback&& callback) const {
switch (componentType) {
case PropertyComponentType::Int8:
callback(
propertyId,
getPropertyViewImpl<int8_t, Normalized>(
primitive,
propertyId,
classProperty));
return;
case PropertyComponentType::Uint8:
callback(
propertyId,
getPropertyViewImpl<uint8_t, Normalized>(
primitive,
propertyId,
classProperty));
return;
case PropertyComponentType::Int16:
callback(
propertyId,
getPropertyViewImpl<int16_t, Normalized>(
primitive,
propertyId,
classProperty));
return;
case PropertyComponentType::Uint16:
callback(
propertyId,
getPropertyViewImpl<uint16_t, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Float32:
callback(
propertyId,
getPropertyViewImpl<float, false>(
primitive,
propertyId,
classProperty));
break;
default:
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty));
break;
}
}
template <typename Callback, glm::length_t N, bool Normalized>
void getVecNPropertyViewImpl(
const MeshPrimitive& primitive,
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyComponentType componentType,
Callback&& callback) const {
switch (componentType) {
case PropertyComponentType::Int8:
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, int8_t>, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Uint8:
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, uint8_t>, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Int16:
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, int16_t>, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Uint16:
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, uint16_t>, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Float32:
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, float>, false>(
primitive,
propertyId,
classProperty));
break;
default:
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty));
break;
}
}
template <typename Callback, bool Normalized>
void getVecNPropertyViewImpl(
const MeshPrimitive& primitive,
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyType type,
PropertyComponentType componentType,
Callback&& callback) const {
const glm::length_t N = getDimensionsFromPropertyType(type);
switch (N) {
case 2:
getVecNPropertyViewImpl<Callback, 2, Normalized>(
primitive,
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback));
break;
case 3:
getVecNPropertyViewImpl<Callback, 3, Normalized>(
primitive,
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback));
break;
case 4:
getVecNPropertyViewImpl<Callback, 4, Normalized>(
primitive,
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback));
break;
default:
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorTypeMismatch));
break;
}
}
template <typename Callback, glm::length_t N, bool Normalized>
void getMatNPropertyViewImpl(
const MeshPrimitive& primitive,
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyComponentType componentType,
Callback&& callback) const {
switch (componentType) {
case PropertyComponentType::Int8:
callback(
propertyId,
getPropertyViewImpl<glm::mat<N, N, int8_t>, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Uint8:
callback(
propertyId,
getPropertyViewImpl<glm::mat<N, N, uint8_t>, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Int16:
callback(
propertyId,
getPropertyViewImpl<glm::mat<N, N, int16_t>, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Uint16:
callback(
propertyId,
getPropertyViewImpl<glm::mat<N, N, uint16_t>, Normalized>(
primitive,
propertyId,
classProperty));
break;
case PropertyComponentType::Float32:
callback(
propertyId,
getPropertyViewImpl<glm::mat<N, N, float>, false>(
primitive,
propertyId,
classProperty));
break;
default:
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty));
break;
}
}
template <typename Callback, bool Normalized>
void getMatNPropertyViewImpl(
const MeshPrimitive& primitive,
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyType type,
PropertyComponentType componentType,
Callback&& callback) const {
glm::length_t N = getDimensionsFromPropertyType(type);
switch (N) {
case 2:
getMatNPropertyViewImpl<Callback, 2, Normalized>(
primitive,
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback));
break;
case 3:
getMatNPropertyViewImpl<Callback, 3, Normalized>(
primitive,
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback));
break;
case 4:
getMatNPropertyViewImpl<Callback, 4, Normalized>(
primitive,
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback));
break;
default:
callback(
propertyId,
PropertyAttributePropertyView<uint8_t>(
PropertyAttributePropertyViewStatus::ErrorTypeMismatch));
break;
}
}
template <typename T, bool Normalized>
PropertyAttributePropertyView<T, Normalized> createPropertyView(
const MeshPrimitive& primitive,
const ClassProperty& classProperty,
const PropertyAttributeProperty& propertyAttributeProperty) const {
const PropertyType type = convertStringToPropertyType(classProperty.type);
if (TypeToPropertyType<T>::value != type) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorTypeMismatch);
}
const PropertyComponentType componentType =
convertStringToPropertyComponentType(
classProperty.componentType.value_or(""));
if (TypeToPropertyType<T>::component != componentType) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorComponentTypeMismatch);
}
if (classProperty.normalized != Normalized) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorNormalizationMismatch);
}
if (primitive.attributes.find(propertyAttributeProperty.attribute) ==
primitive.attributes.end()) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorMissingAttribute);
}
const Accessor* pAccessor = _pModel->getSafe<Accessor>(
&_pModel->accessors,
primitive.attributes.at(propertyAttributeProperty.attribute));
if (!pAccessor) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorInvalidAccessor);
}
if (getAccessorTypeAsPropertyType(*pAccessor) != type) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorAccessorTypeMismatch);
}
if (getAccessorComponentTypeAsPropertyComponentType(*pAccessor) !=
componentType) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::
ErrorAccessorComponentTypeMismatch);
}
if (pAccessor->normalized != Normalized) {
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::
ErrorAccessorNormalizationMismatch);
}
AccessorView<T> accessorView = AccessorView<T>(*_pModel, *pAccessor);
if (accessorView.status() != AccessorViewStatus::Valid) {
switch (accessorView.status()) {
case AccessorViewStatus::InvalidBufferViewIndex:
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorInvalidBufferView);
case AccessorViewStatus::InvalidBufferIndex:
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorInvalidBuffer);
case AccessorViewStatus::BufferViewTooSmall:
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorAccessorOutOfBounds);
case AccessorViewStatus::BufferTooSmall:
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorBufferViewOutOfBounds);
default:
return PropertyAttributePropertyView<T, Normalized>(
PropertyAttributePropertyViewStatus::ErrorInvalidAccessor);
}
}
return PropertyAttributePropertyView<T, Normalized>(
propertyAttributeProperty,
classProperty,
accessorView);
}
const Model* _pModel;
const PropertyAttribute* _pPropertyAttribute;
const Class* _pClass;
PropertyAttributeViewStatus _status;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,76 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/PropertyTableProperty.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
#include <optional>
#include <string>
#include <unordered_map>
namespace CesiumGltf {
/**
* @brief Properties conforming to a class, organized as property values stored
* in binary columnar arrays.
*/
struct CESIUMGLTF_API PropertyTable final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "PropertyTable";
/**
* @brief The name of the property table, e.g. for display purposes.
*/
std::optional<std::string> name;
/**
* @brief The class that property values conform to. The value must be a class
* ID declared in the `classes` dictionary.
*/
std::string classProperty;
/**
* @brief The number of elements in each property array.
*/
int64_t count = int64_t();
/**
* @brief A dictionary, where each key corresponds to a property ID in the
* class' `properties` dictionary and each value is an object describing where
* property values are stored. Required properties must be included in this
* dictionary.
*/
std::unordered_map<std::string, CesiumGltf::PropertyTableProperty> properties;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(PropertyTable));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
accum += int64_t(this->classProperty.capacity() * sizeof(char));
accum += int64_t(
this->properties.bucket_count() *
(sizeof(std::string) + sizeof(CesiumGltf::PropertyTableProperty)));
for (const auto& [k, v] : this->properties) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum +=
v.getSizeBytes() - int64_t(sizeof(CesiumGltf::PropertyTableProperty));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,161 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <CesiumUtility/JsonValue.h>
#include <cstdint>
#include <optional>
#include <string>
namespace CesiumGltf {
/**
* @brief An array of binary property values.
*/
struct CESIUMGLTF_API PropertyTableProperty final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "PropertyTableProperty";
/**
* @brief Known values for The type of values in `arrayOffsets`.
*/
struct ArrayOffsetType {
/** @brief `UINT8` */
inline static const std::string UINT8 = "UINT8";
/** @brief `UINT16` */
inline static const std::string UINT16 = "UINT16";
/** @brief `UINT32` */
inline static const std::string UINT32 = "UINT32";
/** @brief `UINT64` */
inline static const std::string UINT64 = "UINT64";
};
/**
* @brief Known values for The type of values in `stringOffsets`.
*/
struct StringOffsetType {
/** @brief `UINT8` */
inline static const std::string UINT8 = "UINT8";
/** @brief `UINT16` */
inline static const std::string UINT16 = "UINT16";
/** @brief `UINT32` */
inline static const std::string UINT32 = "UINT32";
/** @brief `UINT64` */
inline static const std::string UINT64 = "UINT64";
};
/**
* @brief The index of the buffer view containing property values. The data
* type of property values is determined by the property definition: When
* `type` is `BOOLEAN` values are packed into a bitstream. When `type` is
* `STRING` values are stored as byte sequences and decoded as UTF-8 strings.
* When `type` is `SCALAR`, `VECN`, or `MATN` the values are stored as the
* provided `componentType` and the buffer view `byteOffset` must be aligned
* to a multiple of the `componentType` size. When `type` is `ENUM` values are
* stored as the enum's `valueType` and the buffer view `byteOffset` must be
* aligned to a multiple of the `valueType` size. Each enum value in the array
* must match one of the allowed values in the enum definition. `arrayOffsets`
* is required for variable-length arrays and `stringOffsets` is required for
* strings (for variable-length arrays of strings, both are required).
*/
int32_t values = -1;
/**
* @brief The index of the buffer view containing offsets for variable-length
* arrays. The number of offsets is equal to the property table `count` plus
* one. The offsets represent the start positions of each array, with the last
* offset representing the position after the last array. The array length is
* computed using the difference between the subsequent offset and the current
* offset. If `type` is `STRING` the offsets index into the string offsets
* array (stored in `stringOffsets`), otherwise they index into the property
* array (stored in `values`). The data type of these offsets is determined by
* `arrayOffsetType`. The buffer view `byteOffset` must be aligned to a
* multiple of the `arrayOffsetType` size.
*/
int32_t arrayOffsets = -1;
/**
* @brief The index of the buffer view containing offsets for strings. The
* number of offsets is equal to the number of string elements plus one. The
* offsets represent the byte offsets of each string in the property array
* (stored in `values`), with the last offset representing the byte offset
* after the last string. The string byte length is computed using the
* difference between the subsequent offset and the current offset. The data
* type of these offsets is determined by `stringOffsetType`. The buffer view
* `byteOffset` must be aligned to a multiple of the `stringOffsetType` size.
*/
int32_t stringOffsets = -1;
/**
* @brief The type of values in `arrayOffsets`.
*
* Known values are defined in {@link ArrayOffsetType}.
*
*/
std::string arrayOffsetType = ArrayOffsetType::UINT32;
/**
* @brief The type of values in `stringOffsets`.
*
* Known values are defined in {@link StringOffsetType}.
*
*/
std::string stringOffsetType = StringOffsetType::UINT32;
/**
* @brief An offset to apply to property values. Only applicable when the
* component type is `FLOAT32` or `FLOAT64`, or when the property is
* `normalized`. Overrides the class property's `offset` if both are defined.
*/
std::optional<CesiumUtility::JsonValue> offset;
/**
* @brief A scale to apply to property values. Only applicable when the
* component type is `FLOAT32` or `FLOAT64`, or when the property is
* `normalized`. Overrides the class property's `scale` if both are defined.
*/
std::optional<CesiumUtility::JsonValue> scale;
/**
* @brief Maximum value present in the property values. Only applicable to
* `SCALAR`, `VECN`, and `MATN` types. This is the maximum of all property
* values, after the transforms based on the `normalized`, `offset`, and
* `scale` properties have been applied.
*/
std::optional<CesiumUtility::JsonValue> max;
/**
* @brief Minimum value present in the property values. Only applicable to
* `SCALAR`, `VECN`, and `MATN` types. This is the minimum of all property
* values, after the transforms based on the `normalized`, `offset`, and
* `scale` properties have been applied.
*/
std::optional<CesiumUtility::JsonValue> min;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(PropertyTableProperty));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,791 @@
#pragma once
#include "CesiumGltf/PropertyArrayView.h"
#include "CesiumGltf/PropertyTransformations.h"
#include "CesiumGltf/PropertyTypeTraits.h"
#include "CesiumGltf/PropertyView.h"
#include <CesiumUtility/Assert.h>
#include <cstddef>
#include <cstdint>
#include <span>
#include <string_view>
#include <type_traits>
namespace CesiumGltf {
/**
* @brief Indicates the status of a property table property view.
*
* The {@link PropertyTablePropertyView} constructor always completes successfully.
* However, it may not always reflect the actual content of the
* {@link PropertyTableProperty}, but instead indicate that its `size` is 0.
* This enumeration provides the reason.
*/
class PropertyTablePropertyViewStatus : public PropertyViewStatus {
public:
/**
* @brief This property view was initialized from an invalid
* {@link PropertyTable}.
*/
static const PropertyViewStatusType ErrorInvalidPropertyTable = 14;
/**
* @brief This property view does not have a valid value buffer view index.
*/
static const PropertyViewStatusType ErrorInvalidValueBufferView = 15;
/**
* @brief This array property view does not have a valid array offset buffer
* view index.
*/
static const PropertyViewStatusType ErrorInvalidArrayOffsetBufferView = 16;
/**
* @brief This string property view does not have a valid string offset buffer
* view index.
*/
static const PropertyViewStatusType ErrorInvalidStringOffsetBufferView = 17;
/**
* @brief This property view has a valid value buffer view, but the buffer
* view specifies an invalid buffer index.
*/
static const PropertyViewStatusType ErrorInvalidValueBuffer = 18;
/**
* @brief This property view has a valid array string buffer view, but the
* buffer view specifies an invalid buffer index.
*/
static const PropertyViewStatusType ErrorInvalidArrayOffsetBuffer = 19;
/**
* @brief This property view has a valid string offset buffer view, but the
* buffer view specifies an invalid buffer index.
*/
static const PropertyViewStatusType ErrorInvalidStringOffsetBuffer = 20;
/**
* @brief This property view has a buffer view that points outside the bounds
* of its target buffer.
*/
static const PropertyViewStatusType ErrorBufferViewOutOfBounds = 21;
/**
* @brief This property view has an invalid buffer view; its length is not
* a multiple of the size of its type / offset type.
*/
static const PropertyViewStatusType
ErrorBufferViewSizeNotDivisibleByTypeSize = 22;
/**
* @brief This property view has an invalid buffer view; its length does not
* match the size of the property table.
*/
static const PropertyViewStatusType
ErrorBufferViewSizeDoesNotMatchPropertyTableCount = 23;
/**
* @brief This array property view has both a fixed length and an offset
* buffer view defined.
*/
static const PropertyViewStatusType ErrorArrayCountAndOffsetBufferCoexist =
24;
/**
* @brief This array property view has neither a fixed length nor an offset
* buffer view defined.
*/
static const PropertyViewStatusType ErrorArrayCountAndOffsetBufferDontExist =
25;
/**
* @brief This property view has an unknown array offset type.
*/
static const PropertyViewStatusType ErrorInvalidArrayOffsetType = 26;
/**
* @brief This property view has an unknown string offset type.
*/
static const PropertyViewStatusType ErrorInvalidStringOffsetType = 27;
/**
* @brief This property view's array offset values are not sorted in ascending
* order.
*/
static const PropertyViewStatusType ErrorArrayOffsetsNotSorted = 28;
/**
* @brief This property view's string offset values are not sorted in
* ascending order.
*/
static const PropertyViewStatusType ErrorStringOffsetsNotSorted = 29;
/**
* @brief This property view has an array offset that is out of bounds.
*/
static const PropertyViewStatusType ErrorArrayOffsetOutOfBounds = 30;
/**
* @brief This property view has a string offset that is out of bounds.
*/
static const PropertyViewStatusType ErrorStringOffsetOutOfBounds = 31;
};
/**
* @brief Returns the size in bytes of a \ref PropertyComponentType used as the
* `arrayOffsetType` in the constructor of \ref PropertyTablePropertyView.
*/
int64_t getOffsetTypeSize(PropertyComponentType offsetType) noexcept;
/**
* @brief A view on the data of the {@link PropertyTableProperty} that is created
* by a {@link PropertyTableView}.
*/
template <typename ElementType, bool Normalized = false>
class PropertyTablePropertyView;
/**
* @brief A view on the data of the {@link PropertyTableProperty} that is created
* by a {@link PropertyTableView}.
*
* It provides utility to retrieve the actual data stored in the
* {@link PropertyTableProperty::values} like an array of elements. Data of each
* instance can be accessed through the {@link PropertyTablePropertyView<ElementType, false>::get} method.
*
* @param ElementType must be one of the following: a scalar (uint8_t, int8_t,
* uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double), a
* glm vecN composed of one of the scalar types, a glm matN composed of one of
* the scalar types, bool, std::string_view, or PropertyArrayView<T> with T as
* one of the aforementioned types.
*/
template <typename ElementType>
class PropertyTablePropertyView<ElementType, false>
: public PropertyView<ElementType, false> {
public:
/**
* @brief Constructs an invalid instance for a non-existent property.
*/
PropertyTablePropertyView()
: PropertyView<ElementType, false>(),
_values{},
_size{0},
_arrayOffsets{},
_arrayOffsetType{PropertyComponentType::None},
_arrayOffsetTypeSize{0},
_stringOffsets{},
_stringOffsetType{PropertyComponentType::None},
_stringOffsetTypeSize{0} {}
/**
* @brief Constructs an invalid instance for an erroneous property.
*
* @param status The code from {@link PropertyTablePropertyViewStatus} indicating the error with the property.
*/
PropertyTablePropertyView(PropertyViewStatusType status)
: PropertyView<ElementType, false>(status),
_values{},
_size{0},
_arrayOffsets{},
_arrayOffsetType{PropertyComponentType::None},
_arrayOffsetTypeSize{0},
_stringOffsets{},
_stringOffsetType{PropertyComponentType::None},
_stringOffsetTypeSize{0} {
CESIUM_ASSERT(
this->_status != PropertyTablePropertyViewStatus::Valid &&
"An empty property view should not be constructed with a valid status");
}
/**
* @brief Constructs an instance of an empty property that specifies a default
* value. Although this property has no data, it can return the default value
* when {@link PropertyTablePropertyView<ElementType, false>::get} is called. However,
* {@link PropertyTablePropertyView<ElementType, false>::getRaw} cannot be used.
*
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param size The number of elements in the property table specified by {@link PropertyTable::count}
*/
PropertyTablePropertyView(const ClassProperty& classProperty, int64_t size)
: PropertyView<ElementType, false>(classProperty),
_values{},
_size{0},
_arrayOffsets{},
_arrayOffsetType{PropertyComponentType::None},
_arrayOffsetTypeSize{0},
_stringOffsets{},
_stringOffsetType{PropertyComponentType::None},
_stringOffsetTypeSize{0} {
if (this->_status != PropertyTablePropertyViewStatus::Valid) {
// Don't override the status / size if something is wrong with the class
// property's definition.
return;
}
if (!classProperty.defaultProperty) {
// This constructor should only be called if the class property *has* a
// default value. But in the case that it does not, this property view
// becomes invalid.
this->_status = PropertyTablePropertyViewStatus::ErrorNonexistentProperty;
return;
}
this->_status = PropertyTablePropertyViewStatus::EmptyPropertyWithDefault;
this->_size = size;
}
/**
* @brief Construct an instance pointing to data specified by a {@link PropertyTableProperty}.
* Used for non-array or fixed-length array data.
*
* @param property The {@link PropertyTableProperty}
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param size The number of elements in the property table specified by {@link PropertyTable::count}
* @param values The raw buffer specified by {@link PropertyTableProperty::values}
*/
PropertyTablePropertyView(
const PropertyTableProperty& property,
const ClassProperty& classProperty,
int64_t size,
std::span<const std::byte> values) noexcept
: PropertyView<ElementType>(classProperty, property),
_values{values},
_size{
this->_status == PropertyTablePropertyViewStatus::Valid ? size : 0},
_arrayOffsets{},
_arrayOffsetType{PropertyComponentType::None},
_arrayOffsetTypeSize{0},
_stringOffsets{},
_stringOffsetType{PropertyComponentType::None},
_stringOffsetTypeSize{0} {}
/**
* @brief Construct an instance pointing to the data specified by a {@link PropertyTableProperty}.
*
* @param property The {@link PropertyTableProperty}
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param size The number of elements in the property table specified by {@link PropertyTable::count}
* @param values The raw buffer specified by {@link PropertyTableProperty::values}
* @param arrayOffsets The raw buffer specified by {@link PropertyTableProperty::arrayOffsets}
* @param stringOffsets The raw buffer specified by {@link PropertyTableProperty::stringOffsets}
* @param arrayOffsetType The offset type of arrayOffsets specified by {@link PropertyTableProperty::arrayOffsetType}
* @param stringOffsetType The offset type of stringOffsets specified by {@link PropertyTableProperty::stringOffsetType}
*/
PropertyTablePropertyView(
const PropertyTableProperty& property,
const ClassProperty& classProperty,
int64_t size,
std::span<const std::byte> values,
std::span<const std::byte> arrayOffsets,
std::span<const std::byte> stringOffsets,
PropertyComponentType arrayOffsetType,
PropertyComponentType stringOffsetType) noexcept
: PropertyView<ElementType>(classProperty, property),
_values{values},
_size{
this->_status == PropertyTablePropertyViewStatus::Valid ? size : 0},
_arrayOffsets{arrayOffsets},
_arrayOffsetType{arrayOffsetType},
_arrayOffsetTypeSize{getOffsetTypeSize(arrayOffsetType)},
_stringOffsets{stringOffsets},
_stringOffsetType{stringOffsetType},
_stringOffsetTypeSize{getOffsetTypeSize(stringOffsetType)} {}
/**
* @brief Get the value of an element in the {@link PropertyTable},
* with all value transforms applied. That is, if the property specifies an
* offset and scale, they will be applied to the value before the value is
* returned.
*
* If this property has a specified "no data" value, and the retrieved element
* is equal to that value, then this will return the property's specified
* default value. If the property did not provide a default value, this
* returns std::nullopt.
*
* @param index The element index
* @return The value of the element, or std::nullopt if it matches the "no
* data" value
*/
std::optional<PropertyValueViewToCopy<ElementType>>
get(int64_t index) const noexcept {
if (this->_status ==
PropertyTablePropertyViewStatus::EmptyPropertyWithDefault) {
CESIUM_ASSERT(index >= 0 && "index must be non-negative");
CESIUM_ASSERT(index < size() && "index must be less than size");
return propertyValueViewToCopy(this->defaultValue());
}
ElementType value = getRaw(index);
if (value == this->noData()) {
return propertyValueViewToCopy(this->defaultValue());
} else if constexpr (IsMetadataNumeric<ElementType>::value) {
return transformValue(value, this->offset(), this->scale());
} else if constexpr (IsMetadataNumericArray<ElementType>::value) {
return transformArray(value, this->offset(), this->scale());
} else {
return value;
}
}
/**
* @brief Get the raw value of an element of the {@link PropertyTable},
* without offset or scale applied.
*
* If this property has a specified "no data" value, the raw value will still
* be returned, even if it equals the "no data" value.
*
* @param index The element index
* @return The value of the element
*/
ElementType getRaw(int64_t index) const noexcept {
CESIUM_ASSERT(
this->_status == PropertyTablePropertyViewStatus::Valid &&
"Check the status() first to make sure view is valid");
CESIUM_ASSERT(
size() > 0 &&
"Check the size() of the view to make sure it's not empty");
CESIUM_ASSERT(index >= 0 && "index must be non-negative");
CESIUM_ASSERT(index < size() && "index must be less than size");
if constexpr (IsMetadataNumeric<ElementType>::value) {
return getNumericValue(index);
}
if constexpr (IsMetadataBoolean<ElementType>::value) {
return getBooleanValue(index);
}
if constexpr (IsMetadataString<ElementType>::value) {
return getStringValue(index);
}
if constexpr (IsMetadataNumericArray<ElementType>::value) {
return getNumericArrayValues<
typename MetadataArrayType<ElementType>::type>(index);
}
if constexpr (IsMetadataBooleanArray<ElementType>::value) {
return getBooleanArrayValues(index);
}
if constexpr (IsMetadataStringArray<ElementType>::value) {
return getStringArrayValues(index);
}
}
/**
* @brief Get the number of elements in this
* PropertyTablePropertyView. If the view is valid, this returns
* {@link PropertyTable::count}. Otherwise, this returns 0.
*
* @return The number of elements in this PropertyTablePropertyView.
*/
int64_t size() const noexcept { return _size; }
private:
ElementType getNumericValue(int64_t index) const noexcept {
return reinterpret_cast<const ElementType*>(_values.data())[index];
}
bool getBooleanValue(int64_t index) const noexcept {
const int64_t byteIndex = index / 8;
const int64_t bitIndex = index % 8;
const int bitValue = static_cast<int>(_values[byteIndex] >> bitIndex) & 1;
return bitValue == 1;
}
std::string_view getStringValue(int64_t index) const noexcept {
const size_t currentOffset =
getOffsetFromOffsetsBuffer(index, _stringOffsets, _stringOffsetType);
const size_t nextOffset = getOffsetFromOffsetsBuffer(
index + 1,
_stringOffsets,
_stringOffsetType);
return std::string_view(
reinterpret_cast<const char*>(_values.data() + currentOffset),
nextOffset - currentOffset);
}
template <typename T>
PropertyArrayView<T> getNumericArrayValues(int64_t index) const noexcept {
size_t count = static_cast<size_t>(this->arrayCount());
// Handle fixed-length arrays
if (count > 0) {
size_t arraySize = count * sizeof(T);
const std::span<const std::byte> values(
_values.data() + index * arraySize,
arraySize);
return PropertyArrayView<T>{values};
}
// Handle variable-length arrays. The offsets are interpreted as array
// indices, not byte offsets, so they must be multiplied by sizeof(T)
const size_t currentOffset =
getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType) *
sizeof(T);
const size_t nextOffset =
getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType) *
sizeof(T);
const std::span<const std::byte> values(
_values.data() + currentOffset,
nextOffset - currentOffset);
return PropertyArrayView<T>{values};
}
PropertyArrayView<std::string_view>
getStringArrayValues(int64_t index) const noexcept {
size_t count = static_cast<size_t>(this->arrayCount());
// Handle fixed-length arrays
if (count > 0) {
// Copy the corresponding string offsets to pass to the PropertyArrayView.
const size_t arraySize = count * _stringOffsetTypeSize;
const std::span<const std::byte> stringOffsetValues(
_stringOffsets.data() + index * arraySize,
arraySize + _stringOffsetTypeSize);
return PropertyArrayView<std::string_view>(
_values,
stringOffsetValues,
_stringOffsetType,
count);
}
// Handle variable-length arrays
const size_t currentArrayOffset =
getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType);
const size_t nextArrayOffset =
getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType);
const size_t arraySize = nextArrayOffset - currentArrayOffset;
const std::span<const std::byte> stringOffsetValues(
_stringOffsets.data() + currentArrayOffset,
arraySize + _arrayOffsetTypeSize);
return PropertyArrayView<std::string_view>(
_values,
stringOffsetValues,
_stringOffsetType,
arraySize / _arrayOffsetTypeSize);
}
PropertyArrayView<bool> getBooleanArrayValues(int64_t index) const noexcept {
size_t count = static_cast<size_t>(this->arrayCount());
// Handle fixed-length arrays
if (count > 0) {
const size_t offsetBits = count * index;
const size_t nextOffsetBits = count * (index + 1);
const std::span<const std::byte> buffer(
_values.data() + offsetBits / 8,
(nextOffsetBits / 8 - offsetBits / 8 + 1));
return PropertyArrayView<bool>(buffer, offsetBits % 8, count);
}
// Handle variable-length arrays
const size_t currentOffset =
getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType);
const size_t nextOffset =
getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType);
const size_t totalBits = nextOffset - currentOffset;
const std::span<const std::byte> buffer(
_values.data() + currentOffset / 8,
(nextOffset / 8 - currentOffset / 8 + 1));
return PropertyArrayView<bool>(buffer, currentOffset % 8, totalBits);
}
std::span<const std::byte> _values;
int64_t _size;
std::span<const std::byte> _arrayOffsets;
PropertyComponentType _arrayOffsetType;
int64_t _arrayOffsetTypeSize;
std::span<const std::byte> _stringOffsets;
PropertyComponentType _stringOffsetType;
int64_t _stringOffsetTypeSize;
};
/**
* @brief A view on the normalized data of the {@link PropertyTableProperty}
* that is created by a {@link PropertyTableView}.
*
* It provides utility to retrieve the actual data stored in the
* {@link PropertyTableProperty::values} like an array of elements. Data of each
* instance can be accessed through the \ref get method.
*
* @param ElementType must be one of the following: an integer scalar (uint8_t,
* int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t), a glm vecN
* composed of one of the integer scalar types, a glm matN composed of one of
* the integer scalar types, or PropertyArrayView<T> with T as one of the
* aforementioned types.
*/
template <typename ElementType>
class PropertyTablePropertyView<ElementType, true>
: public PropertyView<ElementType, true> {
private:
using NormalizedType = typename TypeToNormalizedType<ElementType>::type;
public:
/**
* @brief Constructs an invalid instance for a non-existent property.
*/
PropertyTablePropertyView()
: PropertyView<ElementType, true>(),
_values{},
_size{0},
_arrayOffsets{},
_arrayOffsetType{PropertyComponentType::None},
_arrayOffsetTypeSize{0} {}
/**
* @brief Constructs an invalid instance for an erroneous property.
*
* @param status The value of {@link PropertyTablePropertyViewStatus} indicating the error with the property.
*/
PropertyTablePropertyView(PropertyViewStatusType status)
: PropertyView<ElementType, true>(status),
_values{},
_size{0},
_arrayOffsets{},
_arrayOffsetType{PropertyComponentType::None},
_arrayOffsetTypeSize{0} {
CESIUM_ASSERT(
this->_status != PropertyTablePropertyViewStatus::Valid &&
"An empty property view should not be constructed with a valid status");
}
/**
* @brief Constructs an instance of an empty property that specifies a default
* value. Although this property has no data, it can return the default value
* when {@link PropertyTablePropertyView<ElementType, true>::get} is called. However,
* {@link PropertyTablePropertyView<ElementType, true>::getRaw} cannot be used.
*
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param size The number of elements in the property table specified by {@link PropertyTable::count}
*/
PropertyTablePropertyView(const ClassProperty& classProperty, int64_t size)
: PropertyView<ElementType, true>(classProperty),
_values{},
_size{0},
_arrayOffsets{},
_arrayOffsetType{PropertyComponentType::None},
_arrayOffsetTypeSize{0} {
if (this->_status != PropertyTablePropertyViewStatus::Valid) {
// Don't override the status / size if something is wrong with the class
// property's definition.
return;
}
if (!classProperty.defaultProperty) {
// This constructor should only be called if the class property *has* a
// default value. But in the case that it does not, this property view
// becomes invalid.
this->_status = PropertyTablePropertyViewStatus::ErrorNonexistentProperty;
return;
}
this->_status = PropertyTablePropertyViewStatus::EmptyPropertyWithDefault;
this->_size = size;
}
/**
* @brief Construct an instance pointing to data specified by a {@link PropertyTableProperty}.
* Used for non-array or fixed-length array data.
*
* @param property The {@link PropertyTableProperty}
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param size The number of elements in the property table specified by {@link PropertyTable::count}
* @param values The raw buffer specified by {@link PropertyTableProperty::values}
*/
PropertyTablePropertyView(
const PropertyTableProperty& property,
const ClassProperty& classProperty,
int64_t size,
std::span<const std::byte> values) noexcept
: PropertyView<ElementType, true>(classProperty, property),
_values{values},
_size{
this->_status == PropertyTablePropertyViewStatus::Valid ? size : 0},
_arrayOffsets{},
_arrayOffsetType{PropertyComponentType::None},
_arrayOffsetTypeSize{0} {}
/**
* @brief Construct an instance pointing to the data specified by a {@link PropertyTableProperty}.
*
*
* @param property The {@link PropertyTableProperty}
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param size The number of elements in the property table specified by {@link PropertyTable::count}
* @param values The raw buffer specified by {@link PropertyTableProperty::values}
* @param arrayOffsets The raw buffer specified by {@link PropertyTableProperty::arrayOffsets}
* @param arrayOffsetType The offset type of arrayOffsets specified by {@link PropertyTableProperty::arrayOffsetType}
*/
PropertyTablePropertyView(
const PropertyTableProperty& property,
const ClassProperty& classProperty,
int64_t size,
std::span<const std::byte> values,
std::span<const std::byte> arrayOffsets,
PropertyComponentType arrayOffsetType) noexcept
: PropertyView<ElementType, true>(classProperty, property),
_values{values},
_size{
this->_status == PropertyTablePropertyViewStatus::Valid ? size : 0},
_arrayOffsets{arrayOffsets},
_arrayOffsetType{arrayOffsetType},
_arrayOffsetTypeSize{getOffsetTypeSize(arrayOffsetType)} {}
/**
* @brief Get the value of an element of the {@link PropertyTable},
* with normalization and other value transforms applied. In other words, the
* value will be normalized, then transformed by the property's offset
* and scale, if they are defined.
*
* If this property has a specified "no data" value, and the retrieved element
* is equal to that value, then this will return the property's specified
* default value. If the property did not provide a default value, this
* returns std::nullopt.
*
* @param index The element index
* @return The value of the element, or std::nullopt if it matches the "no
* data" value
*/
std::optional<PropertyValueViewToCopy<NormalizedType>>
get(int64_t index) const noexcept {
if (this->_status ==
PropertyTablePropertyViewStatus::EmptyPropertyWithDefault) {
CESIUM_ASSERT(index >= 0 && "index must be non-negative");
CESIUM_ASSERT(index < size() && "index must be less than size");
return propertyValueViewToCopy(this->defaultValue());
}
ElementType value = getRaw(index);
if (this->noData() && value == *(this->noData())) {
return propertyValueViewToCopy(this->defaultValue());
} else if constexpr (IsMetadataScalar<ElementType>::value) {
return transformValue<NormalizedType>(
normalize<ElementType>(value),
this->offset(),
this->scale());
} else if constexpr (IsMetadataVecN<ElementType>::value) {
constexpr glm::length_t N = ElementType::length();
using T = typename ElementType::value_type;
using NormalizedT = typename NormalizedType::value_type;
return transformValue<glm::vec<N, NormalizedT>>(
normalize<N, T>(value),
this->offset(),
this->scale());
} else if constexpr (IsMetadataMatN<ElementType>::value) {
constexpr glm::length_t N = ElementType::length();
using T = typename ElementType::value_type;
using NormalizedT = typename NormalizedType::value_type;
return transformValue<glm::mat<N, N, NormalizedT>>(
normalize<N, T>(value),
this->offset(),
this->scale());
} else if constexpr (IsMetadataArray<ElementType>::value) {
using ArrayElementType = typename MetadataArrayType<ElementType>::type;
if constexpr (IsMetadataScalar<ArrayElementType>::value) {
return transformNormalizedArray<ArrayElementType>(
value,
this->offset(),
this->scale());
} else if constexpr (IsMetadataVecN<ArrayElementType>::value) {
constexpr glm::length_t N = ArrayElementType::length();
using T = typename ArrayElementType::value_type;
return transformNormalizedVecNArray<N, T>(
value,
this->offset(),
this->scale());
} else if constexpr (IsMetadataMatN<ArrayElementType>::value) {
constexpr glm::length_t N = ArrayElementType::length();
using T = typename ArrayElementType::value_type;
return transformNormalizedMatNArray<N, T>(
value,
this->offset(),
this->scale());
}
}
}
/**
* @brief Get the raw value of an element of the {@link PropertyTable},
* without offset, scale, or normalization applied.
*
* If this property has a specified "no data" value, the raw value will still
* be returned, even if it equals the "no data" value.
*
* @param index The element index
* @return The value of the element
*/
ElementType getRaw(int64_t index) const noexcept {
CESIUM_ASSERT(
this->_status == PropertyTablePropertyViewStatus::Valid &&
"Check the status() first to make sure view is valid");
CESIUM_ASSERT(
size() > 0 &&
"Check the size() of the view to make sure it's not empty");
CESIUM_ASSERT(index >= 0 && "index must be non-negative");
CESIUM_ASSERT(index < size() && "index must be less than size");
if constexpr (IsMetadataNumeric<ElementType>::value) {
return getValue(index);
}
if constexpr (IsMetadataNumericArray<ElementType>::value) {
return getArrayValues<typename MetadataArrayType<ElementType>::type>(
index);
}
}
/**
* @brief Get the number of elements in this
* PropertyTablePropertyView. If the view is valid, this returns
* {@link PropertyTable::count}. Otherwise, this returns 0.
*
* @return The number of elements in this PropertyTablePropertyView.
*/
int64_t size() const noexcept {
return this->_status == PropertyTablePropertyViewStatus::Valid ? _size : 0;
}
private:
ElementType getValue(int64_t index) const noexcept {
return reinterpret_cast<const ElementType*>(_values.data())[index];
}
template <typename T>
PropertyArrayView<T> getArrayValues(int64_t index) const noexcept {
size_t count = static_cast<size_t>(this->arrayCount());
// Handle fixed-length arrays
if (count > 0) {
size_t arraySize = count * sizeof(T);
const std::span<const std::byte> values(
_values.data() + index * arraySize,
arraySize);
return PropertyArrayView<T>{values};
}
// Handle variable-length arrays. The offsets are interpreted as array
// indices, not byte offsets, so they must be multiplied by sizeof(T)
const size_t currentOffset =
getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType) *
sizeof(T);
const size_t nextOffset =
getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType) *
sizeof(T);
const std::span<const std::byte> values(
_values.data() + currentOffset,
nextOffset - currentOffset);
return PropertyArrayView<T>{values};
}
std::span<const std::byte> _values;
int64_t _size;
std::span<const std::byte> _arrayOffsets;
PropertyComponentType _arrayOffsetType;
int64_t _arrayOffsetTypeSize;
};
} // namespace CesiumGltf

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/PropertyTextureProperty.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <optional>
#include <string>
#include <unordered_map>
namespace CesiumGltf {
/**
* @brief Properties conforming to a class, organized as property values stored
* in textures.
*/
struct CESIUMGLTF_API PropertyTexture final
: public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "PropertyTexture";
/**
* @brief The name of the property texture, e.g. for display purposes.
*/
std::optional<std::string> name;
/**
* @brief The class that property values conform to. The value must be a class
* ID declared in the `classes` dictionary.
*/
std::string classProperty;
/**
* @brief A dictionary, where each key corresponds to a property ID in the
* class' `properties` dictionary and each value is an object describing where
* property values are stored. Required properties must be included in this
* dictionary.
*/
std::unordered_map<std::string, CesiumGltf::PropertyTextureProperty>
properties;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(PropertyTexture));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
accum += int64_t(this->classProperty.capacity() * sizeof(char));
accum += int64_t(
this->properties.bucket_count() *
(sizeof(std::string) + sizeof(CesiumGltf::PropertyTextureProperty)));
for (const auto& [k, v] : this->properties) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += v.getSizeBytes() -
int64_t(sizeof(CesiumGltf::PropertyTextureProperty));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,75 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/TextureInfo.h>
#include <CesiumUtility/JsonValue.h>
#include <cstdint>
#include <optional>
#include <vector>
namespace CesiumGltf {
/**
* @brief A texture containing property values.
*/
struct CESIUMGLTF_API PropertyTextureProperty final : public TextureInfo {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "PropertyTextureProperty";
/**
* @brief Texture channels containing property values, identified by index.
* The values may be packed into multiple channels if a single channel does
* not have sufficient bit depth. The values are packed in little-endian
* order.
*/
std::vector<int64_t> channels = {0};
/**
* @brief An offset to apply to property values. Only applicable when the
* component type is `FLOAT32` or `FLOAT64`, or when the property is
* `normalized`. Overrides the class property's `offset` if both are defined.
*/
std::optional<CesiumUtility::JsonValue> offset;
/**
* @brief A scale to apply to property values. Only applicable when the
* component type is `FLOAT32` or `FLOAT64`, or when the property is
* `normalized`. Overrides the class property's `scale` if both are defined.
*/
std::optional<CesiumUtility::JsonValue> scale;
/**
* @brief Maximum value present in the property values. Only applicable to
* `SCALAR`, `VECN`, and `MATN` types. This is the maximum of all property
* values, after the transforms based on the `normalized`, `offset`, and
* `scale` properties have been applied.
*/
std::optional<CesiumUtility::JsonValue> max;
/**
* @brief Minimum value present in the property values. Only applicable to
* `SCALAR`, `VECN`, and `MATN` types. This is the minimum of all property
* values, after the transforms based on the `normalized`, `offset`, and
* `scale` properties have been applied.
*/
std::optional<CesiumUtility::JsonValue> min;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(PropertyTextureProperty));
accum += TextureInfo::getSizeBytes() - int64_t(sizeof(TextureInfo));
accum += int64_t(sizeof(int64_t) * this->channels.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,726 @@
#pragma once
#include "CesiumGltf/ImageAsset.h"
#include "CesiumGltf/KhrTextureTransform.h"
#include "CesiumGltf/PropertyTextureProperty.h"
#include "CesiumGltf/PropertyTransformations.h"
#include "CesiumGltf/PropertyTypeTraits.h"
#include "CesiumGltf/PropertyView.h"
#include "CesiumGltf/Sampler.h"
#include "CesiumGltf/TextureView.h"
#include <CesiumUtility/Assert.h>
#include <array>
#include <cmath>
#include <cstdint>
#include <optional>
namespace CesiumGltf {
/**
* @brief Indicates the status of a property texture property view.
*
* The {@link PropertyTexturePropertyView} constructor always completes
* successfully. However it may not always reflect the actual content of the
* corresponding property texture property. This enumeration provides the
* reason.
*/
class PropertyTexturePropertyViewStatus : public PropertyViewStatus {
public:
/**
* @brief This property view was initialized from an invalid
* {@link PropertyTexture}.
*/
static const int ErrorInvalidPropertyTexture = 14;
/**
* @brief This property view is associated with a {@link ClassProperty} of an
* unsupported type.
*/
static const int ErrorUnsupportedProperty = 15;
/**
* @brief This property view does not have a valid texture index.
*/
static const int ErrorInvalidTexture = 16;
/**
* @brief This property view does not have a valid sampler index.
*/
static const int ErrorInvalidSampler = 17;
/**
* @brief This property view does not have a valid image index.
*/
static const int ErrorInvalidImage = 18;
/**
* @brief This property is viewing an empty image.
*/
static const int ErrorEmptyImage = 19;
/**
* @brief This property uses an image with multi-byte channels. Only
* single-byte channels are supported.
*/
static const int ErrorInvalidBytesPerChannel = 20;
/**
* @brief The channels of this property texture property are invalid.
* Channels must be in the range 0-N, where N is the number of available
* channels in the image. There must be a minimum of one channel. Although
* more than four channels can be defined for specialized texture
* formats, this implementation only supports four channels max.
*/
static const int ErrorInvalidChannels = 21;
/**
* @brief The channels of this property texture property do not provide
* the exact number of bytes required by the property type. This may be
* because an incorrect number of channels was provided, or because the
* image itself has a different channel count / byte size than expected.
*/
static const int ErrorChannelsAndTypeMismatch = 22;
};
/**
* @brief Attempts to obtain a scalar value from the given span of bytes.
*
* @tparam ElementType The scalar value type to read from `bytes`.
* @param bytes A span of bytes to convert into a scalar value.
* @returns A value of `ElementType`.
*/
template <typename ElementType>
ElementType assembleScalarValue(const std::span<uint8_t> bytes) noexcept {
if constexpr (std::is_same_v<ElementType, float>) {
CESIUM_ASSERT(
bytes.size() == sizeof(float) &&
"Not enough channel inputs to construct a float.");
uint32_t resultAsUint = 0;
for (size_t i = 0; i < bytes.size(); i++) {
resultAsUint |= static_cast<uint32_t>(bytes[i]) << i * 8;
}
// Reinterpret the bits as a float.
return *reinterpret_cast<float*>(&resultAsUint);
}
if constexpr (IsMetadataInteger<ElementType>::value) {
using UintType = std::make_unsigned_t<ElementType>;
UintType resultAsUint = 0;
for (size_t i = 0; i < bytes.size(); i++) {
resultAsUint |= static_cast<UintType>(bytes[i]) << i * 8;
}
// Reinterpret the bits with the correct signedness.
return *reinterpret_cast<ElementType*>(&resultAsUint);
}
}
/**
* @brief Attempts to obtain a vector value from the given span of bytes.
*
* @tparam ElementType The vector value type to read from `bytes`.
* @param bytes A span of bytes to convert into a vector value.
* @returns A value of `ElementType`.
*/
template <typename ElementType>
ElementType assembleVecNValue(const std::span<uint8_t> bytes) noexcept {
ElementType result = ElementType();
const glm::length_t N =
getDimensionsFromPropertyType(TypeToPropertyType<ElementType>::value);
using T = typename ElementType::value_type;
CESIUM_ASSERT(
sizeof(T) <= 2 && "Components cannot be larger than two bytes in size.");
if constexpr (std::is_same_v<T, int16_t>) {
CESIUM_ASSERT(
N == 2 && "Only vec2s can contain two-byte integer components.");
uint16_t x = static_cast<uint16_t>(bytes[0]) |
(static_cast<uint16_t>(bytes[1]) << 8);
uint16_t y = static_cast<uint16_t>(bytes[2]) |
(static_cast<uint16_t>(bytes[3]) << 8);
result[0] = *reinterpret_cast<int16_t*>(&x);
result[1] = *reinterpret_cast<int16_t*>(&y);
}
if constexpr (std::is_same_v<T, uint16_t>) {
CESIUM_ASSERT(
N == 2 && "Only vec2s can contain two-byte integer components.");
result[0] = static_cast<uint16_t>(bytes[0]) |
(static_cast<uint16_t>(bytes[1]) << 8);
result[1] = static_cast<uint16_t>(bytes[2]) |
(static_cast<uint16_t>(bytes[3]) << 8);
}
if constexpr (std::is_same_v<T, int8_t>) {
for (size_t i = 0; i < bytes.size(); i++) {
result[i] = *reinterpret_cast<const int8_t*>(&bytes[i]);
}
}
if constexpr (std::is_same_v<T, uint8_t>) {
for (size_t i = 0; i < bytes.size(); i++) {
result[i] = bytes[i];
}
}
return result;
}
/**
* @brief Attempts to obtain an array value from the given span of bytes.
*
* @tparam T The element type to read from `bytes`.
* @param bytes A span of bytes to convert into an array value.
* @returns A \ref PropertyArrayCopy containing the elements read.
*/
template <typename T>
PropertyArrayCopy<T>
assembleArrayValue(const std::span<uint8_t> bytes) noexcept {
std::vector<T> result(bytes.size() / sizeof(T));
if constexpr (sizeof(T) == 2) {
for (int i = 0, b = 0; i < result.size(); i++, b += 2) {
using UintType = std::make_unsigned_t<T>;
UintType resultAsUint = static_cast<UintType>(bytes[b]) |
(static_cast<UintType>(bytes[b + 1]) << 8);
result[i] = *reinterpret_cast<T*>(&resultAsUint);
}
} else {
for (size_t i = 0; i < bytes.size(); i++) {
result[i] = *reinterpret_cast<const T*>(&bytes[i]);
}
}
return PropertyArrayCopy<T>(std::move(result));
}
/**
* @brief Assembles the given type from the provided channel values of sampling
* a texture.
*
* @tparam ElementType The type of element to assemble.
* @param bytes The byte values of the sampled channels of the texture.
* @returns The result of \ref assembleScalarValue, \ref assembleVecNValue, or
* \ref assembleArrayValue depending on `ElementType`.
*/
template <typename ElementType>
PropertyValueViewToCopy<ElementType>
assembleValueFromChannels(const std::span<uint8_t> bytes) noexcept {
CESIUM_ASSERT(
bytes.size() > 0 && "Channel input must have at least one value.");
if constexpr (IsMetadataScalar<ElementType>::value) {
return assembleScalarValue<ElementType>(bytes);
}
if constexpr (IsMetadataVecN<ElementType>::value) {
return assembleVecNValue<ElementType>(bytes);
}
if constexpr (IsMetadataArray<ElementType>::value) {
return assembleArrayValue<typename MetadataArrayType<ElementType>::type>(
bytes);
}
}
#pragma region Non - normalized property
/**
* @brief A view of the data specified by a {@link PropertyTextureProperty}.
*
* Provides utilities to sample the property texture property using texture
* coordinates. Property values are retrieved from the NEAREST texel without
* additional filtering applied.
*
* @tparam ElementType The type of the elements represented in the property
* view
* @tparam Normalized Whether or not the property is normalized. If
* normalized, the elements can be retrieved as normalized floating-point
* numbers, as opposed to their integer values.
*/
template <typename ElementType, bool Normalized = false>
class PropertyTexturePropertyView;
/**
* @brief A view of the non-normalized data specified by a
* {@link PropertyTextureProperty}.
*
* Provides utilities to sample the property texture property using texture
* coordinates.
*
* @tparam ElementType The type of the elements represented in the property view
*/
template <typename ElementType>
class PropertyTexturePropertyView<ElementType, false>
: public PropertyView<ElementType, false>, public TextureView {
public:
/**
* @brief Constructs an invalid instance for a non-existent property.
*/
PropertyTexturePropertyView() noexcept
: PropertyView<ElementType, false>(),
TextureView(),
_channels(),
_swizzle() {}
/**
* @brief Constructs an invalid instance for an erroneous property.
*
* @param status The code from {@link PropertyTexturePropertyViewStatus} indicating the error with the property.
*/
PropertyTexturePropertyView(PropertyViewStatusType status) noexcept
: PropertyView<ElementType, false>(status),
TextureView(),
_channels(),
_swizzle() {
CESIUM_ASSERT(
this->_status != PropertyTexturePropertyViewStatus::Valid &&
"An empty property view should not be constructed with a valid status");
}
/**
* @brief Constructs an instance of an empty property that specifies a default
* value. Although this property has no data, it can return the default value
* when \ref get is called. However, \ref getRaw cannot be used.
*
* @param classProperty The {@link ClassProperty} this property conforms to.
*/
PropertyTexturePropertyView(const ClassProperty& classProperty) noexcept
: PropertyView<ElementType, false>(classProperty),
TextureView(),
_channels(),
_swizzle() {
if (this->_status != PropertyTexturePropertyViewStatus::Valid) {
// Don't override the status / size if something is wrong with the class
// property's definition.
return;
}
if (!classProperty.defaultProperty) {
// This constructor should only be called if the class property *has* a
// default value. But in the case that it does not, this property view
// becomes invalid.
this->_status =
PropertyTexturePropertyViewStatus::ErrorNonexistentProperty;
return;
}
this->_status = PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault;
}
/**
* @brief Construct a view of the data specified by a {@link PropertyTextureProperty}.
*
* @param property The {@link PropertyTextureProperty}
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param sampler The {@link Sampler} used by the property.
* @param image The {@link ImageAsset} used by the property.
* @param options The options for constructing the view.
*/
PropertyTexturePropertyView(
const PropertyTextureProperty& property,
const ClassProperty& classProperty,
const Sampler& sampler,
const ImageAsset& image,
const TextureViewOptions& options = TextureViewOptions()) noexcept
: PropertyView<ElementType, false>(classProperty, property),
TextureView(
sampler,
image,
property.texCoord,
property.getExtension<ExtensionKhrTextureTransform>(),
options),
_channels(property.channels),
_swizzle() {
if (this->_status != PropertyTexturePropertyViewStatus::Valid) {
return;
}
switch (this->getTextureViewStatus()) {
case TextureViewStatus::Valid:
break;
case TextureViewStatus::ErrorInvalidSampler:
this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidSampler;
return;
case TextureViewStatus::ErrorInvalidImage:
this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidImage;
return;
case TextureViewStatus::ErrorEmptyImage:
this->_status = PropertyTexturePropertyViewStatus::ErrorEmptyImage;
return;
case TextureViewStatus::ErrorInvalidBytesPerChannel:
this->_status =
PropertyTexturePropertyViewStatus::ErrorInvalidBytesPerChannel;
return;
case TextureViewStatus::ErrorUninitialized:
case TextureViewStatus::ErrorInvalidTexture:
default:
this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidTexture;
return;
}
_swizzle.reserve(_channels.size());
for (size_t i = 0; i < _channels.size(); ++i) {
switch (_channels[i]) {
case 0:
_swizzle += "r";
break;
case 1:
_swizzle += "g";
break;
case 2:
_swizzle += "b";
break;
case 3:
_swizzle += "a";
break;
default:
CESIUM_ASSERT(
false && "A valid channels vector must be passed to the view.");
}
}
}
/**
* @brief Gets the value of the property for the given texture coordinates
* with all value transforms applied. That is, if the property specifies an
* offset and scale, they will be applied to the value before the value is
* returned. The sampler's wrapping mode will be used when sampling the
* texture.
*
* If this property has a specified "no data" value, this will return the
* property's default value for any elements that equal this "no data" value.
* If the property did not specify a default value, this returns std::nullopt.
*
* @param u The u-component of the texture coordinates.
* @param v The v-component of the texture coordinates.
*
* @return The value of the element, or std::nullopt if it matches the "no
* data" value
*/
std::optional<PropertyValueViewToCopy<ElementType>>
get(double u, double v) const noexcept {
if (this->_status ==
PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault) {
return propertyValueViewToCopy(this->defaultValue());
}
PropertyValueViewToCopy<ElementType> value = getRaw(u, v);
if (value == this->noData()) {
return propertyValueViewToCopy(this->defaultValue());
} else if constexpr (IsMetadataNumeric<ElementType>::value) {
return transformValue(value, this->offset(), this->scale());
} else if constexpr (IsMetadataNumericArray<ElementType>::value) {
return transformArray(
propertyValueCopyToView(value),
this->offset(),
this->scale());
} else {
return value;
}
}
/**
* @brief Gets the raw value of the property for the given texture
* coordinates. The sampler's wrapping mode will be used when sampling the
* texture.
*
* If this property has a specified "no data" value, the raw value will still
* be returned, even if it equals the "no data" value.
*
* @param u The u-component of the texture coordinates.
* @param v The v-component of the texture coordinates.
*
* @return The value at the nearest pixel to the texture coordinates.
*/
PropertyValueViewToCopy<ElementType>
getRaw(double u, double v) const noexcept {
CESIUM_ASSERT(
this->_status == PropertyTexturePropertyViewStatus::Valid &&
"Check the status() first to make sure view is valid");
std::vector<uint8_t> sample =
this->sampleNearestPixel(u, v, this->_channels);
return assembleValueFromChannels<ElementType>(
std::span(sample.data(), this->_channels.size()));
}
/**
* @brief Gets the channels of this property texture property.
*/
const std::vector<int64_t>& getChannels() const noexcept {
return this->_channels;
}
/**
* @brief Gets this property's channels as a swizzle string.
*/
const std::string& getSwizzle() const noexcept { return this->_swizzle; }
private:
std::vector<int64_t> _channels;
std::string _swizzle;
};
#pragma endregion
#pragma region Normalized property
/**
* @brief A view of the normalized data specified by a
* {@link PropertyTextureProperty}.
*
* Provides utilities to sample the property texture property using texture
* coordinates.
*/
template <typename ElementType>
class PropertyTexturePropertyView<ElementType, true>
: public PropertyView<ElementType, true>, public TextureView {
private:
using NormalizedType = typename TypeToNormalizedType<ElementType>::type;
public:
/**
* @brief Constructs an invalid instance for a non-existent property.
*/
PropertyTexturePropertyView() noexcept
: PropertyView<ElementType, true>(),
TextureView(),
_channels(),
_swizzle() {}
/**
* @brief Constructs an invalid instance for an erroneous property.
*
* @param status The code from {@link PropertyTexturePropertyViewStatus} indicating the error with the property.
*/
PropertyTexturePropertyView(PropertyViewStatusType status) noexcept
: PropertyView<ElementType, true>(status),
TextureView(),
_channels(),
_swizzle() {
CESIUM_ASSERT(
this->_status != PropertyTexturePropertyViewStatus::Valid &&
"An empty property view should not be constructed with a valid "
"status");
}
/**
* @brief Constructs an instance of an empty property that specifies a
* default value. Although this property has no data, it can return the
* default value when {@link PropertyTexturePropertyView<ElementType, true>::get} is called.
* However, {@link PropertyTexturePropertyView<ElementType, true>::getRaw} cannot be used.
*
* @param classProperty The {@link ClassProperty} this property conforms to.
*/
PropertyTexturePropertyView(const ClassProperty& classProperty) noexcept
: PropertyView<ElementType, true>(classProperty),
TextureView(),
_channels(),
_swizzle() {
if (this->_status != PropertyTexturePropertyViewStatus::Valid) {
// Don't override the status / size if something is wrong with the class
// property's definition.
return;
}
if (!classProperty.defaultProperty) {
// This constructor should only be called if the class property *has* a
// default value. But in the case that it does not, this property view
// becomes invalid.
this->_status =
PropertyTexturePropertyViewStatus::ErrorNonexistentProperty;
return;
}
this->_status = PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault;
}
/**
* @brief Construct a view of the data specified by a {@link PropertyTextureProperty}.
*
* @param property The {@link PropertyTextureProperty}
* @param classProperty The {@link ClassProperty} this property conforms to.
* @param sampler The {@link Sampler} used by the property.
* @param image The {@link ImageAsset} used by the property.
* @param options The options for constructing the view.
*/
PropertyTexturePropertyView(
const PropertyTextureProperty& property,
const ClassProperty& classProperty,
const Sampler& sampler,
const ImageAsset& image,
const TextureViewOptions& options = TextureViewOptions()) noexcept
: PropertyView<ElementType, true>(classProperty, property),
TextureView(
sampler,
image,
property.texCoord,
property.getExtension<ExtensionKhrTextureTransform>(),
options),
_channels(property.channels),
_swizzle() {
if (this->_status != PropertyTexturePropertyViewStatus::Valid) {
return;
}
switch (this->getTextureViewStatus()) {
case TextureViewStatus::Valid:
break;
case TextureViewStatus::ErrorInvalidSampler:
this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidSampler;
return;
case TextureViewStatus::ErrorInvalidImage:
this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidImage;
return;
case TextureViewStatus::ErrorEmptyImage:
this->_status = PropertyTexturePropertyViewStatus::ErrorEmptyImage;
return;
case TextureViewStatus::ErrorInvalidBytesPerChannel:
this->_status =
PropertyTexturePropertyViewStatus::ErrorInvalidBytesPerChannel;
return;
case TextureViewStatus::ErrorUninitialized:
case TextureViewStatus::ErrorInvalidTexture:
default:
this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidTexture;
return;
}
_swizzle.reserve(_channels.size());
for (size_t i = 0; i < _channels.size(); ++i) {
switch (_channels[i]) {
case 0:
_swizzle += "r";
break;
case 1:
_swizzle += "g";
break;
case 2:
_swizzle += "b";
break;
case 3:
_swizzle += "a";
break;
default:
CESIUM_ASSERT(
false && "A valid channels vector must be passed to the view.");
}
}
}
/**
* @brief Gets the value of the property for the given texture coordinates
* with all value transforms applied. That is, if the property specifies an
* offset and scale, they will be applied to the value before the value is
* returned. The sampler's wrapping mode will be used when sampling the
* texture.
*
* If this property has a specified "no data" value, and the retrieved
* element is equal to that value, then this will return the property's
* specified default value. If the property did not provide a default value,
* this returns std::nullopt.
*
* @param u The u-component of the texture coordinates.
* @param v The v-component of the texture coordinates.
*
* @return The value of the element, or std::nullopt if it matches the "no
* data" value
*/
std::optional<PropertyValueViewToCopy<NormalizedType>>
get(double u, double v) const noexcept {
if (this->_status ==
PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault) {
return propertyValueViewToCopy(this->defaultValue());
}
PropertyValueViewToCopy<ElementType> value = getRaw(u, v);
if (value == this->noData()) {
return propertyValueViewToCopy(this->defaultValue());
} else if constexpr (IsMetadataScalar<ElementType>::value) {
return transformValue<NormalizedType>(
normalize<ElementType>(value),
this->offset(),
this->scale());
} else if constexpr (IsMetadataVecN<ElementType>::value) {
constexpr glm::length_t N = ElementType::length();
using T = typename ElementType::value_type;
using NormalizedT = typename NormalizedType::value_type;
return transformValue<glm::vec<N, NormalizedT>>(
normalize<N, T>(value),
this->offset(),
this->scale());
} else if constexpr (IsMetadataArray<ElementType>::value) {
using ArrayElementType = typename MetadataArrayType<ElementType>::type;
if constexpr (IsMetadataScalar<ArrayElementType>::value) {
return transformNormalizedArray<ArrayElementType>(
propertyValueCopyToView(value),
this->offset(),
this->scale());
} else if constexpr (IsMetadataVecN<ArrayElementType>::value) {
constexpr glm::length_t N = ArrayElementType::length();
using T = typename ArrayElementType::value_type;
return transformNormalizedVecNArray<N, T>(
propertyValueCopyToView(value),
this->offset(),
this->scale());
}
}
}
/**
* @brief Gets the raw value of the property for the given texture
* coordinates. The sampler's wrapping mode will be used when sampling the
* texture.
*
* If this property has a specified "no data" value, the raw value will
* still be returned, even if it equals the "no data" value.
*
* @param u The u-component of the texture coordinates.
* @param v The v-component of the texture coordinates.
*
* @return The value at the nearest pixel to the texture coordinates.
*/
PropertyValueViewToCopy<ElementType>
getRaw(double u, double v) const noexcept {
CESIUM_ASSERT(
this->_status == PropertyTexturePropertyViewStatus::Valid &&
"Check the status() first to make sure view is valid");
std::vector<uint8_t> sample =
this->sampleNearestPixel(u, v, this->_channels);
return assembleValueFromChannels<ElementType>(
std::span(sample.data(), this->_channels.size()));
}
/**
* @brief Gets the channels of this property texture property.
*/
const std::vector<int64_t>& getChannels() const noexcept {
return this->_channels;
}
/**
* @brief Gets this property's channels as a swizzle string.
*/
const std::string& getSwizzle() const noexcept { return this->_swizzle; }
private:
std::vector<int64_t> _channels;
std::string _swizzle;
};
#pragma endregion
} // namespace CesiumGltf

View File

@ -0,0 +1,794 @@
#pragma once
#include "CesiumGltf/Class.h"
#include "CesiumGltf/ClassProperty.h"
#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h"
#include "CesiumGltf/Model.h"
#include "CesiumGltf/PropertyTexture.h"
#include "CesiumGltf/PropertyTexturePropertyView.h"
#include "CesiumGltf/TextureView.h"
namespace CesiumGltf {
/**
* @brief Indicates the status of a property texture view.
*
* The {@link PropertyTextureView} constructor always completes successfully.
* However it may not always reflect the actual content of the
* {@link PropertyTexture}. This enumeration provides the reason.
*/
enum class PropertyTextureViewStatus {
/**
* @brief This property texture view is valid and ready to use.
*/
Valid,
/**
* @brief The glTF is missing the EXT_structural_metadata extension.
*/
ErrorMissingMetadataExtension,
/**
* @brief The glTF EXT_structural_metadata extension doesn't contain a schema.
*/
ErrorMissingSchema,
/**
* @brief The property texture's specified class could not be found in the
* extension.
*/
ErrorClassNotFound
};
/**
* @brief A view on a {@link PropertyTexture}.
*
* This should be used to get a {@link PropertyTexturePropertyView} of a property
* in the property texture. It will validate the EXT_structural_metadata format
* and
* ensure {@link PropertyTexturePropertyView} does not access data out of bounds.
*/
class PropertyTextureView {
public:
/**
* @brief Construct a PropertyTextureView.
*
* @param model The glTF that contains the property texture's data.
* @param propertyTexture The {@link PropertyTexture}
* from which the view will retrieve data.
*/
PropertyTextureView(
const Model& model,
const PropertyTexture& propertyTexture) noexcept;
/**
* @brief Gets the status of this property texture view.
*
* Indicates whether the view accurately reflects the property texture's data,
* or whether an error occurred.
*/
PropertyTextureViewStatus status() const noexcept { return this->_status; }
/**
* @brief Gets the name of the property texture being viewed. Returns
* std::nullopt if no name was specified.
*/
const std::optional<std::string>& name() const noexcept {
return _pPropertyTexture->name;
}
/**
* @brief Gets the {@link Class} that this property texture conforms to.
*
* @return A pointer to the {@link Class}. Returns nullptr if the PropertyTexture
* did not specify a valid class.
*/
const Class* getClass() const noexcept { return _pClass; }
/**
* @brief Finds the {@link ClassProperty} that
* describes the type information of the property with the specified id.
* @param propertyId The id of the property to retrieve the class for.
* @return A pointer to the {@link ClassProperty}.
* Return nullptr if the PropertyTextureView is invalid or if no class
* property was found.
*/
const ClassProperty* getClassProperty(const std::string& propertyId) const;
/**
* @brief Gets a {@link PropertyTexturePropertyView} that views the data of a
* property stored in the {@link PropertyTexture}.
*
* This method will validate the EXT_structural_metadata format to ensure
* {@link PropertyTexturePropertyView} retrieves the correct data. T must
* be a scalar with a supported component type (int8_t, uint8_t, int16_t,
* uint16_t, int32_t, uint32_t, float), a glm vecN composed of one of the
* scalar types, or a PropertyArrayView containing one of the scalar types.
*
* If T does not match the type specified by the class property, this returns
* an invalid PropertyTexturePropertyView. Likewise, if the value of
* Normalized does not match the value of {@link ClassProperty::normalized} for that
* class property, this returns an invalid property view. Only types with
* integer components may be normalized.
*
* @tparam T The C++ type corresponding to the type of the data retrieved.
* @tparam Normalized Whether the property is normalized. Only applicable to
* types with integer components.
* @param propertyId The ID of the property to retrieve data from
* @param propertyOptions The options to apply to the property.
* @return A {@link PropertyTexturePropertyView} of the property. If no valid
* property is found, the property view will be invalid.
*/
template <typename T, bool Normalized = false>
PropertyTexturePropertyView<T, Normalized> getPropertyView(
const std::string& propertyId,
const TextureViewOptions& propertyOptions = TextureViewOptions()) const {
if (this->_status != PropertyTextureViewStatus::Valid) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorInvalidPropertyTexture);
}
const ClassProperty* pClassProperty = getClassProperty(propertyId);
if (!pClassProperty) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorNonexistentProperty);
}
return getPropertyViewImpl<T, Normalized>(
propertyId,
*pClassProperty,
propertyOptions);
}
/**
* @brief Gets a {@link PropertyTexturePropertyView} through a callback that accepts a
* property id and a {@link PropertyTexturePropertyView} that views the data
* of the property with the specified id.
*
* This method will validate the EXT_structural_metadata format to ensure
* {@link PropertyTexturePropertyView} retrieves the correct data. T must
* be a scalar with a supported component type (int8_t, uint8_t, int16_t,
* uint16_t, int32_t, uint32_t, float), a glm vecN composed of one of the
* scalar types, or a PropertyArrayView containing one of the scalar types.
*
* If the property is somehow invalid, an empty {@link PropertyTexturePropertyView}
* with an error status will be passed to the callback. Otherwise, a valid
* property view will be passed to the callback.
*
* @param propertyId The id of the property to retrieve data from
* @param callback A callback function that accepts a property id and a
* {@link PropertyTexturePropertyView}
* @param propertyOptions The options to apply to the property.
* @tparam Callback The type of the callback function.
*/
template <typename Callback>
void getPropertyView(
const std::string& propertyId,
Callback&& callback,
const TextureViewOptions& propertyOptions = TextureViewOptions()) const {
if (this->_status != PropertyTextureViewStatus::Valid) {
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorInvalidPropertyTexture));
return;
}
const ClassProperty* pClassProperty = getClassProperty(propertyId);
if (!pClassProperty) {
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorNonexistentProperty));
return;
}
PropertyType type = convertStringToPropertyType(pClassProperty->type);
PropertyComponentType componentType = PropertyComponentType::None;
if (pClassProperty->componentType) {
componentType =
convertStringToPropertyComponentType(*pClassProperty->componentType);
}
bool normalized = pClassProperty->normalized;
if (normalized && !isPropertyComponentTypeInteger(componentType)) {
// Only integer components may be normalized.
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorInvalidNormalization));
return;
}
if (pClassProperty->array) {
if (normalized) {
getArrayPropertyViewImpl<Callback, true>(
propertyId,
*pClassProperty,
type,
componentType,
std::forward<Callback>(callback),
propertyOptions);
} else {
getArrayPropertyViewImpl<Callback, false>(
propertyId,
*pClassProperty,
type,
componentType,
std::forward<Callback>(callback),
propertyOptions);
}
return;
}
if (type == PropertyType::Scalar) {
if (normalized) {
getScalarPropertyViewImpl<Callback, true>(
propertyId,
*pClassProperty,
componentType,
std::forward<Callback>(callback),
propertyOptions);
} else {
getScalarPropertyViewImpl<Callback, false>(
propertyId,
*pClassProperty,
componentType,
std::forward<Callback>(callback),
propertyOptions);
}
return;
}
if (isPropertyTypeVecN(type)) {
if (normalized) {
getVecNPropertyViewImpl<Callback, true>(
propertyId,
*pClassProperty,
type,
componentType,
std::forward<Callback>(callback),
propertyOptions);
} else {
getVecNPropertyViewImpl<Callback, false>(
propertyId,
*pClassProperty,
type,
componentType,
std::forward<Callback>(callback),
propertyOptions);
}
return;
}
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
return;
}
/**
* @brief Iterates over each property in the {@link PropertyTexture} with a callback
* that accepts a property id and a {@link PropertyTexturePropertyView} to view
* the data stored in the {@link PropertyTextureProperty}.
*
* This method will validate the EXT_structural_metadata format to ensure
* {@link PropertyTexturePropertyView} retrieves the correct data. T must be
* a scalar with a supported component type (int8_t, uint8_t, int16_t,
* uint16_t, int32_t, uint32_t, float), a glm vecN composed of one of the
* scalar types, or a PropertyArrayView containing one of the scalar types.
*
* If the property is invalid, an empty {@link PropertyTexturePropertyView} with an
* error status will be passed to the callback. Otherwise, a valid property
* view will be passed to the callback.
*
* @param callback A callback function that accepts property id and
* {@link PropertyTexturePropertyView}
* @param propertyOptions The options to apply to each property in the
* property texture.
* @tparam Callback The type of the callback function.
*/
template <typename Callback>
void forEachProperty(
Callback&& callback,
const TextureViewOptions& propertyOptions = TextureViewOptions()) const {
for (const auto& property : this->_pClass->properties) {
getPropertyView(
property.first,
std::forward<Callback>(callback),
propertyOptions);
}
}
private:
template <typename T, bool Normalized>
PropertyTexturePropertyView<T, Normalized> getPropertyViewImpl(
const std::string& propertyId,
const ClassProperty& classProperty,
const TextureViewOptions& propertyOptions) const {
auto propertyTexturePropertyIter =
_pPropertyTexture->properties.find(propertyId);
if (propertyTexturePropertyIter == _pPropertyTexture->properties.end()) {
if (!classProperty.required && classProperty.defaultProperty) {
// If the property was omitted from the property texture, it is still
// technically valid if it specifies a default value. Create a view that
// just returns the default value.
return PropertyTexturePropertyView<T, Normalized>(classProperty);
}
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorNonexistentProperty);
}
const PropertyTextureProperty& propertyTextureProperty =
propertyTexturePropertyIter->second;
if constexpr (IsMetadataScalar<T>::value) {
return createScalarPropertyView<T, Normalized>(
classProperty,
propertyTextureProperty,
propertyOptions);
}
if constexpr (IsMetadataVecN<T>::value) {
return createVecNPropertyView<T, Normalized>(
classProperty,
propertyTextureProperty,
propertyOptions);
}
if constexpr (IsMetadataArray<T>::value) {
return createArrayPropertyView<
typename MetadataArrayType<T>::type,
Normalized>(classProperty, propertyTextureProperty, propertyOptions);
}
}
template <typename Callback, bool Normalized>
void getArrayPropertyViewImpl(
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyType type,
PropertyComponentType componentType,
Callback&& callback,
const TextureViewOptions& propertyOptions) const {
// Only scalar arrays are supported.
if (type != PropertyType::Scalar) {
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
return;
}
int64_t count = classProperty.count.value_or(0);
if (count <= 0 || count > 4) {
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
return;
}
switch (componentType) {
case PropertyComponentType::Int8:
callback(
propertyId,
getPropertyViewImpl<PropertyArrayView<int8_t>, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
case PropertyComponentType::Uint8:
callback(
propertyId,
getPropertyViewImpl<PropertyArrayView<uint8_t>, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
case PropertyComponentType::Int16:
callback(
propertyId,
getPropertyViewImpl<PropertyArrayView<int16_t>, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
case PropertyComponentType::Uint16:
callback(
propertyId,
getPropertyViewImpl<PropertyArrayView<uint16_t>, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
default:
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
break;
}
}
template <typename Callback, bool Normalized>
void getScalarPropertyViewImpl(
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyComponentType componentType,
Callback&& callback,
const TextureViewOptions& propertyOptions) const {
switch (componentType) {
case PropertyComponentType::Int8:
callback(
propertyId,
getPropertyViewImpl<int8_t, Normalized>(
propertyId,
classProperty,
propertyOptions));
return;
case PropertyComponentType::Uint8:
callback(
propertyId,
getPropertyViewImpl<uint8_t, Normalized>(
propertyId,
classProperty,
propertyOptions));
return;
case PropertyComponentType::Int16:
callback(
propertyId,
getPropertyViewImpl<int16_t, Normalized>(
propertyId,
classProperty,
propertyOptions));
return;
case PropertyComponentType::Uint16:
callback(
propertyId,
getPropertyViewImpl<uint16_t, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
case PropertyComponentType::Int32:
callback(
propertyId,
getPropertyViewImpl<int32_t, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
case PropertyComponentType::Uint32:
callback(
propertyId,
getPropertyViewImpl<uint32_t, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
case PropertyComponentType::Float32:
callback(
propertyId,
getPropertyViewImpl<float, false>(
propertyId,
classProperty,
propertyOptions));
break;
default:
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
break;
}
}
template <typename Callback, glm::length_t N, bool Normalized>
void getVecNPropertyViewImpl(
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyComponentType componentType,
Callback&& callback,
const TextureViewOptions& propertyOptions) const {
switch (componentType) {
case PropertyComponentType::Int8:
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, int8_t>, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
case PropertyComponentType::Uint8:
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, uint8_t>, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
case PropertyComponentType::Int16:
if constexpr (N == 2) {
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, int16_t>, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
}
[[fallthrough]];
case PropertyComponentType::Uint16:
if constexpr (N == 2) {
callback(
propertyId,
getPropertyViewImpl<glm::vec<N, uint16_t>, Normalized>(
propertyId,
classProperty,
propertyOptions));
break;
}
[[fallthrough]];
default:
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
break;
}
}
template <typename Callback, bool Normalized>
void getVecNPropertyViewImpl(
const std::string& propertyId,
const ClassProperty& classProperty,
PropertyType type,
PropertyComponentType componentType,
Callback&& callback,
const TextureViewOptions& propertyOptions) const {
const glm::length_t N = getDimensionsFromPropertyType(type);
switch (N) {
case 2:
getVecNPropertyViewImpl<Callback, 2, Normalized>(
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback),
propertyOptions);
break;
case 3:
getVecNPropertyViewImpl<Callback, 3, Normalized>(
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback),
propertyOptions);
break;
case 4:
getVecNPropertyViewImpl<Callback, 4, Normalized>(
propertyId,
classProperty,
componentType,
std::forward<Callback>(callback),
propertyOptions);
break;
default:
callback(
propertyId,
PropertyTexturePropertyView<uint8_t>(
PropertyTexturePropertyViewStatus::ErrorTypeMismatch));
break;
}
}
template <typename T, bool Normalized>
PropertyTexturePropertyView<T, Normalized> createScalarPropertyView(
const ClassProperty& classProperty,
[[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty,
const TextureViewOptions& propertyOptions) const {
if (classProperty.array) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorArrayTypeMismatch);
}
const PropertyType type = convertStringToPropertyType(classProperty.type);
if (TypeToPropertyType<T>::value != type) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorTypeMismatch);
}
const PropertyComponentType componentType =
convertStringToPropertyComponentType(
classProperty.componentType.value_or(""));
if (TypeToPropertyType<T>::component != componentType) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorComponentTypeMismatch);
}
if (classProperty.normalized != Normalized) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorNormalizationMismatch);
}
// Only up to four bytes of image data are supported.
if constexpr (sizeof(T) <= 4) {
return createPropertyViewImpl<T, Normalized>(
classProperty,
propertyTextureProperty,
sizeof(T),
propertyOptions);
} else {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty);
}
}
template <typename T, bool Normalized>
PropertyTexturePropertyView<T, Normalized> createVecNPropertyView(
const ClassProperty& classProperty,
[[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty,
[[maybe_unused]] const TextureViewOptions& propertyOptions) const {
if (classProperty.array) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorArrayTypeMismatch);
}
const PropertyType type = convertStringToPropertyType(classProperty.type);
if (TypeToPropertyType<T>::value != type) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorTypeMismatch);
}
const PropertyComponentType componentType =
convertStringToPropertyComponentType(
classProperty.componentType.value_or(""));
if (TypeToPropertyType<T>::component != componentType) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorComponentTypeMismatch);
}
if (classProperty.normalized != Normalized) {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorNormalizationMismatch);
}
// Only up to four bytes of image data are supported.
if constexpr (sizeof(T) <= 4) {
return createPropertyViewImpl<T, Normalized>(
classProperty,
propertyTextureProperty,
sizeof(T),
propertyOptions);
} else {
return PropertyTexturePropertyView<T, Normalized>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty);
}
}
template <typename T, bool Normalized>
PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>
createArrayPropertyView(
const ClassProperty& classProperty,
[[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty,
[[maybe_unused]] const TextureViewOptions& propertyOptions) const {
if (!classProperty.array) {
return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
PropertyTexturePropertyViewStatus::ErrorArrayTypeMismatch);
}
const PropertyType type = convertStringToPropertyType(classProperty.type);
if (TypeToPropertyType<T>::value != type) {
return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
PropertyTexturePropertyViewStatus::ErrorTypeMismatch);
}
const PropertyComponentType componentType =
convertStringToPropertyComponentType(
classProperty.componentType.value_or(""));
if (TypeToPropertyType<T>::component != componentType) {
return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
PropertyTexturePropertyViewStatus::ErrorComponentTypeMismatch);
}
if (classProperty.normalized != Normalized) {
return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
PropertyTexturePropertyViewStatus::ErrorNormalizationMismatch);
}
// Only scalar arrays are supported. The scalar component type must not
// exceed two bytes.
if constexpr (IsMetadataScalar<T>::value && sizeof(T) <= 4) {
// Only up to four elements are supported.
int64_t count = classProperty.count.value_or(0);
if (count <= 0 || count > 4) {
return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty);
}
if (count * sizeof(T) > 4) {
return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty);
}
return createPropertyViewImpl<PropertyArrayView<T>, Normalized>(
classProperty,
propertyTextureProperty,
count * sizeof(T),
propertyOptions);
} else {
return PropertyTexturePropertyView<PropertyArrayView<T>, Normalized>(
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty);
}
}
template <typename T, bool Normalized>
PropertyTexturePropertyView<T, Normalized> createPropertyViewImpl(
const ClassProperty& classProperty,
const PropertyTextureProperty& propertyTextureProperty,
size_t elementSize,
const TextureViewOptions& propertyOptions) const {
int32_t samplerIndex;
int32_t imageIndex;
auto status =
getTextureSafe(propertyTextureProperty.index, samplerIndex, imageIndex);
if (status != PropertyTexturePropertyViewStatus::Valid) {
return PropertyTexturePropertyView<T, Normalized>(status);
}
status = checkSampler(samplerIndex);
if (status != PropertyTexturePropertyViewStatus::Valid) {
return PropertyTexturePropertyView<T, Normalized>(status);
}
status = checkImage(imageIndex);
if (status != PropertyTexturePropertyViewStatus::Valid) {
return PropertyTexturePropertyView<T, Normalized>(status);
}
const CesiumUtility::IntrusivePointer<ImageAsset>& pImage =
_pModel->images[imageIndex].pAsset;
const std::vector<int64_t>& channels = propertyTextureProperty.channels;
status = checkChannels(channels, *pImage);
if (status != PropertyTexturePropertyViewStatus::Valid) {
return PropertyTexturePropertyView<T, Normalized>(status);
}
if (channels.size() * pImage->bytesPerChannel != elementSize) {
return PropertyTexturePropertyViewStatus::ErrorChannelsAndTypeMismatch;
}
return PropertyTexturePropertyView<T, Normalized>(
propertyTextureProperty,
classProperty,
_pModel->samplers[samplerIndex],
*pImage,
propertyOptions);
}
PropertyViewStatusType getTextureSafe(
const int32_t textureIndex,
int32_t& samplerIndex,
int32_t& imageIndex) const noexcept;
PropertyViewStatusType
checkSampler(const int32_t samplerIndex) const noexcept;
PropertyViewStatusType checkImage(const int32_t imageIndex) const noexcept;
PropertyViewStatusType checkChannels(
const std::vector<int64_t>& channels,
const ImageAsset& image) const noexcept;
const Model* _pModel;
const PropertyTexture* _pPropertyTexture;
const Class* _pClass;
PropertyTextureViewStatus _status;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,244 @@
#pragma once
#include "CesiumGltf/PropertyArrayView.h"
#include "CesiumGltf/PropertyTypeTraits.h"
#include <glm/common.hpp>
#include <algorithm>
#include <cstdint>
#include <optional>
namespace CesiumGltf {
/**
* @brief Normalizes the given value between [0, 1] if unsigned or [-1, 1] if
* signed, based on the type's maximum value.
*
* @param value The value to normalize.
*/
template <typename T> double normalize(T value) {
constexpr double max = static_cast<double>(std::numeric_limits<T>::max());
if constexpr (std::is_signed_v<T>) {
return std::max(static_cast<double>(value) / max, -1.0);
} else {
return static_cast<double>(value) / max;
}
}
/**
* @brief Normalizes the given vector's components between [0, 1] if unsigned or
* [-1, 1] if signed, based on the type's maximum value.
*
* @param value The value to normalize.
*/
template <glm::length_t N, typename T>
glm::vec<N, double> normalize(glm::vec<N, T> value) {
constexpr double max = static_cast<double>(std::numeric_limits<T>::max());
if constexpr (std::is_signed_v<T>) {
return glm::max(static_cast<glm::vec<N, double>>(value) / max, -1.0);
} else {
return static_cast<glm::vec<N, double>>(value) / max;
}
}
/**
* @brief Normalizes the given matrix's components between [0, 1] if unsigned or
* [-1, 1] if signed, based on the type's maximum value.
*
* @param value The value to normalize.
*/
template <glm::length_t N, typename T>
glm::mat<N, N, double> normalize(glm::mat<N, N, T> value) {
constexpr double max = static_cast<double>(std::numeric_limits<T>::max());
// No max() implementation for matrices, so we have to write our own.
glm::mat<N, N, double> result;
for (glm::length_t i = 0; i < N; i++) {
for (glm::length_t j = 0; j < N; j++) {
if constexpr (std::is_signed_v<T>) {
result[i][j] = glm::max(static_cast<double>(value[i][j]) / max, -1.0);
} else {
result[i][j] = static_cast<double>(value[i][j]) / max;
}
}
}
return result;
}
/**
* @brief Multiplies each component of the value by the given scale factor.
*
* @param value The value to scale.
* @param scale The scale factor to apply to the value.
*/
template <typename T> T applyScale(const T& value, const T& scale) {
if constexpr (IsMetadataMatN<T>::value) {
// Do component-wise multiplication instead of actual matrix
// multiplication.
T matN;
constexpr glm::length_t N = T::length();
for (glm::length_t i = 0; i < N; i++) {
matN[i] = value[i] * scale[i];
}
return matN;
} else {
return value * scale;
}
}
/**
* @brief Transforms the value by optional offset and scale factors.
*
* @param value The value to transform.
* @param offset The amount to offset the value by, or `std::nullopt` to apply
* no offset.
* @param scale The amount to scale the value by, or `std::nullopt` to apply no
* scale. See \ref applyScale.
*/
template <typename T>
T transformValue(
const T& value,
const std::optional<T>& offset,
const std::optional<T>& scale) {
T result = value;
if (scale) {
result = applyScale<T>(result, *scale);
}
if (offset) {
result += *offset;
}
return result;
}
/**
* @brief Transforms each element of an array of values by optional offset and
* scale factors. See \ref transformValue.
*
* @param value The array whose elements will be transformed.
* @param offset The amount to offset each element by, or `std::nullopt` to
* apply no offset.
* @param scale The amount to scale each element by, or `std::nullopt` to apply
* no scale factor.
* @returns A transformed copy of the input array.
*/
template <typename T>
PropertyArrayCopy<T> transformArray(
const PropertyArrayView<T>& value,
const std::optional<PropertyArrayView<T>>& offset,
const std::optional<PropertyArrayView<T>>& scale) {
std::vector<T> result(static_cast<size_t>(value.size()));
for (int64_t i = 0; i < value.size(); i++) {
result[i] = value[i];
if (scale) {
result[i] = applyScale<T>(result[i], (*scale)[i]);
}
if (offset) {
result[i] = result[i] + (*offset)[i];
}
}
return PropertyArrayCopy(std::move(result));
}
/**
* @brief Normalizes each element of an array of values and transforms them by
* optional offset and scale factors. See \ref transformValue and \ref
* transformArray.
*
* @param value The array whose elements will be transformed.
* @param offset The amount to offset each element by, or `std::nullopt` to
* apply no offset. The offset will be applied after normalization.
* @param scale The amount to scale each element by, or `std::nullopt` to apply
* no scale factor. The scale will be applied after normalization.
* @returns A normalized and transformed copy of the input array.
*/
template <
typename T,
typename NormalizedType = typename TypeToNormalizedType<T>::type>
PropertyArrayCopy<NormalizedType> transformNormalizedArray(
const PropertyArrayView<T>& value,
const std::optional<PropertyArrayView<NormalizedType>>& offset,
const std::optional<PropertyArrayView<NormalizedType>>& scale) {
std::vector<NormalizedType> result(static_cast<size_t>(value.size()));
for (int64_t i = 0; i < value.size(); i++) {
result[i] = normalize<T>(value[i]);
if (scale) {
result[i] = result[i] * (*scale)[i];
}
if (offset) {
result[i] = result[i] + (*offset)[i];
}
}
return PropertyArrayCopy(std::move(result));
}
/**
* @brief Normalizes each element of an array of vectors and transforms them by
* optional offset and scale factors. See \ref transformNormalizedArray.
*
* @param value The array whose elements will be transformed.
* @param offset The amount to offset each element by, or `std::nullopt` to
* apply no offset. The offset will be applied after normalization.
* @param scale The amount to scale each element by, or `std::nullopt` to apply
* no scale factor. The scale will be applied after normalization.
* @returns A normalized and transformed copy of the input array.
*/
template <glm::length_t N, typename T>
PropertyArrayCopy<glm::vec<N, double>> transformNormalizedVecNArray(
const PropertyArrayView<glm::vec<N, T>>& value,
const std::optional<PropertyArrayView<glm::vec<N, double>>>& offset,
const std::optional<PropertyArrayView<glm::vec<N, double>>>& scale) {
std::vector<glm::vec<N, double>> result(static_cast<size_t>(value.size()));
for (int64_t i = 0; i < value.size(); i++) {
result[i] = normalize<N, T>(value[i]);
if (scale) {
result[i] = result[i] * (*scale)[i];
}
if (offset) {
result[i] = result[i] + (*offset)[i];
}
}
return PropertyArrayCopy(std::move(result));
}
/**
* @brief Normalizes each element of an array of matrices and transforms them by
* optional offset and scale factors. See \ref transformNormalizedArray.
*
* @param value The array whose elements will be transformed.
* @param offset The amount to offset each element by, or `std::nullopt` to
* apply no offset. The offset will be applied after normalization.
* @param scale The amount to scale each element by, or `std::nullopt` to apply
* no scale factor. The scale will be applied after normalization.
* @returns A normalized and transformed copy of the input array.
*/
template <glm::length_t N, typename T>
PropertyArrayCopy<glm::mat<N, N, double>> transformNormalizedMatNArray(
const PropertyArrayView<glm::mat<N, N, T>>& value,
const std::optional<PropertyArrayView<glm::mat<N, N, double>>>& offset,
const std::optional<PropertyArrayView<glm::mat<N, N, double>>>& scale) {
std::vector<glm::mat<N, N, double>> result(static_cast<size_t>(value.size()));
for (int64_t i = 0; i < value.size(); i++) {
result[i] = normalize<N, T>(value[i]);
if (scale) {
result[i] = applyScale<glm::mat<N, N, double>>(result[i], (*scale)[i]);
}
if (offset) {
result[i] = result[i] + (*offset)[i];
}
}
return PropertyArrayCopy(std::move(result));
}
} // namespace CesiumGltf

View File

@ -0,0 +1,255 @@
#pragma once
#include <glm/common.hpp>
#include <cstdint>
#include <string>
#include <string_view>
namespace CesiumGltf {
/**
* @brief The possible types of a property in a PropertyTableView.
*/
enum class PropertyType {
/**
* @brief An invalid property type.
*/
Invalid,
/**
* @brief A scalar property, i.e. an integer or floating point value.
*/
Scalar,
/**
* @brief A vector with two components.
*/
Vec2,
/**
* @brief A vector with three components.
*/
Vec3,
/**
* @brief A vector with four components.
*/
Vec4,
/**
* @brief A 2x2 matrix.
*/
Mat2,
/**
* @brief A 3x3 matrix.
*/
Mat3,
/**
* @brief A 4x4 matrix.
*/
Mat4,
/**
* @brief A string.
*/
String,
/**
* @brief A boolean.
*/
Boolean,
/**
* @brief An enum.
*/
Enum
};
/**
* @brief The possible types of a property component.
*/
enum class PropertyComponentType {
/**
* @brief No type.
*/
None,
/**
* @brief A property component equivalent to an `int8_t`.
*/
Int8,
/**
* @brief A property component equivalent to a `uint8_t`.
*/
Uint8,
/**
* @brief A property component equivalent to an `int16_t`.
*/
Int16,
/**
* @brief A property component equivalent to a `uint16_t`.
*/
Uint16,
/**
* @brief A property component equivalent to an `int32_t`.
*/
Int32,
/**
* @brief A property component equivalent to a `uint32_t`.
*/
Uint32,
/**
* @brief A property component equivalent to an `int64_t`.
*/
Int64,
/**
* @brief A property component equivalent to a `uint32_t`.
*/
Uint64,
/**
* @brief A property component equivalent to a `float`.
*/
Float32,
/**
* @brief A property component equivalent to a `double`.
*/
Float64,
};
/**
* @brief Converts a \ref PropertyType value to a string.
*
* For example, \ref PropertyType::Mat3 will become `"MAT3"`.
*
* @param type The type to convert to a string.
* @returns The type as a string, or `"INVALID"` if no conversion is possible.
*/
std::string convertPropertyTypeToString(PropertyType type);
/**
* @brief Converts a string into a \ref PropertyType.
*
* For example, `"MAT3"` will become a \ref PropertyType::Mat3.
*
* @param str The string to convert to a \ref PropertyType.
* @returns The string as a \ref PropertyType, or \ref PropertyType::Invalid if
* no conversion is possible.
*/
PropertyType convertStringToPropertyType(const std::string& str);
/**
* @brief Converts a \ref PropertyComponentType value to a string.
*
* For example, \ref PropertyComponentType::Uint8 will become `"UINT8"`.
*
* @param componentType The type to convert to a string.
* @returns The type as a string, or `"NONE"` if no conversion is possible.
*/
std::string
convertPropertyComponentTypeToString(PropertyComponentType componentType);
/**
* @brief Converts a string into a \ref PropertyComponentType.
*
* For example, `"UINT8"` will become a \ref PropertyComponentType::Uint8.
*
* @param str The string to convert to a \ref PropertyComponentType.
* @returns The string as a \ref PropertyComponentType, or \ref
* PropertyComponentType::None if no conversion is possible.
*/
PropertyComponentType
convertStringToPropertyComponentType(const std::string& str);
/**
* @brief Converts a string listed in \ref
* PropertyTableProperty::ArrayOffsetType to its corresponding \ref
* PropertyComponentType.
*
* @param str The string to convert to a \ref PropertyComponentType.
* @returns The string as a \ref PropertyComponentType, or \ref
* PropertyComponentType::None if no conversion is possible.
*/
PropertyComponentType
convertArrayOffsetTypeStringToPropertyComponentType(const std::string& str);
/**
* @brief Converts a string listed in \ref
* PropertyTableProperty::StringOffsetType to its corresponding \ref
* PropertyComponentType.
*
* @param str The string to convert to a \ref PropertyComponentType.
* @returns The string as a \ref PropertyComponentType, or \ref
* PropertyComponentType::None if no conversion is possible.
*/
PropertyComponentType
convertStringOffsetTypeStringToPropertyComponentType(const std::string& str);
/**
* @brief Converts a integer type ID listed in \ref
* AccessorSpec::ComponentType to its corresponding \ref
* PropertyComponentType.
*
* @param componentType The integer ID to convert to a \ref
* PropertyComponentType.
* @returns The ID as a \ref PropertyComponentType, or \ref
* PropertyComponentType::None if no conversion is possible.
*/
PropertyComponentType
convertAccessorComponentTypeToPropertyComponentType(int componentType);
/**
* @brief Checks if the given \ref PropertyType represents a vector with any
* number of components.
*
* @param type The \ref PropertyType to check.
* @returns True if \ref PropertyType is \ref PropertyType::Vec2, \ref
* PropertyType::Vec3, or \ref PropertyType::Vec4, or false otherwise.
*/
bool isPropertyTypeVecN(PropertyType type);
/**
* @brief Checks if the given \ref PropertyType represents a matrix with any
* number of components.
*
* @param type The \ref PropertyType to check.
* @returns True if \ref PropertyType is \ref PropertyType::Mat2, \ref
* PropertyType::Mat3, or \ref PropertyType::Mat4, or false otherwise.
*/
bool isPropertyTypeMatN(PropertyType type);
/**
* @brief Checks if the given \ref PropertyComponentType represents an integer
* value.
*
* @param componentType The \ref PropertyComponentType to check.
* @returns True if the \ref PropertyComponentType is \b not \ref
* PropertyComponentType::Float32 or \ref PropertyComponentType::Float64, false
* otherwise.
*/
bool isPropertyComponentTypeInteger(PropertyComponentType componentType);
/**
* @brief Obtains the number of dimensions in the given \ref PropertyType.
*
* @param type The type of the property to get the dimensions of.
* @returns The number of dimensions in a value of the given \ref PropertyType.
* For example, a value of \ref PropertyType::Scalar has one dimension. A value
* of \ref PropertyType::Mat4 and a value of \ref PropertyType::Vec4 both have
* four dimensions.
*/
glm::length_t getDimensionsFromPropertyType(PropertyType type);
/**
* @brief Obtains the number of components in the given \ref PropertyType.
*
* @param type The type of the property to get the component count of.
* @returns The number of components in a value of the given \ref PropertyType.
* For example, a value of \ref PropertyType::Scalar has one component. A value
* of \ref PropertyType::Vec4 has four components. A value of \ref
* PropertyType::Mat4 has 16 components.
*/
glm::length_t getComponentCountFromPropertyType(PropertyType type);
/**
* @brief Obtains the size in bytes of a value of this \ref
* PropertyComponentType.
*
* @param componentType The component type to get the size of.
* @returns The size in bytes that a value matching this \ref
* PropertyComponentType. For example, a value of \ref
* PropertyComponentType::Uint32 would take up four bytes.
*/
size_t getSizeOfComponentType(PropertyComponentType componentType);
} // namespace CesiumGltf

View File

@ -0,0 +1,648 @@
#pragma once
#include "CesiumGltf/PropertyArrayView.h"
#include "CesiumGltf/PropertyType.h"
#include <glm/glm.hpp>
#include <cstdint>
#include <optional>
#include <type_traits>
namespace CesiumGltf {
/**
* @brief Check if a C++ type can be represented as a scalar property type
*/
template <typename... T> struct IsMetadataScalar;
/** @copydoc IsMetadataScalar */
template <typename T> struct IsMetadataScalar<T> : std::false_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<uint8_t> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<int8_t> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<uint16_t> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<int16_t> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<uint32_t> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<int32_t> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<uint64_t> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<int64_t> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<float> : std::true_type {};
/** @copydoc IsMetadataScalar */
template <> struct IsMetadataScalar<double> : std::true_type {};
/**
* @brief Check if a C++ type can be represented as an integer property type
*/
template <typename... T> struct IsMetadataInteger;
/** @copydoc IsMetadataInteger */
template <typename T> struct IsMetadataInteger<T> : std::false_type {};
/** @copydoc IsMetadataInteger */
template <> struct IsMetadataInteger<uint8_t> : std::true_type {};
/** @copydoc IsMetadataInteger */
template <> struct IsMetadataInteger<int8_t> : std::true_type {};
/** @copydoc IsMetadataInteger */
template <> struct IsMetadataInteger<uint16_t> : std::true_type {};
/** @copydoc IsMetadataInteger */
template <> struct IsMetadataInteger<int16_t> : std::true_type {};
/** @copydoc IsMetadataInteger */
template <> struct IsMetadataInteger<uint32_t> : std::true_type {};
/** @copydoc IsMetadataInteger */
template <> struct IsMetadataInteger<int32_t> : std::true_type {};
/** @copydoc IsMetadataInteger */
template <> struct IsMetadataInteger<uint64_t> : std::true_type {};
/** @copydoc IsMetadataInteger */
template <> struct IsMetadataInteger<int64_t> : std::true_type {};
/**
* @brief Check if a C++ type can be represented as a floating-point property
* type.
*/
template <typename... T> struct IsMetadataFloating;
/** @copydoc IsMetadataFloating */
template <typename T> struct IsMetadataFloating<T> : std::false_type {};
/** @copydoc IsMetadataFloating */
template <> struct IsMetadataFloating<float> : std::true_type {};
/** @copydoc IsMetadataFloating */
template <> struct IsMetadataFloating<double> : std::true_type {};
/**
* @brief Check if a C++ type can be represented as a vecN type.
*/
template <typename... T> struct IsMetadataVecN;
/** @copydoc IsMetadataVecN */
template <typename T> struct IsMetadataVecN<T> : std::false_type {};
/** @copydoc IsMetadataVecN */
template <glm::length_t n, typename T, glm::qualifier P>
struct IsMetadataVecN<glm::vec<n, T, P>> : IsMetadataScalar<T> {};
/**
* @brief Check if a C++ type can be represented as a matN type.
*/
template <typename... T> struct IsMetadataMatN;
/** @copydoc IsMetadataMatN */
template <typename T> struct IsMetadataMatN<T> : std::false_type {};
/** @copydoc IsMetadataMatN */
template <glm::length_t n, typename T, glm::qualifier P>
struct IsMetadataMatN<glm::mat<n, n, T, P>> : IsMetadataScalar<T> {};
/**
* @brief Check if a C++ type can be represented as a numeric property, i.e.
* a scalar / vecN / matN type.
*/
template <typename... T> struct IsMetadataNumeric;
/**
* @copydoc IsMetadataNumeric
*/
template <typename T> struct IsMetadataNumeric<T> {
/**
* @brief Whether the given metadata type is a scalar, a vector, or a matrix.
*/
static constexpr bool value = IsMetadataScalar<T>::value ||
IsMetadataVecN<T>::value ||
IsMetadataMatN<T>::value;
};
/**
* @brief Check if a C++ type can be represented as a boolean property type
*/
template <typename... T> struct IsMetadataBoolean;
/** @copydoc IsMetadataBoolean */
template <typename T> struct IsMetadataBoolean<T> : std::false_type {};
/** @copydoc IsMetadataBoolean */
template <> struct IsMetadataBoolean<bool> : std::true_type {};
/**
* @brief Check if a C++ type can be represented as a string property type
*/
template <typename... T> struct IsMetadataString;
/** @copydoc IsMetadataString */
template <typename T> struct IsMetadataString<T> : std::false_type {};
/** @copydoc IsMetadataString */
template <> struct IsMetadataString<std::string_view> : std::true_type {};
/**
* @brief Check if a C++ type can be represented as an array.
*/
template <typename... T> struct IsMetadataArray;
/** @copydoc IsMetadataArray */
template <typename T> struct IsMetadataArray<T> : std::false_type {};
/** @copydoc IsMetadataArray */
template <typename T>
struct IsMetadataArray<PropertyArrayView<T>> : std::true_type {};
/** @copydoc IsMetadataArray */
template <typename T>
struct IsMetadataArray<PropertyArrayCopy<T>> : std::true_type {};
/**
* @brief Check if a C++ type can be represented as an array of numeric elements
* property type
*/
template <typename... T> struct IsMetadataNumericArray;
/** @copydoc IsMetadataNumericArray */
template <typename T> struct IsMetadataNumericArray<T> : std::false_type {};
/** @copydoc IsMetadataNumericArray */
template <typename T> struct IsMetadataNumericArray<PropertyArrayView<T>> {
/** @brief Whether the component of this \ref PropertyArrayView is numeric. */
static constexpr bool value = IsMetadataNumeric<T>::value;
};
/** @copydoc IsMetadataNumericArray */
template <typename T> struct IsMetadataNumericArray<PropertyArrayCopy<T>> {
/** @brief Whether the component of this \ref PropertyArrayCopy is numeric. */
static constexpr bool value = IsMetadataNumeric<T>::value;
};
/**
* @brief Check if a C++ type can be represented as an array of booleans
* property type
*/
template <typename... T> struct IsMetadataBooleanArray;
/** @copydoc IsMetadataBooleanArray */
template <typename T> struct IsMetadataBooleanArray<T> : std::false_type {};
/** @copydoc IsMetadataBooleanArray */
template <>
struct IsMetadataBooleanArray<PropertyArrayView<bool>> : std::true_type {};
/**
* @brief Check if a C++ type can be represented as an array of strings property
* type
*/
template <typename... T> struct IsMetadataStringArray;
/** @copydoc IsMetadataStringArray */
template <typename T> struct IsMetadataStringArray<T> : std::false_type {};
/** @copydoc IsMetadataStringArray */
template <>
struct IsMetadataStringArray<PropertyArrayView<std::string_view>>
: std::true_type {};
/**
* @brief Retrieve the component type of a metadata array
*/
template <typename T> struct MetadataArrayType {
/** @brief The component type of this metadata array. */
using type = void;
};
/** @copydoc MetadataArrayType */
template <typename T>
struct MetadataArrayType<CesiumGltf::PropertyArrayView<T>> {
/** @brief The component type of this metadata array. */
using type = T;
};
/** @copydoc MetadataArrayType */
template <typename T>
struct MetadataArrayType<CesiumGltf::PropertyArrayCopy<T>> {
/** @brief The component type of this metadata array. */
using type = T;
};
/**
* @brief Convert a C++ type to PropertyType and PropertyComponentType
*/
template <typename T> struct TypeToPropertyType;
#pragma region Scalar Property Types
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<uint8_t> {
/** @brief The \ref PropertyComponentType corresponding to a `uint8_t`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Uint8;
/** @brief The \ref PropertyType corresponding to a `uint8_t`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<int8_t> {
/** @brief The \ref PropertyComponentType corresponding to an `int8_t`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Int8;
/** @brief The \ref PropertyType corresponding to an `int8_t`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<uint16_t> {
/** @brief The \ref PropertyComponentType corresponding to a `uint16_t`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Uint16;
/** @brief The \ref PropertyType corresponding to a `uint16_t`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<int16_t> {
/** @brief The \ref PropertyComponentType corresponding to an `int16_t`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Int16;
/** @brief The \ref PropertyType corresponding to an `int16_t`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<uint32_t> {
/** @brief The \ref PropertyComponentType corresponding to a `uint32_t`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Uint32;
/** @brief The \ref PropertyType corresponding to a `uint32_t`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<int32_t> {
/** @brief The \ref PropertyComponentType corresponding to an `int32_t`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Int32;
/** @brief The \ref PropertyType corresponding to an `int32_t`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<uint64_t> {
/** @brief The \ref PropertyComponentType corresponding to a `uint64_t`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Uint64;
/** @brief The \ref PropertyType corresponding to a `uint64_t`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<int64_t> {
/** @brief The \ref PropertyComponentType corresponding to an `int64_t`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Int64;
/** @brief The \ref PropertyType corresponding to an `int64_t`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<float> {
/** @brief The \ref PropertyComponentType corresponding to a `float`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Float32;
/** @brief The \ref PropertyType corresponding to a `float`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<double> {
/** @brief The \ref PropertyComponentType corresponding to a `double`. */
static constexpr PropertyComponentType component =
PropertyComponentType::Float64;
/** @brief The \ref PropertyType corresponding to a `float`. */
static constexpr PropertyType value = PropertyType::Scalar;
};
#pragma endregion
#pragma region Vector Property Types
/** @copydoc TypeToPropertyType */
template <typename T, glm::qualifier P>
struct TypeToPropertyType<glm::vec<2, T, P>> {
/** @brief The \ref PropertyComponentType corresponding to a `glm::vec<2,
* ...>`. */
static constexpr PropertyComponentType component =
TypeToPropertyType<T>::component;
/** @brief The \ref PropertyType corresponding to a `glm::vec<2, ...>`. */
static constexpr PropertyType value = PropertyType::Vec2;
};
/** @copydoc TypeToPropertyType */
template <typename T, glm::qualifier P>
struct TypeToPropertyType<glm::vec<3, T, P>> {
/** @brief The \ref PropertyComponentType corresponding to a `glm::vec<3,
* ...>`. */
static constexpr PropertyComponentType component =
TypeToPropertyType<T>::component;
/** @brief The \ref PropertyType corresponding to a `glm::vec<3, ...>`. */
static constexpr PropertyType value = PropertyType::Vec3;
};
/** @copydoc TypeToPropertyType */
template <typename T, glm::qualifier P>
struct TypeToPropertyType<glm::vec<4, T, P>> {
/** @brief The \ref PropertyComponentType corresponding to a `glm::vec<4,
* ...>`. */
static constexpr PropertyComponentType component =
TypeToPropertyType<T>::component;
/** @brief The \ref PropertyType corresponding to a `glm::vec<4, ...>`. */
static constexpr PropertyType value = PropertyType::Vec4;
};
#pragma endregion
#pragma region Matrix Property Types
/** @copydoc TypeToPropertyType */
template <typename T, glm::qualifier P>
struct TypeToPropertyType<glm::mat<2, 2, T, P>> {
/** @brief The \ref PropertyComponentType corresponding to a `glm::mat<2, 2,
* ...>`. */
static constexpr PropertyComponentType component =
TypeToPropertyType<T>::component;
/** @brief The \ref PropertyType corresponding to a `glm::mat<2, 2, ...>`. */
static constexpr PropertyType value = PropertyType::Mat2;
};
/** @copydoc TypeToPropertyType */
template <typename T, glm::qualifier P>
struct TypeToPropertyType<glm::mat<3, 3, T, P>> {
/** @brief The \ref PropertyComponentType corresponding to a `glm::mat<3, 3,
* ...>`. */
static constexpr PropertyComponentType component =
TypeToPropertyType<T>::component;
/** @brief The \ref PropertyType corresponding to a `glm::mat<3, 3, ...>`. */
static constexpr PropertyType value = PropertyType::Mat3;
};
/** @copydoc TypeToPropertyType */
template <typename T, glm::qualifier P>
struct TypeToPropertyType<glm::mat<4, 4, T, P>> {
/** @brief The \ref PropertyComponentType corresponding to a `glm::mat<4, 4,
* ...>`. */
static constexpr PropertyComponentType component =
TypeToPropertyType<T>::component;
/** @brief The \ref PropertyType corresponding to a `glm::mat<4, 4, ...>`. */
static constexpr PropertyType value = PropertyType::Mat4;
};
#pragma endregion
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<bool> {
/** @brief The \ref PropertyComponentType corresponding to a `bool`. */
static constexpr PropertyComponentType component =
PropertyComponentType::None;
/** @brief The \ref PropertyType corresponding to a `bool`. */
static constexpr PropertyType value = PropertyType::Boolean;
};
/** @copydoc TypeToPropertyType */
template <> struct TypeToPropertyType<std::string_view> {
/** @brief The \ref PropertyComponentType corresponding to a
* `std::string_view`. */
static constexpr PropertyComponentType component =
PropertyComponentType::None;
/** @brief The \ref PropertyType corresponding to a `std::string_view`. */
static constexpr PropertyType value = PropertyType::String;
};
/**
* @brief Check if a C++ type can be normalized.
*/
template <typename... T> struct CanBeNormalized;
/** @copydoc CanBeNormalized */
template <typename T> struct CanBeNormalized<T> : std::false_type {};
/** @copydoc CanBeNormalized */
template <> struct CanBeNormalized<uint8_t> : std::true_type {};
/** @copydoc CanBeNormalized */
template <> struct CanBeNormalized<int8_t> : std::true_type {};
/** @copydoc CanBeNormalized */
template <> struct CanBeNormalized<uint16_t> : std::true_type {};
/** @copydoc CanBeNormalized */
template <> struct CanBeNormalized<int16_t> : std::true_type {};
/** @copydoc CanBeNormalized */
template <> struct CanBeNormalized<uint32_t> : std::true_type {};
/** @copydoc CanBeNormalized */
template <> struct CanBeNormalized<int32_t> : std::true_type {};
/** @copydoc CanBeNormalized */
template <> struct CanBeNormalized<uint64_t> : std::true_type {};
/** @copydoc CanBeNormalized */
template <> struct CanBeNormalized<int64_t> : std::true_type {};
/** @copydoc CanBeNormalized */
template <glm::length_t n, typename T, glm::qualifier P>
struct CanBeNormalized<glm::vec<n, T, P>> : CanBeNormalized<T> {};
/** @copydoc CanBeNormalized */
template <glm::length_t n, typename T, glm::qualifier P>
struct CanBeNormalized<glm::mat<n, n, T, P>> : CanBeNormalized<T> {};
/** @copydoc CanBeNormalized */
template <typename T>
struct CanBeNormalized<PropertyArrayView<T>> : CanBeNormalized<T> {};
/**
* @brief Convert an integer numeric type to the corresponding representation as
* a double type. Doubles are preferred over floats to maintain more precision.
*/
template <typename T> struct TypeToNormalizedType;
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<int8_t> {
/** @brief The representation of an `int8_t` as a double type. */
using type = double;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<uint8_t> {
/** @brief The representation of a `uint8_t` as a double type. */
using type = double;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<int16_t> {
/** @brief The representation of an `int16_t` as a double type. */
using type = double;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<uint16_t> {
/** @brief The representation of a `uint16_t` as a double type. */
using type = double;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<int32_t> {
/** @brief The representation of an `int32_t` as a double type. */
using type = double;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<uint32_t> {
/** @brief The representation of a `uint32_t` as a double type. */
using type = double;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<int64_t> {
/** @brief The representation of an `int64_t` as a double type. */
using type = double;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<uint64_t> {
/** @brief The representation of a `uint64_t` as a double type. */
using type = double;
};
/** @copydoc TypeToNormalizedType */
template <glm::length_t N, typename T, glm::qualifier Q>
struct TypeToNormalizedType<glm::vec<N, T, Q>> {
/** @brief The representation of a `glm::vec<N, T, Q>` as a double type. */
using type = glm::vec<N, double, Q>;
};
/** @copydoc TypeToNormalizedType */
template <glm::length_t N, typename T, glm::qualifier Q>
struct TypeToNormalizedType<glm::mat<N, N, T, Q>> {
/** @brief The representation of a `glm::mat<N, N, T, Q>` as a double type. */
using type = glm::mat<N, N, double, Q>;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<PropertyArrayView<int8_t>> {
/** @brief The representation of an array of `int8_t` types as an array of its
* double type equivalents. */
using type = PropertyArrayView<double>;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<PropertyArrayView<uint8_t>> {
/** @brief The representation of an array of `uint8_t` types as an array of
* its double type equivalents. */
using type = PropertyArrayView<double>;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<PropertyArrayView<int16_t>> {
/** @brief The representation of an array of `int16_t` types as an array of
* its double type equivalents. */
using type = PropertyArrayView<double>;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<PropertyArrayView<uint16_t>> {
/** @brief The representation of an array of `uint16_t` types as an array of
* its double type equivalents. */
using type = PropertyArrayView<double>;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<PropertyArrayView<int32_t>> {
/** @brief The representation of an array of `int32_t` types as an array of
* its double type equivalents. */
using type = PropertyArrayView<double>;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<PropertyArrayView<uint32_t>> {
/** @brief The representation of an array of `uint32_t` types as an array of
* its double type equivalents. */
using type = PropertyArrayView<double>;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<PropertyArrayView<int64_t>> {
/** @brief The representation of an array of `int64_t` types as an array of
* its double type equivalents. */
using type = PropertyArrayView<double>;
};
/** @copydoc TypeToNormalizedType */
template <> struct TypeToNormalizedType<PropertyArrayView<uint64_t>> {
/** @brief The representation of an array of `uint64_t` types as an array of
* its double type equivalents. */
using type = PropertyArrayView<double>;
};
/** @copydoc TypeToNormalizedType */
template <glm::length_t N, typename T, glm::qualifier Q>
struct TypeToNormalizedType<PropertyArrayView<glm::vec<N, T, Q>>> {
/** @brief The representation of an array of `glm::vec<N, T, Q>` types as an
* array of its double type equivalents. */
using type = PropertyArrayView<glm::vec<N, double, Q>>;
};
/** @copydoc TypeToNormalizedType */
template <glm::length_t N, typename T, glm::qualifier Q>
struct TypeToNormalizedType<PropertyArrayView<glm::mat<N, N, T, Q>>> {
/** @brief The representation of an array of `glm::mat<N, N, T, Q>` types as
* an array of its double type equivalents. */
using type = PropertyArrayView<glm::mat<N, N, double, Q>>;
};
/**
* @brief Transforms a property value type from a view to an equivalent type
* that owns the data it is viewing. For most property types this is an identity
* transformation, because most property types are held by value. However, it
* transforms numeric `PropertyArrayView<T>` to `PropertyArrayCopy<T>` because a
* `PropertyArrayView<T>` only has a pointer to the value it is viewing.
*
* See `propertyValueViewToCopy`.
*
* @remarks This is the inverse of \ref PropertyValueCopyToView
* @tparam T The type of the property value view.
*/
template <typename T>
using PropertyValueViewToCopy = std::conditional_t<
IsMetadataNumericArray<T>::value,
PropertyArrayCopy<typename MetadataArrayType<T>::type>,
T>;
/**
* @brief Transforms a property value type from a copy that owns the data it is
* viewing to a view into that data. For most property types this is an identity
* transformation, because most property types are held by value. However, it
* transforms numeric `PropertyArrayCopy<T>` to `PropertyArrayView<T>`.
*
* See `propertyValueCopyToView`.
*
* @remarks This is the inverse of \ref PropertyValueViewToCopy
* @tparam T The type of the property value copy.
*/
template <typename T>
using PropertyValueCopyToView = std::conditional_t<
IsMetadataNumericArray<T>::value,
PropertyArrayView<typename MetadataArrayType<T>::type>,
T>;
/**
* @brief Creates an optional instance of a type that can be used to own a
* property value from an optional instance that is only a view on that value.
* See {@link PropertyValueViewToCopy}.
*
* @tparam T The type of the view to copy.
* @param view An optional instance of a view on the value that will be copied.
* @return std::optional<PropertyValueViewToCopy<T>>
*/
template <typename T>
static std::optional<PropertyValueViewToCopy<T>>
propertyValueViewToCopy(const std::optional<T>& view) {
if constexpr (IsMetadataNumericArray<T>::value) {
if (view) {
return std::make_optional<PropertyValueViewToCopy<T>>(
std::vector(view->begin(), view->end()));
} else {
return std::nullopt;
}
} else {
return view;
}
}
/**
* @brief Creates an instance of a type that will own a property value from a
* view on that value. See \ref PropertyValueViewToOwner.
*
* @tparam T The type of the view to copy.
* @param view A view on the value that will be copied.
* @return PropertyValueViewToCopy<T>
*/
template <typename T>
static PropertyValueViewToCopy<T> propertyValueViewToCopy(const T& view) {
if constexpr (IsMetadataNumericArray<T>::value) {
return PropertyValueViewToCopy<T>(std::vector(view.begin(), view.end()));
} else {
return view;
}
}
/**
* @brief Creates a view on an owned copy of a property value. See \ref
* PropertyValueCopyToView.
*
* @tparam T The type of the value to create a view from.
* @param copy The value to create a view from.
* @return PropertyValueCopyToView<T>
*/
template <typename T>
static PropertyValueCopyToView<T> propertyValueCopyToView(const T& copy) {
if constexpr (IsMetadataNumericArray<T>::value) {
return copy.view();
} else {
return copy;
}
}
} // namespace CesiumGltf

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <optional>
namespace CesiumGltf {
/**
* @brief Texture sampler properties for filtering and wrapping modes.
*/
struct CESIUMGLTF_API Sampler final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Sampler";
/**
* @brief Known values for Magnification filter.
*/
struct MagFilter {
/** @brief NEAREST (`9728`) */
static constexpr int32_t NEAREST = 9728;
/** @brief LINEAR (`9729`) */
static constexpr int32_t LINEAR = 9729;
};
/**
* @brief Known values for Minification filter.
*/
struct MinFilter {
/** @brief NEAREST (`9728`) */
static constexpr int32_t NEAREST = 9728;
/** @brief LINEAR (`9729`) */
static constexpr int32_t LINEAR = 9729;
/** @brief NEAREST_MIPMAP_NEAREST (`9984`) */
static constexpr int32_t NEAREST_MIPMAP_NEAREST = 9984;
/** @brief LINEAR_MIPMAP_NEAREST (`9985`) */
static constexpr int32_t LINEAR_MIPMAP_NEAREST = 9985;
/** @brief NEAREST_MIPMAP_LINEAR (`9986`) */
static constexpr int32_t NEAREST_MIPMAP_LINEAR = 9986;
/** @brief LINEAR_MIPMAP_LINEAR (`9987`) */
static constexpr int32_t LINEAR_MIPMAP_LINEAR = 9987;
};
/**
* @brief Known values for S (U) wrapping mode.
*/
struct WrapS {
/** @brief CLAMP_TO_EDGE (`33071`) */
static constexpr int32_t CLAMP_TO_EDGE = 33071;
/** @brief MIRRORED_REPEAT (`33648`) */
static constexpr int32_t MIRRORED_REPEAT = 33648;
/** @brief REPEAT (`10497`) */
static constexpr int32_t REPEAT = 10497;
};
/**
* @brief Known values for T (V) wrapping mode.
*/
struct WrapT {
/** @brief CLAMP_TO_EDGE (`33071`) */
static constexpr int32_t CLAMP_TO_EDGE = 33071;
/** @brief MIRRORED_REPEAT (`33648`) */
static constexpr int32_t MIRRORED_REPEAT = 33648;
/** @brief REPEAT (`10497`) */
static constexpr int32_t REPEAT = 10497;
};
/**
* @brief Magnification filter.
*
* Known values are defined in {@link MagFilter}.
*
*/
std::optional<int32_t> magFilter;
/**
* @brief Minification filter.
*
* Known values are defined in {@link MinFilter}.
*
*/
std::optional<int32_t> minFilter;
/**
* @brief S (U) wrapping mode.
*
* Known values are defined in {@link WrapS}.
*
*
* All valid values correspond to WebGL enums.
*/
int32_t wrapS = WrapS::REPEAT;
/**
* @brief T (V) wrapping mode.
*
* Known values are defined in {@link WrapT}.
*
*/
int32_t wrapT = WrapT::REPEAT;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Sampler));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,26 @@
#pragma once
#include <cstdint>
namespace CesiumGltf {
/**
* @brief Applies a sampler's WrapS value to the given U component of a texture
* coordinate.
*
* @param u The U coordinate to apply the sampler wrap value to.
* @param wrapS The sampler's WrapS value, matching a member of \ref
* Sampler::WrapS, to apply.
* @returns The U coordinate after applying the WrapS operation.
*/
double applySamplerWrapS(const double u, const int32_t wrapS);
/**
* @brief Applies a sampler's WrapT value to the given V component of a texture
* coordinate.
*
* @param v The V coordinate to apply the sampler wrap value to.
* @param wrapT The sampler's WrapT value, matching a member of \ref
* Sampler::WrapT, to apply.
* @returns The V coordinate after applying the WrapT operation.
*/
double applySamplerWrapT(const double v, const int32_t wrapT);
} // namespace CesiumGltf

View File

@ -0,0 +1,41 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <cstdint>
#include <vector>
namespace CesiumGltf {
/**
* @brief The root nodes of a scene.
*/
struct CESIUMGLTF_API Scene final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Scene";
/**
* @brief The indices of each root node.
*/
std::vector<int32_t> nodes;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Scene));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
accum += int64_t(sizeof(int32_t) * this->nodes.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,97 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Class.h>
#include <CesiumGltf/Enum.h>
#include <CesiumGltf/Library.h>
#include <CesiumUtility/SharedAsset.h>
#include <optional>
#include <string>
#include <unordered_map>
namespace CesiumGltf {
/**
* @brief An object defining classes and enums.
*/
struct CESIUMGLTF_API Schema final : public CesiumUtility::SharedAsset<Schema> {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Schema";
/**
* @brief Unique identifier for the schema. Schema IDs must be alphanumeric
* identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`.
*/
std::string id;
/**
* @brief The name of the schema, e.g. for display purposes.
*/
std::optional<std::string> name;
/**
* @brief The description of the schema.
*/
std::optional<std::string> description;
/**
* @brief Application-specific version of the schema.
*/
std::optional<std::string> version;
/**
* @brief A dictionary, where each key is a class ID and each value is an
* object defining the class. Class IDs must be alphanumeric identifiers
* matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`.
*/
std::unordered_map<std::string, CesiumGltf::Class> classes;
/**
* @brief A dictionary, where each key is an enum ID and each value is an
* object defining the values for the enum. Enum IDs must be alphanumeric
* identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`.
*/
std::unordered_map<std::string, CesiumGltf::Enum> enums;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Schema));
accum += CesiumUtility::SharedAsset<Schema>::getSizeBytes() -
int64_t(sizeof(CesiumUtility::SharedAsset<Schema>));
accum += int64_t(this->id.capacity() * sizeof(char));
if (this->name) {
accum += int64_t(this->name->capacity() * sizeof(char));
}
if (this->description) {
accum += int64_t(this->description->capacity() * sizeof(char));
}
if (this->version) {
accum += int64_t(this->version->capacity() * sizeof(char));
}
accum += int64_t(
this->classes.bucket_count() *
(sizeof(std::string) + sizeof(CesiumGltf::Class)));
for (const auto& [k, v] : this->classes) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += v.getSizeBytes() - int64_t(sizeof(CesiumGltf::Class));
}
accum += int64_t(
this->enums.bucket_count() *
(sizeof(std::string) + sizeof(CesiumGltf::Enum)));
for (const auto& [k, v] : this->enums) {
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
accum += v.getSizeBytes() - int64_t(sizeof(CesiumGltf::Enum));
}
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,59 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <cstdint>
#include <vector>
namespace CesiumGltf {
/**
* @brief Joints and matrices defining a skin.
*/
struct CESIUMGLTF_API Skin final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Skin";
/**
* @brief The index of the accessor containing the floating-point 4x4
* inverse-bind matrices.
*
* Its `accessor.count` property **MUST** be greater than or equal to the
* number of elements of the `joints` array. When undefined, each matrix is a
* 4x4 identity matrix.
*/
int32_t inverseBindMatrices = -1;
/**
* @brief The index of the node used as a skeleton root.
*
* The node **MUST** be the closest common root of the joints hierarchy or a
* direct or indirect parent node of the closest common root.
*/
int32_t skeleton = -1;
/**
* @brief Indices of skeleton nodes, used as joints in this skin.
*/
std::vector<int32_t> joints;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Skin));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
accum += int64_t(sizeof(int32_t) * this->joints.capacity());
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,48 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumGltf/NamedObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief A texture and its sampler.
*/
struct CESIUMGLTF_API Texture final : public CesiumGltf::NamedObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "Texture";
/**
* @brief The index of the sampler used by this texture. When undefined, a
* sampler with repeat wrapping and auto filtering **SHOULD** be used.
*/
int32_t sampler = -1;
/**
* @brief The index of the image used by this texture. When undefined, an
* extension or other mechanism **SHOULD** supply an alternate texture source,
* otherwise behavior is undefined.
*/
int32_t source = -1;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(Texture));
accum += CesiumGltf::NamedObject::getSizeBytes() -
int64_t(sizeof(CesiumGltf::NamedObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,52 @@
// This file was generated by generate-classes.
// DO NOT EDIT THIS FILE!
#pragma once
#include <CesiumGltf/Library.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <cstdint>
namespace CesiumGltf {
/**
* @brief Reference to a texture.
*/
struct CESIUMGLTF_API TextureInfo : public CesiumUtility::ExtensibleObject {
/**
* @brief The original name of this type.
*/
static constexpr const char* TypeName = "TextureInfo";
/**
* @brief The index of the texture.
*/
int32_t index = -1;
/**
* @brief The set index of texture's TEXCOORD attribute used for texture
* coordinate mapping.
*
* This integer value is used to construct a string in the format
* `TEXCOORD_<set index>` which is a reference to a key in
* `mesh.primitives.attributes` (e.g. a value of `0` corresponds to
* `TEXCOORD_0`). A mesh primitive **MUST** have the corresponding texture
* coordinate attributes for the material to be applicable to it.
*/
int64_t texCoord = 0;
/**
* @brief Calculates the size in bytes of this object, including the contents
* of all collections, pointers, and strings. This will NOT include the size
* of any extensions attached to the object. Calling this method may be slow
* as it requires traversing the object's entire structure.
*/
int64_t getSizeBytes() const {
int64_t accum = 0;
accum += int64_t(sizeof(TextureInfo));
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
int64_t(sizeof(CesiumUtility::ExtensibleObject));
return accum;
}
};
} // namespace CesiumGltf

View File

@ -0,0 +1,225 @@
#pragma once
#include <CesiumGltf/ImageAsset.h>
#include <CesiumGltf/KhrTextureTransform.h>
#include <CesiumGltf/Sampler.h>
#include <CesiumGltf/TextureInfo.h>
#include <CesiumUtility/IntrusivePointer.h>
#include <vector>
namespace CesiumGltf {
struct Model;
/**
* @brief Describes options for constructing a view on a glTF texture.
*/
struct TextureViewOptions {
/**
* @brief Whether to automatically apply the `KHR_texture_transform` extension
* to the texture view, if it exists.
*
* A glTF texture may contain the `KHR_texture_transform` extension, which
* transforms the texture coordinates used to sample the texture. The
* extension may also override the TEXCOORD set index that was specified by
* the original texture info.
*
* If a view is constructed with applyKhrTextureTransformExtension set to
* true, it should automatically apply the texture transform to any UV
* coordinates used to sample the texture. If the extension defines its own
* TEXCOORD set index, it will override the original value.
*
* Otherwise, if the flag is set to false, UVs will not be transformed and
* the original TEXCOORD set index will be preserved. The extension's values
* may still be retrieved using getTextureTransform, if desired.
*/
bool applyKhrTextureTransformExtension = false;
/**
* @brief Whether to copy the input image.
*
* By default, a view is constructed on the input glTF image without copying
* its pixels. This can be problematic for clients that move or delete the
* original glTF model. When this flag is true, the view will manage its own
* copy of the pixel data to avoid such issues.
*/
bool makeImageCopy = false;
};
/**
* @brief Indicates the status of a texture view.
*
* The {@link TextureView} constructor always completes
* successfully. However it may not always reflect the actual content of the
* corresponding texture. This enumeration provides the reason.
*/
enum class TextureViewStatus {
/**
* @brief This texture view is valid and ready to use.
*/
Valid,
/**
* @brief This texture view has not yet been initialized.
*/
ErrorUninitialized,
/**
* @brief This texture view does not have a valid texture index.
*/
ErrorInvalidTexture,
/**
* @brief This texture view does not have a valid sampler index.
*/
ErrorInvalidSampler,
/**
* @brief This texture view does not have a valid image index.
*/
ErrorInvalidImage,
/**
* @brief This texture is viewing an empty image.
*/
ErrorEmptyImage,
/**
* @brief The image for this texture has channels that take up more than a
* byte. Only single-byte channels are supported.
*/
ErrorInvalidBytesPerChannel,
};
/**
* @brief A view into the texture data of a single texture from a \ref Model.
*/
class TextureView {
public:
/**
* @brief Constructs an empty, uninitialized texture view.
*/
TextureView() noexcept;
/**
* @brief Constructs a view of the texture specified by the given {@link TextureInfo}.
*
* @param model The glTF model in which to look for the texture's data.
* @param textureInfo The texture info to create a view for.
* @param options The options for constructing the view.
*/
TextureView(
const Model& model,
const TextureInfo& textureInfo,
const TextureViewOptions& options = TextureViewOptions()) noexcept;
/**
* @brief Constructs a view of the texture specified by the given {@link Sampler}
* and {@link ImageAsset}.
*
* @param sampler The {@link Sampler} used by the texture.
* @param image The {@link ImageAsset} used by the texture.
* @param textureCoordinateSetIndex The set index for the `TEXCOORD_n`
* attribute used to sample this texture.
* @param pKhrTextureTransformExtension A pointer to the KHR_texture_transform
* extension on the texture, if it exists.
* @param options The options for constructing the view.
*/
TextureView(
const Sampler& sampler,
const ImageAsset& image,
int64_t textureCoordinateSetIndex,
const ExtensionKhrTextureTransform* pKhrTextureTransformExtension =
nullptr,
const TextureViewOptions& options = TextureViewOptions()) noexcept;
/**
* @brief Get the status of this texture view.
*
* If invalid, it will not be safe to sample from this view.
*/
TextureViewStatus getTextureViewStatus() const noexcept {
return this->_textureViewStatus;
}
/**
* @brief Get the texture coordinate set index for this view.
* If this view was constructed with options.applyKhrTextureTransformExtension
* as true, and if the texture contains the `KHR_texture_transform` extension,
* then this will return the value from the extension since it is meant to
* override the original index. However, if the extension does not specify a
* TEXCOORD set index, then the original index of the texture is returned.
*/
int64_t getTexCoordSetIndex() const noexcept {
if (this->_applyTextureTransform && this->_textureTransform) {
return this->_textureTransform->getTexCoordSetIndex().value_or(
this->_texCoordSetIndex);
}
return this->_texCoordSetIndex;
}
/**
* @brief Get the sampler describing how to sample the data from the
* property's texture.
*
* This will be nullptr if the property texture property view runs into
* problems during construction.
*/
const Sampler* getSampler() const noexcept { return this->_pSampler; }
/**
* @brief Get the image containing this property's data. If this view was
* constructed with options.makeImageCopy set to true, this will return a
* pointer to the copied image.
*
* This will be nullptr if the texture view runs into
* problems during construction.
*/
const ImageAsset* getImage() const noexcept {
if (this->_pImageCopy) {
return this->_pImageCopy.get();
}
return this->_pImage.get();
}
/**
* @brief Get the KHR_texture_transform for this texture if it exists.
*
* Even if this view was constructed with
* options.applyKhrTextureTransformExtension set to false, it will save the
* extension's values, and they may be retrieved through this function.
*
* If this view was constructed with applyKhrTextureTransformExtension set
* to true, any texture coordinates passed into `get` or `getRaw` will be
* automatically transformed, so there's no need to re-apply the transform
* here.
*/
std::optional<KhrTextureTransform> getTextureTransform() const noexcept {
return this->_textureTransform;
}
/**
* @brief Samples the image at the specified texture coordinates using NEAREST
* pixel filtering, returning the bytes as uint8_t values. A channels vector
* must be supplied to specify how many image channels are needed, and in what
* order the bytes should be retrieved.
*/
std::vector<uint8_t> sampleNearestPixel(
double u,
double v,
const std::vector<int64_t>& channels) const noexcept;
private:
TextureViewStatus _textureViewStatus;
const Sampler* _pSampler;
CesiumUtility::IntrusivePointer<ImageAsset> _pImage;
int64_t _texCoordSetIndex;
bool _applyTextureTransform;
std::optional<KhrTextureTransform> _textureTransform;
CesiumUtility::IntrusivePointer<ImageAsset> _pImageCopy;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,57 @@
#pragma once
#include <array>
#include <string>
namespace CesiumGltf {
/**
* @brief The standard glTF vertex attribute semantics from the specification
* plus additional vertex attribute semantics from extensions.
*/
struct VertexAttributeSemantics {
/**
* @brief Unitless XYZ vertex positions.
*/
static const std::string POSITION;
/**
* @brief Normalized XYZ vertex normals.
*/
static const std::string NORMAL;
/**
* @brief XYZW vertex tangents where the XYZ portion is normalized, and the W
* component is a sign value (-1 or +1) indicating handedness of the tangent
* basis.
*/
static const std::string TANGENT;
/**
* @brief ST texture coordinates
*/
static const std::array<std::string, 8> TEXCOORD_n;
/**
* @brief RGB or RGBA vertex color linear multiplier.
*/
static const std::array<std::string, 8> COLOR_n;
/**
* @brief The indices of the joints from the corresponding skin.joints array
* that affect the vertex.
*/
static const std::array<std::string, 8> JOINTS_n;
/**
* @brief The weights indicating how strongly the joint influences the vertex.
*/
static const std::array<std::string, 8> WEIGHTS_n;
/**
* @brief Feature IDs used by `EXT_mesh_features`.
*/
static const std::array<std::string, 8> FEATURE_ID_n;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,46 @@
#pragma once
#include "CesiumGltf/PropertyType.h"
#include <CesiumUtility/Assert.h>
#include <CesiumUtility/SpanHelper.h>
#include <cstddef>
#include <span>
namespace CesiumGltf {
static size_t getOffsetFromOffsetsBuffer(
size_t index,
const std::span<const std::byte>& offsetBuffer,
PropertyComponentType offsetType) noexcept {
switch (offsetType) {
case PropertyComponentType::Uint8: {
CESIUM_ASSERT(index < offsetBuffer.size() / sizeof(uint8_t));
const uint8_t offset = *reinterpret_cast<const uint8_t*>(
offsetBuffer.data() + index * sizeof(uint8_t));
return static_cast<size_t>(offset);
}
case PropertyComponentType::Uint16: {
CESIUM_ASSERT(index < offsetBuffer.size() / sizeof(uint16_t));
const uint16_t offset = *reinterpret_cast<const uint16_t*>(
offsetBuffer.data() + index * sizeof(uint16_t));
return static_cast<size_t>(offset);
}
case PropertyComponentType::Uint32: {
CESIUM_ASSERT(index < offsetBuffer.size() / sizeof(uint32_t));
const uint32_t offset = *reinterpret_cast<const uint32_t*>(
offsetBuffer.data() + index * sizeof(uint32_t));
return static_cast<size_t>(offset);
}
case PropertyComponentType::Uint64: {
CESIUM_ASSERT(index < offsetBuffer.size() / sizeof(uint64_t));
const uint64_t offset = *reinterpret_cast<const uint64_t*>(
offsetBuffer.data() + index * sizeof(uint64_t));
return static_cast<size_t>(offset);
}
default:
CESIUM_ASSERT(false && "Offset type is invalid");
return 0;
}
}
} // namespace CesiumGltf