File libs/mesh/cube.h changed (mode: 100644) (index 6e5bc0d..ebaa994) |
1 |
1 |
#pragma once |
#pragma once |
2 |
2 |
|
|
3 |
3 |
#include "base.h" |
#include "base.h" |
4 |
|
#include <math/math.h> |
|
|
4 |
|
#include <math/vector.h> |
|
5 |
|
#include <math/matrix.h> |
5 |
6 |
#include <simd/simd.h> |
#include <simd/simd.h> |
6 |
7 |
#include <limits> |
#include <limits> |
7 |
8 |
|
|
|
12 |
13 |
#define ARGS CONDITION_ARGS, floating_t, index_t |
#define ARGS CONDITION_ARGS, floating_t, index_t |
13 |
14 |
#define MESH_TEMPLATE Mesh_T<ARGS> |
#define MESH_TEMPLATE Mesh_T<ARGS> |
14 |
15 |
|
|
15 |
|
namespace mesh |
|
|
16 |
|
namespace mesh::cube |
16 |
17 |
{ |
{ |
17 |
|
namespace cube |
|
18 |
|
{ |
|
19 |
|
enum Face : uint8_t |
|
20 |
|
{ |
|
21 |
|
FACE1 = 0, |
|
22 |
|
FACE2 = 1, |
|
23 |
|
FACE3 = 2, |
|
24 |
|
FACE4 = 3, |
|
25 |
|
FACE5 = 4, |
|
26 |
|
FACE6 = 5, |
|
27 |
|
|
|
28 |
|
FACE_COUNT, |
|
29 |
|
|
|
30 |
|
TOP = FACE1, |
|
31 |
|
BOTTOM = FACE2, |
|
32 |
|
NORTH = FACE3, |
|
33 |
|
SOUTH = FACE4, |
|
34 |
|
WEST = FACE5, |
|
35 |
|
EAST = FACE6, |
|
36 |
|
}; |
|
37 |
|
|
|
38 |
|
constexpr static const math::v3f NORMALS[Face::FACE_COUNT] = |
|
39 |
|
{ |
|
40 |
|
{ 0, 1, 0 },//TOP |
|
41 |
|
{ 0, -1, 0 },//BOTTOM |
|
42 |
|
{ 0, 0, 1 },//NORTH |
|
43 |
|
{ 0, 0, -1 },//SOUTH |
|
44 |
|
{ -1, 0, 0 },//WEST |
|
45 |
|
{ 1, 0, 0 },//EAST |
|
46 |
|
}; |
|
47 |
|
|
|
48 |
|
template<typename float_t> |
|
49 |
|
[[nodiscard]] constexpr inline math::vec3<float_t> face_coordinate_to_real(unsigned int face, |
|
50 |
|
float_t x, float_t y); |
|
51 |
|
|
|
52 |
|
template<typename float_t> |
|
53 |
|
[[nodiscard]] constexpr inline Face real_coordinate_to_face(float_t x, float_t y, float_t z); |
|
54 |
|
|
|
55 |
|
namespace build |
|
56 |
|
{ |
|
57 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY = modify_vertex::dummy> |
|
58 |
|
[[nodiscard]] bool tesselated(index_t edge_cell_count, floating_t scale, MESH_TEMPLATE *p_mesh); |
|
59 |
|
|
|
60 |
|
|
|
61 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY = modify_vertex::dummy> |
|
62 |
|
[[nodiscard]] bool tesselated_face(Face face, index_t edge_cell_count, floating_t scale, |
|
63 |
|
MESH_TEMPLATE *p_mesh); |
|
64 |
|
} |
|
65 |
|
|
|
66 |
|
template<typename T> |
|
67 |
|
struct rotations_t |
|
68 |
|
{ |
|
69 |
|
constexpr rotations_t() = default; |
|
70 |
|
math::matrix<3, 3, T> operator[](Face i) const { return _[i]; } |
|
71 |
|
math::matrix<3, 3, T> _[FACE_COUNT]; |
|
72 |
|
}; |
|
73 |
|
|
|
74 |
|
template<typename T> |
|
75 |
|
constexpr inline math::matrix<3, 3, T> rotation(Face face); |
|
76 |
|
|
|
77 |
|
template<typename T> |
|
78 |
|
constexpr inline rotations_t<T> create_rotations(); |
|
79 |
|
|
|
80 |
|
template<typename floating_t> |
|
81 |
|
constexpr rotations_t rotations = create_rotations<floating_t>(); |
|
82 |
|
} |
|
|
18 |
|
enum Face : uint8_t { |
|
19 |
|
FACE1 = 0, FACE2 = 1, FACE3 = 2, FACE4 = 3, FACE5 = 4, FACE6 = 5, |
|
20 |
|
FACE_COUNT, |
|
21 |
|
TOP = FACE1, BOTTOM = FACE2, |
|
22 |
|
NORTH = FACE3, SOUTH = FACE4, |
|
23 |
|
WEST = FACE5, EAST = FACE6, |
|
24 |
|
}; |
|
25 |
|
|
|
26 |
|
constexpr static const math::v3f NORMALS[Face::FACE_COUNT] = { |
|
27 |
|
{ 0, 1, 0 },//TOP |
|
28 |
|
{ 0, -1, 0 },//BOTTOM |
|
29 |
|
{ 0, 0, 1 },//NORTH |
|
30 |
|
{ 0, 0, -1 },//SOUTH |
|
31 |
|
{ -1, 0, 0 },//WEST |
|
32 |
|
{ 1, 0, 0 },//EAST |
|
33 |
|
}; |
|
34 |
|
|
|
35 |
|
template<typename float_t> [[nodiscard]] constexpr inline |
|
36 |
|
math::vec3<float_t> |
|
37 |
|
face_coordinate_to_real(unsigned int face, float_t x, float_t y); |
|
38 |
|
|
|
39 |
|
template<typename float_t> [[nodiscard]] constexpr inline |
|
40 |
|
Face |
|
41 |
|
real_coordinate_to_face(float_t x, float_t y, float_t z); |
|
42 |
|
|
|
43 |
|
namespace build { |
|
44 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY = modify_vertex::dummy> |
|
45 |
|
[[nodiscard]] bool |
|
46 |
|
tesselated(index_t edge_cell_count, floating_t scale, |
|
47 |
|
MESH_TEMPLATE *p_mesh); |
|
48 |
|
|
|
49 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY = modify_vertex::dummy> |
|
50 |
|
[[nodiscard]] bool |
|
51 |
|
tesselated_face(Face face, index_t edge_cell_count, floating_t scale, |
|
52 |
|
MESH_TEMPLATE *p_mesh); |
|
53 |
|
} |
|
54 |
|
|
|
55 |
|
template<typename T> |
|
56 |
|
struct rotations_t { |
|
57 |
|
constexpr rotations_t() = default; |
|
58 |
|
math::matrix<3, 3, T> operator[](Face i) const { return _[i]; } |
|
59 |
|
math::matrix<3, 3, T> _[FACE_COUNT]; |
|
60 |
|
}; |
|
61 |
|
|
|
62 |
|
template<typename T> constexpr inline |
|
63 |
|
math::matrix<3, 3, T> rotation(Face face); |
|
64 |
|
|
|
65 |
|
template<typename T> constexpr inline |
|
66 |
|
rotations_t<T> create_rotations(); |
|
67 |
|
|
|
68 |
|
template<typename floating_t> constexpr rotations_t |
|
69 |
|
rotations = create_rotations<floating_t>(); |
83 |
70 |
} |
} |
84 |
71 |
|
|
85 |
|
namespace mesh |
|
|
72 |
|
namespace mesh::cube |
86 |
73 |
{ |
{ |
87 |
|
namespace cube |
|
88 |
|
{ |
|
89 |
|
template<typename float_t> |
|
90 |
|
[[nodiscard]] constexpr inline math::vec3<float_t> face_coordinate_to_real(Face face, float_t x, float_t y) |
|
91 |
|
{ using namespace math; using vec3 = vec3<float_t>; |
|
92 |
|
|
|
93 |
|
switch (face) |
|
94 |
|
{ |
|
95 |
|
case TOP : return vec3 { x, 1, y } - float_t(0.5); |
|
96 |
|
case BOTTOM: return vec3 { y, 0, x } - float_t(0.5); |
|
97 |
|
case NORTH : return vec3 { y, x, 1 } - float_t(0.5); |
|
98 |
|
case SOUTH : return vec3 { x, y, 0 } - float_t(0.5); |
|
99 |
|
case WEST : return vec3 { 0, x, y } - float_t(0.5); |
|
100 |
|
case EAST : |
|
101 |
|
default : return vec3 { 1, y, x } - float_t(0.5); |
|
102 |
|
} |
|
103 |
|
} |
|
104 |
|
|
|
105 |
|
template<typename T> |
|
106 |
|
[[nodiscard]] constexpr inline Face real_coordinate_to_face(T x, T y, T z) |
|
107 |
|
{ |
|
108 |
|
const Face faceX = x >= 0 ? Face::EAST : Face::WEST; |
|
109 |
|
const Face faceY = y >= 0 ? Face::TOP : Face::BOTTOM; |
|
110 |
|
const Face faceZ = z >= 0 ? Face::NORTH : Face::SOUTH; |
|
111 |
|
|
|
112 |
|
const auto abs_x = std::abs(x); |
|
113 |
|
const auto abs_y = std::abs(y); |
|
114 |
|
const auto abs_z = std::abs(z); |
|
115 |
|
if (abs_x > abs_y) |
|
116 |
|
return abs_z > abs_x ? faceZ : faceX; |
|
117 |
|
else |
|
118 |
|
return abs_z > abs_y ? faceZ : faceY; |
|
119 |
|
} |
|
120 |
|
|
|
121 |
|
template<simd::Level level> |
|
122 |
|
[[nodiscard]] constexpr inline simd::pint_simd<level> real_coordinate_to_face_simd |
|
123 |
|
( |
|
124 |
|
simd::pint_simd<level> x, |
|
125 |
|
simd::pint_simd<level> y, |
|
126 |
|
simd::pint_simd<level> z |
|
127 |
|
) |
|
128 |
|
{ |
|
129 |
|
using pi = simd::pint_simd<level>; |
|
130 |
|
|
|
131 |
|
const pi zero = 0; |
|
132 |
|
const auto faceX = (x < zero).blendv(pi(EAST), pi(WEST)); |
|
133 |
|
const auto faceY = (y < zero).blendv(pi(TOP), pi(BOTTOM)); |
|
134 |
|
const auto faceZ = (z < zero).blendv(pi(NORTH), pi(SOUTH)); |
|
135 |
|
|
|
136 |
|
const auto abs_x = x.abs(); |
|
137 |
|
const auto abs_y = y.abs(); |
|
138 |
|
const auto abs_z = z.abs(); |
|
139 |
|
|
|
140 |
|
const auto faceZX = (abs_z > abs_x).blendv(faceX,faceZ); |
|
141 |
|
const auto faceZY = (abs_z > abs_y).blendv(faceY,faceZ); |
|
142 |
|
return (abs_x > abs_y).blendv(faceZY,faceZX); |
|
143 |
|
} |
|
144 |
|
|
|
145 |
|
|
|
146 |
|
template<typename T> |
|
147 |
|
constexpr inline math::matrix<3, 3, T> rotation(Face face) |
|
148 |
|
{ |
|
149 |
|
if (face == 0) |
|
150 |
|
return math::scale<3>(1); |
|
151 |
|
|
|
152 |
|
|
|
153 |
|
if (face == Face::BOTTOM) |
|
154 |
|
{ |
|
155 |
|
constexpr auto faceN_vert = face_coordinate_to_real(Face::NORTH, T(0.5), T(0.5)) * 2; |
|
156 |
|
return math::rotation(faceN_vert, math::radians(T(180))); |
|
157 |
|
} |
|
158 |
|
|
|
159 |
|
constexpr auto face0_vert = face_coordinate_to_real(Face(0), T(0.5), T(0.5)) * 2; |
|
160 |
|
auto faceX_vert = face_coordinate_to_real(Face(face), T(0.5), T(0.5)) * 2; |
|
161 |
|
return math::rotation(math::cross(face0_vert, faceX_vert), angle(face0_vert, faceX_vert)); |
|
162 |
|
} |
|
163 |
|
|
|
164 |
|
template<typename T> |
|
165 |
|
constexpr inline rotations_t<T> create_rotations() |
|
166 |
|
{ |
|
167 |
|
rotations_t<T> r{}; |
|
168 |
|
for (Face i = Face(0); i < FACE_COUNT; i = Face(i + Face(1))) |
|
169 |
|
r._[i] = rotation<T>(i); |
|
170 |
|
return r; |
|
171 |
|
} |
|
172 |
|
|
|
173 |
|
namespace build |
|
174 |
|
{ |
|
175 |
|
namespace __hiden |
|
176 |
|
{ |
|
177 |
|
template<CONDITION_ARGSF, typename floating_t> |
|
178 |
|
using SET_TEX_COORD = void(*)(Face, math::vector<VEC_SIZE<CONDITION_ARGS>, floating_t> &vec, |
|
179 |
|
floating_t u, floating_t v); |
|
180 |
|
|
|
181 |
|
namespace set_texture_coordinates |
|
182 |
|
{ |
|
183 |
|
template<CONDITION_ARGSF, typename floating_t> |
|
184 |
|
constexpr inline void x1(Face, math::vector<VEC_SIZE<CONDITION_ARGS>, floating_t> &vertex, |
|
185 |
|
floating_t u, floating_t v) |
|
186 |
|
{ |
|
187 |
|
if (texture_coord) |
|
188 |
|
math::setSubVector<3,2>(vertex, math::vec2<floating_t>{ u, v }); |
|
189 |
|
} |
|
190 |
|
|
|
191 |
|
template<CONDITION_ARGSF, typename floating_t> |
|
192 |
|
constexpr inline void x6(Face face, |
|
193 |
|
math::vector<VEC_SIZE<CONDITION_ARGS>, floating_t> &vertex, |
|
194 |
|
floating_t u, floating_t v) |
|
195 |
|
{ |
|
196 |
|
if (texture_coord) |
|
197 |
|
math::setSubVector<3,2>(vertex, math::vec2<floating_t>(u, (face + v) / 6)); |
|
198 |
|
} |
|
199 |
|
} |
|
200 |
|
|
|
201 |
|
|
|
202 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY, |
|
203 |
|
SET_TEX_COORD<CONDITION_ARGS, floating_t> set_tex_coord> |
|
204 |
|
|
|
205 |
|
inline void fill_face |
|
206 |
|
( |
|
207 |
|
Face face, |
|
208 |
|
index_t edge_cell_count, |
|
209 |
|
floating_t scale, |
|
210 |
|
index_t &vertex_index, |
|
211 |
|
index_t &index_index, |
|
212 |
|
index_t &vertex_indexNextRow, |
|
213 |
|
MESH_TEMPLATE *p_mesh |
|
214 |
|
) |
|
215 |
|
{ using namespace math; |
|
216 |
|
|
|
217 |
|
for (index_t x = 0; x <= edge_cell_count; ++x) |
|
218 |
|
{ |
|
219 |
|
floating_t x_ratio = floating_t(x) / edge_cell_count; |
|
220 |
|
for (index_t y = 0; y <= edge_cell_count; ++y) |
|
221 |
|
{ |
|
222 |
|
if (y != edge_cell_count && x != edge_cell_count) |
|
223 |
|
{ |
|
224 |
|
p_mesh->indexes[ index_index] = vertex_index; |
|
225 |
|
p_mesh->indexes[++index_index] = vertex_index + 1; |
|
226 |
|
p_mesh->indexes[++index_index] = ++vertex_indexNextRow; |
|
227 |
|
p_mesh->indexes[++index_index] = vertex_indexNextRow; |
|
228 |
|
p_mesh->indexes[++index_index] = vertex_indexNextRow - 1; |
|
229 |
|
p_mesh->indexes[++index_index] = vertex_index; |
|
230 |
|
++index_index; |
|
231 |
|
} |
|
232 |
|
else ++vertex_indexNextRow; |
|
233 |
|
|
|
234 |
|
floating_t y_ratio = floating_t(y) / edge_cell_count; |
|
235 |
|
|
|
236 |
|
auto pos = MODIFY(face_coordinate_to_real(face, x_ratio, y_ratio)); |
|
237 |
|
|
|
238 |
|
setSubVector<0,3>(p_mesh->vertexes[vertex_index], pos * scale); |
|
239 |
|
set_tex_coord(face, p_mesh->vertexes[vertex_index], x_ratio, y_ratio); |
|
240 |
|
if (normals) |
|
241 |
|
setSubVector<N_OFFSET<texture_coord>,3>(p_mesh->vertexes[vertex_index], NORMALS[face]); |
|
242 |
|
++vertex_index; |
|
243 |
|
} |
|
244 |
|
} |
|
245 |
|
} |
|
246 |
|
} |
|
247 |
|
|
|
248 |
|
|
|
249 |
|
|
|
250 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY> |
|
251 |
|
|
|
252 |
|
[[nodiscard]] bool tesselated(index_t edge_cell_count, floating_t scale, MESH_TEMPLATE *p_mesh) |
|
253 |
|
{ |
|
254 |
|
static_assert(std::is_floating_point<floating_t>::value); |
|
|
74 |
|
template<typename float_t> [[nodiscard]] constexpr inline |
|
75 |
|
math::vec3<float_t> face_coordinate_to_real(Face face, float_t x, float_t y) { |
|
76 |
|
using vec3 = math::vec3<float_t>; |
|
77 |
|
switch (face) { |
|
78 |
|
case TOP : return vec3 { x, 1, y } - float_t(0.5); |
|
79 |
|
case BOTTOM: return vec3 { y, 0, x } - float_t(0.5); |
|
80 |
|
case NORTH : return vec3 { y, x, 1 } - float_t(0.5); |
|
81 |
|
case SOUTH : return vec3 { x, y, 0 } - float_t(0.5); |
|
82 |
|
case WEST : return vec3 { 0, x, y } - float_t(0.5); |
|
83 |
|
case EAST : |
|
84 |
|
default : return vec3 { 1, y, x } - float_t(0.5); |
|
85 |
|
} |
|
86 |
|
} |
|
87 |
|
|
|
88 |
|
template<typename T> |
|
89 |
|
[[nodiscard]] constexpr inline Face real_coordinate_to_face(T x, T y, T z) { |
|
90 |
|
const Face faceX = x >= 0 ? Face::EAST : Face::WEST; |
|
91 |
|
const Face faceY = y >= 0 ? Face::TOP : Face::BOTTOM; |
|
92 |
|
const Face faceZ = z >= 0 ? Face::NORTH : Face::SOUTH; |
|
93 |
|
|
|
94 |
|
const auto abs_x = std::abs(x); |
|
95 |
|
const auto abs_y = std::abs(y); |
|
96 |
|
const auto abs_z = std::abs(z); |
|
97 |
|
if (abs_x > abs_y) |
|
98 |
|
return abs_z > abs_x ? faceZ : faceX; |
|
99 |
|
else |
|
100 |
|
return abs_z > abs_y ? faceZ : faceY; |
|
101 |
|
} |
|
102 |
|
|
|
103 |
|
template<simd::Level level> [[nodiscard]] constexpr inline |
|
104 |
|
simd::pint_simd<level> real_coordinate_to_face_simd( |
|
105 |
|
simd::pint_simd<level> x, |
|
106 |
|
simd::pint_simd<level> y, |
|
107 |
|
simd::pint_simd<level> z) |
|
108 |
|
{ |
|
109 |
|
using pi = simd::pint_simd<level>; |
|
110 |
|
|
|
111 |
|
const pi zero = 0; |
|
112 |
|
|
|
113 |
|
const auto faceX = (x < zero).blendv(pi(EAST), pi(WEST)); |
|
114 |
|
const auto faceY = (y < zero).blendv(pi(TOP), pi(BOTTOM)); |
|
115 |
|
const auto faceZ = (z < zero).blendv(pi(NORTH), pi(SOUTH)); |
|
116 |
|
|
|
117 |
|
const auto abs_x = x.abs(); |
|
118 |
|
const auto abs_y = y.abs(); |
|
119 |
|
const auto abs_z = z.abs(); |
|
120 |
|
|
|
121 |
|
const auto faceZX = (abs_z > abs_x).blendv(faceX,faceZ); |
|
122 |
|
const auto faceZY = (abs_z > abs_y).blendv(faceY,faceZ); |
|
123 |
|
return (abs_x > abs_y).blendv(faceZY,faceZX); |
|
124 |
|
} |
|
125 |
|
|
|
126 |
|
template<typename T> constexpr inline |
|
127 |
|
math::matrix<3, 3, T> rotation(Face face) { |
|
128 |
|
if (face == 0) |
|
129 |
|
return math::scale<3>(1); |
|
130 |
|
|
|
131 |
|
if (face == Face::BOTTOM) { |
|
132 |
|
constexpr auto faceN_vert = |
|
133 |
|
face_coordinate_to_real(Face::NORTH, T(0.5), T(0.5)) * 2; |
|
134 |
|
return math::rotation(faceN_vert, math::radians(T(180))); |
|
135 |
|
} |
|
136 |
|
|
|
137 |
|
constexpr auto face0_vert = |
|
138 |
|
face_coordinate_to_real(Face(0), T(0.5), T(0.5)) * 2; |
|
139 |
|
auto faceX_vert = face_coordinate_to_real(Face(face), T(0.5), T(0.5)) * 2; |
|
140 |
|
return math::rotation(math::cross(face0_vert, faceX_vert), |
|
141 |
|
angle(face0_vert, faceX_vert)); |
|
142 |
|
} |
|
143 |
|
|
|
144 |
|
template<typename T> constexpr inline |
|
145 |
|
rotations_t<T> create_rotations() { |
|
146 |
|
rotations_t<T> r{}; |
|
147 |
|
for (Face i = Face(0); i < FACE_COUNT; i = Face(i + Face(1))) |
|
148 |
|
r._[i] = rotation<T>(i); |
|
149 |
|
return r; |
|
150 |
|
} |
|
151 |
|
} |
|
152 |
|
namespace mesh::cube::build::detail |
|
153 |
|
{ |
|
154 |
|
template<CONDITION_ARGSF, typename floating_t> |
|
155 |
|
using SET_TEX_COORD = |
|
156 |
|
void(*)(Face, math::vector<VEC_SIZE<CONDITION_ARGS>, |
|
157 |
|
floating_t> &vec, floating_t u, floating_t v); |
|
158 |
|
|
|
159 |
|
namespace set_texture_coordinates { |
|
160 |
|
template<CONDITION_ARGSF, typename floating_t> constexpr inline |
|
161 |
|
void x1(Face, math::vector<VEC_SIZE<CONDITION_ARGS>, floating_t> &vertex, |
|
162 |
|
floating_t u, floating_t v) { |
|
163 |
|
if (texture_coord) |
|
164 |
|
vertex.template part<4,2>() = math::vec2<floating_t>{ u, v }; |
|
165 |
|
} |
|
166 |
|
|
|
167 |
|
template<CONDITION_ARGSF, typename floating_t> constexpr inline |
|
168 |
|
void x6(Face face, math::vector<VEC_SIZE<CONDITION_ARGS>, |
|
169 |
|
floating_t> &vertex, floating_t u, floating_t v) { |
|
170 |
|
if (texture_coord) |
|
171 |
|
vertex.template part<3,2>() = math::vec2<floating_t>(u, (face + v) / 6); |
|
172 |
|
} |
|
173 |
|
} |
|
174 |
|
|
|
175 |
|
|
|
176 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY, |
|
177 |
|
SET_TEX_COORD<CONDITION_ARGS, floating_t> set_tex_coord> |
|
178 |
|
|
|
179 |
|
inline |
|
180 |
|
void fill_face( |
|
181 |
|
Face face, |
|
182 |
|
index_t edge_cell_count, |
|
183 |
|
floating_t scale, |
|
184 |
|
index_t &vertex_index, |
|
185 |
|
index_t &index_index, |
|
186 |
|
index_t &vertex_indexNextRow, |
|
187 |
|
MESH_TEMPLATE *p_mesh) |
|
188 |
|
{ |
|
189 |
|
using namespace math; |
|
190 |
|
|
|
191 |
|
for (index_t x = 0; x <= edge_cell_count; ++x) { |
|
192 |
|
floating_t x_ratio = floating_t(x) / edge_cell_count; |
|
193 |
|
for (index_t y = 0; y <= edge_cell_count; ++y) { |
|
194 |
|
if (y != edge_cell_count && x != edge_cell_count) { |
|
195 |
|
p_mesh->indexes[ index_index] = vertex_index; |
|
196 |
|
p_mesh->indexes[++index_index] = vertex_index + 1; |
|
197 |
|
p_mesh->indexes[++index_index] = ++vertex_indexNextRow; |
|
198 |
|
p_mesh->indexes[++index_index] = vertex_indexNextRow; |
|
199 |
|
p_mesh->indexes[++index_index] = vertex_indexNextRow - 1; |
|
200 |
|
p_mesh->indexes[++index_index] = vertex_index; |
|
201 |
|
++index_index; |
|
202 |
|
} |
|
203 |
|
else ++vertex_indexNextRow; |
|
204 |
|
|
|
205 |
|
floating_t y_ratio = floating_t(y) / edge_cell_count; |
|
206 |
|
|
|
207 |
|
auto pos = MODIFY(face_coordinate_to_real(face, x_ratio, y_ratio)); |
|
208 |
|
|
|
209 |
|
auto &ver = p_mesh->vertexes[vertex_index]; |
|
210 |
|
ver.template part<0,3> = pos * scale; |
|
211 |
|
set_tex_coord(face, ver, x_ratio, y_ratio); |
|
212 |
|
if (normals) |
|
213 |
|
ver.template part<N_OFFSET<texture_coord>,3> = NORMALS[face]; |
|
214 |
|
|
|
215 |
|
++vertex_index; |
|
216 |
|
} |
|
217 |
|
} |
|
218 |
|
} |
|
219 |
|
} |
|
220 |
|
namespace mesh::cube::build |
|
221 |
|
{ |
|
222 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY> [[nodiscard]] |
|
223 |
|
bool tesselated(index_t edge_cell_count, floating_t scale, |
|
224 |
|
MESH_TEMPLATE *p_mesh) |
|
225 |
|
{ |
|
226 |
|
static_assert(std::is_floating_point<floating_t>::value); |
255 |
227 |
#ifndef NDEBUG |
#ifndef NDEBUG |
256 |
|
size_t _requested_size = size_t((edge_cell_count)) * edge_cell_count * FACE_COUNT * 6; |
|
257 |
|
jassert(_requested_size >= std::numeric_limits<index_t>::max(), "index overflow"); |
|
|
228 |
|
{ |
|
229 |
|
size_t size = size_t((edge_cell_count)) * edge_cell_count * FACE_COUNT*6; |
|
230 |
|
jassert(size >= std::numeric_limits<index_t>::max(), "index overflow"); |
|
231 |
|
} |
258 |
232 |
#endif |
#endif |
259 |
|
index_t vertex_count = (edge_cell_count+1) * (edge_cell_count+1) * FACE_COUNT; |
|
260 |
|
index_t index_count = (edge_cell_count) * (edge_cell_count) * FACE_COUNT * 6; |
|
261 |
|
if (not p_mesh->init(vertex_count, index_count)) |
|
262 |
|
return false; |
|
263 |
|
|
|
264 |
|
index_t vertexIndex = 0, |
|
265 |
|
vertexIndexNextRow = edge_cell_count + 1, |
|
266 |
|
indexIndex = 0; |
|
267 |
|
|
|
268 |
|
using namespace __hiden; |
|
269 |
|
|
|
270 |
|
for (Face i = FACE1; i < FACE_COUNT; i = Face(i + 1)) |
|
271 |
|
{ |
|
272 |
|
fill_face<ARGS, MODIFY, set_texture_coordinates::x6<CONDITION_ARGS, floating_t>> |
|
273 |
|
( |
|
274 |
|
i, |
|
275 |
|
edge_cell_count, |
|
276 |
|
scale, |
|
277 |
|
vertexIndex, |
|
278 |
|
indexIndex, |
|
279 |
|
vertexIndexNextRow, |
|
280 |
|
p_mesh |
|
281 |
|
); |
|
282 |
|
} |
|
283 |
|
|
|
284 |
|
return true; |
|
285 |
|
} |
|
286 |
|
|
|
287 |
|
|
|
288 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY> |
|
289 |
|
|
|
290 |
|
[[nodiscard]] bool tesselated_face(Face face, index_t edge_cell_count, floating_t scale, |
|
291 |
|
MESH_TEMPLATE *p_mesh) |
|
292 |
|
{ |
|
293 |
|
static_assert(std::is_floating_point<floating_t>::value); |
|
294 |
|
jassert(size_t((edge_cell_count)) * edge_cell_count * 6 < std::numeric_limits<index_t>::max(), |
|
295 |
|
"index_t overflow"); |
|
296 |
|
jassert(face < FACE_COUNT, "incorrect face"); |
|
297 |
|
|
|
298 |
|
index_t vertex_count = (edge_cell_count+1) * (edge_cell_count+1); |
|
299 |
|
index_t index_count = (edge_cell_count) * (edge_cell_count) * 6; |
|
300 |
|
if (not p_mesh->init(vertex_count, index_count)) |
|
301 |
|
return false; |
|
302 |
|
|
|
303 |
|
index_t vertexIndex = 0; |
|
304 |
|
index_t vertexIndexNextRow = edge_cell_count + 1; |
|
305 |
|
index_t indexIndex = 0; |
|
306 |
|
|
|
307 |
|
using namespace __hiden; |
|
308 |
|
|
|
309 |
|
fill_face<ARGS, MODIFY, set_texture_coordinates::x1<CONDITION_ARGS, floating_t>> |
|
310 |
|
( |
|
311 |
|
face, |
|
312 |
|
edge_cell_count, |
|
313 |
|
scale, |
|
314 |
|
vertexIndex, |
|
315 |
|
indexIndex, |
|
316 |
|
vertexIndexNextRow, |
|
317 |
|
p_mesh |
|
318 |
|
); |
|
319 |
|
|
|
320 |
|
return true; |
|
321 |
|
} |
|
322 |
|
} |
|
323 |
|
} |
|
|
233 |
|
index_t vcount = (edge_cell_count+1) * (edge_cell_count+1) * FACE_COUNT; |
|
234 |
|
index_t icount = (edge_cell_count) * (edge_cell_count) * FACE_COUNT * 6; |
|
235 |
|
if (not p_mesh->init(vcount, icount)) |
|
236 |
|
return false; |
|
237 |
|
|
|
238 |
|
index_t vIndex = 0, vIndexNextRow = edge_cell_count + 1, iIndex = 0; |
|
239 |
|
|
|
240 |
|
for (Face i = FACE1; i < FACE_COUNT; i = Face(i + 1)) { |
|
241 |
|
detail::fill_face<ARGS, MODIFY, |
|
242 |
|
detail::set_texture_coordinates::x6<CONDITION_ARGS, floating_t>> |
|
243 |
|
(i, edge_cell_count, scale, vIndex, iIndex, vIndexNextRow, p_mesh); |
|
244 |
|
} |
|
245 |
|
return true; |
|
246 |
|
} |
|
247 |
|
|
|
248 |
|
|
|
249 |
|
template<ARGSF, PF_ModifyVertex<floating_t> MODIFY> [[nodiscard]] |
|
250 |
|
bool tesselated_face(Face face, index_t edge_cell_count, floating_t scale, |
|
251 |
|
MESH_TEMPLATE *p_mesh) { |
|
252 |
|
static_assert(std::is_floating_point<floating_t>::value); |
|
253 |
|
jassert(size_t((edge_cell_count)) * edge_cell_count * 6 |
|
254 |
|
< std::numeric_limits<index_t>::max(), |
|
255 |
|
"index_t overflow"); |
|
256 |
|
jassert(face < FACE_COUNT, "incorrect face"); |
|
257 |
|
|
|
258 |
|
index_t vcount = (edge_cell_count+1) * (edge_cell_count+1); |
|
259 |
|
index_t icount = (edge_cell_count) * (edge_cell_count) * 6; |
|
260 |
|
if (not p_mesh->init(vcount, icount)) |
|
261 |
|
return false; |
|
262 |
|
|
|
263 |
|
index_t vIndex = 0; |
|
264 |
|
index_t vIndexNextRow = edge_cell_count + 1; |
|
265 |
|
index_t iIndex = 0; |
|
266 |
|
|
|
267 |
|
detail::fill_face<ARGS, MODIFY, |
|
268 |
|
detail::set_texture_coordinates::x1<CONDITION_ARGS, floating_t>> |
|
269 |
|
(face, edge_cell_count, scale, vIndex, iIndex, vIndexNextRow, p_mesh); |
|
270 |
|
|
|
271 |
|
return true; |
|
272 |
|
} |
324 |
273 |
} |
} |
325 |
274 |
|
|
326 |
275 |
#undef CONDITION_ARGS |
#undef CONDITION_ARGS |
File libs/mesh/plane.h changed (mode: 100644) (index 27c742f..ad6d5d9) |
6 |
6 |
#define ARGS texture_coord, normals, floating_t, index_t |
#define ARGS texture_coord, normals, floating_t, index_t |
7 |
7 |
#define MESH_TEMPLATE Mesh_T<ARGS> |
#define MESH_TEMPLATE Mesh_T<ARGS> |
8 |
8 |
|
|
9 |
|
namespace mesh |
|
10 |
|
{ |
|
11 |
|
namespace plane |
|
12 |
|
{ |
|
13 |
|
namespace build |
|
14 |
|
{ |
|
15 |
|
TEMPLATE_ARGS |
|
16 |
|
[[nodiscard]] bool common(floating_t width, floating_t length, MESH_TEMPLATE *p_mesh); |
|
17 |
|
|
|
18 |
|
TEMPLATE_ARGS |
|
19 |
|
[[nodiscard]] bool tesselated(floating_t width, floating_t length, |
|
20 |
|
index_t width_cell_count, index_t length_cell_count, |
|
21 |
|
MESH_TEMPLATE *p_mesh); |
|
22 |
|
} |
|
23 |
|
} |
|
24 |
|
} |
|
|
9 |
|
namespace mesh::plane::build { |
|
10 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
11 |
|
bool |
|
12 |
|
common(floating_t width, floating_t length, MESH_TEMPLATE *p_mesh); |
25 |
13 |
|
|
|
14 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
15 |
|
bool |
|
16 |
|
tesselated(floating_t width, floating_t length, |
|
17 |
|
index_t width_cell_count, index_t length_cell_count, |
|
18 |
|
MESH_TEMPLATE *p_mesh); |
26 |
19 |
|
|
27 |
|
namespace mesh |
|
28 |
|
{ |
|
29 |
|
namespace plane |
|
30 |
|
{ |
|
31 |
|
namespace build |
|
32 |
|
{ |
|
33 |
|
template<CONDITION_ARGS, typename floating_t> |
|
34 |
|
void set_tex(math::vector<VEC_SIZE<texture_coord, normals>, floating_t> &vertex, |
|
35 |
|
floating_t x, floating_t y) |
|
36 |
|
{ |
|
37 |
|
if (texture_coord) |
|
38 |
|
math::setSubVector<3,2>(vertex, math::vec2<floating_t>{ x, y }); |
|
39 |
|
} |
|
|
20 |
|
template<CONDITION_ARGS, typename floating_t> |
|
21 |
|
void |
|
22 |
|
set_tex(math::vector<VEC_SIZE<texture_coord, normals>, floating_t> &vertex, |
|
23 |
|
floating_t x, floating_t y) { |
|
24 |
|
if (texture_coord) |
|
25 |
|
vertex.template part<3,2>() = math::vec2<floating_t>{ x, y }; |
|
26 |
|
} |
40 |
27 |
|
|
41 |
|
TEMPLATE_ARGS |
|
42 |
|
[[nodiscard]] bool common(floating_t width, floating_t length, MESH_TEMPLATE *p_mesh) |
|
43 |
|
{ |
|
44 |
|
static_assert (normals != true, "not implemented"); |
|
|
28 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
29 |
|
bool |
|
30 |
|
common(floating_t width, floating_t length, MESH_TEMPLATE *p_mesh) { |
|
31 |
|
static_assert (normals != true, "not implemented"); |
45 |
32 |
|
|
|
33 |
|
if (not p_mesh->init(4, 6)) |
|
34 |
|
return false; |
46 |
35 |
|
|
47 |
|
if (not p_mesh->init(4, 6)) |
|
48 |
|
return false; |
|
|
36 |
|
p_mesh->vertexes[3].template part<0,3>() = { 0, 0 , 0 }; |
|
37 |
|
p_mesh->vertexes[3].template part<0,3>() = { 0, length, 0 }; |
|
38 |
|
p_mesh->vertexes[3].template part<0,3>() = { width, 0, 0 }; |
|
39 |
|
p_mesh->vertexes[3].template part<0,3>() = { width, length, 0 }; |
49 |
40 |
|
|
50 |
|
math::setSubVector<0,3>(p_mesh->vertexes[0], { 0, 0 , 0 }); |
|
51 |
|
math::setSubVector<0,3>(p_mesh->vertexes[1], { 0, length, 0 }); |
|
52 |
|
math::setSubVector<0,3>(p_mesh->vertexes[2], { width, 0, 0 }); |
|
53 |
|
math::setSubVector<0,3>(p_mesh->vertexes[3], { width, length, 0 }); |
|
|
41 |
|
set_tex(p_mesh->vertexes[0], 0, 0); |
|
42 |
|
set_tex(p_mesh->vertexes[1], 0, 1); |
|
43 |
|
set_tex(p_mesh->vertexes[2], 1, 0); |
|
44 |
|
set_tex(p_mesh->vertexes[3], 1, 1); |
54 |
45 |
|
|
55 |
|
set_tex(p_mesh->vertexes[0], math::cast<floating_t>(0), math::cast<floating_t>(0)); |
|
56 |
|
set_tex(p_mesh->vertexes[1], math::cast<floating_t>(0), math::cast<floating_t>(1)); |
|
57 |
|
set_tex(p_mesh->vertexes[2], math::cast<floating_t>(1), math::cast<floating_t>(0)); |
|
58 |
|
set_tex(p_mesh->vertexes[3], math::cast<floating_t>(1), math::cast<floating_t>(1)); |
|
|
46 |
|
p_mesh->indexes[0] = 0; |
|
47 |
|
p_mesh->indexes[1] = 1; |
|
48 |
|
p_mesh->indexes[2] = 2; |
|
49 |
|
p_mesh->indexes[3] = 3; |
|
50 |
|
p_mesh->indexes[4] = 2; |
|
51 |
|
p_mesh->indexes[5] = 1; |
59 |
52 |
|
|
60 |
|
p_mesh->indexes[0] = 0; |
|
61 |
|
p_mesh->indexes[1] = 1; |
|
62 |
|
p_mesh->indexes[2] = 2; |
|
63 |
|
p_mesh->indexes[3] = 3; |
|
64 |
|
p_mesh->indexes[4] = 2; |
|
65 |
|
p_mesh->indexes[5] = 1; |
|
|
53 |
|
return true; |
|
54 |
|
} |
66 |
55 |
|
|
67 |
|
return true; |
|
68 |
|
} |
|
69 |
56 |
/* |
/* |
70 |
|
template<bool tex_coord, typename floating_t, typename index_t> [[nodiscard]] |
|
71 |
|
bool tesselated |
|
72 |
|
( |
|
73 |
|
Mesh_T<tex_coord, floating_t, index_t> &mesh, |
|
74 |
|
floating_t width, |
|
75 |
|
floating_t length, |
|
76 |
|
index_t width_cell_count, |
|
77 |
|
index_t length_cell_count |
|
78 |
|
) |
|
79 |
|
{ |
|
80 |
|
//TODO |
|
|
57 |
|
template<bool tex_coord, typename floating_t, typename index_t> [[nodiscard]] |
|
58 |
|
bool tesselated |
|
59 |
|
( |
|
60 |
|
Mesh_T<tex_coord, floating_t, index_t> &mesh, |
|
61 |
|
floating_t width, |
|
62 |
|
floating_t length, |
|
63 |
|
index_t width_cell_count, |
|
64 |
|
index_t length_cell_count |
|
65 |
|
) |
|
66 |
|
{ |
|
67 |
|
//TODO |
81 |
68 |
#ifndef NDEBUG |
#ifndef NDEBUG |
82 |
|
if (size_t(width_cell_count) * size_t(length_cell_count) * 6 >= std::numeric_limits<index_t>::max()) |
|
83 |
|
error_output("mesh::sphere::build::uv - index_t overflow"); |
|
|
69 |
|
if (size_t(width_cell_count) * size_t(length_cell_count) * 6 |
|
70 |
|
>= std::numeric_limits<index_t>::max()) |
|
71 |
|
error_output("mesh::sphere::build::uv - index_t overflow"); |
84 |
72 |
#endif |
#endif |
85 |
|
index_t vertex_count = (width_cell_count + 1) * (length_cell_count + 1); |
|
86 |
|
index_t index_count = width_cell_count * length_cell_count * 6; |
|
87 |
|
if (!mesh.init(vertex_count, index_count)) |
|
88 |
|
return false; |
|
89 |
|
|
|
90 |
|
index_t indexIndex = 0, vertexIndex = 0; |
|
91 |
|
index_t vertexIndexNextRow = width_cell_count + 1; |
|
92 |
|
float xPos; |
|
93 |
|
for(uint32_t x = 0; x < length_cell_count; ++x) |
|
94 |
|
{ |
|
95 |
|
borders.min = math::v3f{} - (scale / 2); |
|
96 |
|
borders.max = borders.max + scale; |
|
97 |
|
xPos = float(x) / float(length_cell_count); |
|
98 |
|
for (uint32_t y = 0; y < width_cell_count; ++y) |
|
99 |
|
{ |
|
100 |
|
mesh.vertexes[vertexIndex] = {xPos, y / float(width_cell_count) }; |
|
101 |
|
|
|
102 |
|
mesh.indexes[indexIndex] = vertexIndex; |
|
103 |
|
mesh.indexes[++indexIndex] = vertexIndex + 1; |
|
104 |
|
mesh.indexes[++indexIndex] = ++vertexIndexNextRow; |
|
105 |
|
mesh.indexes[++indexIndex] = vertexIndexNextRow; |
|
106 |
|
mesh.indexes[++indexIndex] = vertexIndexNextRow - 1; |
|
107 |
|
mesh.indexes[++indexIndex] = vertexIndex; |
|
108 |
|
++indexIndex; |
|
109 |
|
++vertexIndex; |
|
110 |
|
} |
|
111 |
|
mesh.vertexes[vertexIndex++] = { x / float(length_cell_count), 1 }; |
|
112 |
|
++vertexIndexNextRow; |
|
113 |
|
} |
|
114 |
|
for (uint32_t y = 0; y < width_cell_count; ++y) |
|
115 |
|
mesh.vertexes[vertexIndex++] = { 1, y / float(width_cell_count) }; |
|
116 |
|
|
|
117 |
|
mesh.vertexes[vertexIndex] = { 1, 1 }; |
|
118 |
|
|
|
119 |
|
return true; |
|
120 |
|
}*/ |
|
121 |
|
} |
|
122 |
|
} |
|
|
73 |
|
index_t vertex_count = (width_cell_count + 1) * (length_cell_count + 1); |
|
74 |
|
index_t index_count = width_cell_count * length_cell_count * 6; |
|
75 |
|
if (!mesh.init(vertex_count, index_count)) |
|
76 |
|
return false; |
|
77 |
|
|
|
78 |
|
index_t indexIndex = 0, vertexIndex = 0; |
|
79 |
|
index_t vertexIndexNextRow = width_cell_count + 1; |
|
80 |
|
float xPos; |
|
81 |
|
for(uint32_t x = 0; x < length_cell_count; ++x) |
|
82 |
|
{ |
|
83 |
|
borders.min = math::v3f{} - (scale / 2); |
|
84 |
|
borders.max = borders.max + scale; |
|
85 |
|
xPos = float(x) / float(length_cell_count); |
|
86 |
|
for (uint32_t y = 0; y < width_cell_count; ++y) |
|
87 |
|
{ |
|
88 |
|
mesh.vertexes[vertexIndex] = {xPos, y / float(width_cell_count) }; |
|
89 |
|
|
|
90 |
|
mesh.indexes[indexIndex] = vertexIndex; |
|
91 |
|
mesh.indexes[++indexIndex] = vertexIndex + 1; |
|
92 |
|
mesh.indexes[++indexIndex] = ++vertexIndexNextRow; |
|
93 |
|
mesh.indexes[++indexIndex] = vertexIndexNextRow; |
|
94 |
|
mesh.indexes[++indexIndex] = vertexIndexNextRow - 1; |
|
95 |
|
mesh.indexes[++indexIndex] = vertexIndex; |
|
96 |
|
++indexIndex; |
|
97 |
|
++vertexIndex; |
|
98 |
|
} |
|
99 |
|
mesh.vertexes[vertexIndex++] = { x / float(length_cell_count), 1 }; |
|
100 |
|
++vertexIndexNextRow; |
|
101 |
|
} |
|
102 |
|
for (uint32_t y = 0; y < width_cell_count; ++y) |
|
103 |
|
mesh.vertexes[vertexIndex++] = { 1, y / float(width_cell_count) }; |
|
104 |
|
|
|
105 |
|
mesh.vertexes[vertexIndex] = { 1, 1 }; |
|
106 |
|
|
|
107 |
|
return true; |
|
108 |
|
}*/ |
123 |
109 |
} |
} |
124 |
110 |
#undef CONDITION_ARGS |
#undef CONDITION_ARGS |
125 |
111 |
#undef ARGS |
#undef ARGS |
File libs/mesh/polyhedron/icosahedron.h changed (mode: 100644) (index dcbd839..0e80865) |
6 |
6 |
#define TEMPLATE_ARGS template<bool texture_coord, bool normals, typename floating_t, typename index_t> |
#define TEMPLATE_ARGS template<bool texture_coord, bool normals, typename floating_t, typename index_t> |
7 |
7 |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
8 |
8 |
|
|
9 |
|
namespace mesh |
|
10 |
|
{ |
|
11 |
|
namespace icosahedron |
|
12 |
|
{ |
|
13 |
|
namespace build |
|
14 |
|
{ |
|
15 |
|
TEMPLATE_ARGS |
|
16 |
|
[[nodiscard]] inline bool icosahedron(MESH_TEMPLATE *p_mesh); |
|
17 |
|
} |
|
18 |
|
|
|
19 |
|
constexpr static const unsigned int FACE_COUNT = 20; |
|
20 |
|
constexpr static const unsigned int VERTEX_COUNT = 12; |
|
21 |
|
constexpr static const unsigned int INDEX_COUNT = FACE_COUNT * 3; |
|
22 |
|
|
|
23 |
|
TEMPLATE_ARGS |
|
24 |
|
struct Icosahedron |
|
25 |
|
{ |
|
26 |
|
constexpr Icosahedron() {} |
|
27 |
|
|
|
28 |
|
constexpr static const floating_t GOLDEN_RATIO = (1 + gcem::sqrt<floating_t>(5)) / 2; |
|
29 |
|
constexpr static const floating_t RADIUS_RATIO = floating_t(1.9021130326L); |
|
30 |
|
constexpr static const auto VECTOR_SIZE = VEC_SIZE<texture_coord, normals>; |
|
31 |
|
|
|
32 |
|
constexpr static const floating_t ANGLE_NEIGHBOUR_VERTICES = angle({ -1, GOLDEN_RATIO, 0 }, |
|
33 |
|
{ 1, GOLDEN_RATIO, 0 }); |
|
34 |
|
|
|
35 |
|
using vertex = math::vector<VECTOR_SIZE, floating_t>; |
|
36 |
|
|
|
37 |
|
struct vertices |
|
38 |
|
{ |
|
39 |
|
constexpr vertices() = default; |
|
40 |
|
constexpr static index_t COUNT = VERTEX_COUNT; |
|
41 |
|
|
|
42 |
|
vertex operator[](index_t i) const { return _[i]; } |
|
43 |
|
vertex _[COUNT]; |
|
44 |
|
}; |
|
45 |
|
|
|
46 |
|
constexpr static vertices create_vertices() |
|
47 |
|
{ |
|
48 |
|
struct vertices result{}; |
|
49 |
|
constexpr math::vec3<floating_t> array[vertices::COUNT] = |
|
50 |
|
{ |
|
51 |
|
math::vec3<floating_t> { -1, GOLDEN_RATIO, 0 }.normalize(), |
|
52 |
|
math::vec3<floating_t> { 1, GOLDEN_RATIO, 0 }.normalize(), |
|
53 |
|
math::vec3<floating_t> { -1, -GOLDEN_RATIO, 0 }.normalize(), |
|
54 |
|
math::vec3<floating_t> { 1, -GOLDEN_RATIO, 0 }.normalize(), |
|
55 |
|
|
|
56 |
|
math::vec3<floating_t> { 0, -1, GOLDEN_RATIO }.normalize(), |
|
57 |
|
math::vec3<floating_t> { 0, 1, GOLDEN_RATIO }.normalize(), |
|
58 |
|
math::vec3<floating_t> { 0, -1, -GOLDEN_RATIO }.normalize(), |
|
59 |
|
math::vec3<floating_t> { 0, 1, -GOLDEN_RATIO }.normalize(), |
|
60 |
|
|
|
61 |
|
math::vec3<floating_t> { GOLDEN_RATIO, 0, -1 }.normalize(), |
|
62 |
|
math::vec3<floating_t> { GOLDEN_RATIO, 0, 1 }.normalize(), |
|
63 |
|
math::vec3<floating_t> { -GOLDEN_RATIO, 0, -1 }.normalize(), |
|
64 |
|
math::vec3<floating_t> { -GOLDEN_RATIO, 0, 1 }.normalize() |
|
65 |
|
}; |
|
66 |
|
for (uint_fast8_t i = 0; i < vertices::COUNT; ++i) |
|
67 |
|
{ |
|
68 |
|
math::setSubVector<0,3>(result._[i], array[i]); |
|
69 |
|
if (texture_coord) |
|
70 |
|
math::setSubVector<3,2>(result._[i], __texture_coordinates::uv(array[i])); |
|
71 |
|
if (normals) |
|
72 |
|
math::setSubVector<N_OFFSET<texture_coord>,3>(result._[i], array[i]); |
|
73 |
|
} |
|
74 |
|
return result; |
|
75 |
|
} |
|
76 |
|
static_assert (vertices()._[0][0] != -1); |
|
77 |
|
|
|
78 |
|
struct indices |
|
79 |
|
{ |
|
80 |
|
constexpr indices() = default; |
|
81 |
|
constexpr static index_t COUNT = INDEX_COUNT; |
|
82 |
|
|
|
83 |
|
index_t operator[](index_t i) const { return _[i]; } |
|
84 |
|
|
|
85 |
|
index_t _[COUNT]; |
|
86 |
|
}; |
|
87 |
|
constexpr static indices create_indices() |
|
88 |
|
{ |
|
89 |
|
struct indices result{}; |
|
90 |
|
index_t array[indices::COUNT] = |
|
91 |
|
{ |
|
92 |
|
0, 11, 5, |
|
93 |
|
0, 5, 1, |
|
94 |
|
0, 1, 7, |
|
95 |
|
0, 7, 10, |
|
96 |
|
0, 10, 11, |
|
97 |
|
|
|
98 |
|
1, 5, 9, |
|
99 |
|
5, 11, 4, |
|
100 |
|
11, 10, 2, |
|
101 |
|
10, 7, 6, |
|
102 |
|
7, 1, 8, |
|
103 |
|
|
|
104 |
|
3, 9, 4, |
|
105 |
|
3, 4, 2, |
|
106 |
|
3, 2, 6, |
|
107 |
|
3, 6, 8, |
|
108 |
|
3, 8, 9, |
|
109 |
|
|
|
110 |
|
4, 9, 5, |
|
111 |
|
2, 4, 11, |
|
112 |
|
6, 2, 10, |
|
113 |
|
8, 6, 7, |
|
114 |
|
9, 8, 1 |
|
115 |
|
}; |
|
116 |
|
for (uint_fast8_t i = 0; i < indices::COUNT; ++i) |
|
117 |
|
result._[i] = array[i]; |
|
118 |
|
return result; |
|
119 |
|
} |
|
120 |
|
|
|
121 |
|
constexpr static vertices vertice = create_vertices(); |
|
122 |
|
constexpr static indices indice = create_indices(); |
|
123 |
|
}; |
|
124 |
|
|
|
125 |
|
TEMPLATE_ARGS |
|
126 |
|
constexpr static const Icosahedron<texture_coord, normals, floating_t, index_t> pre_compiled{}; |
|
127 |
|
|
|
128 |
|
namespace build |
|
129 |
|
{ |
|
130 |
|
TEMPLATE_ARGS |
|
131 |
|
[[nodiscard]] inline bool icosahedron(MESH_TEMPLATE *p_mesh) |
|
132 |
|
{ |
|
133 |
|
using Icosahedron = Icosahedron<texture_coord, normals, floating_t, index_t>; |
|
134 |
|
|
|
135 |
|
if (not p_mesh->init(Icosahedron::vertices::COUNT, Icosahedron::indices::COUNT)) |
|
136 |
|
return false; |
|
137 |
|
|
|
138 |
|
constexpr Icosahedron icosahedron_data{}; |
|
139 |
|
|
|
140 |
|
index_t size = Icosahedron::vertices::COUNT * sizeof (Icosahedron::vector); |
|
141 |
|
|
|
142 |
|
memcpy(p_mesh->vertexes.p_array, &icosahedron_data.vertices, size); |
|
143 |
|
|
|
144 |
|
|
|
145 |
|
size = Icosahedron::indices::COUNT * sizeof (index_t); |
|
146 |
|
|
|
147 |
|
memcpy(p_mesh->indexes.p_array, &icosahedron_data.indices, size); |
|
148 |
|
|
|
149 |
|
return true; |
|
150 |
|
} |
|
151 |
|
} |
|
152 |
|
} |
|
|
9 |
|
namespace mesh::icosahedron::build { |
|
10 |
|
TEMPLATE_ARGS |
|
11 |
|
[[nodiscard]] inline bool icosahedron(MESH_TEMPLATE *p_mesh); |
|
12 |
|
} |
|
13 |
|
namespace mesh::icosahedron { |
|
14 |
|
constexpr static const unsigned int FACE_COUNT = 20; |
|
15 |
|
constexpr static const unsigned int VERTEX_COUNT = 12; |
|
16 |
|
constexpr static const unsigned int INDEX_COUNT = FACE_COUNT * 3; |
|
17 |
|
|
|
18 |
|
TEMPLATE_ARGS |
|
19 |
|
struct Icosahedron |
|
20 |
|
{ |
|
21 |
|
constexpr Icosahedron() {} |
|
22 |
|
|
|
23 |
|
constexpr static const |
|
24 |
|
floating_t GOLDEN_RATIO = (1 + gcem::sqrt<floating_t>(5)) / 2; |
|
25 |
|
constexpr static const |
|
26 |
|
floating_t RADIUS_RATIO = floating_t(1.9021130326L); |
|
27 |
|
constexpr static const |
|
28 |
|
auto VECTOR_SIZE = VEC_SIZE<texture_coord, normals>; |
|
29 |
|
|
|
30 |
|
constexpr static const |
|
31 |
|
floating_t ANGLE_NEIGHBOUR_VERTICES = |
|
32 |
|
angle({ -1, GOLDEN_RATIO, 0 }, { 1, GOLDEN_RATIO, 0 }); |
|
33 |
|
|
|
34 |
|
using vertex = math::vector<VECTOR_SIZE, floating_t>; |
|
35 |
|
|
|
36 |
|
struct vertices { |
|
37 |
|
constexpr vertices() = default; |
|
38 |
|
constexpr static index_t COUNT = VERTEX_COUNT; |
|
39 |
|
|
|
40 |
|
vertex operator[](index_t i) const { return _[i]; } |
|
41 |
|
vertex _[COUNT]; |
|
42 |
|
}; |
|
43 |
|
|
|
44 |
|
constexpr static vertices create_vertices() |
|
45 |
|
{ |
|
46 |
|
struct vertices result{}; |
|
47 |
|
constexpr math::vec3<floating_t> array[vertices::COUNT] = |
|
48 |
|
{ |
|
49 |
|
math::vec3<floating_t> { -1, GOLDEN_RATIO, 0 }.normalize(), |
|
50 |
|
math::vec3<floating_t> { 1, GOLDEN_RATIO, 0 }.normalize(), |
|
51 |
|
math::vec3<floating_t> { -1, -GOLDEN_RATIO, 0 }.normalize(), |
|
52 |
|
math::vec3<floating_t> { 1, -GOLDEN_RATIO, 0 }.normalize(), |
|
53 |
|
|
|
54 |
|
math::vec3<floating_t> { 0, -1, GOLDEN_RATIO }.normalize(), |
|
55 |
|
math::vec3<floating_t> { 0, 1, GOLDEN_RATIO }.normalize(), |
|
56 |
|
math::vec3<floating_t> { 0, -1, -GOLDEN_RATIO }.normalize(), |
|
57 |
|
math::vec3<floating_t> { 0, 1, -GOLDEN_RATIO }.normalize(), |
|
58 |
|
|
|
59 |
|
math::vec3<floating_t> { GOLDEN_RATIO, 0, -1 }.normalize(), |
|
60 |
|
math::vec3<floating_t> { GOLDEN_RATIO, 0, 1 }.normalize(), |
|
61 |
|
math::vec3<floating_t> { -GOLDEN_RATIO, 0, -1 }.normalize(), |
|
62 |
|
math::vec3<floating_t> { -GOLDEN_RATIO, 0, 1 }.normalize() |
|
63 |
|
}; |
|
64 |
|
for (uint_fast8_t i = 0; i < vertices::COUNT; ++i) { |
|
65 |
|
result._[i].template part<0,3>() = array[i]; |
|
66 |
|
if (texture_coord) |
|
67 |
|
result._[i].template part<3,2>() = |
|
68 |
|
detail::texture_coordinates::uv(array[i]); |
|
69 |
|
if (normals) |
|
70 |
|
result._[i].template part<N_OFFSET<texture_coord>,3>() = array[i]; |
|
71 |
|
} |
|
72 |
|
return result; |
|
73 |
|
} |
|
74 |
|
static_assert (vertices()._[0][0] != -1); |
|
75 |
|
|
|
76 |
|
struct indices { |
|
77 |
|
constexpr indices() = default; |
|
78 |
|
constexpr static index_t COUNT = INDEX_COUNT; |
|
79 |
|
|
|
80 |
|
index_t operator[](index_t i) const { return _[i]; } |
|
81 |
|
|
|
82 |
|
index_t _[COUNT]; |
|
83 |
|
}; |
|
84 |
|
constexpr static indices create_indices() { |
|
85 |
|
struct indices result{}; |
|
86 |
|
index_t array[indices::COUNT] = |
|
87 |
|
{ |
|
88 |
|
0, 11, 5, |
|
89 |
|
0, 5, 1, |
|
90 |
|
0, 1, 7, |
|
91 |
|
0, 7, 10, |
|
92 |
|
0, 10, 11, |
|
93 |
|
|
|
94 |
|
1, 5, 9, |
|
95 |
|
5, 11, 4, |
|
96 |
|
11, 10, 2, |
|
97 |
|
10, 7, 6, |
|
98 |
|
7, 1, 8, |
|
99 |
|
|
|
100 |
|
3, 9, 4, |
|
101 |
|
3, 4, 2, |
|
102 |
|
3, 2, 6, |
|
103 |
|
3, 6, 8, |
|
104 |
|
3, 8, 9, |
|
105 |
|
|
|
106 |
|
4, 9, 5, |
|
107 |
|
2, 4, 11, |
|
108 |
|
6, 2, 10, |
|
109 |
|
8, 6, 7, |
|
110 |
|
9, 8, 1 |
|
111 |
|
}; |
|
112 |
|
for (uint_fast8_t i = 0; i < indices::COUNT; ++i) |
|
113 |
|
result._[i] = array[i]; |
|
114 |
|
return result; |
|
115 |
|
} |
|
116 |
|
|
|
117 |
|
constexpr static vertices vertice = create_vertices(); |
|
118 |
|
constexpr static indices indice = create_indices(); |
|
119 |
|
}; |
|
120 |
|
|
|
121 |
|
TEMPLATE_ARGS |
|
122 |
|
constexpr static const |
|
123 |
|
Icosahedron<texture_coord, normals, floating_t, index_t> pre_compiled{}; |
|
124 |
|
} |
|
125 |
|
namespace mesh::icosahedron::build { |
|
126 |
|
TEMPLATE_ARGS |
|
127 |
|
[[nodiscard]] inline bool icosahedron(MESH_TEMPLATE *p_mesh) { |
|
128 |
|
using IH = Icosahedron<texture_coord,normals, floating_t, index_t>; |
|
129 |
|
|
|
130 |
|
if (not p_mesh->init(IH::vertices::COUNT, IH::indices::COUNT)) |
|
131 |
|
return false; |
|
132 |
|
|
|
133 |
|
constexpr IH icosahedron_data{}; |
|
134 |
|
index_t size = IH::vertices::COUNT * sizeof (IH::vector); |
|
135 |
|
memcpy(p_mesh->vertexes.p_array, &icosahedron_data.vertices, size); |
|
136 |
|
size = IH::indices::COUNT * sizeof (index_t); |
|
137 |
|
memcpy(p_mesh->indexes.p_array, &icosahedron_data.indices, size); |
|
138 |
|
return true; |
|
139 |
|
} |
153 |
140 |
} |
} |
154 |
141 |
|
|
155 |
142 |
#undef TEMPLATE_ARGS |
#undef TEMPLATE_ARGS |
File libs/mesh/polyhedron/icosahedron_quad.h changed (mode: 100644) (index a008c42..71e6f6a) |
6 |
6 |
#define TEMPLATE_ARGS template<bool texture_coord, bool normals, typename floating_t, typename index_t> |
#define TEMPLATE_ARGS template<bool texture_coord, bool normals, typename floating_t, typename index_t> |
7 |
7 |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
8 |
8 |
|
|
9 |
|
namespace mesh |
|
|
9 |
|
namespace mesh::icosahedron_quad |
10 |
10 |
{ |
{ |
11 |
|
namespace icosahedron_quad |
|
12 |
|
{ |
|
13 |
|
constexpr static const unsigned int COUNT = 10; |
|
14 |
|
|
|
15 |
|
template<typename floating_t = float, typename index_t = uint16_t> |
|
16 |
|
struct Quad |
|
17 |
|
{ |
|
18 |
|
constexpr static const floating_t phi = math::golden_ratio<floating_t>; |
|
19 |
|
|
|
20 |
|
constexpr static const index_t VERTEX_COUNT = 4; |
|
21 |
|
constexpr static const index_t INDEX_COUNT = 6; |
|
22 |
|
|
|
23 |
|
constexpr static const floating_t ANGLE_NEIGHBOUR_VERTICES = math::angle<floating_t>({ -1, phi, 0 }, |
|
24 |
|
{ 1, phi, 0 }); |
|
25 |
|
constexpr static const floating_t EDGE_LENGTH = gcem::sin(math::pi2<floating_t> / floating_t(5)); |
|
26 |
|
|
|
27 |
|
math::vec3<floating_t> vertices[VERTEX_COUNT]; |
|
28 |
|
index_t indices[INDEX_COUNT]; |
|
29 |
|
|
|
30 |
|
constexpr static const math::vec2<floating_t> TEXTURE_COORDINATES[VERTEX_COUNT] = { {0, 0}, {1, 0}, |
|
31 |
|
{0, 1}, {1, 1} }; |
|
32 |
|
}; |
|
33 |
|
|
|
34 |
|
template<typename floating_t> |
|
35 |
|
|
|
36 |
|
constexpr static const math::vec3<floating_t> vertices[12] = |
|
37 |
|
{ |
|
38 |
|
math::vec3<floating_t> { -1, Quad<floating_t>::phi, 0 }.normalize(), |
|
39 |
|
math::vec3<floating_t> { 1, Quad<floating_t>::phi, 0 }.normalize(), |
|
40 |
|
math::vec3<floating_t> { -1, -Quad<floating_t>::phi, 0 }.normalize(), |
|
41 |
|
math::vec3<floating_t> { 1, -Quad<floating_t>::phi, 0 }.normalize(), |
|
42 |
|
|
|
43 |
|
math::vec3<floating_t> { 0, -1, Quad<floating_t>::phi }.normalize(), |
|
44 |
|
math::vec3<floating_t> { 0, 1, Quad<floating_t>::phi }.normalize(), |
|
45 |
|
math::vec3<floating_t> { 0, -1, -Quad<floating_t>::phi }.normalize(), |
|
46 |
|
math::vec3<floating_t> { 0, 1, -Quad<floating_t>::phi }.normalize(), |
|
47 |
|
|
|
48 |
|
math::vec3<floating_t> { Quad<floating_t>::phi, 0, -1 }.normalize(), |
|
49 |
|
math::vec3<floating_t> { Quad<floating_t>::phi, 0, 1 }.normalize(), |
|
50 |
|
math::vec3<floating_t> { -Quad<floating_t>::phi, 0, -1 }.normalize(), |
|
51 |
|
math::vec3<floating_t> { -Quad<floating_t>::phi, 0, 1 }.normalize(), |
|
52 |
|
}; |
|
53 |
|
template<typename index_t> |
|
54 |
|
constexpr static const index_t indices[Quad<>::INDEX_COUNT] = { 0, 1, 2, 2, 1, 3 }; |
|
|
11 |
|
constexpr static const unsigned int COUNT = 10; |
|
12 |
|
|
|
13 |
|
template<typename floating_t = float, typename index_t = uint16_t> |
|
14 |
|
struct Quad |
|
15 |
|
{ |
|
16 |
|
constexpr static const floating_t phi = math::golden_ratio<floating_t>; |
|
17 |
|
|
|
18 |
|
constexpr static const index_t VERTEX_COUNT = 4; |
|
19 |
|
constexpr static const index_t INDEX_COUNT = 6; |
|
20 |
|
|
|
21 |
|
constexpr static const |
|
22 |
|
floating_t ANGLE_NEIGHBOUR_VERTICES = math::angle<floating_t>( |
|
23 |
|
{ -1, phi, 0 }, { 1, phi, 0 } |
|
24 |
|
); |
|
25 |
|
constexpr static const |
|
26 |
|
floating_t EDGE_LENGTH = gcem::sin(math::pi2<floating_t> / floating_t(5)); |
|
27 |
|
|
|
28 |
|
math::vec3<floating_t> vertices[VERTEX_COUNT]; |
|
29 |
|
index_t indices[INDEX_COUNT]; |
|
30 |
|
|
|
31 |
|
constexpr static const |
|
32 |
|
math::vec2<floating_t> TEXTURE_COORDINATES[VERTEX_COUNT] = { |
|
33 |
|
{0, 0}, {1, 0}, {0, 1}, {1, 1} |
|
34 |
|
}; |
|
35 |
|
}; |
|
36 |
|
|
|
37 |
|
template<typename floating_t> |
|
38 |
|
constexpr static const math::vec3<floating_t> vertices[12] = { |
|
39 |
|
math::vec3<floating_t> { -1, Quad<floating_t>::phi, 0 }.normalize(), |
|
40 |
|
math::vec3<floating_t> { 1, Quad<floating_t>::phi, 0 }.normalize(), |
|
41 |
|
math::vec3<floating_t> { -1, -Quad<floating_t>::phi, 0 }.normalize(), |
|
42 |
|
math::vec3<floating_t> { 1, -Quad<floating_t>::phi, 0 }.normalize(), |
|
43 |
|
|
|
44 |
|
math::vec3<floating_t> { 0, -1, Quad<floating_t>::phi }.normalize(), |
|
45 |
|
math::vec3<floating_t> { 0, 1, Quad<floating_t>::phi }.normalize(), |
|
46 |
|
math::vec3<floating_t> { 0, -1, -Quad<floating_t>::phi }.normalize(), |
|
47 |
|
math::vec3<floating_t> { 0, 1, -Quad<floating_t>::phi }.normalize(), |
|
48 |
|
|
|
49 |
|
math::vec3<floating_t> { Quad<floating_t>::phi, 0, -1 }.normalize(), |
|
50 |
|
math::vec3<floating_t> { Quad<floating_t>::phi, 0, 1 }.normalize(), |
|
51 |
|
math::vec3<floating_t> { -Quad<floating_t>::phi, 0, -1 }.normalize(), |
|
52 |
|
math::vec3<floating_t> { -Quad<floating_t>::phi, 0, 1 }.normalize(), |
|
53 |
|
}; |
|
54 |
|
|
|
55 |
|
template<typename index_t> |
|
56 |
|
constexpr static const |
|
57 |
|
index_t indices[Quad<>::INDEX_COUNT] = { 0, 1, 2, 2, 1, 3 }; |
55 |
58 |
|
|
56 |
59 |
|
|
57 |
60 |
#define VERTICES(i1,i2,i3,i4) { vertices<floating_t>[i1], vertices<floating_t>[i2], \ |
#define VERTICES(i1,i2,i3,i4) { vertices<floating_t>[i1], vertices<floating_t>[i2], \ |
|
... |
... |
namespace mesh |
61 |
64 |
indices<index_t>[2], indices<index_t>[3], \ |
indices<index_t>[2], indices<index_t>[3], \ |
62 |
65 |
indices<index_t>[4], indices<index_t>[5] } |
indices<index_t>[4], indices<index_t>[5] } |
63 |
66 |
|
|
64 |
|
template<typename floating_t, typename index_t = uint16_t> |
|
65 |
|
constexpr static const Quad<floating_t, index_t> quads[COUNT] = |
|
66 |
|
{ |
|
67 |
|
|
|
68 |
|
{ .vertices = VERTICES(0, 11, 5, 4), .indices = INDICES }, //0 |
|
69 |
|
{ .vertices = VERTICES(0, 5, 1, 9), .indices = INDICES }, |
|
70 |
|
{ .vertices = VERTICES(0, 1, 7, 8), .indices = INDICES }, //2 |
|
71 |
|
{ .vertices = VERTICES(0, 7, 10, 6), .indices = INDICES }, |
|
72 |
|
{ .vertices = VERTICES(0, 10, 11, 2), .indices = INDICES }, //4 |
|
73 |
|
{ .vertices = VERTICES(5, 4, 9, 3), .indices = INDICES }, |
|
74 |
|
{ .vertices = VERTICES(1, 9, 8, 3), .indices = INDICES }, //6 |
|
75 |
|
{ .vertices = VERTICES(7, 8, 6, 3), .indices = INDICES }, |
|
76 |
|
{ .vertices = VERTICES(10, 6, 2, 3), .indices = INDICES }, //8 |
|
77 |
|
{ .vertices = VERTICES(11, 2, 4, 3), .indices = INDICES } |
|
78 |
|
}; |
|
|
67 |
|
template<typename floating_t, typename index_t = uint16_t> |
|
68 |
|
constexpr static const Quad<floating_t, index_t> quads[COUNT] = { |
|
69 |
|
{ .vertices = VERTICES(0, 11, 5, 4), .indices = INDICES }, //0 |
|
70 |
|
{ .vertices = VERTICES(0, 5, 1, 9), .indices = INDICES }, |
|
71 |
|
{ .vertices = VERTICES(0, 1, 7, 8), .indices = INDICES }, //2 |
|
72 |
|
{ .vertices = VERTICES(0, 7, 10, 6), .indices = INDICES }, |
|
73 |
|
{ .vertices = VERTICES(0, 10, 11, 2), .indices = INDICES }, //4 |
|
74 |
|
{ .vertices = VERTICES(5, 4, 9, 3), .indices = INDICES }, |
|
75 |
|
{ .vertices = VERTICES(1, 9, 8, 3), .indices = INDICES }, //6 |
|
76 |
|
{ .vertices = VERTICES(7, 8, 6, 3), .indices = INDICES }, |
|
77 |
|
{ .vertices = VERTICES(10, 6, 2, 3), .indices = INDICES }, //8 |
|
78 |
|
{ .vertices = VERTICES(11, 2, 4, 3), .indices = INDICES } |
|
79 |
|
}; |
79 |
80 |
|
|
80 |
81 |
#undef VERTICES |
#undef VERTICES |
81 |
82 |
#undef INDICES |
#undef INDICES |
82 |
83 |
|
|
83 |
84 |
#define VERTICE(quad_i, ver_i) quads<floating_t>[quad_i].vertices[ver_i] |
#define VERTICE(quad_i, ver_i) quads<floating_t>[quad_i].vertices[ver_i] |
84 |
85 |
|
|
85 |
|
template<typename floating_t> |
|
86 |
|
constexpr static const math::vec3<floating_t> quads_diagonal[COUNT] = |
|
87 |
|
{ |
|
88 |
|
VERTICE(0,3) - VERTICE(0,0), |
|
89 |
|
VERTICE(1,3) - VERTICE(1,0), |
|
90 |
|
VERTICE(2,3) - VERTICE(2,0), |
|
91 |
|
VERTICE(3,3) - VERTICE(3,0), |
|
92 |
|
VERTICE(4,3) - VERTICE(4,0), |
|
93 |
|
VERTICE(5,3) - VERTICE(5,0), |
|
94 |
|
VERTICE(6,3) - VERTICE(6,0), |
|
95 |
|
VERTICE(7,3) - VERTICE(7,0), |
|
96 |
|
VERTICE(8,3) - VERTICE(8,0), |
|
97 |
|
VERTICE(9,3) - VERTICE(9,0), |
|
98 |
|
}; |
|
99 |
|
|
|
100 |
|
template<typename floating_t> |
|
101 |
|
constexpr static const math::vec3<floating_t> quads_horizontal[COUNT] = |
|
102 |
|
{ |
|
103 |
|
VERTICE(0,2) - VERTICE(0,1), |
|
104 |
|
VERTICE(1,2) - VERTICE(1,1), |
|
105 |
|
VERTICE(2,2) - VERTICE(2,1), |
|
106 |
|
VERTICE(3,2) - VERTICE(3,1), |
|
107 |
|
VERTICE(4,2) - VERTICE(4,1), |
|
108 |
|
VERTICE(5,2) - VERTICE(5,1), |
|
109 |
|
VERTICE(6,2) - VERTICE(6,1), |
|
110 |
|
VERTICE(7,2) - VERTICE(7,1), |
|
111 |
|
VERTICE(8,2) - VERTICE(8,1), |
|
112 |
|
VERTICE(9,2) - VERTICE(9,1), |
|
113 |
|
}; |
|
114 |
|
|
|
115 |
|
template<typename floating_t> |
|
116 |
|
constexpr static const math::vec3<floating_t> quads_height[COUNT] = //vector - diff between top and bottom |
|
117 |
|
{ |
|
118 |
|
medium(VERTICE(0,1), VERTICE(0,2)) - medium(VERTICE(0,0), VERTICE(0,3)), |
|
119 |
|
medium(VERTICE(1,1), VERTICE(1,2)) - medium(VERTICE(1,0), VERTICE(1,3)), |
|
120 |
|
medium(VERTICE(2,1), VERTICE(2,2)) - medium(VERTICE(2,0), VERTICE(2,3)), |
|
121 |
|
medium(VERTICE(3,1), VERTICE(3,2)) - medium(VERTICE(3,0), VERTICE(3,3)), |
|
122 |
|
medium(VERTICE(4,1), VERTICE(4,2)) - medium(VERTICE(4,0), VERTICE(4,3)), |
|
123 |
|
medium(VERTICE(5,1), VERTICE(5,2)) - medium(VERTICE(5,0), VERTICE(5,3)), |
|
124 |
|
medium(VERTICE(6,1), VERTICE(6,2)) - medium(VERTICE(6,0), VERTICE(6,3)), |
|
125 |
|
medium(VERTICE(7,1), VERTICE(7,2)) - medium(VERTICE(7,0), VERTICE(7,3)), |
|
126 |
|
medium(VERTICE(8,1), VERTICE(8,2)) - medium(VERTICE(8,0), VERTICE(8,3)), |
|
127 |
|
medium(VERTICE(9,1), VERTICE(9,2)) - medium(VERTICE(9,0), VERTICE(9,3)) |
|
128 |
|
}; |
|
129 |
|
|
|
130 |
|
namespace build |
|
131 |
|
{ |
|
132 |
|
TEMPLATE_ARGS |
|
133 |
|
|
|
134 |
|
[[nodiscard]] bool quad(unsigned int quad_index, MESH_TEMPLATE *p_mesh) |
|
135 |
|
{ |
|
136 |
|
using namespace math; |
|
137 |
|
using quad = icosahedron_quad::Quad<floating_t, index_t>; |
|
138 |
|
auto &quads_ = quads<floating_t, index_t>; |
|
139 |
|
|
|
140 |
|
if (not p_mesh->init(quad::VERTEX_COUNT, quad::INDEX_COUNT)) |
|
141 |
|
return false; |
|
142 |
|
|
|
143 |
|
auto &vertices = quads_[quad_index].vertices; |
|
144 |
|
for (index_t i = 0; i < quad::VERTEX_COUNT; ++i) |
|
145 |
|
{ |
|
146 |
|
setSubVector<0,3>(p_mesh->vertexes[i], vertices[i]); |
|
147 |
|
if (texture_coord) |
|
148 |
|
setSubVector<3,2>(p_mesh->vertexes[i], quad::TEXTURE_COORDINATES[i]); |
|
149 |
|
if (normals) |
|
150 |
|
setSubVector<N_OFFSET<texture_coord>,3>(p_mesh->vertexes[i], vertices[i]); |
|
151 |
|
} |
|
152 |
|
memcpy(p_mesh->indexes.p_array, quads_[quad_index].indices, sizeof (index_t) * quad::INDEX_COUNT); |
|
153 |
|
|
|
154 |
|
return true; |
|
155 |
|
} |
|
156 |
|
} |
|
157 |
|
|
|
158 |
|
template<typename T> |
|
159 |
|
struct rotations_t |
|
160 |
|
{ |
|
161 |
|
constexpr rotations_t() = default; |
|
162 |
|
math::matrix<3, 3, T> operator[](unsigned int i) const { return _[i]; } |
|
163 |
|
math::matrix<3, 3, T> _[COUNT]; |
|
164 |
|
}; |
|
165 |
|
|
|
166 |
|
template<typename T> |
|
167 |
|
constexpr math::matrix<3, 3, T> rotation(unsigned int quad_index) |
|
168 |
|
{ |
|
169 |
|
using namespace math; |
|
170 |
|
|
|
171 |
|
constexpr auto HALF_OF_COUNT = COUNT / 2; |
|
172 |
|
constexpr T single_angle = pi2<T> / T(HALF_OF_COUNT); |
|
173 |
|
if (quad_index < HALF_OF_COUNT) |
|
174 |
|
{ |
|
175 |
|
T angle = - T(quad_index) * single_angle; |
|
176 |
|
return rotation(vertices<T>[0], angle); |
|
177 |
|
} |
|
178 |
|
else |
|
179 |
|
{ |
|
180 |
|
constexpr auto& t = quads<T>[0].vertices[3]; |
|
181 |
|
constexpr auto& b = quads<T>[5].vertices[3]; |
|
182 |
|
constexpr T second_half_angle = angle(t,b); |
|
183 |
|
constexpr auto unit = cross(b,t).normalize(); |
|
184 |
|
|
|
185 |
|
T angle = single_angle * (T(HALF_OF_COUNT-1 - quad_index) - half<T>); |
|
186 |
|
return rotation(vertices<T>[0], angle) * rotation(unit, second_half_angle); |
|
187 |
|
} |
|
188 |
|
} |
|
189 |
|
|
|
190 |
|
template<typename T> constexpr |
|
191 |
|
rotations_t<T> create_rotations() |
|
192 |
|
{ |
|
193 |
|
rotations_t<T> r{}; |
|
194 |
|
for (unsigned int i = 0; i < COUNT; ++i) |
|
195 |
|
r._[i] = rotation<T>(i); |
|
196 |
|
return r; |
|
197 |
|
} |
|
198 |
|
template<typename floating_t> |
|
199 |
|
constexpr rotations_t rotations = create_rotations<floating_t>(); |
|
200 |
|
} |
|
|
86 |
|
template<typename floating_t> |
|
87 |
|
constexpr static const math::vec3<floating_t> quads_diagonal[COUNT] = |
|
88 |
|
{ |
|
89 |
|
VERTICE(0,3) - VERTICE(0,0), |
|
90 |
|
VERTICE(1,3) - VERTICE(1,0), |
|
91 |
|
VERTICE(2,3) - VERTICE(2,0), |
|
92 |
|
VERTICE(3,3) - VERTICE(3,0), |
|
93 |
|
VERTICE(4,3) - VERTICE(4,0), |
|
94 |
|
VERTICE(5,3) - VERTICE(5,0), |
|
95 |
|
VERTICE(6,3) - VERTICE(6,0), |
|
96 |
|
VERTICE(7,3) - VERTICE(7,0), |
|
97 |
|
VERTICE(8,3) - VERTICE(8,0), |
|
98 |
|
VERTICE(9,3) - VERTICE(9,0), |
|
99 |
|
}; |
|
100 |
|
|
|
101 |
|
template<typename floating_t> |
|
102 |
|
constexpr static const math::vec3<floating_t> quads_horizontal[COUNT] = |
|
103 |
|
{ |
|
104 |
|
VERTICE(0,2) - VERTICE(0,1), |
|
105 |
|
VERTICE(1,2) - VERTICE(1,1), |
|
106 |
|
VERTICE(2,2) - VERTICE(2,1), |
|
107 |
|
VERTICE(3,2) - VERTICE(3,1), |
|
108 |
|
VERTICE(4,2) - VERTICE(4,1), |
|
109 |
|
VERTICE(5,2) - VERTICE(5,1), |
|
110 |
|
VERTICE(6,2) - VERTICE(6,1), |
|
111 |
|
VERTICE(7,2) - VERTICE(7,1), |
|
112 |
|
VERTICE(8,2) - VERTICE(8,1), |
|
113 |
|
VERTICE(9,2) - VERTICE(9,1), |
|
114 |
|
}; |
|
115 |
|
|
|
116 |
|
template<typename floating_t> |
|
117 |
|
//vector - diff between top and bottom |
|
118 |
|
constexpr static const math::vec3<floating_t> quads_height[COUNT] = { |
|
119 |
|
medium(VERTICE(0,1), VERTICE(0,2)) - medium(VERTICE(0,0), VERTICE(0,3)), |
|
120 |
|
medium(VERTICE(1,1), VERTICE(1,2)) - medium(VERTICE(1,0), VERTICE(1,3)), |
|
121 |
|
medium(VERTICE(2,1), VERTICE(2,2)) - medium(VERTICE(2,0), VERTICE(2,3)), |
|
122 |
|
medium(VERTICE(3,1), VERTICE(3,2)) - medium(VERTICE(3,0), VERTICE(3,3)), |
|
123 |
|
medium(VERTICE(4,1), VERTICE(4,2)) - medium(VERTICE(4,0), VERTICE(4,3)), |
|
124 |
|
medium(VERTICE(5,1), VERTICE(5,2)) - medium(VERTICE(5,0), VERTICE(5,3)), |
|
125 |
|
medium(VERTICE(6,1), VERTICE(6,2)) - medium(VERTICE(6,0), VERTICE(6,3)), |
|
126 |
|
medium(VERTICE(7,1), VERTICE(7,2)) - medium(VERTICE(7,0), VERTICE(7,3)), |
|
127 |
|
medium(VERTICE(8,1), VERTICE(8,2)) - medium(VERTICE(8,0), VERTICE(8,3)), |
|
128 |
|
medium(VERTICE(9,1), VERTICE(9,2)) - medium(VERTICE(9,0), VERTICE(9,3)) |
|
129 |
|
}; |
|
130 |
|
} |
|
131 |
|
namespace mesh::icosahedron_quad::build |
|
132 |
|
{ |
|
133 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
134 |
|
bool |
|
135 |
|
quad(unsigned int quad_index, MESH_TEMPLATE *p_mesh) { |
|
136 |
|
using quad = icosahedron_quad::Quad<floating_t, index_t>; |
|
137 |
|
auto &quads_ = quads<floating_t, index_t>; |
|
138 |
|
|
|
139 |
|
if (not p_mesh->init(quad::VERTEX_COUNT, quad::INDEX_COUNT)) |
|
140 |
|
return false; |
|
141 |
|
|
|
142 |
|
auto &vertices = quads_[quad_index].vertices; |
|
143 |
|
for (index_t i = 0; i < quad::VERTEX_COUNT; ++i) { |
|
144 |
|
p_mesh->vertexes[i].template part<0,3>() = vertices[i]; |
|
145 |
|
if (texture_coord) |
|
146 |
|
p_mesh->vertexes[i].template part<3,2>() = quad::TEXTURE_COORDINATES[i]; |
|
147 |
|
if (normals) |
|
148 |
|
p_mesh->vertexes[i].template part<N_OFFSET<texture_coord>,3>() |
|
149 |
|
= vertices[i]; |
|
150 |
|
} |
|
151 |
|
memcpy(p_mesh->indexes.p_array, quads_[quad_index].indices, |
|
152 |
|
sizeof(index_t) * quad::INDEX_COUNT); |
|
153 |
|
return true; |
|
154 |
|
} |
|
155 |
|
} |
|
156 |
|
namespace mesh::icosahedron_quad |
|
157 |
|
{ |
|
158 |
|
template<typename T> struct rotations_t { |
|
159 |
|
constexpr rotations_t() = default; |
|
160 |
|
math::matrix<3, 3, T> operator[](unsigned int i) const { return _[i]; } |
|
161 |
|
math::matrix<3, 3, T> _[COUNT]; |
|
162 |
|
}; |
|
163 |
|
|
|
164 |
|
template<typename T> constexpr |
|
165 |
|
math::matrix<3, 3, T> |
|
166 |
|
rotation(unsigned int quad_index) { |
|
167 |
|
constexpr auto HALF_OF_COUNT = COUNT / 2; |
|
168 |
|
constexpr T single_angle = math::pi2<T> / T(HALF_OF_COUNT); |
|
169 |
|
if (quad_index < HALF_OF_COUNT) { |
|
170 |
|
T angle = - T(quad_index) * single_angle; |
|
171 |
|
return rotation(vertices<T>[0], angle); |
|
172 |
|
} |
|
173 |
|
else { |
|
174 |
|
constexpr auto& t = quads<T>[0].vertices[3]; |
|
175 |
|
constexpr auto& b = quads<T>[5].vertices[3]; |
|
176 |
|
constexpr T second_half_angle = angle(t,b); |
|
177 |
|
constexpr auto unit = cross(b,t).normalize(); |
|
178 |
|
|
|
179 |
|
T angle = single_angle |
|
180 |
|
* (T(HALF_OF_COUNT-1 - quad_index) - math::half<T>); |
|
181 |
|
return rotation(vertices<T>[0], angle) |
|
182 |
|
* rotation(unit, second_half_angle); |
|
183 |
|
} |
|
184 |
|
} |
|
185 |
|
|
|
186 |
|
template<typename T> constexpr |
|
187 |
|
rotations_t<T> |
|
188 |
|
create_rotations() { |
|
189 |
|
rotations_t<T> r{}; |
|
190 |
|
for (unsigned int i = 0; i < COUNT; ++i) |
|
191 |
|
r._[i] = rotation<T>(i); |
|
192 |
|
return r; |
|
193 |
|
} |
|
194 |
|
|
|
195 |
|
template<typename floating_t> constexpr |
|
196 |
|
rotations_t rotations = create_rotations<floating_t>(); |
201 |
197 |
} |
} |
202 |
198 |
|
|
203 |
199 |
#undef TEMPLATE_ARGS |
#undef TEMPLATE_ARGS |
File libs/mesh/polyhedron/icosahedron_quad_tesselated.h changed (mode: 100644) (index 4adb861..0a2bf24) |
1 |
1 |
#pragma once |
#pragma once |
2 |
2 |
#include "icosahedron_quad.h" |
#include "icosahedron_quad.h" |
3 |
3 |
|
|
4 |
|
#include "../../simd/simd.h" |
|
|
4 |
|
#include <simd/simd.h> |
|
5 |
|
#include <templates/tree/red_black_key.h> |
5 |
6 |
|
|
6 |
7 |
#define TEMPLATE_ARGS template<bool texture_coord, bool normals, typename floating_t, typename index_t> |
#define TEMPLATE_ARGS template<bool texture_coord, bool normals, typename floating_t, typename index_t> |
7 |
8 |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
8 |
9 |
|
|
9 |
|
namespace mesh |
|
|
10 |
|
namespace mesh::icosahedron_quad::QuadTesselated |
10 |
11 |
{ |
{ |
11 |
|
namespace icosahedron_quad |
|
12 |
|
{ |
|
13 |
|
namespace QuadTesselated |
|
14 |
|
{ |
|
15 |
|
constexpr static const unsigned int SUBDIVISIONS_MAX = 6; |
|
16 |
|
|
|
17 |
|
template<typename index_t> |
|
18 |
|
constexpr static index_t index_count(unsigned int subdivision_count) |
|
19 |
|
{ |
|
20 |
|
index_t index_count = 6; |
|
21 |
|
for (unsigned int i = 0; i < subdivision_count; ++i) |
|
22 |
|
index_count *= 4; |
|
23 |
|
return index_count; |
|
24 |
|
}; |
|
25 |
|
|
|
26 |
|
template<typename index_t> |
|
27 |
|
constexpr static const index_t VERTEX_COUNT[SUBDIVISIONS_MAX+1] |
|
28 |
|
{ |
|
29 |
|
4, 9, 25, 81, 289, 1089, 4225 |
|
30 |
|
}; |
|
31 |
|
} |
|
32 |
|
|
|
33 |
|
template<typename T> |
|
34 |
|
using floating_check = typename std::enable_if<std::is_floating_point<T>::value, math::vec3<T>>::type; |
|
35 |
|
|
|
36 |
|
|
|
37 |
|
template<typename T> |
|
38 |
|
[[nodiscard]] constexpr inline floating_check<T> quad_coordinate_to_real |
|
39 |
|
( |
|
40 |
|
unsigned int quad_i, |
|
41 |
|
|
|
42 |
|
T u, |
|
43 |
|
T v |
|
44 |
|
) |
|
45 |
|
{ using namespace math; |
|
46 |
|
|
|
47 |
|
T diagonal_ratio_2 = (u + v); |
|
48 |
|
T horizontal_ratio = (v - u) / two<T>; |
|
49 |
|
|
|
50 |
|
T up_ratio = diagonal_ratio_2 > one<T> |
|
51 |
|
? 2 - diagonal_ratio_2 |
|
52 |
|
: up_ratio = diagonal_ratio_2; |
|
53 |
|
|
|
54 |
|
auto dH = quads_horizontal<T>[quad_i] * horizontal_ratio; |
|
55 |
|
auto dD = quads_diagonal <T>[quad_i] * diagonal_ratio_2 / two<T>; |
|
56 |
|
auto dUP = quads_height <T>[quad_i] * up_ratio; |
|
57 |
|
return normalize(quads<T>[quad_i].vertices[0] + dH + dD + dUP); |
|
58 |
|
} |
|
59 |
|
|
|
60 |
|
|
|
61 |
|
template<simd::Level l> |
|
62 |
|
[[nodiscard]] inline math::vec3<simd::pfloat_simd<l>> |
|
63 |
|
quad_coordinate_to_real |
|
64 |
|
( |
|
65 |
|
unsigned int quad_i, |
|
66 |
|
|
|
67 |
|
simd::pfloat_simd<l> u, |
|
68 |
|
simd::pfloat_simd<l> v |
|
69 |
|
) |
|
70 |
|
{ using namespace math; using namespace simd; using pf = simd::pfloat_simd<l>; |
|
71 |
|
|
|
72 |
|
pf diagonal_ratio_x2 = (u + v); |
|
73 |
|
pf horizontal_ratio = (v - u) / pf(2.f); |
|
74 |
|
|
|
75 |
|
pf up_ratio = (pf(1.f) < diagonal_ratio_x2).blendv(diagonal_ratio_x2, pf(2.f) - diagonal_ratio_x2); |
|
76 |
|
|
|
77 |
|
auto horizontal = quads_horizontal<float>[quad_i]; |
|
78 |
|
auto diagonal = quads_diagonal <float>[quad_i]; |
|
79 |
|
auto up = quads_height <float>[quad_i]; |
|
80 |
|
auto main = quads <float>[quad_i].vertices[0]; |
|
81 |
|
|
|
82 |
|
pf diagonal_ratio = diagonal_ratio_x2 / pf(2.f); |
|
83 |
|
|
|
84 |
|
pf x = pf(main.x) + pf(up.x) * up_ratio |
|
85 |
|
+ pf(diagonal.x) * diagonal_ratio |
|
86 |
|
+ pf(horizontal.x) * horizontal_ratio; |
|
87 |
|
|
|
88 |
|
pf y = pf(main.y) + pf(up.y) * up_ratio |
|
89 |
|
+ pf(diagonal.y) * diagonal_ratio |
|
90 |
|
+ pf(horizontal.y) * horizontal_ratio; |
|
91 |
|
|
|
92 |
|
pf z = pf(main.z) + pf(up.z) * up_ratio |
|
93 |
|
+ pf(diagonal.z) * diagonal_ratio |
|
94 |
|
+ pf(horizontal.z) * horizontal_ratio; |
|
95 |
|
|
|
96 |
|
pf rsqrtdot = (x * x + y * y + z * z).rsqrt(); |
|
97 |
|
return vec3<pf>{x * rsqrtdot,y * rsqrtdot,z * rsqrtdot}; |
|
98 |
|
} |
|
99 |
|
|
|
100 |
|
namespace build |
|
101 |
|
{ |
|
102 |
|
namespace __hiden |
|
103 |
|
{ |
|
104 |
|
template<unsigned int vec_size, typename floating_t> |
|
105 |
|
[[nodiscard]] constexpr inline math::vector<vec_size, floating_t> middle_vertex |
|
106 |
|
( |
|
107 |
|
math::vector<vec_size, floating_t> vertex1, |
|
108 |
|
math::vector<vec_size, floating_t> vertex2 |
|
109 |
|
) |
|
110 |
|
{ using namespace math; |
|
111 |
|
|
|
112 |
|
auto result = medium(vertex1, vertex2); |
|
113 |
|
|
|
114 |
|
setSubVector<0,3>(result, normalize(subVector<0,3>(result))); |
|
115 |
|
|
|
116 |
|
return result; |
|
117 |
|
} |
|
118 |
|
} |
|
119 |
|
|
|
120 |
|
TEMPLATE_ARGS |
|
121 |
|
[[nodiscard]] bool quad_tesselated(unsigned int quad_index, unsigned int subdivision_count, |
|
122 |
|
MESH_TEMPLATE *p_mesh) |
|
123 |
|
{ |
|
124 |
|
using namespace math; using namespace __hiden; |
|
125 |
|
using quad = icosahedron_quad::Quad<floating_t, index_t>; |
|
126 |
|
const auto &quads_ = quads<floating_t, index_t>; |
|
127 |
|
void(*TREE_CB)(index_t, int) = [] (index_t, int) { jabort_release("duplicates must not exist"); }; |
|
128 |
|
|
|
129 |
|
jassert (subdivision_count <= QuadTesselated::SUBDIVISIONS_MAX, "incorrect subdivision value"); |
|
130 |
|
jassert (QuadTesselated::index_count<size_t>(subdivision_count) <= std::numeric_limits<index_t>::max(), |
|
131 |
|
"index value overflow"); |
|
132 |
|
|
|
133 |
|
index_t vertex_count = QuadTesselated::VERTEX_COUNT<index_t>[subdivision_count]; |
|
134 |
|
index_t index_count = QuadTesselated::index_count<index_t>(subdivision_count); |
|
135 |
|
|
|
136 |
|
|
|
137 |
|
if (not p_mesh->init(vertex_count, index_count)) |
|
138 |
|
return false; |
|
139 |
|
|
|
140 |
|
index_t *p_indices_src, *p_indices_dst = p_mesh->indexes.p_array; |
|
141 |
|
if (not allocate(p_indices_src, index_count)) |
|
142 |
|
{ |
|
143 |
|
p_mesh->destroy(); |
|
144 |
|
return false; |
|
145 |
|
} |
|
146 |
|
|
|
147 |
|
memcpy(p_indices_dst, quads_[quad_index].indices, sizeof (index_t) * quad::INDEX_COUNT); |
|
148 |
|
|
|
149 |
|
auto &vertices = quads_[quad_index].vertices; |
|
150 |
|
for (index_t i = 0; i < quad::VERTEX_COUNT; ++i) |
|
151 |
|
{ |
|
152 |
|
setSubVector<0,3>(p_mesh->vertexes[i], vertices[i]); |
|
153 |
|
if (texture_coord) |
|
154 |
|
setSubVector<3,2>(p_mesh->vertexes[i], quad::TEXTURE_COORDINATES[i]); |
|
155 |
|
if (normals) |
|
156 |
|
setSubVector<N_OFFSET<texture_coord>,3>(p_mesh->vertexes[i], vertices[i]); |
|
157 |
|
} |
|
158 |
|
memcpy(p_mesh->indexes.p_array, quads_[quad_index].indices, sizeof (index_t) * quad::INDEX_COUNT); |
|
159 |
|
|
|
160 |
|
//declarations |
|
161 |
|
index_t ind_middle_12, ind_middle_23, ind_middle_13; |
|
162 |
|
index_t index_i = quad::INDEX_COUNT; |
|
163 |
|
index_t vertex_i = quad::VERTEX_COUNT - 1; |
|
164 |
|
|
|
165 |
|
|
|
166 |
|
mtl::tree::red_black_keys<index_t, vec3<floating_t>> unique_vertices; |
|
167 |
|
unique_vertices.init(); |
|
168 |
|
|
|
169 |
|
for (unsigned int i = 0; i < subdivision_count; ++i) |
|
170 |
|
{ |
|
171 |
|
std::swap(p_indices_src, p_indices_dst); |
|
172 |
|
|
|
173 |
|
index_t p_index_count = index_i; |
|
174 |
|
index_i = 0; |
|
175 |
|
for (index_t j = 0; j < p_index_count; j += 3) |
|
176 |
|
{ |
|
177 |
|
auto vertex1 = p_mesh->vertexes[p_indices_src[j + 0]]; |
|
178 |
|
auto vertex2 = p_mesh->vertexes[p_indices_src[j + 1]]; |
|
179 |
|
auto vertex3 = p_mesh->vertexes[p_indices_src[j + 2]]; |
|
180 |
|
|
|
181 |
|
auto vec_middle_12 = middle_vertex(vertex1, vertex2); |
|
182 |
|
auto vec_middle_23 = middle_vertex(vertex2, vertex3); |
|
183 |
|
auto vec_middle_13 = middle_vertex(vertex1, vertex3); |
|
184 |
|
|
|
185 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_12), ind_middle_12)) |
|
186 |
|
{ |
|
187 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_12; |
|
188 |
|
ind_middle_12 = vertex_i; |
|
189 |
|
if (not unique_vertices.insert(ind_middle_12, subVector<0,3>(vec_middle_12), TREE_CB, 0)) |
|
190 |
|
goto CANCEL; |
|
191 |
|
} |
|
192 |
|
|
|
193 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_23), ind_middle_23)) |
|
194 |
|
{ |
|
195 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_23; |
|
196 |
|
ind_middle_23 = vertex_i; |
|
197 |
|
if (not unique_vertices.insert(ind_middle_23, subVector<0,3>(vec_middle_23), TREE_CB, 0)) |
|
198 |
|
goto CANCEL; |
|
199 |
|
} |
|
200 |
|
|
|
201 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_13), ind_middle_13)) |
|
202 |
|
{ |
|
203 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_13; |
|
204 |
|
ind_middle_13 = vertex_i; |
|
205 |
|
if (not unique_vertices.insert(ind_middle_13, subVector<0,3>(vec_middle_13), TREE_CB, 0)) |
|
206 |
|
goto CANCEL; |
|
207 |
|
} |
|
208 |
|
|
|
209 |
|
p_indices_dst[ index_i] = p_indices_src[j]; |
|
210 |
|
p_indices_dst[++index_i] = ind_middle_12; |
|
211 |
|
p_indices_dst[++index_i] = ind_middle_13; |
|
212 |
|
|
|
213 |
|
p_indices_dst[++index_i] = ind_middle_12; |
|
214 |
|
p_indices_dst[++index_i] = p_indices_src[j + 1]; |
|
215 |
|
p_indices_dst[++index_i] = ind_middle_23; |
|
216 |
|
|
|
217 |
|
p_indices_dst[++index_i] = ind_middle_13; |
|
218 |
|
p_indices_dst[++index_i] = ind_middle_23; |
|
219 |
|
p_indices_dst[++index_i] = p_indices_src[j + 2]; |
|
220 |
|
|
|
221 |
|
p_indices_dst[++index_i] = ind_middle_12; |
|
222 |
|
p_indices_dst[++index_i] = ind_middle_23; |
|
223 |
|
p_indices_dst[++index_i] = ind_middle_13; |
|
224 |
|
++index_i; |
|
225 |
|
} |
|
226 |
|
} |
|
227 |
|
jassert(index_i == index_count && vertex_i + 1 == vertex_count, "wrong result"); |
|
228 |
|
|
|
229 |
|
p_mesh->indexes.p_array = p_indices_dst; |
|
230 |
|
jl::deallocate(&p_indices_src); |
|
231 |
|
unique_vertices.destroy(); |
|
232 |
|
|
|
233 |
|
return true; |
|
234 |
|
|
|
235 |
|
CANCEL: jl::deallocate(&p_indices_src); |
|
236 |
|
p_mesh->destroy(); |
|
237 |
|
unique_vertices.destroy(); |
|
238 |
|
return false; |
|
239 |
|
} |
|
240 |
|
} |
|
241 |
|
} |
|
|
12 |
|
constexpr static const unsigned int SUBDIVISIONS_MAX = 6; |
|
13 |
|
|
|
14 |
|
template<typename index_t> constexpr static |
|
15 |
|
index_t index_count(unsigned int subdivision_count) { |
|
16 |
|
index_t index_count = 6; |
|
17 |
|
for (unsigned int i = 0; i < subdivision_count; ++i) |
|
18 |
|
index_count *= 4; |
|
19 |
|
return index_count; |
|
20 |
|
}; |
|
21 |
|
|
|
22 |
|
template<typename index_t> constexpr static const |
|
23 |
|
index_t VERTEX_COUNT[SUBDIVISIONS_MAX+1] { 4, 9, 25, 81, 289, 1089, 4225 }; |
|
24 |
|
} |
|
25 |
|
namespace mesh::icosahedron_quad |
|
26 |
|
{ |
|
27 |
|
template<typename T> |
|
28 |
|
using floating_check = typename |
|
29 |
|
std::enable_if<std::is_floating_point<T>::value, math::vec3<T>>::type; |
|
30 |
|
|
|
31 |
|
template<typename T> [[nodiscard]] constexpr inline |
|
32 |
|
floating_check<T> quad_coordinate_to_real(unsigned int quad_i, T u, T v) |
|
33 |
|
{ |
|
34 |
|
using namespace math; |
|
35 |
|
|
|
36 |
|
T diagonal_ratio_2 = (u + v); |
|
37 |
|
T horizontal_ratio = (v - u) / two<T>; |
|
38 |
|
|
|
39 |
|
T up_ratio = diagonal_ratio_2 > one<T> |
|
40 |
|
? 2 - diagonal_ratio_2 |
|
41 |
|
: up_ratio = diagonal_ratio_2; |
|
42 |
|
|
|
43 |
|
auto dH = quads_horizontal<T>[quad_i] * horizontal_ratio; |
|
44 |
|
auto dD = quads_diagonal <T>[quad_i] * diagonal_ratio_2 / two<T>; |
|
45 |
|
auto dUP = quads_height <T>[quad_i] * up_ratio; |
|
46 |
|
return normalize(quads<T>[quad_i].vertices[0] + dH + dD + dUP); |
|
47 |
|
} |
|
48 |
|
|
|
49 |
|
template<simd::Level l> [[nodiscard]] inline |
|
50 |
|
math::vec3<simd::pfloat_simd<l>> quad_coordinate_to_real( |
|
51 |
|
unsigned int quad_i, simd::pfloat_simd<l> u, simd::pfloat_simd<l> v) |
|
52 |
|
{ |
|
53 |
|
using namespace math; |
|
54 |
|
using namespace simd; |
|
55 |
|
using pf = simd::pfloat_simd<l>; |
|
56 |
|
|
|
57 |
|
pf diagonal_ratio_x2 = (u + v); |
|
58 |
|
pf horizontal_ratio = (v - u) / pf(2.f); |
|
59 |
|
|
|
60 |
|
pf up_ratio = (pf(1.f) < diagonal_ratio_x2) |
|
61 |
|
.blendv(diagonal_ratio_x2, pf(2.f) - diagonal_ratio_x2); |
|
62 |
|
|
|
63 |
|
auto horizontal = quads_horizontal<float>[quad_i]; |
|
64 |
|
auto diagonal = quads_diagonal <float>[quad_i]; |
|
65 |
|
auto up = quads_height <float>[quad_i]; |
|
66 |
|
auto main = quads <float>[quad_i].vertices[0]; |
|
67 |
|
|
|
68 |
|
pf diagonal_ratio = diagonal_ratio_x2 / pf(2.f); |
|
69 |
|
|
|
70 |
|
pf x = pf(main.x) + pf(up.x) * up_ratio |
|
71 |
|
+ pf(diagonal.x) * diagonal_ratio |
|
72 |
|
+ pf(horizontal.x) * horizontal_ratio; |
|
73 |
|
|
|
74 |
|
pf y = pf(main.y) + pf(up.y) * up_ratio |
|
75 |
|
+ pf(diagonal.y) * diagonal_ratio |
|
76 |
|
+ pf(horizontal.y) * horizontal_ratio; |
|
77 |
|
|
|
78 |
|
pf z = pf(main.z) + pf(up.z) * up_ratio |
|
79 |
|
+ pf(diagonal.z) * diagonal_ratio |
|
80 |
|
+ pf(horizontal.z) * horizontal_ratio; |
|
81 |
|
|
|
82 |
|
pf rsqrtdot = (x * x + y * y + z * z).rsqrt(); |
|
83 |
|
return vec3<pf>{x * rsqrtdot,y * rsqrtdot,z * rsqrtdot}; |
|
84 |
|
} |
|
85 |
|
} |
|
86 |
|
namespace mesh::icosahedron_quad::build::detail |
|
87 |
|
{ |
|
88 |
|
template<unsigned int vec_size, typename floating_t> [[nodiscard]] constexpr |
|
89 |
|
inline |
|
90 |
|
math::vector<vec_size, floating_t> middle_vertex( |
|
91 |
|
math::vector<vec_size, floating_t> vertex1, |
|
92 |
|
math::vector<vec_size, floating_t> vertex2) { |
|
93 |
|
auto result = math::medium(vertex1, vertex2); |
|
94 |
|
result.template part<0,3>().normalize(); |
|
95 |
|
return result; |
|
96 |
|
} |
|
97 |
|
} |
|
98 |
|
namespace mesh::icosahedron_quad::build |
|
99 |
|
{ |
|
100 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
101 |
|
bool quad_tesselated(unsigned int quad_index, unsigned int subdivision_count, |
|
102 |
|
MESH_TEMPLATE *p_mesh) |
|
103 |
|
{ |
|
104 |
|
using namespace math; |
|
105 |
|
using namespace detail; |
|
106 |
|
using quad = icosahedron_quad::Quad<floating_t, index_t>; |
|
107 |
|
const auto &quads_ = quads<floating_t, index_t>; |
|
108 |
|
void(*TREE_CB)(index_t, int) = [] (index_t, int) { |
|
109 |
|
jabort_release("duplicates must not exist"); |
|
110 |
|
}; |
|
111 |
|
|
|
112 |
|
jassert (subdivision_count <= QuadTesselated::SUBDIVISIONS_MAX, |
|
113 |
|
"incorrect subdivision value"); |
|
114 |
|
jassert (QuadTesselated::index_count<size_t>(subdivision_count) |
|
115 |
|
<= std::numeric_limits<index_t>::max(), |
|
116 |
|
"index value overflow"); |
|
117 |
|
|
|
118 |
|
index_t vcount = QuadTesselated::VERTEX_COUNT<index_t>[subdivision_count]; |
|
119 |
|
index_t icount = QuadTesselated::index_count<index_t>(subdivision_count); |
|
120 |
|
|
|
121 |
|
if (not p_mesh->init(vcount, icount)) |
|
122 |
|
return false; |
|
123 |
|
index_t *p_indices_src, *p_indices_dst = p_mesh->indexes.p_array; |
|
124 |
|
if (not allocate(p_indices_src, icount)) { |
|
125 |
|
p_mesh->destroy(); |
|
126 |
|
return false; |
|
127 |
|
} |
|
128 |
|
|
|
129 |
|
memcpy(p_indices_dst, |
|
130 |
|
quads_[quad_index].indices, |
|
131 |
|
sizeof (index_t) * quad::INDEX_COUNT); |
|
132 |
|
|
|
133 |
|
auto &vertices = quads_[quad_index].vertices; |
|
134 |
|
for (index_t i = 0; i < quad::VERTEX_COUNT; ++i) { |
|
135 |
|
auto &v = p_mesh->vertexes[i]; |
|
136 |
|
v.template part<0,3>() = vertices[i]; |
|
137 |
|
if (texture_coord) |
|
138 |
|
v.template part<3,2>() = quad::TEXTURE_COORDINATES[i]; |
|
139 |
|
if (normals) |
|
140 |
|
v.template part<N_OFFSET<texture_coord>,3>() = vertices[i]; |
|
141 |
|
} |
|
142 |
|
memcpy(p_mesh->indexes.p_array, |
|
143 |
|
quads_[quad_index].indices, |
|
144 |
|
sizeof (index_t) * quad::INDEX_COUNT); |
|
145 |
|
|
|
146 |
|
index_t ind_middle_12, ind_middle_23, ind_middle_13; |
|
147 |
|
index_t index_i = quad::INDEX_COUNT; |
|
148 |
|
index_t vertex_i = quad::VERTEX_COUNT - 1; |
|
149 |
|
|
|
150 |
|
mtl::tree::red_black_keys<index_t, vec3<floating_t>> unique_vertices; |
|
151 |
|
unique_vertices.init(); |
|
152 |
|
|
|
153 |
|
for (unsigned int i = 0; i < subdivision_count; ++i) { |
|
154 |
|
std::swap(p_indices_src, p_indices_dst); |
|
155 |
|
|
|
156 |
|
index_t p_index_count = index_i; |
|
157 |
|
index_i = 0; |
|
158 |
|
for (index_t j = 0; j < p_index_count; j += 3) |
|
159 |
|
{ |
|
160 |
|
auto vertex1 = p_mesh->vertexes[p_indices_src[j + 0]]; |
|
161 |
|
auto vertex2 = p_mesh->vertexes[p_indices_src[j + 1]]; |
|
162 |
|
auto vertex3 = p_mesh->vertexes[p_indices_src[j + 2]]; |
|
163 |
|
|
|
164 |
|
auto vec_middle_12 = middle_vertex(vertex1, vertex2); |
|
165 |
|
auto vec_middle_23 = middle_vertex(vertex2, vertex3); |
|
166 |
|
auto vec_middle_13 = middle_vertex(vertex1, vertex3); |
|
167 |
|
auto &v12_pos = vec_middle_12.template part<0,3>(); |
|
168 |
|
auto &v23_pos = vec_middle_23.template part<0,3>(); |
|
169 |
|
auto &v13_pos = vec_middle_13.template part<0,3>(); |
|
170 |
|
|
|
171 |
|
if (not unique_vertices.find(v12_pos, ind_middle_12)) { |
|
172 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_12; |
|
173 |
|
ind_middle_12 = vertex_i; |
|
174 |
|
if (not unique_vertices.insert(ind_middle_12, v12_pos, TREE_CB, 0)) |
|
175 |
|
goto CANCEL; |
|
176 |
|
} |
|
177 |
|
if (not unique_vertices.find(v23_pos, ind_middle_23)) { |
|
178 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_23; |
|
179 |
|
ind_middle_23 = vertex_i; |
|
180 |
|
if (not unique_vertices.insert(ind_middle_23, v23_pos, TREE_CB, 0)) |
|
181 |
|
goto CANCEL; |
|
182 |
|
} |
|
183 |
|
if (not unique_vertices.find(v13_pos, ind_middle_13)) { |
|
184 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_13; |
|
185 |
|
ind_middle_13 = vertex_i; |
|
186 |
|
if (not unique_vertices.insert(ind_middle_13, v13_pos, TREE_CB, 0)) |
|
187 |
|
goto CANCEL; |
|
188 |
|
} |
|
189 |
|
|
|
190 |
|
p_indices_dst[index_i++] = p_indices_src[j]; |
|
191 |
|
p_indices_dst[index_i++] = ind_middle_12; |
|
192 |
|
p_indices_dst[index_i++] = ind_middle_13; |
|
193 |
|
|
|
194 |
|
p_indices_dst[index_i++] = ind_middle_12; |
|
195 |
|
p_indices_dst[index_i++] = p_indices_src[j + 1]; |
|
196 |
|
p_indices_dst[index_i++] = ind_middle_23; |
|
197 |
|
|
|
198 |
|
p_indices_dst[index_i++] = ind_middle_13; |
|
199 |
|
p_indices_dst[index_i++] = ind_middle_23; |
|
200 |
|
p_indices_dst[index_i++] = p_indices_src[j + 2]; |
|
201 |
|
|
|
202 |
|
p_indices_dst[index_i++] = ind_middle_12; |
|
203 |
|
p_indices_dst[index_i++] = ind_middle_23; |
|
204 |
|
p_indices_dst[index_i++] = ind_middle_13; |
|
205 |
|
} |
|
206 |
|
} |
|
207 |
|
jassert(index_i == icount && vertex_i + 1 == vcount, "wrong result"); |
|
208 |
|
|
|
209 |
|
p_mesh->indexes.p_array = p_indices_dst; |
|
210 |
|
jl::deallocate(&p_indices_src); |
|
211 |
|
unique_vertices.destroy(); |
|
212 |
|
|
|
213 |
|
return true; |
|
214 |
|
|
|
215 |
|
CANCEL: |
|
216 |
|
jl::deallocate(&p_indices_src); |
|
217 |
|
p_mesh->destroy(); |
|
218 |
|
unique_vertices.destroy(); |
|
219 |
|
return false; |
|
220 |
|
} |
242 |
221 |
} |
} |
243 |
222 |
|
|
244 |
223 |
#undef TEMPLATE_ARGS |
#undef TEMPLATE_ARGS |
File libs/mesh/polyhedron/icosahedron_tesselated.h changed (mode: 100644) (index d025d88..931cb4d) |
7 |
7 |
#define TEMPLATE_ARGS template<CONDITION_ARGS, typename floating_t, typename index_t> |
#define TEMPLATE_ARGS template<CONDITION_ARGS, typename floating_t, typename index_t> |
8 |
8 |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
9 |
9 |
|
|
10 |
|
namespace mesh |
|
|
10 |
|
namespace mesh::icosahedron_tesselated::build |
11 |
11 |
{ |
{ |
12 |
|
namespace icosahedron_tesselated |
|
13 |
|
{ |
|
14 |
|
namespace build |
|
15 |
|
{ |
|
16 |
|
template<CONDITION_ARGS, unsigned int subdivision_count, |
|
17 |
|
typename floating_t, typename index_t, PF_ModifyVertex<floating_t>> |
|
18 |
|
|
|
19 |
|
[[nodiscard]] inline bool icosahedron_tesselated_constexpr(MESH_TEMPLATE *p_mesh); |
|
20 |
|
|
|
21 |
|
|
|
22 |
|
template<CONDITION_ARGS, typename floating_t, typename index_t> |
|
23 |
|
|
|
24 |
|
[[nodiscard]] bool icosahedron_tesselated(unsigned int subdivision_count, MESH_TEMPLATE *p_mesh); |
|
25 |
|
} |
|
26 |
|
|
|
27 |
|
namespace __hiden |
|
28 |
|
{ |
|
29 |
|
template<unsigned int vec_size, typename floating_t> |
|
30 |
|
[[nodiscard]] constexpr inline math::vector<vec_size, floating_t> middle_vector |
|
31 |
|
( |
|
32 |
|
math::vector<vec_size, floating_t> vertex1, |
|
33 |
|
math::vector<vec_size, floating_t> vertex2 |
|
34 |
|
) |
|
35 |
|
{ using namespace math; |
|
36 |
|
|
|
37 |
|
auto result = medium(vertex1, vertex2); |
|
38 |
|
|
|
39 |
|
setSubVector<0,3>(result, normalize(subVector<0,3>(result))); |
|
40 |
|
setSubVector<5,3>(result, subVector<0,3>(result)); |
|
41 |
|
if (vec_size > 3) |
|
42 |
|
setSubVector<3,2>(result, __texture_coordinates::uv(subVector<0,3>(result))); |
|
43 |
|
return result; |
|
44 |
|
} |
|
45 |
|
} |
|
46 |
|
|
|
47 |
|
namespace icosahedron_tesselated |
|
48 |
|
{ |
|
49 |
|
template<typename index_t> constexpr inline |
|
50 |
|
index_t triangle_count(unsigned int subdivision_count) |
|
51 |
|
{ |
|
52 |
|
index_t _scale = 1; |
|
53 |
|
for (index_t i = 0; i < subdivision_count; ++i) |
|
54 |
|
_scale *= 4; |
|
55 |
|
|
|
56 |
|
return _scale * index_t(icosahedron::FACE_COUNT); |
|
57 |
|
} |
|
58 |
|
|
|
59 |
|
template<typename index_t> constexpr inline |
|
60 |
|
index_t index_count(index_t triangle_count) |
|
61 |
|
{ |
|
62 |
|
return triangle_count * index_t(3); |
|
63 |
|
} |
|
64 |
|
|
|
65 |
|
template<typename index_t> constexpr inline |
|
66 |
|
index_t vertex_count(index_t triangle_count) |
|
67 |
|
{ |
|
68 |
|
return triangle_count / index_t(2) + index_t(2); |
|
69 |
|
} |
|
70 |
|
} |
|
71 |
|
|
|
72 |
|
namespace compile_time |
|
73 |
|
{ |
|
74 |
|
template<CONDITION_ARGS, unsigned int subdivision_count, typename floating_t, typename index_t> |
|
75 |
|
struct IcosahedronTesselated |
|
76 |
|
{ |
|
77 |
|
using Icosahedron = icosahedron::Icosahedron<ARGS>; |
|
78 |
|
using vertex = typename Icosahedron::vertex; |
|
79 |
|
|
|
80 |
|
constexpr static size_t index_count_needed() |
|
81 |
|
{ |
|
82 |
|
size_t _scale = 1; |
|
83 |
|
for (index_t i = 0; i < subdivision_count; ++i) |
|
84 |
|
_scale *= 4; |
|
85 |
|
return _scale * size_t(icosahedron::FACE_COUNT) * 3; |
|
86 |
|
} |
|
87 |
|
static_assert(index_count_needed() <= std::numeric_limits<index_t>::max()); |
|
88 |
|
|
|
89 |
|
constexpr static index_t index_count = index_t(index_count_needed()); |
|
90 |
|
constexpr static index_t triangle_count = index_count / index_t(3); |
|
91 |
|
constexpr static index_t vertex_count = triangle_count / index_t(2) + index_t(2); |
|
92 |
|
|
|
93 |
|
vertex vertices[vertex_count]; |
|
94 |
|
index_t indices[ index_count]; |
|
95 |
|
}; |
|
96 |
|
|
|
97 |
|
|
|
98 |
|
|
|
99 |
|
template<CONDITION_ARGS, unsigned int subdivision_count, typename floating_t, typename index_t, |
|
100 |
|
PF_ModifyVertex<floating_t> MODIFY> |
|
101 |
|
|
|
102 |
|
[[nodiscard]] constexpr IcosahedronTesselated<texture_coord,normals,subdivision_count,floating_t,index_t> |
|
103 |
|
icosahedron_tesselated_constexpr() |
|
104 |
|
{ |
|
105 |
|
using namespace math; |
|
106 |
|
using polyhedra = IcosahedronTesselated<texture_coord, normals, subdivision_count, floating_t, index_t>; |
|
107 |
|
polyhedra result{}; |
|
108 |
|
|
|
109 |
|
//prepare swap-indices arrays |
|
110 |
|
uint_fast8_t s_i = 0; //subdivision_index % 2 |
|
111 |
|
index_t indices[2][polyhedra::index_count]{}; |
|
112 |
|
|
|
113 |
|
//fill first indices |
|
114 |
|
for (uint_fast8_t i = 0; i < polyhedra::icosahedron::indices::COUNT; ++i) |
|
115 |
|
indices[0][i] = icosahedron::pre_compiled<ARGS>.indice._[i]; |
|
116 |
|
|
|
117 |
|
//fill first vertices |
|
118 |
|
for (uint_fast8_t i = 0; i < polyhedra::icosahedron::vertices::COUNT; ++i) |
|
119 |
|
result.vertices[i] = icosahedron::pre_compiled<ARGS>.vertice._[i]; |
|
120 |
|
index_t vertex_i = icosahedron::VERTEX_COUNT - 1; |
|
121 |
|
|
|
122 |
|
//declarations |
|
123 |
|
index_t ind_middle_12{}, ind_middle_23{}, ind_middle_13{}; |
|
124 |
|
|
|
125 |
|
using Value = index_t; |
|
126 |
|
using Key = vec3<floating_t>; |
|
127 |
|
using Index = index_t; |
|
128 |
|
auto &Size = polyhedra::vertex_count; |
|
129 |
|
mtl::compile_time::associative_array<Value, Key, Index, Size> unique_vertices{}; |
|
130 |
|
|
|
131 |
|
index_t index_i = icosahedron::INDEX_COUNT, p_index_count{}; |
|
132 |
|
|
|
133 |
|
for (unsigned int i = 0; i < subdivision_count; ++i) |
|
134 |
|
{ |
|
135 |
|
using namespace __hiden; |
|
136 |
|
|
|
137 |
|
p_index_count = index_i; |
|
138 |
|
index_i = 0; |
|
139 |
|
uint_fast8_t p_s_i = s_i; //previous s_i |
|
140 |
|
s_i = (s_i + 1) % 2; |
|
141 |
|
for (index_t j = 0; j < p_index_count; j += 3) |
|
142 |
|
{ |
|
143 |
|
auto vertex1 = result.vertices[indices[p_s_i][j + 0]]; |
|
144 |
|
auto vertex2 = result.vertices[indices[p_s_i][j + 1]]; |
|
145 |
|
auto vertex3 = result.vertices[indices[p_s_i][j + 2]]; |
|
146 |
|
|
|
147 |
|
auto vec_middle_12 = middle_vector<MODIFY>(vertex1, vertex2); |
|
148 |
|
auto vec_middle_23 = middle_vector<MODIFY>(vertex2, vertex3); |
|
149 |
|
auto vec_middle_13 = middle_vector<MODIFY>(vertex1, vertex3); |
|
150 |
|
|
|
151 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_12), ind_middle_12)) |
|
152 |
|
{ |
|
153 |
|
result.vertices[++vertex_i] = vec_middle_12; |
|
154 |
|
ind_middle_12 = vertex_i; |
|
155 |
|
unique_vertices.insert(ind_middle_12, subVector<0,3>(vec_middle_12)); |
|
156 |
|
} |
|
157 |
|
|
|
158 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_23), ind_middle_23)) |
|
159 |
|
{ |
|
160 |
|
result.vertices[++vertex_i] = vec_middle_23; |
|
161 |
|
ind_middle_23 = vertex_i; |
|
162 |
|
unique_vertices.insert(ind_middle_23, subVector<0,3>(vec_middle_23)); |
|
163 |
|
} |
|
164 |
|
|
|
165 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_13), ind_middle_13)) |
|
166 |
|
{ |
|
167 |
|
result.vertices[++vertex_i] = vec_middle_13; |
|
168 |
|
ind_middle_13 = vertex_i; |
|
169 |
|
unique_vertices.insert(ind_middle_13, subVector<0,3>(vec_middle_13)); |
|
170 |
|
}//true==true; |
|
171 |
|
|
|
172 |
|
indices[s_i][ index_i] = indices[p_s_i][j]; |
|
173 |
|
indices[s_i][++index_i] = ind_middle_12; |
|
174 |
|
indices[s_i][++index_i] = ind_middle_13; |
|
175 |
|
|
|
176 |
|
indices[s_i][++index_i] = ind_middle_12; |
|
177 |
|
indices[s_i][++index_i] = indices[p_s_i][j + 1]; |
|
178 |
|
indices[s_i][++index_i] = ind_middle_23; |
|
179 |
|
|
|
180 |
|
indices[s_i][++index_i] = ind_middle_13; |
|
181 |
|
indices[s_i][++index_i] = ind_middle_23; |
|
182 |
|
indices[s_i][++index_i] = indices[p_s_i][j + 2]; |
|
183 |
|
|
|
184 |
|
indices[s_i][++index_i] = ind_middle_12; |
|
185 |
|
indices[s_i][++index_i] = ind_middle_23; |
|
186 |
|
indices[s_i][++index_i] = ind_middle_13; |
|
187 |
|
++index_i; |
|
188 |
|
} |
|
189 |
|
} |
|
190 |
|
if (index_i != polyhedra::index_count) |
|
191 |
|
unique_vertices.error(); |
|
192 |
|
|
|
193 |
|
if (vertex_i + 1 != polyhedra::vertex_count) |
|
194 |
|
unique_vertices.error(); |
|
195 |
|
|
|
196 |
|
for (index_t i = 0; i < index_i; ++i) |
|
197 |
|
result.indices[i] = indices[s_i][i]; |
|
198 |
|
|
|
199 |
|
return result; |
|
200 |
|
} |
|
201 |
|
} |
|
202 |
|
template<CONDITION_ARGS, unsigned int subdivision_count = 0, |
|
203 |
|
typename floating_t = float, typename index_t = uint8_t, |
|
204 |
|
PF_ModifyVertex<floating_t> MODIFY = modify_vertex::dummy> |
|
205 |
|
|
|
206 |
|
constexpr static const auto pre_compiled = compile_time:: |
|
207 |
|
icosahedron_tesselated_constexpr<texture_coord, normals, subdivision_count, floating_t, index_t, MODIFY>(); |
|
208 |
|
|
|
209 |
|
namespace build |
|
210 |
|
{ |
|
211 |
|
|
|
212 |
|
template<CONDITION_ARGS, unsigned int subdivision_count, |
|
213 |
|
typename floating_t, typename index_t, PF_ModifyVertex<floating_t> MODIFY> |
|
214 |
|
|
|
215 |
|
[[nodiscard]] bool icosahedron_tesselated_constexpr(MESH_TEMPLATE *p_mesh) |
|
216 |
|
{ |
|
217 |
|
auto &compiled = pre_compiled<texture_coord,normals, subdivision_count, floating_t, index_t, MODIFY>; |
|
218 |
|
if (not p_mesh->init(compiled.vertex_count, compiled.index_count)) |
|
219 |
|
return false; |
|
220 |
|
|
|
221 |
|
index_t size = compiled.vertex_count * sizeof (*p_mesh->vertexes.p_array); |
|
222 |
|
memcpy(p_mesh->vertexes.p_array, &compiled.vertices, size); |
|
223 |
|
|
|
224 |
|
size = compiled.index_count * sizeof (index_t); |
|
225 |
|
memcpy(p_mesh->indexes.p_array, &compiled.indices, size); |
|
226 |
|
return true; |
|
227 |
|
} |
|
228 |
|
|
|
229 |
|
template<CONDITION_ARGS, typename floating_t, typename index_t> |
|
230 |
|
[[nodiscard]] bool icosahedron_tesselated(unsigned int subdivision_count, MESH_TEMPLATE *p_mesh) |
|
231 |
|
{ |
|
232 |
|
using namespace math; using namespace __hiden; |
|
233 |
|
void(*TREE_CB)(index_t, int) = [] (index_t, int) { jabort_release("duplicates must not exist"); }; |
|
234 |
|
{ |
|
235 |
|
size_t __triangle_count = icosahedron_tesselated::triangle_count<size_t>(subdivision_count); |
|
236 |
|
size_t __index_count = icosahedron_tesselated::index_count<size_t>(__triangle_count); |
|
237 |
|
jassert(__index_count <= std::numeric_limits<index_t>::max(), "index value overflow"); |
|
238 |
|
} |
|
239 |
|
index_t triangle_count = icosahedron_tesselated::triangle_count<index_t>(subdivision_count); |
|
240 |
|
index_t vertex_count = icosahedron_tesselated::vertex_count <index_t>(triangle_count), |
|
241 |
|
index_count = icosahedron_tesselated::index_count <index_t>(triangle_count); |
|
242 |
|
|
|
243 |
|
if (not p_mesh->init(vertex_count, index_count)) |
|
244 |
|
return false; |
|
245 |
|
|
|
246 |
|
//prepare swap-indices arrays |
|
247 |
|
index_t *p_indices_src, *p_indices_dst = p_mesh->indexes.begin(); |
|
248 |
|
if (not jl::allocate(&p_indices_src, index_count)) |
|
249 |
|
{ |
|
250 |
|
p_mesh->destroy(); |
|
251 |
|
return false; |
|
252 |
|
} |
|
253 |
|
|
|
254 |
|
//fill first indices |
|
255 |
|
for (uint_fast8_t i = 0; i < icosahedron::INDEX_COUNT; ++i) |
|
256 |
|
p_indices_dst[i] = icosahedron::pre_compiled<ARGS>.indice._[i]; |
|
257 |
|
|
|
258 |
|
//fill first vertices |
|
259 |
|
for (uint_fast8_t i = 0; i < icosahedron::VERTEX_COUNT; ++i) |
|
260 |
|
p_mesh->vertexes[i] = icosahedron::pre_compiled<ARGS>.vertice._[i]; |
|
261 |
|
|
|
262 |
|
//declarations |
|
263 |
|
index_t ind_middle_12, ind_middle_23, ind_middle_13; |
|
264 |
|
index_t index_i = icosahedron::INDEX_COUNT; |
|
265 |
|
index_t vertex_i = icosahedron::VERTEX_COUNT - 1; |
|
266 |
|
|
|
267 |
|
mtl::tree::red_black_keys<index_t, vec3<floating_t>> unique_vertices; unique_vertices.init(); |
|
268 |
|
|
|
269 |
|
for (unsigned int i = 0; i < subdivision_count; ++i) |
|
270 |
|
{ |
|
271 |
|
std::swap(p_indices_src, p_indices_dst); |
|
272 |
|
|
|
273 |
|
index_t p_index_count = index_i; |
|
274 |
|
index_i = 0; |
|
275 |
|
for (index_t j = 0; j < p_index_count; j += 3) |
|
276 |
|
{ |
|
277 |
|
auto vertex1 = p_mesh->vertexes[p_indices_src[j + 0]]; |
|
278 |
|
auto vertex2 = p_mesh->vertexes[p_indices_src[j + 1]]; |
|
279 |
|
auto vertex3 = p_mesh->vertexes[p_indices_src[j + 2]]; |
|
280 |
|
|
|
281 |
|
auto vec_middle_12 = middle_vector(vertex1, vertex2); |
|
282 |
|
auto vec_middle_23 = middle_vector(vertex2, vertex3); |
|
283 |
|
auto vec_middle_13 = middle_vector(vertex1, vertex3); |
|
284 |
|
|
|
285 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_12), ind_middle_12)) |
|
286 |
|
{ |
|
287 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_12; |
|
288 |
|
ind_middle_12 = vertex_i; |
|
289 |
|
if (not unique_vertices.insert(ind_middle_12, subVector<0,3>(vec_middle_12), TREE_CB, 0)) |
|
290 |
|
goto CANCEL; |
|
291 |
|
} |
|
292 |
|
|
|
293 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_23), ind_middle_23)) |
|
294 |
|
{ |
|
295 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_23; |
|
296 |
|
ind_middle_23 = vertex_i; |
|
297 |
|
if (not unique_vertices.insert(ind_middle_23, subVector<0,3>(vec_middle_23), TREE_CB, 0)) |
|
298 |
|
goto CANCEL; |
|
299 |
|
} |
|
300 |
|
|
|
301 |
|
if (not unique_vertices.find(subVector<0,3>(vec_middle_13), ind_middle_13)) |
|
302 |
|
{ |
|
303 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_13; |
|
304 |
|
ind_middle_13 = vertex_i; |
|
305 |
|
if (not unique_vertices.insert(ind_middle_13, subVector<0,3>(vec_middle_13), TREE_CB, 0)) |
|
306 |
|
goto CANCEL; |
|
307 |
|
} |
|
308 |
|
|
|
309 |
|
p_indices_dst[ index_i] = p_indices_src[j]; |
|
310 |
|
p_indices_dst[++index_i] = ind_middle_12; |
|
311 |
|
p_indices_dst[++index_i] = ind_middle_13; |
|
312 |
|
|
|
313 |
|
p_indices_dst[++index_i] = ind_middle_12; |
|
314 |
|
p_indices_dst[++index_i] = p_indices_src[j + 1]; |
|
315 |
|
p_indices_dst[++index_i] = ind_middle_23; |
|
316 |
|
|
|
317 |
|
p_indices_dst[++index_i] = ind_middle_13; |
|
318 |
|
p_indices_dst[++index_i] = ind_middle_23; |
|
319 |
|
p_indices_dst[++index_i] = p_indices_src[j + 2]; |
|
320 |
|
|
|
321 |
|
p_indices_dst[++index_i] = ind_middle_12; |
|
322 |
|
p_indices_dst[++index_i] = ind_middle_23; |
|
323 |
|
p_indices_dst[++index_i] = ind_middle_13; |
|
324 |
|
++index_i; |
|
325 |
|
} |
|
326 |
|
} |
|
327 |
|
jassert(index_i == index_count && vertex_i + 1 == vertex_count, "wrong result"); |
|
328 |
|
|
|
329 |
|
jl::deallocate(&p_indices_src); |
|
330 |
|
|
|
331 |
|
return true; |
|
332 |
|
|
|
333 |
|
CANCEL: jl::deallocate(&p_indices_src); |
|
334 |
|
jl::deallocate(&p_indices_dst); |
|
335 |
|
p_mesh->vertexes.destroy(); |
|
336 |
|
unique_vertices.destroy(); |
|
337 |
|
return false; |
|
338 |
|
} |
|
339 |
|
} |
|
340 |
|
} |
|
|
12 |
|
template<CONDITION_ARGS, unsigned int subdivision_count, |
|
13 |
|
typename floating_t, typename index_t, PF_ModifyVertex<floating_t>> |
|
14 |
|
[[nodiscard]] inline |
|
15 |
|
bool icosahedron_tesselated_constexpr(MESH_TEMPLATE *p_mesh); |
|
16 |
|
|
|
17 |
|
template<CONDITION_ARGS, typename floating_t, typename index_t> [[nodiscard]] |
|
18 |
|
bool icosahedron_tesselated(unsigned int subdivision_count, |
|
19 |
|
MESH_TEMPLATE *p_mesh); |
|
20 |
|
} |
|
21 |
|
namespace mesh::icosahedron_tesselated::detail |
|
22 |
|
{ |
|
23 |
|
template<unsigned int vec_size, typename floating_t> |
|
24 |
|
[[nodiscard]] constexpr inline |
|
25 |
|
math::vector<vec_size, floating_t> middle_vector( |
|
26 |
|
math::vector<vec_size, floating_t> vertex1, |
|
27 |
|
math::vector<vec_size, floating_t> vertex2) |
|
28 |
|
{ |
|
29 |
|
auto result = medium(vertex1, vertex2); |
|
30 |
|
result.template part<0,3>() = result.template part<0,3>.normalized(); |
|
31 |
|
result.template part<5,3>() = result.template part<0,3>(result); |
|
32 |
|
if (vec_size > 3) |
|
33 |
|
result.template part<3,2>() = |
|
34 |
|
mesh::detail::texture_coordinates::uv(result.template part<0,3>()); |
|
35 |
|
return result; |
|
36 |
|
} |
|
37 |
|
} |
|
38 |
|
|
|
39 |
|
namespace mesh::icosahedron_tesselated |
|
40 |
|
{ |
|
41 |
|
template<typename index_t> constexpr inline |
|
42 |
|
index_t triangle_count(unsigned int subdivision_count) { |
|
43 |
|
index_t _scale = 1; |
|
44 |
|
for (index_t i = 0; i < subdivision_count; ++i) |
|
45 |
|
_scale *= 4; |
|
46 |
|
return _scale * index_t(icosahedron::FACE_COUNT); |
|
47 |
|
} |
|
48 |
|
template<typename index_t> constexpr inline |
|
49 |
|
index_t index_count(index_t triangle_count) { |
|
50 |
|
return triangle_count * index_t(3); |
|
51 |
|
} |
|
52 |
|
template<typename index_t> constexpr inline |
|
53 |
|
index_t vertex_count(index_t triangle_count) { |
|
54 |
|
return triangle_count / index_t(2) + index_t(2); |
|
55 |
|
} |
|
56 |
|
} |
|
57 |
|
|
|
58 |
|
namespace mesh::icosahedron_tesselated::compile_time |
|
59 |
|
{ |
|
60 |
|
template<CONDITION_ARGS, unsigned int subdivision_count, |
|
61 |
|
typename floating_t, typename index_t> |
|
62 |
|
struct IcosahedronTesselated |
|
63 |
|
{ |
|
64 |
|
using Icosahedron = icosahedron::Icosahedron<ARGS>; |
|
65 |
|
using vertex = typename Icosahedron::vertex; |
|
66 |
|
|
|
67 |
|
constexpr static size_t index_count_needed() { |
|
68 |
|
size_t _scale = 1; |
|
69 |
|
for (index_t i = 0; i < subdivision_count; ++i) |
|
70 |
|
_scale *= 4; |
|
71 |
|
return _scale * size_t(icosahedron::FACE_COUNT) * 3; |
|
72 |
|
} |
|
73 |
|
static_assert(index_count_needed() <= std::numeric_limits<index_t>::max()); |
|
74 |
|
|
|
75 |
|
constexpr static const |
|
76 |
|
index_t index_count = index_t(index_count_needed()); |
|
77 |
|
constexpr static const |
|
78 |
|
index_t triangle_count = index_count / index_t(3); |
|
79 |
|
constexpr static const |
|
80 |
|
index_t vertex_count = triangle_count / index_t(2) + index_t(2); |
|
81 |
|
|
|
82 |
|
vertex vertices[vertex_count]; |
|
83 |
|
index_t indices[ index_count]; |
|
84 |
|
}; |
|
85 |
|
|
|
86 |
|
template<CONDITION_ARGS, unsigned int subdivision_count, |
|
87 |
|
typename floating_t, typename index_t, |
|
88 |
|
PF_ModifyVertex<floating_t> MODIFY> |
|
89 |
|
[[nodiscard]] constexpr |
|
90 |
|
IcosahedronTesselated<texture_coord,normals,subdivision_count,floating_t,index_t> |
|
91 |
|
icosahedron_tesselated_constexpr() { |
|
92 |
|
using namespace math; |
|
93 |
|
using polyhedra = IcosahedronTesselated<texture_coord, normals, subdivision_count, floating_t, index_t>; |
|
94 |
|
polyhedra result{}; |
|
95 |
|
|
|
96 |
|
//prepare swap-indices arrays |
|
97 |
|
uint_fast8_t s_i = 0; //subdivision_index % 2 |
|
98 |
|
index_t indices[2][polyhedra::index_count]{}; |
|
99 |
|
|
|
100 |
|
//fill first indices |
|
101 |
|
for (uint_fast8_t i = 0; i < polyhedra::icosahedron::indices::COUNT; ++i) |
|
102 |
|
indices[0][i] = icosahedron::pre_compiled<ARGS>.indice._[i]; |
|
103 |
|
|
|
104 |
|
//fill first vertices |
|
105 |
|
for (uint_fast8_t i = 0; i < polyhedra::icosahedron::vertices::COUNT; ++i) |
|
106 |
|
result.vertices[i] = icosahedron::pre_compiled<ARGS>.vertice._[i]; |
|
107 |
|
index_t vertex_i = icosahedron::VERTEX_COUNT - 1; |
|
108 |
|
|
|
109 |
|
//declarations |
|
110 |
|
index_t ind_middle_12{}, ind_middle_23{}, ind_middle_13{}; |
|
111 |
|
|
|
112 |
|
using Value = index_t; |
|
113 |
|
using Key = vec3<floating_t>; |
|
114 |
|
using Index = index_t; |
|
115 |
|
auto &Size = polyhedra::vertex_count; |
|
116 |
|
mtl::compile_time::associative_array<Value, Key, Index, Size> unique_vertices{}; |
|
117 |
|
|
|
118 |
|
index_t index_i = icosahedron::INDEX_COUNT, p_index_count{}; |
|
119 |
|
|
|
120 |
|
for (unsigned int i = 0; i < subdivision_count; ++i) |
|
121 |
|
{ |
|
122 |
|
using namespace detail; |
|
123 |
|
|
|
124 |
|
p_index_count = index_i; |
|
125 |
|
index_i = 0; |
|
126 |
|
uint_fast8_t p_s_i = s_i; //previous s_i |
|
127 |
|
s_i = (s_i + 1) % 2; |
|
128 |
|
for (index_t j = 0; j < p_index_count; j += 3) |
|
129 |
|
{ |
|
130 |
|
auto vertex1 = result.vertices[indices[p_s_i][j + 0]]; |
|
131 |
|
auto vertex2 = result.vertices[indices[p_s_i][j + 1]]; |
|
132 |
|
auto vertex3 = result.vertices[indices[p_s_i][j + 2]]; |
|
133 |
|
|
|
134 |
|
auto vec_middle_12 = middle_vector<MODIFY>(vertex1, vertex2); |
|
135 |
|
auto vec_middle_23 = middle_vector<MODIFY>(vertex2, vertex3); |
|
136 |
|
auto vec_middle_13 = middle_vector<MODIFY>(vertex1, vertex3); |
|
137 |
|
|
|
138 |
|
auto &v12_pos = vec_middle_12.template part<0,3>(); |
|
139 |
|
if (not unique_vertices.find(v12_pos, ind_middle_12)) { |
|
140 |
|
result.vertices[++vertex_i] = vec_middle_12; |
|
141 |
|
ind_middle_12 = vertex_i; |
|
142 |
|
unique_vertices.insert(ind_middle_12, v12_pos); |
|
143 |
|
} |
|
144 |
|
auto &v23_pos = vec_middle_23.template part<0,3>(); |
|
145 |
|
if (not unique_vertices.find(v23_pos, ind_middle_23)) { |
|
146 |
|
result.vertices[++vertex_i] = vec_middle_23; |
|
147 |
|
ind_middle_23 = vertex_i; |
|
148 |
|
unique_vertices.insert(ind_middle_23, v23_pos); |
|
149 |
|
} |
|
150 |
|
auto &v13_pos = vec_middle_13.template part<0,3>(); |
|
151 |
|
if (not unique_vertices.find(v13_pos, ind_middle_13)) { |
|
152 |
|
result.vertices[++vertex_i] = vec_middle_13; |
|
153 |
|
ind_middle_13 = vertex_i; |
|
154 |
|
unique_vertices.insert(ind_middle_13, v13_pos); |
|
155 |
|
} |
|
156 |
|
|
|
157 |
|
indices[s_i][index_i++] = indices[p_s_i][j]; |
|
158 |
|
indices[s_i][index_i++] = ind_middle_12; |
|
159 |
|
indices[s_i][index_i++] = ind_middle_13; |
|
160 |
|
|
|
161 |
|
indices[s_i][index_i++] = ind_middle_12; |
|
162 |
|
indices[s_i][index_i++] = indices[p_s_i][j + 1]; |
|
163 |
|
indices[s_i][index_i++] = ind_middle_23; |
|
164 |
|
|
|
165 |
|
indices[s_i][index_i++] = ind_middle_13; |
|
166 |
|
indices[s_i][index_i++] = ind_middle_23; |
|
167 |
|
indices[s_i][index_i++] = indices[p_s_i][j + 2]; |
|
168 |
|
|
|
169 |
|
indices[s_i][index_i++] = ind_middle_12; |
|
170 |
|
indices[s_i][index_i++] = ind_middle_23; |
|
171 |
|
indices[s_i][index_i++] = ind_middle_13; |
|
172 |
|
} |
|
173 |
|
} |
|
174 |
|
if (index_i != polyhedra::index_count) |
|
175 |
|
unique_vertices.error(); |
|
176 |
|
if (vertex_i + 1 != polyhedra::vertex_count) |
|
177 |
|
unique_vertices.error(); |
|
178 |
|
for (index_t i = 0; i < index_i; ++i) |
|
179 |
|
result.indices[i] = indices[s_i][i]; |
|
180 |
|
return result; |
|
181 |
|
} |
|
182 |
|
} |
|
183 |
|
namespace mesh::icosahedron_tesselated { |
|
184 |
|
template<CONDITION_ARGS, unsigned int subdivision_count = 0, |
|
185 |
|
typename floating_t = float, typename index_t = uint8_t, |
|
186 |
|
PF_ModifyVertex<floating_t> MODIFY = modify_vertex::dummy> |
|
187 |
|
constexpr static const |
|
188 |
|
auto pre_compiled = compile_time::icosahedron_tesselated_constexpr<texture_coord, normals, subdivision_count, floating_t, index_t, MODIFY>(); |
|
189 |
|
} |
|
190 |
|
namespace mesh::icosahedron_tesselated::build |
|
191 |
|
{ |
|
192 |
|
template<CONDITION_ARGS, unsigned int subdivision_count, |
|
193 |
|
typename floating_t, typename index_t, |
|
194 |
|
PF_ModifyVertex<floating_t> MODIFY> [[nodiscard]] |
|
195 |
|
bool icosahedron_tesselated_constexpr(MESH_TEMPLATE *p_mesh) { |
|
196 |
|
auto &compiled = pre_compiled<texture_coord,normals, subdivision_count, |
|
197 |
|
floating_t, index_t, MODIFY>; |
|
198 |
|
if (not p_mesh->init(compiled.vertex_count, compiled.index_count)) |
|
199 |
|
return false; |
|
200 |
|
|
|
201 |
|
index_t size = compiled.vertex_count * sizeof (*p_mesh->vertexes.p_array); |
|
202 |
|
memcpy(p_mesh->vertexes.p_array, &compiled.vertices, size); |
|
203 |
|
|
|
204 |
|
size = compiled.index_count * sizeof (index_t); |
|
205 |
|
memcpy(p_mesh->indexes.p_array, &compiled.indices, size); |
|
206 |
|
return true; |
|
207 |
|
} |
|
208 |
|
|
|
209 |
|
template<CONDITION_ARGS, typename floating_t, typename index_t> [[nodiscard]] |
|
210 |
|
bool |
|
211 |
|
icosahedron_tesselated(unsigned int subdivision_count, MESH_TEMPLATE *p_mesh) |
|
212 |
|
{ |
|
213 |
|
using namespace math; |
|
214 |
|
using namespace detail; |
|
215 |
|
|
|
216 |
|
void(*TREE_CB)(index_t, int) = [] (index_t, int) { |
|
217 |
|
jabort_release("duplicates must not exist"); |
|
218 |
|
}; |
|
219 |
|
{ |
|
220 |
|
size_t triangle_count = icosahedron_tesselated:: |
|
221 |
|
triangle_count<size_t>(subdivision_count); |
|
222 |
|
size_t icount = icosahedron_tesselated:: |
|
223 |
|
index_count<size_t>(triangle_count); |
|
224 |
|
jassert(icount <= std::numeric_limits<index_t>::max(), |
|
225 |
|
"index value overflow"); |
|
226 |
|
} |
|
227 |
|
index_t triangle_count = icosahedron_tesselated:: |
|
228 |
|
triangle_count<index_t>(subdivision_count); |
|
229 |
|
index_t vertex_count = icosahedron_tesselated:: |
|
230 |
|
vertex_count <index_t>(triangle_count); |
|
231 |
|
index_t index_count = icosahedron_tesselated:: |
|
232 |
|
index_count <index_t>(triangle_count); |
|
233 |
|
|
|
234 |
|
if (not p_mesh->init(vertex_count, index_count)) |
|
235 |
|
return false; |
|
236 |
|
|
|
237 |
|
//prepare swap-indices arrays |
|
238 |
|
index_t *p_indices_src, *p_indices_dst = p_mesh->indexes.begin(); |
|
239 |
|
if (not jl::allocate(&p_indices_src, index_count)) { |
|
240 |
|
p_mesh->destroy(); |
|
241 |
|
return false; |
|
242 |
|
} |
|
243 |
|
|
|
244 |
|
//fill first indices |
|
245 |
|
for (uint_fast8_t i = 0; i < icosahedron::INDEX_COUNT; ++i) |
|
246 |
|
p_indices_dst[i] = icosahedron::pre_compiled<ARGS>.indice._[i]; |
|
247 |
|
|
|
248 |
|
//fill first vertices |
|
249 |
|
for (uint_fast8_t i = 0; i < icosahedron::VERTEX_COUNT; ++i) |
|
250 |
|
p_mesh->vertexes[i] = icosahedron::pre_compiled<ARGS>.vertice._[i]; |
|
251 |
|
|
|
252 |
|
//declarations |
|
253 |
|
index_t ind_middle_12, ind_middle_23, ind_middle_13; |
|
254 |
|
index_t index_i = icosahedron::INDEX_COUNT; |
|
255 |
|
index_t vertex_i = icosahedron::VERTEX_COUNT - 1; |
|
256 |
|
|
|
257 |
|
mtl::tree::red_black_keys<index_t, vec3<floating_t>> unique_vertices; unique_vertices.init(); |
|
258 |
|
|
|
259 |
|
for (unsigned int i = 0; i < subdivision_count; ++i) |
|
260 |
|
{ |
|
261 |
|
std::swap(p_indices_src, p_indices_dst); |
|
262 |
|
|
|
263 |
|
index_t p_index_count = index_i; |
|
264 |
|
index_i = 0; |
|
265 |
|
for (index_t j = 0; j < p_index_count; j += 3) |
|
266 |
|
{ |
|
267 |
|
auto vertex1 = p_mesh->vertexes[p_indices_src[j + 0]]; |
|
268 |
|
auto vertex2 = p_mesh->vertexes[p_indices_src[j + 1]]; |
|
269 |
|
auto vertex3 = p_mesh->vertexes[p_indices_src[j + 2]]; |
|
270 |
|
|
|
271 |
|
auto vec_middle_12 = middle_vector(vertex1, vertex2); |
|
272 |
|
auto vec_middle_23 = middle_vector(vertex2, vertex3); |
|
273 |
|
auto vec_middle_13 = middle_vector(vertex1, vertex3); |
|
274 |
|
auto &v12_pos = vec_middle_12.template part<0,3>(); |
|
275 |
|
auto &v23_pos = vec_middle_23.template part<0,3>(); |
|
276 |
|
auto &v13_pos = vec_middle_13.template part<0,3>(); |
|
277 |
|
|
|
278 |
|
if (not unique_vertices.find(v12_pos, ind_middle_12)) { |
|
279 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_12; |
|
280 |
|
ind_middle_12 = vertex_i; |
|
281 |
|
if (not unique_vertices.insert(ind_middle_12, v12_pos, TREE_CB, 0)) |
|
282 |
|
goto CANCEL; |
|
283 |
|
} |
|
284 |
|
if (not unique_vertices.find(v23_pos, ind_middle_23)) { |
|
285 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_23; |
|
286 |
|
ind_middle_23 = vertex_i; |
|
287 |
|
if (not unique_vertices.insert(ind_middle_23, v23_pos, TREE_CB, 0)) |
|
288 |
|
goto CANCEL; |
|
289 |
|
} |
|
290 |
|
if (not unique_vertices.find(v13_pos, ind_middle_13)) { |
|
291 |
|
p_mesh->vertexes[++vertex_i] = vec_middle_13; |
|
292 |
|
ind_middle_13 = vertex_i; |
|
293 |
|
if (not unique_vertices.insert(ind_middle_13, v13_pos, TREE_CB, 0)) |
|
294 |
|
goto CANCEL; |
|
295 |
|
} |
|
296 |
|
|
|
297 |
|
p_indices_dst[index_i++] = p_indices_src[j]; |
|
298 |
|
p_indices_dst[index_i++] = ind_middle_12; |
|
299 |
|
p_indices_dst[index_i++] = ind_middle_13; |
|
300 |
|
|
|
301 |
|
p_indices_dst[index_i++] = ind_middle_12; |
|
302 |
|
p_indices_dst[index_i++] = p_indices_src[j + 1]; |
|
303 |
|
p_indices_dst[index_i++] = ind_middle_23; |
|
304 |
|
|
|
305 |
|
p_indices_dst[index_i++] = ind_middle_13; |
|
306 |
|
p_indices_dst[index_i++] = ind_middle_23; |
|
307 |
|
p_indices_dst[index_i++] = p_indices_src[j + 2]; |
|
308 |
|
|
|
309 |
|
p_indices_dst[index_i++] = ind_middle_12; |
|
310 |
|
p_indices_dst[index_i++] = ind_middle_23; |
|
311 |
|
p_indices_dst[index_i++] = ind_middle_13; |
|
312 |
|
} |
|
313 |
|
} |
|
314 |
|
jassert(index_i == index_count and vertex_i + 1 == vertex_count, |
|
315 |
|
"wrong result"); |
|
316 |
|
jl::deallocate(&p_indices_src); |
|
317 |
|
return true; |
|
318 |
|
|
|
319 |
|
CANCEL: |
|
320 |
|
jl::deallocate(&p_indices_src); |
|
321 |
|
jl::deallocate(&p_indices_dst); |
|
322 |
|
p_mesh->vertexes.destroy(); |
|
323 |
|
unique_vertices.destroy(); |
|
324 |
|
return false; |
|
325 |
|
} |
341 |
326 |
} |
} |
342 |
327 |
|
|
343 |
328 |
#undef CONDITION_ARGS |
#undef CONDITION_ARGS |
File libs/mesh/sphere.h changed (mode: 100644) (index b200cc4..e735d2e) |
4 |
4 |
#include "cube.h" |
#include "cube.h" |
5 |
5 |
#include "polyhedron/icosahedron_tesselated.h" |
#include "polyhedron/icosahedron_tesselated.h" |
6 |
6 |
#include <limits> |
#include <limits> |
|
7 |
|
#include <math/coordinates/coordinates.h> |
7 |
8 |
|
|
8 |
9 |
#define TEMPLATE_ARGS template<bool texture_coord, bool normals, typename floating_t, typename index_t> |
#define TEMPLATE_ARGS template<bool texture_coord, bool normals, typename floating_t, typename index_t> |
9 |
10 |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
#define MESH_TEMPLATE Mesh_T<texture_coord, normals, floating_t, index_t> |
10 |
11 |
|
|
11 |
|
namespace mesh |
|
|
12 |
|
namespace mesh::sphere::build |
12 |
13 |
{ |
{ |
13 |
|
namespace sphere |
|
14 |
|
{ |
|
15 |
|
namespace build |
|
16 |
|
{ |
|
17 |
|
|
|
18 |
|
TEMPLATE_ARGS |
|
19 |
|
[[nodiscard]] bool uv(index_t parallels_count, index_t meridians_count, floating_t radius, |
|
20 |
|
MESH_TEMPLATE *p_mesh); |
|
21 |
|
|
|
22 |
|
TEMPLATE_ARGS |
|
23 |
|
[[nodiscard]] inline bool cube_normalized(index_t edge_cell_count, floating_t edge_size, |
|
24 |
|
MESH_TEMPLATE *p_mesh); |
|
25 |
|
|
|
26 |
|
TEMPLATE_ARGS |
|
27 |
|
[[nodiscard]] inline bool cube_spherified(index_t edge_vertex_count, floating_t edge_size, |
|
28 |
|
MESH_TEMPLATE *p_mesh); |
|
29 |
|
|
|
30 |
|
TEMPLATE_ARGS |
|
31 |
|
[[nodiscard]] inline bool icosahedron_tesselated(unsigned int subdivision_count, MESH_TEMPLATE *p_mesh); |
|
32 |
|
} |
|
33 |
|
} |
|
|
14 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
15 |
|
bool |
|
16 |
|
uv(index_t parallels_count, index_t meridians_count, floating_t radius, |
|
17 |
|
MESH_TEMPLATE *p_mesh); |
|
18 |
|
|
|
19 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
20 |
|
bool |
|
21 |
|
cube_normalized(index_t edge_cell_count, floating_t edge_size, |
|
22 |
|
MESH_TEMPLATE *p_mesh); |
|
23 |
|
|
|
24 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
25 |
|
bool |
|
26 |
|
cube_spherified(index_t edge_vertex_count, floating_t edge_size, |
|
27 |
|
MESH_TEMPLATE *p_mesh); |
|
28 |
|
|
|
29 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
30 |
|
bool |
|
31 |
|
icosahedron_tesselated(unsigned int subdivision_count, MESH_TEMPLATE *p_mesh); |
34 |
32 |
} |
} |
35 |
33 |
|
|
36 |
|
namespace mesh |
|
|
34 |
|
namespace mesh::sphere::build::detail |
37 |
35 |
{ |
{ |
38 |
|
namespace sphere |
|
39 |
|
{ |
|
40 |
|
namespace build |
|
41 |
|
{ |
|
42 |
|
namespace __hiden |
|
43 |
|
{ |
|
44 |
|
template<unsigned int vec_size, typename floating_t> |
|
45 |
|
void set_texture_coordinate |
|
46 |
|
( |
|
47 |
|
math::vector<vec_size, floating_t> &vertex, |
|
48 |
|
floating_t u, |
|
49 |
|
floating_t v |
|
50 |
|
) |
|
51 |
|
{ using namespace math; |
|
52 |
|
|
|
53 |
|
if (vec_size == 5) |
|
54 |
|
setSubVector<3,2>(vertex, vec2<floating_t>{ v, u }); |
|
55 |
|
} |
|
56 |
|
} |
|
57 |
|
|
|
58 |
|
TEMPLATE_ARGS |
|
59 |
|
[[nodiscard]] bool uv(index_t parallels_count, index_t meridians_count, floating_t radius, |
|
60 |
|
MESH_TEMPLATE *p_mesh) |
|
61 |
|
{ |
|
62 |
|
using namespace math; |
|
63 |
|
static_assert(std::is_floating_point<floating_t>::value); |
|
64 |
|
using namespace __hiden; |
|
|
36 |
|
template<unsigned int vec_size, typename floating_t> |
|
37 |
|
void |
|
38 |
|
set_texture_coordinate(math::vector<vec_size, floating_t> &vertex, |
|
39 |
|
floating_t u, floating_t v) { |
|
40 |
|
if (vec_size == 5) |
|
41 |
|
vertex.template part<3,2>() = math::vec2<floating_t>{ v, u }; |
|
42 |
|
} |
|
43 |
|
} |
|
44 |
|
namespace mesh::sphere::build |
|
45 |
|
{ |
|
46 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
47 |
|
bool |
|
48 |
|
uv(index_t parallels_count, index_t meridians_count, floating_t radius, |
|
49 |
|
MESH_TEMPLATE *p_mesh) |
|
50 |
|
{ |
|
51 |
|
using namespace math; |
|
52 |
|
static_assert(std::is_floating_point<floating_t>::value); |
|
53 |
|
using namespace detail; |
65 |
54 |
#ifndef NDEBUG |
#ifndef NDEBUG |
66 |
|
fassert(size_t(parallels_count) * size_t(meridians_count) * 6 < std::numeric_limits<index_t>::max(), |
|
67 |
|
"index overflow"); |
|
|
55 |
|
fassert(size_t(parallels_count) * size_t(meridians_count) * 6 |
|
56 |
|
< std::numeric_limits<index_t>::max(), |
|
57 |
|
"index overflow"); |
68 |
58 |
#endif |
#endif |
69 |
|
index_t vertexCount = parallels_count * (meridians_count+1); |
|
70 |
|
if (not p_mesh->init(vertexCount, (parallels_count - 2) * (meridians_count + 1) * 6)) |
|
71 |
|
return false; |
|
72 |
|
|
|
73 |
|
math::coordinates::spherical_3D<floating_t> spherical_pos = { .radius = radius }; |
|
74 |
|
|
|
75 |
|
floating_t x_ratio, y_ratio; |
|
76 |
|
floating_t x_ratio_diff = math::cast<floating_t>(1) / (parallels_count - 1); |
|
77 |
|
floating_t y_ratio_diff = math::cast<floating_t>(1) / meridians_count; |
|
78 |
|
index_t indexIndex = 0, vertexIndex = 0; |
|
79 |
|
index_t vertexIndexNextRow = meridians_count; |
|
80 |
|
|
|
81 |
|
x_ratio = 0; |
|
82 |
|
y_ratio = 0; |
|
83 |
|
for (index_t y = 0; y < meridians_count; ++y, y_ratio += y_ratio_diff) |
|
84 |
|
{ |
|
85 |
|
spherical_pos.azimuth = pi2<floating_t> * y_ratio; |
|
86 |
|
|
|
87 |
|
p_mesh->indexes[ indexIndex] = vertexIndexNextRow; |
|
88 |
|
p_mesh->indexes[++indexIndex] = vertexIndex; |
|
89 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
90 |
|
++indexIndex; |
|
91 |
|
|
|
92 |
|
setSubVector<0,3>(p_mesh->vertexes[vertexIndex], spherical_pos.to_cartesian()); |
|
93 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
94 |
|
} |
|
95 |
|
y_ratio = 1; |
|
96 |
|
spherical_pos.azimuth = 0; |
|
97 |
|
|
|
98 |
|
p_mesh->indexes[ indexIndex] = vertexIndexNextRow; |
|
99 |
|
p_mesh->indexes[++indexIndex] = vertexIndex; |
|
100 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
101 |
|
++indexIndex; |
|
102 |
|
|
|
103 |
|
setSubVector<0,3>(p_mesh->vertexes[vertexIndex], spherical_pos.to_cartesian()); |
|
104 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
105 |
|
x_ratio += x_ratio_diff; |
|
106 |
|
|
|
107 |
|
for(index_t x = 1; x < parallels_count - 2; ++x, x_ratio += x_ratio_diff) |
|
108 |
|
{ |
|
109 |
|
spherical_pos.inclination = pi<floating_t> * x_ratio; |
|
110 |
|
y_ratio = 0; |
|
111 |
|
for (index_t y = 0; y < meridians_count; ++y, y_ratio += y_ratio_diff) |
|
112 |
|
{ |
|
113 |
|
spherical_pos.azimuth = pi2<floating_t> * y_ratio; |
|
114 |
|
|
|
115 |
|
p_mesh->indexes[ indexIndex] = vertexIndex; |
|
116 |
|
p_mesh->indexes[++indexIndex] = vertexIndex + 1; |
|
117 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
118 |
|
p_mesh->indexes[++indexIndex] = vertexIndexNextRow; |
|
119 |
|
p_mesh->indexes[++indexIndex] = vertexIndexNextRow - 1; |
|
120 |
|
p_mesh->indexes[++indexIndex] = vertexIndex; |
|
121 |
|
++indexIndex; |
|
122 |
|
|
|
123 |
|
setSubVector<0,3>(p_mesh->vertexes[vertexIndex], spherical_pos.to_cartesian()); |
|
124 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
125 |
|
} |
|
126 |
|
y_ratio = 1; |
|
127 |
|
spherical_pos.azimuth = 0; |
|
128 |
|
|
|
129 |
|
p_mesh->indexes[ indexIndex] = vertexIndex; |
|
130 |
|
p_mesh->indexes[++indexIndex] = vertexIndex + 1; |
|
131 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
132 |
|
p_mesh->indexes[++indexIndex] = vertexIndexNextRow; |
|
133 |
|
p_mesh->indexes[++indexIndex] = vertexIndexNextRow - 1; |
|
134 |
|
p_mesh->indexes[++indexIndex] = vertexIndex; |
|
135 |
|
++indexIndex; |
|
136 |
|
|
|
137 |
|
setSubVector<0,3>(p_mesh->vertexes[vertexIndex], spherical_pos.to_cartesian()); |
|
138 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
139 |
|
} |
|
140 |
|
{ |
|
141 |
|
spherical_pos.inclination = pi<floating_t> * x_ratio; |
|
142 |
|
y_ratio = 0; |
|
143 |
|
for (index_t y = 0; y < meridians_count; ++y, y_ratio += y_ratio_diff) |
|
144 |
|
{ |
|
145 |
|
spherical_pos.azimuth = pi2<floating_t> * y_ratio; |
|
146 |
|
|
|
147 |
|
p_mesh->indexes[ indexIndex] = vertexIndex; |
|
148 |
|
p_mesh->indexes[++indexIndex] = vertexIndex + 1; |
|
149 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
150 |
|
++indexIndex; |
|
151 |
|
|
|
152 |
|
setSubVector<0,3>(p_mesh->vertexes[vertexIndex], spherical_pos.to_cartesian()); |
|
153 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
154 |
|
} |
|
155 |
|
y_ratio = 1; |
|
156 |
|
spherical_pos.azimuth = 0; |
|
157 |
|
|
|
158 |
|
p_mesh->indexes[ indexIndex] = vertexIndex; |
|
159 |
|
p_mesh->indexes[++indexIndex] = vertexIndex + 1; |
|
160 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
161 |
|
++indexIndex; |
|
162 |
|
|
|
163 |
|
setSubVector<0,3>(p_mesh->vertexes[vertexIndex], spherical_pos.to_cartesian()); |
|
164 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
165 |
|
} |
|
166 |
|
x_ratio = 1; |
|
167 |
|
spherical_pos.inclination = pi<floating_t>; |
|
168 |
|
y_ratio = 0; |
|
169 |
|
for (index_t y = 0; y < meridians_count; ++y, y_ratio += y_ratio_diff) |
|
170 |
|
{ |
|
171 |
|
spherical_pos.azimuth = pi2<floating_t> * y_ratio; |
|
172 |
|
|
|
173 |
|
setSubVector<0,3>(p_mesh->vertexes[vertexIndex], spherical_pos.to_cartesian()); |
|
174 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
175 |
|
} |
|
176 |
|
y_ratio = 1; |
|
177 |
|
spherical_pos.azimuth = 0; |
|
178 |
|
setSubVector<0,3>(p_mesh->vertexes[vertexIndex], spherical_pos.to_cartesian()); |
|
179 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex], x_ratio, y_ratio); |
|
180 |
|
return true; |
|
181 |
|
} |
|
182 |
|
|
|
183 |
|
|
|
184 |
|
TEMPLATE_ARGS |
|
185 |
|
[[nodiscard]] inline bool cube_normalized(index_t edge_cell_count, floating_t edge_size, |
|
186 |
|
MESH_TEMPLATE *p_mesh) |
|
187 |
|
{ |
|
188 |
|
return cube::build::tesselated<texture_coord, normals, floating_t, index_t, |
|
189 |
|
modify_vertex::normalize> |
|
190 |
|
(p_mesh, edge_cell_count, edge_size); |
|
191 |
|
} |
|
192 |
|
|
|
193 |
|
TEMPLATE_ARGS |
|
194 |
|
[[nodiscard]] inline bool cube_spherified(index_t edge_vertex_count, floating_t edge_size, |
|
195 |
|
MESH_TEMPLATE *p_mesh) |
|
196 |
|
{ |
|
197 |
|
return cube::build::tesselated<texture_coord, normals, floating_t, index_t, |
|
198 |
|
modify_vertex::spheriy_vertex> |
|
199 |
|
(p_mesh, edge_vertex_count, edge_size); |
|
200 |
|
} |
|
201 |
|
|
|
202 |
|
TEMPLATE_ARGS |
|
203 |
|
[[nodiscard]] inline bool icosahedron_tesselated(unsigned int subdivision_count, MESH_TEMPLATE *p_mesh) |
|
204 |
|
{ |
|
205 |
|
return icosahedron_tesselated::build::icosahedron_tesselated<texture_coord, floating_t, index_t> |
|
206 |
|
(p_mesh, subdivision_count); |
|
207 |
|
} |
|
208 |
|
} |
|
209 |
|
} |
|
|
59 |
|
index_t vertexCount = parallels_count * (meridians_count+1); |
|
60 |
|
if (not p_mesh->init(vertexCount, (parallels_count - 2) * (meridians_count + 1) * 6)) |
|
61 |
|
return false; |
|
62 |
|
|
|
63 |
|
math::coordinates::spherical_3D<floating_t> spherical_pos = { |
|
64 |
|
.radius = radius |
|
65 |
|
}; |
|
66 |
|
|
|
67 |
|
floating_t x_ratio, y_ratio; |
|
68 |
|
floating_t x_ratio_diff = math::cast<floating_t>(1) / (parallels_count - 1); |
|
69 |
|
floating_t y_ratio_diff = math::cast<floating_t>(1) / meridians_count; |
|
70 |
|
index_t indexIndex = 0, vertexIndex = 0; |
|
71 |
|
index_t vertexIndexNextRow = meridians_count; |
|
72 |
|
|
|
73 |
|
x_ratio = 0; |
|
74 |
|
y_ratio = 0; |
|
75 |
|
for (index_t y = 0; y < meridians_count; ++y, y_ratio += y_ratio_diff) { |
|
76 |
|
spherical_pos.azimuth = pi2<floating_t> * y_ratio; |
|
77 |
|
|
|
78 |
|
p_mesh->indexes[ indexIndex] = vertexIndexNextRow; |
|
79 |
|
p_mesh->indexes[++indexIndex] = vertexIndex; |
|
80 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
81 |
|
++indexIndex; |
|
82 |
|
|
|
83 |
|
p_mesh->vertexes[vertexIndex].template part<0,3>() = |
|
84 |
|
spherical_pos.to_cartesian(); |
|
85 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
86 |
|
} |
|
87 |
|
y_ratio = 1; |
|
88 |
|
spherical_pos.azimuth = 0; |
|
89 |
|
|
|
90 |
|
p_mesh->indexes[ indexIndex] = vertexIndexNextRow; |
|
91 |
|
p_mesh->indexes[++indexIndex] = vertexIndex; |
|
92 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
93 |
|
++indexIndex; |
|
94 |
|
|
|
95 |
|
p_mesh->vertexes[vertexIndex].template part<0,3>() = |
|
96 |
|
spherical_pos.to_cartesian(); |
|
97 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
98 |
|
x_ratio += x_ratio_diff; |
|
99 |
|
|
|
100 |
|
for(index_t x = 1; x < parallels_count - 2; ++x, x_ratio += x_ratio_diff) |
|
101 |
|
{ |
|
102 |
|
spherical_pos.inclination = pi<floating_t> * x_ratio; |
|
103 |
|
y_ratio = 0; |
|
104 |
|
for (index_t y = 0; y < meridians_count; ++y, y_ratio += y_ratio_diff) |
|
105 |
|
{ |
|
106 |
|
spherical_pos.azimuth = pi2<floating_t> * y_ratio; |
|
107 |
|
|
|
108 |
|
p_mesh->indexes[ indexIndex] = vertexIndex; |
|
109 |
|
p_mesh->indexes[++indexIndex] = vertexIndex + 1; |
|
110 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
111 |
|
p_mesh->indexes[++indexIndex] = vertexIndexNextRow; |
|
112 |
|
p_mesh->indexes[++indexIndex] = vertexIndexNextRow - 1; |
|
113 |
|
p_mesh->indexes[++indexIndex] = vertexIndex; |
|
114 |
|
++indexIndex; |
|
115 |
|
|
|
116 |
|
p_mesh->vertexes[vertexIndex].template part<0,3>() = |
|
117 |
|
spherical_pos.to_cartesian(); |
|
118 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
119 |
|
} |
|
120 |
|
y_ratio = 1; |
|
121 |
|
spherical_pos.azimuth = 0; |
|
122 |
|
|
|
123 |
|
p_mesh->indexes[ indexIndex] = vertexIndex; |
|
124 |
|
p_mesh->indexes[++indexIndex] = vertexIndex + 1; |
|
125 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
126 |
|
p_mesh->indexes[++indexIndex] = vertexIndexNextRow; |
|
127 |
|
p_mesh->indexes[++indexIndex] = vertexIndexNextRow - 1; |
|
128 |
|
p_mesh->indexes[++indexIndex] = vertexIndex; |
|
129 |
|
++indexIndex; |
|
130 |
|
|
|
131 |
|
p_mesh->vertexes[vertexIndex].template part<0,3>() = |
|
132 |
|
spherical_pos.to_cartesian(); |
|
133 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
134 |
|
} |
|
135 |
|
{ |
|
136 |
|
spherical_pos.inclination = pi<floating_t> * x_ratio; |
|
137 |
|
y_ratio = 0; |
|
138 |
|
for (index_t y = 0; y < meridians_count; ++y, y_ratio += y_ratio_diff) |
|
139 |
|
{ |
|
140 |
|
spherical_pos.azimuth = pi2<floating_t> * y_ratio; |
|
141 |
|
|
|
142 |
|
p_mesh->indexes[ indexIndex] = vertexIndex; |
|
143 |
|
p_mesh->indexes[++indexIndex] = vertexIndex + 1; |
|
144 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
145 |
|
++indexIndex; |
|
146 |
|
|
|
147 |
|
p_mesh->vertexes[vertexIndex].template part<0,3>() = |
|
148 |
|
spherical_pos.to_cartesian(); |
|
149 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
150 |
|
} |
|
151 |
|
y_ratio = 1; |
|
152 |
|
spherical_pos.azimuth = 0; |
|
153 |
|
|
|
154 |
|
p_mesh->indexes[ indexIndex] = vertexIndex; |
|
155 |
|
p_mesh->indexes[++indexIndex] = vertexIndex + 1; |
|
156 |
|
p_mesh->indexes[++indexIndex] = ++vertexIndexNextRow; |
|
157 |
|
++indexIndex; |
|
158 |
|
|
|
159 |
|
p_mesh->vertexes[vertexIndex].template part<0,3>() = |
|
160 |
|
spherical_pos.to_cartesian(); |
|
161 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
162 |
|
} |
|
163 |
|
x_ratio = 1; |
|
164 |
|
spherical_pos.inclination = pi<floating_t>; |
|
165 |
|
y_ratio = 0; |
|
166 |
|
for (index_t y = 0; y < meridians_count; ++y, y_ratio += y_ratio_diff) |
|
167 |
|
{ |
|
168 |
|
spherical_pos.azimuth = pi2<floating_t> * y_ratio; |
|
169 |
|
|
|
170 |
|
p_mesh->vertexes[vertexIndex].template part<0,3>() = |
|
171 |
|
spherical_pos.to_cartesian(); |
|
172 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex++], x_ratio, y_ratio); |
|
173 |
|
} |
|
174 |
|
y_ratio = 1; |
|
175 |
|
spherical_pos.azimuth = 0; |
|
176 |
|
p_mesh->vertexes[vertexIndex].template part<0,3>() = |
|
177 |
|
spherical_pos.to_cartesian(); |
|
178 |
|
set_texture_coordinate(p_mesh->vertexes[vertexIndex], x_ratio, y_ratio); |
|
179 |
|
return true; |
|
180 |
|
} |
|
181 |
|
|
|
182 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
183 |
|
bool |
|
184 |
|
cube_normalized(index_t edge_cell_count, floating_t edge_size, |
|
185 |
|
MESH_TEMPLATE *p_mesh) { |
|
186 |
|
return cube::build::tesselated<texture_coord, normals, floating_t, index_t, |
|
187 |
|
modify_vertex::normalize>(p_mesh, edge_cell_count, edge_size); |
|
188 |
|
} |
|
189 |
|
|
|
190 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
191 |
|
bool |
|
192 |
|
cube_spherified(index_t edge_vertex_count, floating_t edge_size, |
|
193 |
|
MESH_TEMPLATE *p_mesh) { |
|
194 |
|
return cube::build::tesselated<texture_coord, normals, floating_t, index_t, |
|
195 |
|
modify_vertex::spheriy_vertex>(p_mesh, edge_vertex_count, edge_size); |
|
196 |
|
} |
|
197 |
|
|
|
198 |
|
TEMPLATE_ARGS [[nodiscard]] |
|
199 |
|
bool |
|
200 |
|
icosahedron_tesselated(unsigned int subdivision_count, |
|
201 |
|
MESH_TEMPLATE *p_mesh) { |
|
202 |
|
return icosahedron_tesselated::build:: |
|
203 |
|
icosahedron_tesselated<texture_coord, floating_t, index_t> |
|
204 |
|
(p_mesh, subdivision_count); |
|
205 |
|
} |
210 |
206 |
} |
} |
211 |
207 |
|
|
212 |
208 |
#undef TEMPLATE_ARGS |
#undef TEMPLATE_ARGS |