custom meta array view for property

This commit is contained in:
Bao Tran 2021-05-29 21:42:03 -04:00
parent 3cc40b6ed1
commit 3dff283062
6 changed files with 262 additions and 4 deletions

View File

@ -0,0 +1,83 @@
#pragma once
#include "CesiumGltf/PropertyType.h"
#include <cassert>
#include <cstddef>
#include <gsl/span>
namespace CesiumGltf {
template <typename ElementType> class MetaArrayView {
public:
MetaArrayView(gsl::span<ElementType> buffer) : _valueBuffer{buffer} {}
const ElementType& operator[](size_t index) const {
return _valueBuffer[index];
}
size_t size() const { _valueBuffer.size(); }
private:
gsl::span<ElementType> _valueBuffer;
};
template <> class MetaArrayView<std::string_view> {
public:
MetaArrayView(
gsl::span<const std::byte> buffer,
gsl::span<const std::byte> offsetBuffer,
PropertyType offsetType,
size_t size)
: _valueBuffer{buffer},
_offsetBuffer{offsetBuffer},
_offsetType{offsetType},
_size{size} {}
std::string_view operator[](size_t index) const {
size_t currentOffset =
getOffsetFromOffsetBuffer(index, _offsetBuffer, _offsetType);
size_t nextOffset =
getOffsetFromOffsetBuffer(index + 1, _offsetBuffer, _offsetType);
return std::string_view(
reinterpret_cast<const char*>(_valueBuffer.data() + currentOffset),
(nextOffset - currentOffset));
}
size_t size() const { return _size; }
private:
static size_t getOffsetFromOffsetBuffer(
size_t instance,
const gsl::span<const std::byte>& offsetBuffer,
PropertyType offsetType) {
switch (offsetType) {
case PropertyType::Uint8: {
uint8_t offset = *reinterpret_cast<const uint8_t*>(
offsetBuffer.data() + instance * sizeof(uint8_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint16: {
uint16_t offset = *reinterpret_cast<const uint16_t*>(
offsetBuffer.data() + instance * sizeof(uint16_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint32: {
uint32_t offset = *reinterpret_cast<const uint32_t*>(
offsetBuffer.data() + instance * sizeof(uint32_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint64: {
uint64_t offset = *reinterpret_cast<const uint64_t*>(
offsetBuffer.data() + instance * sizeof(uint64_t));
return static_cast<size_t>(offset);
}
default:
assert(false && "Offset type has unknown type");
return 0;
}
}
gsl::span<const std::byte> _valueBuffer;
gsl::span<const std::byte> _offsetBuffer;
PropertyType _offsetType;
size_t _size;
};
} // namespace CesiumGltf

View File

@ -0,0 +1,130 @@
#pragma once
#include "CesiumGltf/MetaArrayView.h"
#include "CesiumGltf/PropertyType.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <gsl/span>
#include <string_view>
#include <type_traits>
namespace CesiumGltf {
namespace Impl {
template <typename... T> struct IsNumeric;
template <typename T> struct IsNumeric<T> : std::false_type {};
template <> struct IsNumeric<uint8_t> : std::true_type {};
template <> struct IsNumeric<int8_t> : std::true_type {};
template <> struct IsNumeric<uint16_t> : std::true_type {};
template <> struct IsNumeric<int16_t> : std::true_type {};
template <> struct IsNumeric<uint32_t> : std::true_type {};
template <> struct IsNumeric<int32_t> : std::true_type {};
template <> struct IsNumeric<uint64_t> : std::true_type {};
template <> struct IsNumeric<int64_t> : std::true_type {};
template <> struct IsNumeric<float> : std::true_type {};
template <> struct IsNumeric<double> : std::true_type {};
template <typename... T> struct IsBoolean;
template <typename T> struct IsBoolean<T> : std::false_type {};
template <> struct IsBoolean<bool> : std::true_type {};
template <typename... T> struct IsString;
template <typename T> struct IsString<T> : std::false_type {};
template <> struct IsString<std::string_view> : std::true_type {};
} // namespace Impl
template <typename ElementType> class TPropertyView {
public:
TPropertyView(
gsl::span<const std::byte> valueBuffer,
gsl::span<const std::byte> arrayOffsetBuffer,
gsl::span<const std::byte> stringOffsetBuffer,
PropertyType offsetType,
size_t componentCount,
size_t instanceCount)
: _valueBuffer{valueBuffer},
_arrayOffsetBuffer{arrayOffsetBuffer},
_stringOffsetBuffer{stringOffsetBuffer},
_offsetType{offsetType},
_componentCount{componentCount},
_instanceCount{instanceCount} {}
ElementType operator[](size_t instance) const {
if constexpr (Impl::IsNumeric<ElementType>::value) {
return getNumeric(instance);
}
if constexpr (Impl::IsBoolean<ElementType>::value) {
return getBoolean(instance);
}
if constexpr (Impl::IsString<ElementType>::value) {
return getString(instance);
}
}
size_t size() const { return _instanceCount; }
private:
ElementType getNumeric(size_t instance) const {
return reinterpret_cast<const ElementType*>(_valueBuffer.data())[instance];
}
bool getBoolean(size_t instance) const {
size_t byteIndex = instance / 8;
size_t bitIndex = instance % 8;
int bitValue = static_cast<int>(_valueBuffer[byteIndex] >> bitIndex) & 1;
return bitValue == 1;
}
std::string_view getString(size_t instance) const {
size_t currentOffset =
getOffsetFromOffsetBuffer(instance, _stringOffsetBuffer, _offsetType);
size_t nextOffset = getOffsetFromOffsetBuffer(
instance + 1,
_stringOffsetBuffer,
_offsetType);
return std::string_view(
reinterpret_cast<const char*>(_valueBuffer.data() + currentOffset),
(nextOffset - currentOffset));
}
static size_t getOffsetFromOffsetBuffer(
size_t instance,
const gsl::span<const std::byte>& offsetBuffer,
PropertyType offsetType) {
switch (offsetType) {
case PropertyType::Uint8: {
uint8_t offset = *reinterpret_cast<const uint8_t*>(
offsetBuffer.data() + instance * sizeof(uint8_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint16: {
uint16_t offset = *reinterpret_cast<const uint16_t*>(
offsetBuffer.data() + instance * sizeof(uint16_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint32: {
uint32_t offset = *reinterpret_cast<const uint32_t*>(
offsetBuffer.data() + instance * sizeof(uint32_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint64: {
uint64_t offset = *reinterpret_cast<const uint64_t*>(
offsetBuffer.data() + instance * sizeof(uint64_t));
return static_cast<size_t>(offset);
}
default:
assert(false && "Offset type has unknown type");
return 0;
}
}
gsl::span<const std::byte> _valueBuffer;
gsl::span<const std::byte> _arrayOffsetBuffer;
gsl::span<const std::byte> _stringOffsetBuffer;
PropertyType _offsetType;
size_t _componentCount;
size_t _instanceCount;
};
} // namespace CesiumGltf

View File

@ -29,7 +29,8 @@ namespace CesiumGltf {
bool PropertyAccessorView::getBoolean(size_t instance) const {
size_t byteIndex = instance / 8;
size_t bitIndex = instance % 8;
int bitValue = static_cast<int>(_valueBuffer.buffer[byteIndex] >> bitIndex) & 1;
int bitValue =
static_cast<int>(_valueBuffer.buffer[byteIndex] >> bitIndex) & 1;
return bitValue == 1;
}

View File

@ -0,0 +1,37 @@
#include "CesiumGltf/TPropertyView.h"
#include <cassert>
namespace CesiumGltf {
namespace Impl {
size_t getOffsetFromOffsetBuffer(
size_t instance,
const gsl::span<const std::byte>& offsetBuffer,
PropertyType offsetType) {
switch (offsetType) {
case PropertyType::Uint8: {
uint8_t offset = *reinterpret_cast<const uint8_t*>(
offsetBuffer.data() + instance * sizeof(uint8_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint16: {
uint16_t offset = *reinterpret_cast<const uint16_t*>(
offsetBuffer.data() + instance * sizeof(uint16_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint32: {
uint32_t offset = *reinterpret_cast<const uint32_t*>(
offsetBuffer.data() + instance * sizeof(uint32_t));
return static_cast<size_t>(offset);
}
case PropertyType::Uint64: {
uint64_t offset = *reinterpret_cast<const uint64_t*>(
offsetBuffer.data() + instance * sizeof(uint64_t));
return static_cast<size_t>(offset);
}
default:
assert(false && "Offset type has unknown type");
return 0;
}
}
} // namespace Impl
} // namespace CesiumGltf

View File

@ -280,7 +280,7 @@ TEST_CASE("Access boolean value") {
metadata.schema->name = "TestSchema";
// copy data to buffer
std::bitset<sizeof(unsigned long) * CHAR_BIT> bits = 0b11110101;
std::bitset<sizeof(unsigned long)* CHAR_BIT> bits = 0b11110101;
unsigned long data = bits.to_ulong();
CesiumGltf::Buffer& buffer = model.buffers.emplace_back();
buffer.cesium.data.resize(sizeof(data));
@ -295,7 +295,8 @@ TEST_CASE("Access boolean value") {
CesiumGltf::Class& metaClass = metadata.schema->classes["Test"];
CesiumGltf::ClassProperty& metaProperty =
metaClass.properties["TestProperty"];
metaProperty.type = CesiumGltf::convertProperttTypeToString(CesiumGltf::PropertyType::Boolean);
metaProperty.type = CesiumGltf::convertProperttTypeToString(
CesiumGltf::PropertyType::Boolean);
// create feature table
CesiumGltf::FeatureTable& featureTable = metadata.featureTables["Tests"];
@ -315,7 +316,9 @@ TEST_CASE("Access boolean value") {
featureTableProperty,
featureTable.count);
REQUIRE(propertyView != std::nullopt);
REQUIRE(propertyView->getType() == static_cast<uint32_t>(CesiumGltf::PropertyType::Boolean));
REQUIRE(
propertyView->getType() ==
static_cast<uint32_t>(CesiumGltf::PropertyType::Boolean));
REQUIRE(propertyView->numOfInstances() == sizeof(data));
for (size_t i = 0; i < bits.size(); ++i) {
REQUIRE(propertyView->get<bool>(i) == bits[i]);

View File

@ -0,0 +1,4 @@
#include "CesiumGltf/TPropertyView.h"
#include "catch2/catch.hpp"
TEST_CASE("Check create property view") {}