Skip to content

Commit a502b46

Browse files
committed
Introduced Enum Parsing, BufferView completed, added GCC Segfault workaround, continued work on other fields
1 parent 7b1ded8 commit a502b46

15 files changed

+186
-35
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
[submodule "3rdparty/Catch"]
1111
path = 3rdparty/Catch
1212
url = https://github.com/philsquared/Catch.git
13+
[submodule "3rdparty/better-enums"]
14+
path = 3rdparty/better-enums
15+
url = https://github.com/aantron/better-enums.git

3rdparty/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
add_library(nlohmann_json INTERFACE)
22
target_include_directories(nlohmann_json SYSTEM INTERFACE json/src)
3+
target_compile_features(nlohmann_json INTERFACE cxx_std_11)
34

45
add_library(microsoft_gsl INTERFACE)
56
target_include_directories(microsoft_gsl SYSTEM INTERFACE GSL/include)
67

78
add_library(boost_outcome INTERFACE)
89
target_include_directories(boost_outcome SYSTEM INTERFACE "boost.outcome/include")
910
target_compile_definitions(boost_outcome INTERFACE BOOST_OUTCOME_ENABLE_ADVANCED)
11+
target_compile_features(boost_outcome INTERFACE cxx_std_14)
1012

1113
add_library(Catch INTERFACE)
1214
target_include_directories(Catch SYSTEM INTERFACE "Catch/include")
15+
16+
add_library(better_enums INTERFACE)
17+
target_include_directories(better_enums SYSTEM INTERFACE "better-enums")
18+
target_compile_features(better_enums INTERFACE cxx_std_11)

3rdparty/Catch

Submodule Catch updated from 0bb8e12 to 377c9a7

3rdparty/GSL

3rdparty/better-enums

Submodule better-enums added at 37d8f98

gltfpp/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ if(Boost_FOUND)
44
endif()
55

66
add_library(gltfpp INTERFACE)
7-
target_link_libraries(gltfpp INTERFACE nlohmann_json microsoft_gsl boost_outcome)
7+
target_link_libraries(gltfpp INTERFACE nlohmann_json microsoft_gsl boost_outcome better_enums)
88
target_include_directories(gltfpp SYSTEM INTERFACE ${BOOST_NONCOMPILED_DIR})
99
target_include_directories(gltfpp INTERFACE "include")
1010

gltfpp/include/Accessor.h

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,38 @@
11
#pragma once
22
#include "BufferView.h"
33
#include <boost/hana/define_struct.hpp>
4+
#include <gsl/span>
5+
#include "Error.h"
6+
#include "parsers/Parsing.h"
47

58
namespace gltfpp {
69
inline namespace v1 {
10+
template<typename T>
711
struct Accessor {
8-
BOOST_HANA_DEFINE_STRUCT(Accessor, (BufferView, bufferView));
12+
enum ComponentType {
13+
14+
};
15+
16+
enum Type { SCALAR, VEC2, VEC3, VEC4, MAT2, MAT3, MAT4 };
17+
18+
BOOST_HANA_DEFINE_STRUCT(Accessor,
19+
(BufferView *, bufferView),
20+
(bool, normalized),
21+
(std::vector<double>, min),
22+
(std::vector<double>, max),
23+
(option<std::string>, name),
24+
(option<nlohmann::json>, sparse),
25+
(option<nlohmann::json>, extensions),
26+
(option<nlohmann::json>, extras)
27+
);/*
28+
(ptrdiff_t, byteOffset),
29+
(size_t, count),
30+
(ComponentType, componentType),
31+
*/
32+
gsl::span<T> elements;
933
};
34+
35+
template<typename T>
36+
auto parse(Accessor<T> &) -> gltf_result<ParseContext>;
1037
} // namespace v1
1138
} // namespace gltfpp

gltfpp/include/BufferView.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@
44
#include <boost/hana/define_struct.hpp>
55
#include <gsl/span>
66
#include <json.hpp>
7+
#include "Enum.h"
78

89
namespace gltfpp {
910
inline namespace v1 {
11+
12+
BETTER_ENUM(BufferViewTarget, int32_t, ARRAY_BUFFER = 34962, ELEMENT_ARRAY_BUFFER = 34963)
13+
1014
struct BufferView {
1115
BufferView()
1216
: byteStride{0} {
1317
}
1418

15-
enum Target { ARRAY_BUFFER = 34962, ELEMENT_ARRAY_BUFFER = 34963 };
16-
1719
BOOST_HANA_DEFINE_STRUCT(BufferView,
18-
(int, target), // TODO enum parsing
20+
(option<BufferViewTarget>, target),
1921
(option<std::string>, name),
2022
(uint8_t, byteStride),
2123
(option<nlohmann::json>, extensions),

gltfpp/include/Enum.h

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
#define BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum) \
3+
public: \
4+
Enum() = default;
5+
#include <enum.h>

gltfpp/include/Material.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@
66
namespace gltfpp {
77
inline namespace v1 {
88
struct Material {
9-
BOOST_HANA_DEFINE_STRUCT(Material(std::vector<Texture>, textures));
9+
BOOST_HANA_DEFINE_STRUCT(Material,
10+
(std::vector<Texture>, textures),
11+
(option<std::string>, name),
12+
(option<nlohmann::json>, extensions),
13+
(option<nlohmann::json>, exteas),
14+
//metallic roughness
15+
(std::array<float, 3>, emissiveFactor)
16+
);
1017
};
1118
} // namespace v1
1219
} // namespace gltfpp

gltfpp/include/Meta.h

+42-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,35 @@
44

55
namespace gltfpp {
66
inline namespace v1 {
7+
template<typename...>
8+
using void_t = void;
9+
10+
enum class nonesuch{};
11+
12+
namespace detail {
13+
template <typename Default, typename AlwaysVoid,
14+
template<typename...> class Op, typename... Args>
15+
struct detector {
16+
using value_t = std::false_type;
17+
using type = Default;
18+
};
19+
20+
template <typename Default, template<typename...> class Op, typename... Args>
21+
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
22+
using value_t = std::true_type;
23+
using type = Op<Args...>;
24+
};
25+
} // namespace detail
26+
27+
template <template<typename...> class Op, typename... Args>
28+
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
29+
30+
template <template<typename...> class Op, typename... Args>
31+
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
32+
33+
template <typename Default, template<typename...> class Op, typename... Args>
34+
using detected_or = detail::detector<Default, void, Op, Args...>;
35+
736
template <typename...>
837
struct disjunction : std::false_type {};
938
template <typename B1>
@@ -18,23 +47,27 @@ namespace gltfpp {
1847
template <typename T, template <typename...> class Base>
1948
constexpr bool is_specialization_of_v = is_specialization_of<T, Base>::value;
2049

50+
template<typename T, typename... Seq>
51+
using is_any_of = disjunction<std::is_same<T, Seq>...>;
52+
2153
namespace detail {
54+
template<typename T>
55+
using detect_better_enum = typename T::_enumerated;
56+
2257
template <typename T>
23-
constexpr bool is_fundamental_json_type = disjunction<std::is_arithmetic<T>,
24-
std::is_same<T, std::string>,
25-
std::is_same<T, nlohmann::json>>::value;
58+
constexpr bool is_enumeration = is_detected<detect_better_enum, T>::value;
59+
60+
template <typename T>
61+
constexpr bool is_fundamental_json_type = !is_enumeration<T> &&
62+
disjunction<std::is_arithmetic<T>, is_any_of<T, std::string, nlohmann::json>>::value;
2663

2764
// Make this public as customization point?
2865
template <typename T>
2966
constexpr bool is_field_list = is_specialization_of_v<T, std::vector>;
30-
67+
3168
// FIXME proper concept checking
3269
template <typename T>
33-
constexpr bool is_field_aggregate = !is_fundamental_json_type<T> && !is_field_list<T>;
34-
35-
// TODO We need fancy enums with hana::strings
36-
template <typename T>
37-
constexpr bool is_enumeration = std::is_enum<T>::value;
70+
constexpr bool is_field_aggregate = !is_fundamental_json_type<T> && !is_field_list<T> && !is_enumeration<T>;
3871
} // namespace detail
3972
} // namespace v1
4073
} // namespace gltfpp

gltfpp/include/Skin.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace gltfpp {
77
inline namespace v1 {
88
struct Skin {
9-
BOOST_HANA_DEFINE_STRUCT(Skin, (std::vector<Accessor>, accessors));
9+
//BOOST_HANA_DEFINE_STRUCT(Skin, (std::vector<Accessor>, accessors));
1010
};
1111
} // namespace v1
1212
} // namespace gltfpp

gltfpp/include/parsers/Parsing.h

+61-16
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,32 @@ namespace gltfpp {
1919
const nlohmann::json *json = nullptr;
2020
};
2121

22+
template<typename T>
23+
struct defaulted {
24+
template<typename... Args>
25+
defaulted(Args &&... args)
26+
: val{std::forward<Args>(args)...} {}
27+
28+
operator T &() {
29+
return val;
30+
}
31+
32+
operator const T &() const {
33+
return val;
34+
}
35+
36+
T &get() {
37+
return val;
38+
}
39+
40+
const T &get() const {
41+
return val;
42+
}
43+
44+
private:
45+
T val;
46+
};
47+
2248
template <typename T, typename std::enable_if_t<detail::is_field_aggregate<T>> * = nullptr>
2349
auto parse(T &target);
2450

@@ -27,10 +53,13 @@ namespace gltfpp {
2753

2854
template <typename T, typename std::enable_if_t<detail::is_field_list<T>> * = nullptr>
2955
auto parse(T &target);
56+
57+
template<typename T, typename std::enable_if_t<detail::is_enumeration<T>> * = nullptr>
58+
auto parse(T &target);
3059

3160
template <typename T>
3261
auto field(option<T> &target, const char *key) {
33-
return [&, key](ParseContext ctx) -> gltf_result<ParseContext> {
62+
return [&target, key](ParseContext ctx) -> gltf_result<ParseContext> {
3463
auto valIt = ctx.json->find(key);
3564
if(valIt != ctx.json->end()) {
3665
target.set_value();
@@ -47,7 +76,7 @@ namespace gltfpp {
4776

4877
template <typename T>
4978
auto field(T &target, const char *key) {
50-
return [&, key](ParseContext ctx) -> gltf_result<ParseContext> {
79+
return [&target, key](ParseContext ctx) -> gltf_result<ParseContext> {
5180
auto valIt = ctx.json->find(key);
5281
if(valIt != ctx.json->end()) {
5382
auto newCtx = ParseContext{ctx.root, std::addressof(*valIt)};
@@ -65,19 +94,19 @@ namespace gltfpp {
6594

6695
template <typename T>
6796
auto aggregate(T &target) {
68-
return [&](ParseContext ctx) -> gltf_result<ParseContext> {
69-
constexpr auto accessor = boost::hana::accessors<T>();
70-
auto names = boost::hana::transform(accessor, boost::hana::first);
71-
auto members = boost::hana::transform(accessor, boost::hana::second);
72-
auto refs = boost::hana::transform(members, [&](auto acc) { return std::ref(acc(target)); });
73-
74-
auto res = boost::hana::fold(
75-
boost::hana::zip(names, refs), gltf_result<ParseContext>{ctx}, [&](auto c, auto entry) {
97+
return [&target](ParseContext ctx) -> gltf_result<ParseContext> {
98+
using namespace boost::hana;
99+
constexpr auto accessor = accessors<T>();
100+
auto names = transform(accessor, first);
101+
auto members = transform(accessor, second);
102+
auto refs = transform(members, [&](auto acc) { return std::ref(acc(target)); });
103+
104+
auto res = fold(zip(names, refs), gltf_result<ParseContext>{ctx}, [&](auto c, auto entry) {
76105
if(!c) {
77106
return c; // I hope the optimizer understands that...
78107
}
79-
auto name = boost::hana::to<const char *>(entry[boost::hana::size_c<0>]);
80-
auto &member = entry[boost::hana::size_c<1>].get();
108+
auto name = to<const char *>(entry[size_c<0>]);
109+
auto &member = entry[size_c<1>].get();
81110
return c >> field(member, name);
82111
});
83112
if(!res) {
@@ -94,7 +123,7 @@ namespace gltfpp {
94123

95124
template <typename T, typename std::enable_if_t<detail::is_fundamental_json_type<T>> *>
96125
auto parse(T &target) {
97-
return [&](ParseContext ctx) -> gltf_result<ParseContext> {
126+
return [&target](ParseContext ctx) -> gltf_result<ParseContext> {
98127
// TODO this is not a complete check
99128
if(ctx.json) {
100129
target = ctx.json->template get<T>();
@@ -106,7 +135,7 @@ namespace gltfpp {
106135

107136
template <typename T, typename std::enable_if_t<detail::is_field_list<T>> *>
108137
auto parse(T &target) {
109-
return [&](ParseContext ctx) -> gltf_result<ParseContext> {
138+
return [&target](ParseContext ctx) -> gltf_result<ParseContext> {
110139
if(!ctx.json) {
111140
return make_unexpected(gltf_error::key_not_found);
112141
}
@@ -116,10 +145,10 @@ namespace gltfpp {
116145

117146
target.resize(ctx.json->size());
118147

119-
auto in = ctx.json;
148+
auto in = ctx.json->begin();
120149
auto out = target.begin();
121150
for(; out != target.end(); ++in, ++out) {
122-
auto res = parse(*out)({ctx.root, in});
151+
auto res = parse(*out)({ctx.root, &*in});
123152
static_assert(std::is_same<gltf_result<ParseContext>, decltype(res)>{},
124153
"Return type of the parser function must be gltf_result<ParseContext>");
125154
if(!res) {
@@ -129,6 +158,22 @@ namespace gltfpp {
129158
return ctx;
130159
};
131160
}
161+
162+
template<typename T, typename std::enable_if_t<detail::is_enumeration<T>> *>
163+
auto parse(T &target) {
164+
return [&target](ParseContext ctx) -> gltf_result<ParseContext> {
165+
if(!ctx.json) {
166+
return make_unexpected(gltf_error::key_not_found);
167+
}
168+
const auto str = ctx.json->get<std::string>();
169+
const auto parsed = T::_from_string_nothrow(str.c_str());
170+
if(!parsed) {
171+
return make_unexpected(gltf_error::decode_error);
172+
}
173+
target = *parsed;
174+
return ctx;
175+
};
176+
}
132177

133178
template <typename CharInputIterator, typename ByteOutputIterator>
134179
auto decode_embedded_base64(CharInputIterator first, CharInputIterator last, ByteOutputIterator out) {

test/glTF.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,26 @@ TEST_CASE("glTF_Buffer", "[glTF]") {
3535
}
3636

3737
TEST_CASE("glTF_BufferView", "[glTF]") {
38+
glTF target;
39+
auto source = minimalglTF;
40+
json minimalBuffer{"byteLength", 42};
41+
source["buffer"] = {minimalBuffer, minimalBuffer, minimalBuffer};
42+
43+
json minimalBufferView{
44+
{"buffer", 0},
45+
{"byteOffset", 0},
46+
{"byteLength", 1},
47+
{"byteStride", 0},
48+
{"target", "ARRAY_BUFFER"}
49+
};
50+
51+
source["bufferViews"] = {minimalBufferView, minimalBufferView};
52+
53+
const auto success = from_json(source, target);
54+
REQUIRE(success);
55+
REQUIRE(target.bufferViews);
56+
REQUIRE(target.bufferViews->size() == 2);
57+
REQUIRE(target.bufferViews.get()[0].target);
58+
const bool asdf = target.bufferViews.get()[0].target.get() == +BufferViewTarget::ARRAY_BUFFER;
59+
//REQUIRE(asdf);
3860
}

test/simple_consumer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include <cstdio>
2-
#include <glTF.h>
2+
#include <gltfpp.h>
33

44
int main(int argc, char **argv) {
55
gltfpp::glTF g;

0 commit comments

Comments
 (0)