GCC Code Coverage Report


./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 of 67, 0 excluded
0.0%
Functions:
0 of 17, 0 excluded
0.0%
Branches:
0 of 91, 0 excluded
0.0%

libs/core/src/eu/core/geom.extract.cc
Line Branch Exec Source
1 #include "eu/core/geom.h"
2
3 #include "eu/assert/assert.h"
4 #include "eu/base/cint.h"
5
6 #include "eu/core/geom.extract.h"
7 #include "eu/core/vertex_layout.h"
8
9 #include <numeric>
10
11 namespace eu::core
12 {
13
14 using ByteBuffer = std::vector<char>;
15
16 std::vector<u32> compile_indices(const Geom& geom)
17 {
18 std::vector<u32> indices;
19 const auto push = [&indices](const u32 i)
20 {
21 indices.emplace_back(i);
22 };
23 for (const auto& f: geom.faces)
24 {
25 push(f.a);
26 push(f.b);
27 push(f.c);
28 }
29 return indices;
30 }
31
32 void push_float(ByteBuffer* vv, float f)
33 {
34 // todo(Gustav): is this safe?
35 union
36 {
37 float f;
38 char bytes[4];
39 } convert {};
40
41 convert.f = f;
42 for (int byte_index = 0; byte_index < 4; byte_index += 1)
43 {
44 vv->emplace_back(convert.bytes[byte_index]);
45 }
46 }
47
48 void push2(ByteBuffer* vv, const v2& p)
49 {
50 push_float(vv, p.x);
51 push_float(vv, p.y);
52 }
53
54 void push3(ByteBuffer* vv, const v3& p)
55 {
56 push_float(vv, p.x);
57 push_float(vv, p.y);
58 push_float(vv, p.z);
59 }
60
61 void push4(ByteBuffer* vv, const v4& p)
62 {
63 push_float(vv, p.x);
64 push_float(vv, p.y);
65 push_float(vv, p.z);
66 push_float(vv, p.w);
67 }
68
69 struct BufferData
70 {
71 using PerVertex = void (*)(ByteBuffer*, const Vertex&);
72
73 std::vector<ExtractedAttribute> attributes;
74 std::vector<PerVertex> per_vertex;
75 };
76
77 ExtractedGeom extract_geom(const Geom& geom, const CompiledGeomVertexAttributes& layout)
78 {
79 const auto indices = compile_indices(geom);
80
81 const BufferData attribute_descriptions = [&]()
82 {
83 auto data = BufferData{};
84 data.attributes.reserve(layout.elements.size());
85 data.per_vertex.reserve(layout.elements.size());
86
87 for (const auto& element: layout.elements)
88 {
89 switch (element.type)
90 {
91 #define MAP(VT, PROP, COUNT) \
92 case VT: \
93 data.attributes.emplace_back(ExtractedAttribute{ExtractedAttributeType::Float, COUNT, sizeof(float) * (COUNT)}); \
94 data.per_vertex.emplace_back([](ByteBuffer* vertices, const Vertex& vertex) { push##COUNT(vertices, PROP); }); \
95 break
96 MAP(VertexType::position2xy, (v2{vertex.position.x, vertex.position.y}), 2);
97 MAP(VertexType::position2xz, (v2{vertex.position.x, vertex.position.z}), 2);
98 MAP(VertexType::position3, vertex.position, 3);
99 MAP(VertexType::normal3, vertex.normal, 3);
100 MAP(VertexType::color3, vertex.color, 3);
101 MAP(VertexType::color4, v4(vertex.color, 1.0f), 4);
102 MAP(VertexType::texture2, vertex.uv, 2);
103 #undef MAP
104 case VertexType::instance_transform:
105 DIE("can't use instance types for extraction");
106 break; // todo(Gustav): should something else be done here?
107 default: DIE("Invalid buffer type"); break;
108 }
109 }
110 return data;
111 }();
112
113 const std::size_t bytes_per_vertex = std::accumulate(
114 attribute_descriptions.attributes.begin(),
115 attribute_descriptions.attributes.end(),
116 static_cast<std::size_t>(0),
117 [](std::size_t s, const ExtractedAttribute& d) -> std::size_t { return s + d.size; }
118 );
119 const auto vertices = [&]()
120 {
121 auto verts = ByteBuffer{};
122 verts.reserve(geom.vertices.size() * bytes_per_vertex);
123 for (const auto& vertex: geom.vertices)
124 {
125 for (const auto& per_vertex: attribute_descriptions.per_vertex)
126 {
127 per_vertex(&verts, vertex);
128 }
129 }
130 return verts;
131 }();
132
133 const auto face_size = static_cast<i32>(geom.faces.size());
134
135 return {vertices, bytes_per_vertex, attribute_descriptions.attributes, indices, face_size};
136 }
137
138 } // namespace eu::core
139