cesium-native 0.43.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 AccessorViewStatus _status;
94
95public:
99 typedef T value_type;
100
112 : _pData(nullptr), _stride(0), _offset(0), _size(0), _status(status) {}
113
126 const std::byte* pData,
127 int64_t stride,
128 int64_t offset,
129 int64_t size)
130 : _pData(pData),
131 _stride(stride),
132 _offset(offset),
133 _size(size),
134 _status(AccessorViewStatus::Valid) {}
135
147 AccessorView(const Model& model, const Accessor& accessor) noexcept
148 : AccessorView() {
149 this->create(model, accessor);
150 }
151
164 AccessorView(const Model& model, int32_t accessorIndex) noexcept
165 : AccessorView() {
166 const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex);
167 if (!pAccessor) {
169 return;
170 }
171
172 this->create(model, *pAccessor);
173 }
174
183 const T& operator[](int64_t i) const {
184 if (i < 0 || i >= this->_size) {
185 throw std::range_error("index out of range");
186 }
187
188 return *reinterpret_cast<const T*>(
189 this->_pData + i * this->_stride + this->_offset);
190 }
191
199 int64_t size() const noexcept { return this->_size; }
200
207 AccessorViewStatus status() const noexcept { return this->_status; }
208
215 int64_t stride() const noexcept { return this->_stride; }
216
223 int64_t offset() const noexcept { return this->_offset; }
224
231 const std::byte* data() const noexcept {
232 return this->_pData + this->_offset;
233 }
234
235private:
236 void create(const Model& model, const Accessor& accessor) noexcept {
237 const CesiumGltf::BufferView* pBufferView =
238 Model::getSafe(&model.bufferViews, accessor.bufferView);
239 if (!pBufferView) {
241 return;
242 }
243
244 const CesiumGltf::Buffer* pBuffer =
245 Model::getSafe(&model.buffers, pBufferView->buffer);
246 if (!pBuffer) {
248 return;
249 }
250
251 const std::vector<std::byte>& data = pBuffer->cesium.data;
252 const int64_t bufferBytes = int64_t(data.size());
253 if (pBufferView->byteOffset + pBufferView->byteLength > bufferBytes) {
255 return;
256 }
257
258 const int64_t accessorByteStride = accessor.computeByteStride(model);
259 if (accessorByteStride < 0) {
261 return;
262 }
263
264 const int64_t accessorComponentElements =
265 accessor.computeNumberOfComponents();
266 const int64_t accessorComponentBytes =
267 accessor.computeByteSizeOfComponent();
268 const int64_t accessorBytesPerStride =
269 accessorComponentElements * accessorComponentBytes;
270
271 if (sizeof(T) != accessorBytesPerStride) {
272 this->_status = AccessorViewStatus::WrongSizeT;
273 return;
274 }
275
276 const int64_t accessorBytes = accessorByteStride * accessor.count;
277 const int64_t bytesRemainingInBufferView =
278 pBufferView->byteLength -
279 (accessor.byteOffset + accessorByteStride * (accessor.count - 1) +
280 accessorBytesPerStride);
281 if (accessorBytes > pBufferView->byteLength ||
282 bytesRemainingInBufferView < 0) {
284 return;
285 }
286
287 this->_pData = pBuffer->cesium.data.data();
288 this->_stride = accessorByteStride;
289 this->_offset = accessor.byteOffset + pBufferView->byteOffset;
290 this->_size = accessor.count;
291 this->_status = AccessorViewStatus::Valid;
292 }
293};
294
300#pragma pack(push, 1)
301
307 template <typename T> struct SCALAR {
311 T value[1];
312 };
313
319 template <typename T> struct VEC2 {
323 T value[2];
324 };
325
331 template <typename T> struct VEC3 {
335 T value[3];
336 };
337
343 template <typename T> struct VEC4 {
347 T value[4];
348 };
349
355 template <typename T> struct MAT2 {
359 T value[4];
360 };
361
367 template <typename T> struct MAT3 {
371 T value[9];
372 };
373
379 template <typename T> struct MAT4 {
383 T value[16];
384 };
385
386#pragma pack(pop)
387};
388
389namespace CesiumImpl {
390template <typename TCallback, typename TElement>
391std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<TElement>>>
392createAccessorView(
393 const Model& model,
394 const Accessor& accessor,
395 TCallback&& callback) {
396 if (accessor.type == Accessor::Type::SCALAR) {
397 return callback(
399 }
400 if (accessor.type == Accessor::Type::VEC2) {
401 return callback(
402 AccessorView<AccessorTypes::VEC2<TElement>>(model, accessor));
403 }
404 if (accessor.type == Accessor::Type::VEC3) {
405 return callback(
406 AccessorView<AccessorTypes::VEC3<TElement>>(model, accessor));
407 }
408 if (accessor.type == Accessor::Type::VEC4) {
409 return callback(
410 AccessorView<AccessorTypes::VEC4<TElement>>(model, accessor));
411 }
412 if (accessor.type == Accessor::Type::MAT2) {
413 return callback(
414 AccessorView<AccessorTypes::MAT2<TElement>>(model, accessor));
415 }
416 if (accessor.type == Accessor::Type::MAT3) {
417 return callback(
418 AccessorView<AccessorTypes::MAT3<TElement>>(model, accessor));
419 }
420 if (accessor.type == Accessor::Type::MAT4) {
421 return callback(
422 AccessorView<AccessorTypes::MAT4<TElement>>(model, accessor));
423 }
424 // TODO Print a warning here???
425 return callback(AccessorView<AccessorTypes::SCALAR<TElement>>(
427}
428} // namespace CesiumImpl
429
445template <typename TCallback>
446std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>>
448 const Model& model,
449 const Accessor& accessor,
450 TCallback&& callback) {
451 switch (accessor.componentType) {
452 case Accessor::ComponentType::BYTE:
453 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int8_t>(
454 model,
455 accessor,
456 std::forward<TCallback>(callback));
457 case Accessor::ComponentType::UNSIGNED_BYTE:
458 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint8_t>(
459 model,
460 accessor,
461 std::forward<TCallback>(callback));
462 case Accessor::ComponentType::SHORT:
463 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int16_t>(
464 model,
465 accessor,
466 std::forward<TCallback>(callback));
467 case Accessor::ComponentType::UNSIGNED_SHORT:
468 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint16_t>(
469 model,
470 accessor,
471 std::forward<TCallback>(callback));
472 case Accessor::ComponentType::INT:
473 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int32_t>(
474 model,
475 accessor,
476 std::forward<TCallback>(callback));
477 case Accessor::ComponentType::UNSIGNED_INT:
478 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint32_t>(
479 model,
480 accessor,
481 std::forward<TCallback>(callback));
482 case Accessor::ComponentType::INT64:
483 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int64_t>(
484 model,
485 accessor,
486 std::forward<TCallback>(callback));
487 case Accessor::ComponentType::UNSIGNED_INT64:
488 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint64_t>(
489 model,
490 accessor,
491 std::forward<TCallback>(callback));
492 case Accessor::ComponentType::FLOAT:
493 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, float>(
494 model,
495 accessor,
496 std::forward<TCallback>(callback));
497 case Accessor::ComponentType::DOUBLE:
498 return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, double>(
499 model,
500 accessor,
501 std::forward<TCallback>(callback));
502 default:
505 }
506}
507
524template <typename TCallback>
525std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>>
527 const Model& model,
528 int32_t accessorIndex,
529 TCallback&& callback) {
530 const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex);
531 if (!pAccessor) {
534 }
535
536 return createAccessorView(model, *pAccessor, callback);
537}
538} // namespace CesiumGltf
A view on the data of one accessor of a glTF asset.
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...
T value_type
The type of the elements in the accessor.
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.
AccessorView(const std::byte *pData, int64_t stride, int64_t offset, int64_t size)
Creates a new instance from low-level parameters.
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.
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