-
Notifications
You must be signed in to change notification settings - Fork 1
/
mesh_builder.cpp
138 lines (121 loc) · 3.83 KB
/
mesh_builder.cpp
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
#include <tess/mesh_builder.h>
namespace tess
{
static const unsigned int GL_TRIANGLES = 0x0004;
static const unsigned int GL_TRIANGLE_STRIP = 0x0005;
static const unsigned int GL_TRIANGLE_FAN = 0x0006;
//----------------------------------------------------------------------------------------------------------------------------------------------------------
// mesh_builder::public
//----------------------------------------------------------------------------------------------------------------------------------------------------------
mesh_builder::mesh_builder() : _curr_prim_mode(GL_TRIANGLES),
_num_curr_elements(0),
_invert_winding(false)
{
_curr_elements[0] = 0;
_curr_elements[1] = 0;
}
void mesh_builder::begin()
{
_vertices.clear();
_vertices.reserve(65535);
_elements.clear();
_elements.reserve(65535 * 12);
_curr_prim_mode = GL_TRIANGLES;
_curr_elements[0] = 0;
_curr_elements[1] = 0;
_num_curr_elements = 0;
_invert_winding = false;
}
void mesh_builder::set_primitive_mode(unsigned int mode)
{
if(mode != GL_TRIANGLES && mode != GL_TRIANGLE_FAN && mode != GL_TRIANGLE_STRIP)
{
throw std::invalid_argument("Primitive mode for cad::mesh_builder must be one of: GL_TRIANGLES, GL_TRIANGLE_FAN or GL_TRIANGLE_STRIP.");
}
_curr_prim_mode = mode;
_num_curr_elements = 0;
_invert_winding = false;
}
void mesh_builder::add_element(element elem)
{
// Add the vertex index
if(_num_curr_elements == 2)
{
// If two vertices were previously given, then this vertex completes a triangle
switch(_curr_prim_mode)
{
case GL_TRIANGLES:
_add_triangle(elem);
break;
case GL_TRIANGLE_FAN:
_add_triangle_fan(elem);
break;
case GL_TRIANGLE_STRIP:
_add_triangle_strip(elem);
break;
default:
throw std::logic_error("Invalid primitive mode stored in cad::mesh_builder.");
}
}
else
{
// All modes need at least two vertices
_curr_elements[_num_curr_elements++] = elem;
}
}
unsigned int mesh_builder::add_vertex(const vertex& v)
{
_vertices.push_back(v);
return static_cast<unsigned int>(_vertices.size() - 1);
}
const vertex& mesh_builder::get_vertex(unsigned int idx)
{
return _vertices[idx];
}
triangle_mesh mesh_builder::end()
{
return {_vertices, _elements};
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
// mesh_builder::private
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void mesh_builder::_add_triangle(element last_elem)
{
// Three vertices make one unique triangle
_elements.push_back(_curr_elements[0]);
_elements.push_back(_curr_elements[1]);
_elements.push_back(last_elem);
_num_curr_elements = 0;
}
void mesh_builder::_add_triangle_fan(element last_elem)
{
_elements.push_back(_curr_elements[0]);
_elements.push_back(_curr_elements[1]);
_elements.push_back(last_elem);
// First vertex is anchor of fan, latest index should make next triangle's first edge.
// keep _numCurrElements equal to 2
_curr_elements[1] = last_elem;
}
void mesh_builder::_add_triangle_strip(element last_elem)
{
// Order of indices depend on current winding
if(!_invert_winding)
{
_elements.push_back(_curr_elements[0]);
_elements.push_back(_curr_elements[1]);
_elements.push_back(last_elem);
}
else
{
_elements.push_back(_curr_elements[0]);
_elements.push_back(last_elem);
_elements.push_back(_curr_elements[1]);
}
// Last two vertices should make first edge of next triangle
// keep _numCurrElements equal to 2
_curr_elements[0] = _curr_elements[1];
_curr_elements[1] = last_elem;
// Swap winding
_invert_winding = !_invert_winding;
}
} // namespace tess