cesium-native  0.41.0
AccessorView.h
1 #pragma once
2 
3 #include "CesiumGltf/Model.h"
4 
5 #include <cstddef>
6 #include <stdexcept>
7 
8 namespace CesiumGltf {
9 
18 enum class AccessorViewStatus {
22  Valid,
23 
28 
34 
40 
45 
50 
55  WrongSizeT,
56 
61 
66 };
67 
80 template <class T> class AccessorView final {
81 private:
82  const std::byte* _pData;
83  int64_t _stride;
84  int64_t _offset;
85  int64_t _size;
86  AccessorViewStatus _status;
87 
88 public:
92  typedef T value_type;
93 
105  : _pData(nullptr), _stride(0), _offset(0), _size(0), _status(status) {}
106 
119  const std::byte* pData,
120  int64_t stride,
121  int64_t offset,
122  int64_t size)
123  : _pData(pData),
124  _stride(stride),
125  _offset(offset),
126  _size(size),
127  _status(AccessorViewStatus::Valid) {}
128 
140  AccessorView(const Model& model, const Accessor& accessor) noexcept
141  : AccessorView() {
142  this->create(model, accessor);
143  }
144 
157  AccessorView(const Model& model, int32_t accessorIndex) noexcept
158  : AccessorView() {
159  const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex);
160  if (!pAccessor) {
162  return;
163  }
164 
165  this->create(model, *pAccessor);
166  }
167 
176  const T& operator[](int64_t i) const {
177  if (i < 0 || i >= this->_size) {
178  throw std::range_error("index out of range");
179  }
180 
181  return *reinterpret_cast<const T*>(
182  this->_pData + i * this->_stride + this->_offset);
183  }
184 
192  int64_t size() const noexcept { return this->_size; }
193 
200  AccessorViewStatus status() const noexcept { return this->_status; }
201 
208  int64_t stride() const noexcept { return this->_stride; }
209 
216  const std::byte* data() const noexcept {
217  return this->_pData + this->_offset;
218  }
219 
220 private:
221  void create(const Model& model, const Accessor& accessor) noexcept {
222  const CesiumGltf::BufferView* pBufferView =
223  Model::getSafe(&model.bufferViews, accessor.bufferView);
224  if (!pBufferView) {
226  return;
227  }
228 
229  const CesiumGltf::Buffer* pBuffer =
230  Model::getSafe(&model.buffers, pBufferView->buffer);
231  if (!pBuffer) {
233  return;
234  }
235 
236  const std::vector<std::byte>& data = pBuffer->cesium.data;
237  const int64_t bufferBytes = int64_t(data.size());
238  if (pBufferView->byteOffset + pBufferView->byteLength > bufferBytes) {
239  this->_status = AccessorViewStatus::BufferTooSmall;
240  return;
241  }
242 
243  const int64_t accessorByteStride = accessor.computeByteStride(model);
244  const int64_t accessorComponentElements =
245  accessor.computeNumberOfComponents();
246  const int64_t accessorComponentBytes =
247  accessor.computeByteSizeOfComponent();
248  const int64_t accessorBytesPerStride =
249  accessorComponentElements * accessorComponentBytes;
250 
251  if (sizeof(T) != accessorBytesPerStride) {
252  this->_status = AccessorViewStatus::WrongSizeT;
253  return;
254  }
255 
256  const int64_t accessorBytes = accessorByteStride * accessor.count;
257  const int64_t bytesRemainingInBufferView =
258  pBufferView->byteLength -
259  (accessor.byteOffset + accessorByteStride * (accessor.count - 1) +
260  accessorBytesPerStride);
261  if (accessorBytes > pBufferView->byteLength ||
262  bytesRemainingInBufferView < 0) {
264  return;
265  }
266 
267  this->_pData = pBuffer->cesium.data.data();
268  this->_stride = accessorByteStride;
269  this->_offset = accessor.byteOffset + pBufferView->byteOffset;
270  this->_size = accessor.count;
271  this->_status = AccessorViewStatus::Valid;
272  }
273 };
274 
280 #pragma pack(push, 1)
281 
287  template <typename T> struct SCALAR {
291  T value[1];
292  };
293 
299  template <typename T> struct VEC2 {
303  T value[2];
304  };
305 
311  template <typename T> struct VEC3 {
315  T value[3];
316  };
317 
323  template <typename T> struct VEC4 {
327  T value[4];
328  };
329 
335  template <typename T> struct MAT2 {
339  T value[4];
340  };
341 
347  template <typename T> struct MAT3 {
351  T value[9];
352  };
353 
359  template <typename T> struct MAT4 {
363  T value[16];
364  };
365 
366 #pragma pack(pop)
367 };
368 
369 namespace CesiumImpl {
370 template <typename TCallback, typename TElement>
371 std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<TElement>>>
373  const Model& model,
374  const Accessor& accessor,
375  TCallback&& callback) {
376  if (accessor.type == Accessor::Type::SCALAR) {
377  return callback(
379  }
380  if (accessor.type == Accessor::Type::VEC2) {
381  return callback(
382  AccessorView<AccessorTypes::VEC2<TElement>>(model, accessor));
383  }
384  if (accessor.type == Accessor::Type::VEC3) {
385  return callback(
386  AccessorView<AccessorTypes::VEC3<TElement>>(model, accessor));
387  }
388  if (accessor.type == Accessor::Type::VEC4) {
389  return callback(
390  AccessorView<AccessorTypes::VEC4<TElement>>(model, accessor));
391  }
392  if (accessor.type == Accessor::Type::MAT2) {
393  return callback(
394  AccessorView<AccessorTypes::MAT2<TElement>>(model, accessor));
395  }
396  if (accessor.type == Accessor::Type::MAT3) {
397  return callback(
398  AccessorView<AccessorTypes::MAT3<TElement>>(model, accessor));
399  }
400  if (accessor.type == Accessor::Type::MAT4) {
401  return callback(
402  AccessorView<AccessorTypes::MAT4<TElement>>(model, accessor));
403  }
404  // TODO Print a warning here???
405  return callback(AccessorView<AccessorTypes::SCALAR<TElement>>(
407 }
408 } // namespace CesiumImpl
409 
425 template <typename TCallback>
426 std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>>
428  const Model& model,
429  const Accessor& accessor,
430  TCallback&& callback) {
431  switch (accessor.componentType) {
432  case Accessor::ComponentType::BYTE:
433  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int8_t>(
434  model,
435  accessor,
436  std::forward<TCallback>(callback));
437  case Accessor::ComponentType::UNSIGNED_BYTE:
438  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint8_t>(
439  model,
440  accessor,
441  std::forward<TCallback>(callback));
442  case Accessor::ComponentType::SHORT:
443  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int16_t>(
444  model,
445  accessor,
446  std::forward<TCallback>(callback));
447  case Accessor::ComponentType::UNSIGNED_SHORT:
448  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint16_t>(
449  model,
450  accessor,
451  std::forward<TCallback>(callback));
452  case Accessor::ComponentType::INT:
453  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int32_t>(
454  model,
455  accessor,
456  std::forward<TCallback>(callback));
457  case Accessor::ComponentType::UNSIGNED_INT:
458  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint32_t>(
459  model,
460  accessor,
461  std::forward<TCallback>(callback));
462  case Accessor::ComponentType::INT64:
463  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int64_t>(
464  model,
465  accessor,
466  std::forward<TCallback>(callback));
467  case Accessor::ComponentType::UNSIGNED_INT64:
468  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint64_t>(
469  model,
470  accessor,
471  std::forward<TCallback>(callback));
472  case Accessor::ComponentType::FLOAT:
473  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, float>(
474  model,
475  accessor,
476  std::forward<TCallback>(callback));
477  case Accessor::ComponentType::DOUBLE:
478  return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, double>(
479  model,
480  accessor,
481  std::forward<TCallback>(callback));
482  default:
485  }
486 }
487 
504 template <typename TCallback>
505 std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>>
507  const Model& model,
508  int32_t accessorIndex,
509  TCallback&& callback) {
510  const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex);
511  if (!pAccessor) {
514  }
515 
516  return createAccessorView(model, *pAccessor, callback);
517 }
518 } // namespace CesiumGltf
A view on the data of one accessor of a glTF asset.
Definition: AccessorView.h:80
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...
Definition: AccessorView.h:208
int64_t size() const noexcept
Returns the size (number of elements) of this accessor.
Definition: AccessorView.h:192
AccessorView(AccessorViewStatus status=AccessorViewStatus::InvalidAccessorIndex)
Construct a new instance not pointing to any data.
Definition: AccessorView.h:103
AccessorView(const Model &model, int32_t accessorIndex) noexcept
Creates a new instance from a given model and accessor index.
Definition: AccessorView.h:157
const T & operator[](int64_t i) const
Provides the specified accessor element.
Definition: AccessorView.h:176
AccessorView(const std::byte *pData, int64_t stride, int64_t offset, int64_t size)
Creates a new instance from low-level parameters.
Definition: AccessorView.h:118
const std::byte * data() const noexcept
Returns a pointer to the first byte of this accessor view's data. The elements are stored contiguousl...
Definition: AccessorView.h:216
AccessorView(const Model &model, const Accessor &accessor) noexcept
Creates a new instance from a given model and Accessor.
Definition: AccessorView.h:140
AccessorViewStatus status() const noexcept
Gets the status of this accessor view.
Definition: AccessorView.h:200
T value_type
The type of the elements in the accessor.
Definition: AccessorView.h:92
Classes for working with glTF models.
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.
Definition: AccessorView.h:427
AccessorViewStatus
Indicates the status of an accessor view.
Definition: AccessorView.h:18
@ BufferViewTooSmall
The accessor is too large to fit in its bufferView.
@ Valid
This accessor is valid and ready to use.
@ InvalidBufferViewIndex
The accessor's bufferView index does not refer to a valid bufferView.
@ 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 Accessor:type is invalid.
@ InvalidComponentType
The Accessor::componentType is invalid.
std::string type
Specifies if the accessor's elements are scalars, vectors, or matrices.
Definition: AccessorSpec.h:119
int32_t componentType
The datatype of the accessor's components.
Definition: AccessorSpec.h:92
A 2x2 matrix element for an AccessorView.
Definition: AccessorView.h:335
T value[4]
The component values of this element.
Definition: AccessorView.h:339
A 3x3 matrix element for an AccessorView.
Definition: AccessorView.h:347
T value[9]
The component values of this element.
Definition: AccessorView.h:351
A 4x4 matrix element for an AccessorView.
Definition: AccessorView.h:359
T value[16]
The component values of this element.
Definition: AccessorView.h:363
A scalar element for an AccessorView.
Definition: AccessorView.h:287
T value[1]
The component values of this element.
Definition: AccessorView.h:291
A 2D vector element for an AccessorView.
Definition: AccessorView.h:299
T value[2]
The component values of this element.
Definition: AccessorView.h:303
A 3D vector element for an AccessorView.
Definition: AccessorView.h:311
T value[3]
The component values of this element.
Definition: AccessorView.h:315
A 4D vector element for an AccessorView.
Definition: AccessorView.h:323
T value[4]
The component values of this element.
Definition: AccessorView.h:327
Contains types that may optionally be used with AccessorView for various Accessor::componentType valu...
Definition: AccessorView.h:279
A typed view into a buffer view that contains raw binary data.
Definition: Accessor.h:12
std::vector< std::byte > data
The buffer's data.
Definition: BufferCesium.h:17
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:41
int32_t buffer
The index of the buffer.
Definition: BufferView.h:31
int64_t byteOffset
The offset into the buffer in bytes.
Definition: BufferView.h:36
A buffer points to binary geometry, animation, or skins.
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:14
std::vector< CesiumGltf::Accessor > accessors
An array of accessors.
Definition: ModelSpec.h:49
The root object for a glTF asset.
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:179