-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmesh.hpp
221 lines (183 loc) · 7.61 KB
/
mesh.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#ifndef GRAPHICS_MESH_HPP
#define GRAPHICS_MESH_HPP
#include <array>
#include <unordered_map>
#include <vector>
#include <graphics/color.hpp>
#include <math/math.hpp>
namespace framework::graphics
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @addtogroup graphics_renderer_module
/// @{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Mesh.
///
/// Meshes contain vertex data (positions, normals, texture coordinates etc.)
/// and vertex indices, which forms some kind of primitive to render.
/// All vertex data must be in arrays of the same size.
/// Data for i-th vertex is at index "i" in each array.
///
/// For every vertex there can be a position, normal, tangent, color and up to 8 texture coordinates.
///
/// Each mesh consist of group of vertex indices, called Submesh.
/// At least one submesh must be defined to render something.
class Mesh final
{
public:
/// @brief Represents what kind of primitive a submesh is describe.
enum class PrimitiveType
{
points, ///< Each index is individual point.
lines, ///< Vertices 0 and 1 are considered a line. Vertices 2 and 3 are considered a line. And so on.
line_strip, ///< The adjacent vertices are considered lines. If you pass n vertices, you will get n-1 lines.
line_loop, ///< As line strips, except that the first and last vertices are also used as a line.
triangles, ///< Vertices 0, 1, and 2 form a triangle. Vertices 3, 4, and 5 form a triangle. And so on.
triangle_strip, ///< Every group of 3 adjacent vertices forms a triangle. The face direction of the strip is
///< determined by the winding of the first triangle. Each successive triangle will have its
///< effective face order reversed, so the system compensates for that by testing it in the
///< opposite way. A vertex stream of n length will generate n-2 triangles.
triangle_fan, ///< The first vertex is always held fixed. From there on, every group of 2 adjacent vertices form
///< a triangle with the first. So with a vertex stream, you get a list of triangles like so:
///< (0, 1, 2) (0, 2, 3), (0, 3, 4), etc. A vertex stream of n length will generate n-2 triangles.
};
using VertexData = std::vector<math::Vector3f>;
using TextureCoordinatesData = std::vector<math::Vector2f>;
using ColorData = std::vector<Color>;
using IndicesData = std::vector<std::uint32_t>;
struct SubMesh
{
IndicesData indices;
PrimitiveType primitive_type;
};
using SubMeshIndexType = std::size_t;
using SubMeshMap = std::unordered_map<SubMeshIndexType, SubMesh>;
static constexpr size_t max_texture_coordinates = 8;
Mesh();
Mesh(const Mesh& other);
Mesh(Mesh&& other) noexcept;
~Mesh();
Mesh& operator=(const Mesh& other);
Mesh& operator=(Mesh&& other) noexcept;
/// @brief Assign new vertex positions to Mesh.
///
/// @param vertices New vertex data.
void set_vertices(const VertexData& vertices);
/// @brief Assign new vertex positions to Mesh.
///
/// @param vertices New vertex data.
void set_vertices(VertexData&& vertices);
/// @brief Assign new vertex normals to Mesh.
///
/// @param normals New normals data.
void set_normals(const VertexData& normals);
/// @brief Assign new vertex normals to Mesh.
///
/// @param normals New normals data.
void set_normals(VertexData&& normals);
/// @brief Assign new vertex tangents to Mesh.
///
/// @param tangents New tangents data.
void set_tangents(const VertexData& tangents);
/// @brief Assign new vertex tangents to Mesh.
///
/// @param tangents New tangents data.
void set_tangents(VertexData&& tangents);
/// @brief Assign new vertex colors to Mesh.
///
/// @param colors New colors data.
void set_colors(const ColorData& colors);
/// @brief Assign new vertex colors to Mesh.
///
/// @param colors New colors data.
void set_colors(ColorData&& colors);
/// @brief Assign new texture coordinates to Mesh.
///
/// Mesh can have up to `max_texture_coordinates` texture coordinates.
///
/// @param index Texture coordinates array index.
/// @param coordinates New texture coordinates data.
void set_texture_coordinates(std::size_t index, const TextureCoordinatesData& coordinates);
/// @brief Assign new texture coordinates to Mesh.
///
/// Mesh can have up to `max_texture_coordinates` texture coordinates.
///
/// @param index Texture coordinates array index.
/// @param coordinates New texture coordinates data.
void set_texture_coordinates(std::size_t index, TextureCoordinatesData&& coordinates);
/// @brief Set indices data for Mesh.
///
/// @param indices New indices.
/// @param type Kind of primitives for sub mesh.
///
/// @return Index of new sub mesh.
SubMeshIndexType add_submesh(const IndicesData& indices, PrimitiveType type = PrimitiveType::triangles);
/// @brief Set indices data for Mesh.
///
/// @param indices New indices.
/// @param type Kind of primitives for sub mesh.
///
/// @return Index of new sub mesh.
SubMeshIndexType add_submesh(IndicesData&& indices, PrimitiveType type = PrimitiveType::triangles);
/// @brief Remove previously created sub mesh.
///
/// @param index Sub mesh to delete.
void remove_submesh(SubMeshIndexType index);
/// @brief Remove all data from Mesh.
///
/// If Mesh loaded to Renderer, it's can be freely cleaned.
///
/// @see Renderer::load.
void clear();
/// @brief Get vertex positions.
///
/// @return Vertex positions.
const VertexData& vertices() const;
/// @brief Get vertex normals.
///
/// @return Vertex normals.
const VertexData& normals() const;
/// @brief Get vertex tangents.
///
/// @return Vertex tangents.
const VertexData& tangents() const;
/// @brief Get vertex colors.
///
/// @return Vertex colors.
const ColorData& colors() const;
/// @brief Get vertex texture coordinates.
///
/// @param index Texture coordinates array.
///
/// @return Texture coordinates.
const TextureCoordinatesData& texture_coordinates(std::size_t index) const;
/// @brief Checks if sub mesh with index exists in Mesh.
///
/// @param index Sub mesh index to check.
///
/// @return `true` if mesh with index exists in the Mesh.
bool has_submesh(SubMeshIndexType index) const;
/// @brief Get all sub meshes of the Mesh.
///
/// @return Sub meshes.
const SubMeshMap& submeshes() const;
private:
friend void swap(Mesh& lhs, Mesh& rhs) noexcept;
VertexData m_vertices;
VertexData m_normals;
VertexData m_tanegents;
ColorData m_colors;
std::array<TextureCoordinatesData, max_texture_coordinates> m_texture_coordinates;
SubMeshMap m_submeshes;
std::size_t m_last_submesh_index = 0;
};
/// @brief Swaps two Meshes.
///
/// @param lhs Mesh to swap.
/// @param rhs Mesh to swap.
void swap(Mesh& lhs, Mesh& rhs) noexcept;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
} // namespace framework::graphics
#endif