81{
83 const double max_sq = max_edge_length * max_edge_length;
84 const size_t tri_count = indices.size() / 3;
85 const bool have_canon = !verts.
canon.empty();
86
87
88
89 const size_t expect = std::max<size_t>(size_t(1) << 16, tri_count);
92
93
94
95 const auto key_of = [&](
int v) -> int64_t {
return have_canon ? verts.
canon[size_t(v)] : v; };
96 const auto mark_edge = [&](int a, int b) {
97 const int64_t u = key_of(a), v = key_of(b);
98 if (u < v) split_edges.get_or_set_key(u, v, 0, 1);
99 else split_edges.get_or_set_key(v, u, 0, 1);
100 };
101 const auto is_marked = [&](int a, int b) {
102 const int64_t u = key_of(a), v = key_of(b);
103 return (u < v ? split_edges.get_key(u, v, 0) : split_edges.get_key(v, u, 0)) != -1;
104 };
105
106
107
108
109
110 const auto too_long = [&](int a, int b) {
112 if (len_sq <= max_sq)
113 return false;
114 if (!within)
115 return true;
116 const double len = std::sqrt(len_sq);
117 return within((verts.
pos[
size_t(a)] + verts.
pos[
size_t(b)]) * 0.5,
119 };
120
121
122
123
124
125
126 std::vector<uint8_t> want(tri_count, 0);
127 tbb::parallel_for(tbb::blocked_range<size_t>(0, tri_count), [&](
const tbb::blocked_range<size_t> &
range) {
128 for (
size_t t =
range.begin(); t <
range.end(); ++t) {
129 const int a = indices[t * 3], b = indices[t * 3 + 1], c = indices[t * 3 + 2];
130 want[t] = uint8_t(too_long(a, b)) | uint8_t(too_long(b, c) << 1) | uint8_t(too_long(c, a) << 2);
131 }
132 });
133 const auto mark_wanted = [&](size_t t) {
134 const int a = indices[t * 3], b = indices[t * 3 + 1], c = indices[t * 3 + 2];
135 if (want[t] & 1) mark_edge(a, b);
136 if (want[t] & 2) mark_edge(b, c);
137 if (want[t] & 4) mark_edge(c, a);
138 };
139 std::vector<size_t> unreached;
140 for (size_t t = 0; t < tri_count; ++t)
141 if (face_excluded.empty() || !face_excluded[t])
142 mark_wanted(t);
143 else if (within && want[t] != 0)
144 unreached.push_back(t);
145
146 for (size_t n = 0; n != unreached.size();) {
147 n = unreached.size();
148 unreached.erase(std::remove_if(unreached.begin(), unreached.end(), [&](size_t t) {
149 const int a = indices[t * 3], b = indices[t * 3 + 1], c = indices[t * 3 + 2];
150 const bool reached = is_marked(a, b) || is_marked(b, c) || is_marked(c, a);
151 if (reached)
152 mark_wanted(t);
153 return reached;
154 }), unreached.end());
155 }
156 if (split_edges.size() == 0) {
160 return out;
161 }
162
163
164
165
166 std::vector<uint8_t> tri_marks(tri_count);
167 const size_t predicted = tbb::parallel_reduce(
168 tbb::blocked_range<size_t>(0, tri_count), size_t(0),
169 [&](
const tbb::blocked_range<size_t> &
range,
size_t acc) {
170 for (
size_t t =
range.begin(); t <
range.end(); ++t) {
171 const int a = indices[t * 3], b = indices[t * 3 + 1], c = indices[t * 3 + 2];
172 const uint8_t m = uint8_t(is_marked(a, b)) | uint8_t(is_marked(b, c) << 1) |
173 uint8_t(is_marked(c, a) << 2);
174 tri_marks[t] = m;
175 const int n = (m & 1) + ((m >> 1) & 1) + ((m >> 2) & 1);
176 acc += (n == 0) ? 1 : size_t(n + 1);
177 }
178 return acc;
179 },
180 std::plus<size_t>());
181 if (predicted > size_t(safety_cap)) {
186 return out;
187 }
188
189
190 out.
indices.resize(predicted * 3);
191 if (!face_excluded.empty())
193 if (!face_parent_id.empty())
195 size_t wi = 0, fi = 0;
196 const auto emit_face_data = [&](uint8_t excl, int pid, int times) {
197 for (int k = 0; k < times; ++k) {
200 ++fi;
201 }
202 };
203 const auto emit = [&](int x, int y, int z) {
205 };
206
207 for (size_t t = 0; t < tri_count; ++t) {
208 const int a = indices[t * 3], b = indices[t * 3 + 1], c = indices[t * 3 + 2];
209 const uint8_t excl = face_excluded.empty() ? uint8_t(0) : face_excluded[t];
210 const int pid = face_parent_id.empty() ? 0 : face_parent_id[t];
211 const bool s_ab = (tri_marks[t] & 1) != 0, s_bc = (tri_marks[t] & 2) != 0, s_ca = (tri_marks[t] & 4) != 0;
212 const int n = int(s_ab) + int(s_bc) + int(s_ca);
213
214 if (n == 0) {
215 emit(a, b, c);
216 emit_face_data(excl, pid, 1);
217 } else if (n == 3) {
218
219
220
221
222
223 const int m_ab =
get_midpoint(verts, mid_cache, a, b, pos_canon_map);
224 const int m_bc =
get_midpoint(verts, mid_cache, b, c, pos_canon_map);
225 const int m_ca =
get_midpoint(verts, mid_cache, c, a, pos_canon_map);
226 emit(a, m_ab, m_ca);
227 emit(m_ab, b, m_bc);
228 emit(m_ca, m_bc, c);
229 emit(m_ab, m_bc, m_ca);
230 emit_face_data(excl, pid, 4);
231 } else if (n == 1) {
232 if (s_ab) {
233 const int m =
get_midpoint(verts, mid_cache, a, b, pos_canon_map);
234 emit(a, m, c);
235 emit(m, b, c);
236 } else if (s_bc) {
237 const int m =
get_midpoint(verts, mid_cache, b, c, pos_canon_map);
238 emit(a, b, m);
239 emit(a, m, c);
240 } else {
241 const int m =
get_midpoint(verts, mid_cache, c, a, pos_canon_map);
242 emit(a, b, m);
243 emit(m, b, c);
244 }
245 emit_face_data(excl, pid, 2);
246 } else {
247
248
249
250
251
252
253
254 if (!s_ab) {
255 const int m_bc =
get_midpoint(verts, mid_cache, b, c, pos_canon_map);
256 const int m_ca =
get_midpoint(verts, mid_cache, c, a, pos_canon_map);
257 emit(a, b, m_bc);
258 emit(a, m_bc, m_ca);
259 emit(c, m_ca, m_bc);
260 } else if (!s_bc) {
261 const int m_ab =
get_midpoint(verts, mid_cache, a, b, pos_canon_map);
262 const int m_ca =
get_midpoint(verts, mid_cache, c, a, pos_canon_map);
263 emit(a, m_ab, m_ca);
264 emit(m_ab, b, c);
265 emit(m_ab, c, m_ca);
266 } else {
267 const int m_ab =
get_midpoint(verts, mid_cache, a, b, pos_canon_map);
268 const int m_bc =
get_midpoint(verts, mid_cache, b, c, pos_canon_map);
269 emit(b, m_bc, m_ab);
270 emit(a, m_ab, m_bc);
271 emit(a, m_bc, c);
272 }
273 emit_face_data(excl, pid, 3);
274 }
275 }
276
278 return out;
279}
Definition TextureBakeIndex.hpp:39
int get_midpoint(VertStore &verts, QuantizedPointMap &cache, int a, int b, QuantizedPointMap *pos_canon_map)
Definition TextureBakeSubdivide.cpp:40
bool capped
Definition TextureBakeSubdivide.cpp:68
bool changed
Definition TextureBakeSubdivide.cpp:67
std::vector< uint8_t > face_excluded
Definition TextureBakeSubdivide.cpp:65
std::vector< int > face_parent_id
Definition TextureBakeSubdivide.cpp:66
double edge_len_sq(const VertStore &v, int a, int b)
Definition TextureBakeSubdivide.cpp:24
std::vector< int > indices
Definition TextureBakeSubdivide.cpp:64
Definition TextureBakeSubdivide.cpp:63
static constexpr double SUBDIVIDE_GRADE
Definition TextureBakeSubdivide.hpp:33
auto range(Cont &&cont)
Definition libslic3r.h:405