cesium-native 0.62.0
Loading...
Searching...
No Matches
AccessorView.h
1#pragma once
2
3#include <CesiumGltf/Accessor.h>
4#include <CesiumGltf/Model.h>
5
6#include <cstddef>
7#include <stdexcept>
8
9namespace CesiumGltf {
10
74
87template <class T> class AccessorView final {
88private:
89 const std::byte* _pData;
90 int64_t _stride;
91 int64_t _offset;
92 int64_t _size;
93 bool _normalized;
94 AccessorViewStatus _status;
95
96public:
100 typedef T value_type;
101
113 : _pData(nullptr),
114 _stride(0),
115 _offset(0),
116 _size(0),
117 _normalized(false),
118 _status(status) {}
119
133 const std::byte* pData,
134 int64_t stride,
135 int64_t offset,
136 int64_t size,
137 bool normalized)
138 : _pData(pData),
139 _stride(stride),
140 _offset(offset),
141 _size(size),
142 _normalized(normalized),
143 _status(AccessorViewStatus::Valid) {}
144
156 AccessorView(const Model& model, const Accessor& accessor) noexcept
157 : AccessorView() {
158 this->create(model, accessor);
159 }
160
173 AccessorView(const Model& model, int32_t accessorIndex) noexcept
174 : AccessorView() {
175 const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex);
176 if (!pAccessor) {
178 return;
179 }
180
181 this->create(model, *pAccessor);
182 }
183
192 const T& operator[](int64_t i) const {
193 if (i < 0 || i >= this->_size) {
194 throw std::range_error("index out of range");
195 }
196
197 return *reinterpret_cast<const T*>(
198 this->_pData + i * this->_stride + this->_offset);
199 }
200
208 int64_t size() const noexcept { return this->_size; }
209
216 AccessorViewStatus status() const noexcept { return this->_status; }
217
224 int64_t stride() const noexcept { return this->_stride; }
225
232 int64_t offset() const noexcept { return this->_offset; }
233
239 bool normalized() const noexcept { return this->_normalized; }
240
247 const std::byte* data() const noexcept {
248 return this->_pData + this->_offset;
249 }
250
251private:
252 void create(const Model& model, const Accessor& accessor) noexcept {
253 const CesiumGltf::BufferView* pBufferView =
254 Model::getSafe(&model.bufferViews, accessor.bufferView);
255 if (!pBufferView) {
257 return;
258 }
259
260 const CesiumGltf::Buffer* pBuffer =
261 Model::getSafe(&model.buffers, pBufferView->buffer);
262 if (!pBuffer) {
264 return;
265 }
266
267 const std::vector<std::byte>& data = pBuffer->cesium.data;
268 const int64_t bufferBytes = int64_t(data.size());
269 if (pBufferView->byteOffset + pBufferView->byteLength > bufferBytes) {
271 return;
272 }
273
274 const int64_t accessorByteStride = accessor.computeByteStride(model);
275 if (accessorByteStride < 0) {
277 return;
278 }
279
280 const int64_t accessorComponentElements =
281 accessor.computeNumberOfComponents();
282 const int64_t accessorComponentBytes =
283 accessor.computeByteSizeOfComponent();
284 const int64_t accessorBytesPerStride =
285 accessorComponentElements * accessorComponentBytes;
286
287 if (sizeof(T) != accessorBytesPerStride) {
288 this->_status = AccessorViewStatus::WrongSizeT;
289 return;
290 }
291
292 const int64_t accessorBytes = accessorByteStride * accessor.count;
293 const int64_t bytesRemainingInBufferView =
294 pBufferView->byteLength -
295 (accessor.byteOffset + accessorByteStride * (accessor.count - 1) +
296 accessorBytesPerStride);
297 if (accessorBytes > pBufferView->byteLength ||
298 bytesRemainingInBufferView < 0) {
300 return;
301 }
302
303 this->_pData = pBuffer->cesium.data.data();
304 this->_stride = accessorByteStride;
305 this->_offset = accessor.byteOffset + pBufferView->byteOffset;
306 this->_size = accessor.count;
307 this->_normalized = accessor.normalized;
308 this->_status = AccessorViewStatus::Valid;
309 }
310};
311
317#pragma pack(push, 1)
318
324 template <typename T> struct SCALAR {
328 T value[1];
329 };
330
336 template <typename T> struct VEC2 {
340 T value[2];
341 };
342
348 template <typename T> struct VEC3 {
352 T value[3];
353 };
354
360 template <typename T> struct VEC4 {
364 T value[4];
365 };
366
372 template <typename T> struct MAT2 {
376 T value[4];
377 };
378
384 template <typename T> struct MAT3 {
388 T value[9];
389 };
390
396 template <typename T> struct MAT4 {
400 T value[16];
401 };
402
403#pragma pack(pop)
404};
405
406namespace CesiumImpl {
407template <typename TCallback, typename TElement>
408std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<TElement>>>
410 const Model& model,
411 const Accessor& accessor,
412 TCallback&& callback) {
413 if (accessor.type == Accessor::Type::SCALAR) {
414 return callback(
416 }
417 if (accessor.type == Accessor::Type::VEC2) {
418 return callback(
419 AccessorView<AccessorTypes::VEC2<TElement>>(model, accessor));
420 }
421 if (accessor.type == Accessor::Type::VEC3) {
422 return callback(
423 AccessorView<AccessorTypes::VEC3<TElement>>(model, accessor));
424 }
425 if (accessor.type == Accessor::Type::VEC4) {
426 return callback(
427 AccessorView<AccessorTypes::VEC4<TElement>>(model, accessor));
428 }
429 if (accessor.type == Accessor::Type::MAT2) {
430 return callback(
431 AccessorView<AccessorTypes::MAT2<TElement>>(model, accessor));
432 }
433 if (accessor.type == Accessor::Type::MAT3) {
434 return callback(
435 AccessorView<AccessorTypes::MAT3<TElement>>(model, accessor));
436 }
437 if (accessor.type == Accessor::Type::MAT4) {
438 return callback(
439 AccessorView<AccessorTypes::MAT4<TElement>>(model, accessor));
440 }
441 // TODO Print a warning here???
442 return callback(AccessorView<AccessorTypes::SCALAR<TElement>>(
444}
445} // namespace CesiumImpl
446
462template <typename TCallback>
463std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>>
465 const Model& model,
466 const Accessor& accessor,
467 TCallback&& callback) {
468 switch (accessor.componentType) {
469 case Accessor::ComponentType::BYTE:
470 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int8_t>(
471 model,
472 accessor,
473 std::forward<TCallback>(callback));
474 case Accessor::ComponentType::UNSIGNED_BYTE:
475 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint8_t>(
476 model,
477 accessor,
478 std::forward<TCallback>(callback));
479 case Accessor::ComponentType::SHORT:
480 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int16_t>(
481 model,
482 accessor,
483 std::forward<TCallback>(callback));
484 case Accessor::ComponentType::UNSIGNED_SHORT:
485 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint16_t>(
486 model,
487 accessor,
488 std::forward<TCallback>(callback));
489 case Accessor::ComponentType::INT:
490 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int32_t>(
491 model,
492 accessor,
493 std::forward<TCallback>(callback));
494 case Accessor::ComponentType::UNSIGNED_INT:
495 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint32_t>(
496 model,
497 accessor,
498 std::forward<TCallback>(callback));
499 case Accessor::ComponentType::INT64:
500 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int64_t>(
501 model,
502 accessor,
503 std::forward<TCallback>(callback));
504 case Accessor::ComponentType::UNSIGNED_INT64:
505 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint64_t>(
506 model,
507 accessor,
508 std::forward<TCallback>(callback));
509 case Accessor::ComponentType::FLOAT:
510 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, float>(
511 model,
512 accessor,
513 std::forward<TCallback>(callback));
514 case Accessor::ComponentType::DOUBLE:
515 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, double>(
516 model,
517 accessor,
518 std::forward<TCallback>(callback));
519 default:
522 }
523}
524
541template <typename TCallback>
542std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>>
544 const Model& model,
545 int32_t accessorIndex,
546 TCallback&& callback) {
547 const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex);
548 if (!pAccessor) {
551 }
552
553 return createAccessorView(model, *pAccessor, callback);
554}
555} // namespace CesiumGltf
A view on the data of one accessor of a glTF asset.
bool normalized() const noexcept
Returns whether the accessor values are normalized.
int64_t offset() const noexcept
Returns the offset of this accessor, which is the number of bytes from the start of the buffer to the...
int64_t stride() const noexcept
Returns the stride of this accessor, which is the number of bytes from the start of one element to th...
AccessorView(const std::byte *pData, int64_t stride, int64_t offset, int64_t size, bool normalized)
Creates a new instance from low-level parameters.
int64_t size() const noexcept
Returns the size (number of elements) of this accessor.
AccessorView(AccessorViewStatus status=AccessorViewStatus::InvalidAccessorIndex)
Construct a new instance not pointing to any data.
const std::byte * data() const noexcept
Returns a pointer to the first byte of this accessor view's data. The elements are stored contiguousl...
AccessorView(const Model &model, int32_t accessorIndex) noexcept
Creates a new instance from a given model and accessor index.
const T & operator[](int64_t i) const
Provides the specified accessor element.
AccessorView(const Model &model, const Accessor &accessor) noexcept
Creates a new instance from a given model and Accessor.
AccessorViewStatus status() const noexcept
Gets the status of this accessor view.
T value_type
The type of the elements in the accessor.
Classes for working with glTF models.
AccessorViewStatus
Indicates the status of an accessor view.
@ BufferViewTooSmall
The accessor is too large to fit in its bufferView.
@ InvalidByteStride
The BufferView::byteStride is negative, which is invalid.
@ Valid
This accessor is valid and ready to use.
@ InvalidBufferViewIndex
The accessor's bufferView index does not refer to a valid bufferView.
@ WrongSizeT
The sizeof(T) does not match the accessor's Accessor::computeBytesPerVertex.
@ InvalidBufferIndex
The accessor's bufferView's buffer index does not refer to a valid buffer.
@ InvalidAccessorIndex
The accessor index does not refer to a valid accessor.
@ BufferTooSmall
The accessor's bufferView is too large to fit in its buffer.
@ InvalidType
The AccessorSpec:type is invalid.
@ InvalidComponentType
The AccessorSpec::componentType is invalid.
std::invoke_result_t< TCallback, AccessorView< AccessorTypes::SCALAR< float > > > createAccessorView(const Model &model, const Accessor &accessor, TCallback &&callback)
Creates an appropriate AccessorView for a given accessor.
std::string type
Specifies if the accessor's elements are scalars, vectors, or matrices.
int32_t componentType
The datatype of the accessor's components.
A 2x2 matrix element for an AccessorView.
T value[4]
The component values of this element.
A 3x3 matrix element for an AccessorView.
T value[9]
The component values of this element.
A 4x4 matrix element for an AccessorView.
T value[16]
The component values of this element.
A scalar element for an AccessorView.
T value[1]
The component values of this element.
A 2D vector element for an AccessorView.
T value[2]
The component values of this element.
A 3D vector element for an AccessorView.
T value[3]
The component values of this element.
A 4D vector element for an AccessorView.
T value[4]
The component values of this element.
Contains types that may optionally be used with AccessorView for various Accessor::componentType valu...
This class is not meant to be instantiated directly. Use Accessor instead.
Definition Accessor.h:12
std::vector< std::byte > data
The buffer's data.
A view into a buffer generally representing a subset of the buffer.
Definition BufferView.h:15
int64_t byteLength
The length of the bufferView in bytes.
Definition BufferView.h:46
int32_t buffer
The index of the buffer.
Definition BufferView.h:36
int64_t byteOffset
The offset into the buffer in bytes.
Definition BufferView.h:41
This class is not meant to be instantiated directly. Use Buffer instead.
Definition Buffer.h:9
BufferCesium cesium
Holds properties that are specific to the glTF loader rather than part of the glTF spec.
Definition Buffer.h:16
std::vector< CesiumGltf::Accessor > accessors
An array of accessors.
Definition ModelSpec.h:51
This class is not meant to be instantiated directly. Use Model instead.
Definition Model.h:14
static const T & getSafe(const std::vector< T > &items, int32_t index)
Safely gets the element with a given index, returning a default instance if the index is outside the ...
Definition Model.h:181