Blender V4.3
MOD_screw.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9/* Screw modifier: revolves the edges about an axis */
10#include <climits>
11
12#include "BLI_utildefines.h"
13
14#include "BLI_bitmap.h"
15#include "BLI_math_geom.h"
16#include "BLI_math_matrix.h"
17#include "BLI_math_rotation.h"
18#include "BLI_math_vector.h"
19#include "BLI_span.hh"
20
21#include "BLT_translation.hh"
22
23#include "DNA_defaults.h"
24#include "DNA_mesh_types.h"
25#include "DNA_object_types.h"
26#include "DNA_screen_types.h"
27
28#include "BKE_attribute.hh"
29#include "BKE_customdata.hh"
30#include "BKE_lib_id.hh"
31#include "BKE_lib_query.hh"
32#include "BKE_mesh.hh"
33
34#include "UI_interface.hh"
35#include "UI_resources.hh"
36
37#include "RNA_access.hh"
38#include "RNA_prototypes.hh"
39
41
42#include "MEM_guardedalloc.h"
43
44#include "MOD_modifiertypes.hh"
45#include "MOD_ui_common.hh"
46
48
49#include "BLI_strict_flags.h" /* Keep last. */
50
51using namespace blender;
52
61
65 float dist_sq;
67 float co[3];
69 uint v[2];
72 char flag;
73};
74
81
82#define SV_UNUSED (UINT_MAX)
83#define SV_INVALID ((UINT_MAX)-1)
84#define SV_IS_VALID(v) ((v) < SV_INVALID)
85
88 uint v_init,
89 uint dir)
90{
91 iter->v_array = array;
92 iter->v = v_init;
93
94 if (SV_IS_VALID(v_init)) {
95 iter->v_poin = &array[v_init];
96 iter->v_other = iter->v_poin->v[dir];
97 iter->e = iter->v_poin->e[!dir];
98 }
99 else {
100 iter->v_poin = nullptr;
101 iter->e = nullptr;
102 }
103}
104
106{
107 if (iter->v_poin->v[0] == iter->v_other) {
108 iter->v_other = iter->v;
109 iter->v = iter->v_poin->v[1];
110 }
111 else if (iter->v_poin->v[1] == iter->v_other) {
112 iter->v_other = iter->v;
113 iter->v = iter->v_poin->v[0];
114 }
115 if (SV_IS_VALID(iter->v)) {
116 iter->v_poin = &iter->v_array[iter->v];
117 iter->e = iter->v_poin->e[(iter->v_poin->e[0] == iter->e)];
118 }
119 else {
120 iter->e = nullptr;
121 iter->v_poin = nullptr;
122 }
123}
124
126 blender::MutableSpan<blender::float3> vert_positions_new,
127 const uint totvert,
128 const uint step_tot,
129 const float axis_vec[3],
130 const float axis_offset[3],
131 const float merge_threshold)
132{
133 BLI_bitmap *vert_tag = BLI_BITMAP_NEW(totvert, __func__);
134
135 const float merge_threshold_sq = square_f(merge_threshold);
136 const bool use_offset = axis_offset != nullptr;
137 uint tot_doubles = 0;
138 for (uint i = 0; i < totvert; i += 1) {
139 float axis_co[3];
140 if (use_offset) {
141 float offset_co[3];
142 sub_v3_v3v3(offset_co, vert_positions_new[i], axis_offset);
143 project_v3_v3v3_normalized(axis_co, offset_co, axis_vec);
144 add_v3_v3(axis_co, axis_offset);
145 }
146 else {
147 project_v3_v3v3_normalized(axis_co, vert_positions_new[i], axis_vec);
148 }
149 const float dist_sq = len_squared_v3v3(axis_co, vert_positions_new[i]);
150 if (dist_sq <= merge_threshold_sq) {
151 BLI_BITMAP_ENABLE(vert_tag, i);
152 tot_doubles += 1;
153 copy_v3_v3(vert_positions_new[i], axis_co);
154 }
155 }
156
157 if (tot_doubles != 0) {
158 uint tot = totvert * step_tot;
159 int *full_doubles_map = static_cast<int *>(MEM_malloc_arrayN(tot, sizeof(int), __func__));
160 copy_vn_i(full_doubles_map, int(tot), -1);
161
162 uint tot_doubles_left = tot_doubles;
163 for (uint i = 0; i < totvert; i += 1) {
164 if (BLI_BITMAP_TEST(vert_tag, i)) {
165 int *doubles_map = &full_doubles_map[totvert + i];
166 for (uint step = 1; step < step_tot; step += 1) {
167 *doubles_map = int(i);
168 doubles_map += totvert;
169 }
170 tot_doubles_left -= 1;
171 if (tot_doubles_left == 0) {
172 break;
173 }
174 }
175 }
176
177 Mesh *tmp = result;
178
179 /* TODO(mano-wii): Polygons with all vertices merged are the ones that form duplicates.
180 * Therefore the duplicate face test can be skipped. */
181 result = geometry::mesh_merge_verts(*tmp,
182 MutableSpan<int>{full_doubles_map, result->verts_num},
183 int(tot_doubles * (step_tot - 1)),
184 false);
185
186 BKE_id_free(nullptr, tmp);
187 MEM_freeN(full_doubles_map);
188 }
189
190 MEM_freeN(vert_tag);
191
192 return result;
193}
194
195static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
196{
197 using namespace blender;
198 const Mesh *mesh = meshData;
199 Mesh *result;
201 const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER) != 0;
202
203 int face_index = 0;
204 uint step;
205 uint j;
206 uint i1, i2;
207 uint step_tot = use_render_params ? ltmd->render_steps : ltmd->steps;
208 const bool do_flip = (ltmd->flag & MOD_SCREW_NORMAL_FLIP) != 0;
209
210 const int quad_ord[4] = {
211 do_flip ? 3 : 0,
212 do_flip ? 2 : 1,
213 do_flip ? 1 : 2,
214 do_flip ? 0 : 3,
215 };
216 const int quad_ord_ofs[4] = {
217 do_flip ? 2 : 0,
218 1,
219 do_flip ? 0 : 2,
220 3,
221 };
222
223 uint maxVerts = 0, maxEdges = 0, maxPolys = 0;
224 const uint totvert = uint(mesh->verts_num);
225 const uint totedge = uint(mesh->edges_num);
226 const uint faces_num = uint(mesh->faces_num);
227
228 uint *edge_face_map = nullptr; /* orig edge to orig face */
229 uint *vert_loop_map = nullptr; /* orig vert to orig loop */
230
231 /* UV Coords */
232 const uint mloopuv_layers_tot = uint(
233 CustomData_number_of_layers(&mesh->corner_data, CD_PROP_FLOAT2));
234 blender::Array<blender::float2 *> mloopuv_layers(mloopuv_layers_tot);
235 float uv_u_scale;
236 float uv_v_minmax[2] = {FLT_MAX, -FLT_MAX};
237 float uv_v_range_inv;
238 float uv_axis_plane[4];
239
240 char axis_char = 'X';
241 bool close;
242 float angle = ltmd->angle;
243 float screw_ofs = ltmd->screw_ofs;
244 float axis_vec[3] = {0.0f, 0.0f, 0.0f};
245 float tmp_vec1[3], tmp_vec2[3];
246 float mat3[3][3];
247 /* transform the coords by an object relative to this objects transformation */
248 float mtx_tx[4][4];
249 float mtx_tx_inv[4][4]; /* inverted */
250 float mtx_tmp_a[4][4];
251
252 uint vc_tot_linked = 0;
253 short other_axis_1, other_axis_2;
254 const float *tmpf1, *tmpf2;
255
256 uint edge_offset;
257
258 blender::int2 *edge_new, *med_new_firstloop;
259 Object *ob_axis = ltmd->ob_axis;
260
261 ScrewVertConnect *vc, *vc_tmp, *vert_connect = nullptr;
262
263 const bool use_flat_shading = (ltmd->flag & MOD_SCREW_SMOOTH_SHADING) == 0;
264
265 /* don't do anything? */
266 if (!totvert) {
267 return BKE_mesh_new_nomain_from_template(mesh, 0, 0, 0, 0);
268 }
269
270 switch (ltmd->axis) {
271 case 0:
272 other_axis_1 = 1;
273 other_axis_2 = 2;
274 break;
275 case 1:
276 other_axis_1 = 0;
277 other_axis_2 = 2;
278 break;
279 default: /* 2, use default to quiet warnings */
280 other_axis_1 = 0;
281 other_axis_2 = 1;
282 break;
283 }
284
285 axis_vec[ltmd->axis] = 1.0f;
286
287 if (ob_axis != nullptr) {
288 /* Calculate the matrix relative to the axis object. */
289 invert_m4_m4(mtx_tmp_a, ctx->object->object_to_world().ptr());
290 copy_m4_m4(mtx_tx_inv, ob_axis->object_to_world().ptr());
291 mul_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv);
292
293 /* Calculate the axis vector. */
294 mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */
295 normalize_v3(axis_vec);
296
297 /* screw */
298 if (ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
299 /* Find the offset along this axis relative to this objects matrix. */
300 float totlen = len_v3(mtx_tx[3]);
301
302 if (totlen != 0.0f) {
303 const float zero[3] = {0.0f, 0.0f, 0.0f};
304 float cp[3];
305 screw_ofs = closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
306 }
307 else {
308 screw_ofs = 0.0f;
309 }
310 }
311
312 /* angle */
313
314#if 0 /* can't include this, not predictable enough, though quite fun. */
315 if (ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
316 float mtx3_tx[3][3];
317 copy_m3_m4(mtx3_tx, mtx_tx);
318
319 float vec[3] = {0, 1, 0};
320 float cross1[3];
321 float cross2[3];
322 cross_v3_v3v3(cross1, vec, axis_vec);
323
324 mul_v3_m3v3(cross2, mtx3_tx, cross1);
325 {
326 float c1[3];
327 float c2[3];
328 float axis_tmp[3];
329
330 cross_v3_v3v3(c1, cross2, axis_vec);
331 cross_v3_v3v3(c2, axis_vec, c1);
332
333 angle = angle_v3v3(cross1, c2);
334
335 cross_v3_v3v3(axis_tmp, cross1, c2);
336 normalize_v3(axis_tmp);
337
338 if (len_v3v3(axis_tmp, axis_vec) > 1.0f) {
339 angle = -angle;
340 }
341 }
342 }
343#endif
344 }
345 else {
346 axis_char = char(axis_char + ltmd->axis); /* 'X' + axis */
347
348 /* Useful to be able to use the axis vector in some cases still. */
349 zero_v3(axis_vec);
350 axis_vec[ltmd->axis] = 1.0f;
351 }
352
353 /* apply the multiplier */
354 angle *= float(ltmd->iter);
355 screw_ofs *= float(ltmd->iter);
356 uv_u_scale = 1.0f / float(step_tot);
357
358 /* multiplying the steps is a bit tricky, this works best */
359 step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
360
361 /* Will the screw be closed?
362 * NOTE: smaller than `FLT_EPSILON * 100`
363 * gives problems with float precision so its never closed. */
364 if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) &&
365 fabsf(fabsf(angle) - (float(M_PI) * 2.0f)) <= (FLT_EPSILON * 100.0f) && step_tot > 3)
366 {
367 close = true;
368 step_tot--;
369
370 maxVerts = totvert * step_tot; /* -1 because we're joining back up */
371 maxEdges = (totvert * step_tot) + /* these are the edges between new verts */
372 (totedge * step_tot); /* -1 because vert edges join */
373 maxPolys = totedge * step_tot;
374
375 screw_ofs = 0.0f;
376 }
377 else {
378 close = false;
379 if (step_tot < 2) {
380 step_tot = 2;
381 }
382
383 maxVerts = totvert * step_tot; /* -1 because we're joining back up */
384 maxEdges = (totvert * (step_tot - 1)) + /* these are the edges between new verts */
385 (totedge * step_tot); /* -1 because vert edges join */
386 maxPolys = totedge * (step_tot - 1);
387 }
388
389 if ((ltmd->flag & MOD_SCREW_UV_STRETCH_U) == 0) {
390 uv_u_scale = (uv_u_scale / float(ltmd->iter)) * (angle / (float(M_PI) * 2.0f));
391 }
392
393 /* The `screw_ofs` cannot change from now on. */
394 const bool do_remove_doubles = (ltmd->flag & MOD_SCREW_MERGE) && (screw_ofs == 0.0f);
395
397 mesh, int(maxVerts), int(maxEdges), int(maxPolys), int(maxPolys) * 4);
398 /* The modifier doesn't support original index mapping on the edge or face domains. Remove
399 * original index layers, since otherwise edges aren't displayed at all in wireframe view. */
400 CustomData_free_layers(&result->edge_data, CD_ORIGINDEX, result->edges_num);
401 CustomData_free_layers(&result->face_data, CD_ORIGINDEX, result->edges_num);
402
403 const blender::Span<float3> vert_positions_orig = mesh->vert_positions();
404 const blender::Span<int2> edges_orig = mesh->edges();
405 const OffsetIndices faces_orig = mesh->faces();
406 const blender::Span<int> corner_verts_orig = mesh->corner_verts();
407 const blender::Span<int> corner_edges_orig = mesh->corner_edges();
408
409 blender::MutableSpan<float3> vert_positions_new = result->vert_positions_for_write();
410 blender::MutableSpan<int2> edges_new = result->edges_for_write();
411 MutableSpan<int> face_offests_new = result->face_offsets_for_write();
412 blender::MutableSpan<int> corner_verts_new = result->corner_verts_for_write();
413 blender::MutableSpan<int> corner_edges_new = result->corner_edges_for_write();
414 bke::MutableAttributeAccessor attributes = result->attributes_for_write();
415 bke::SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_span<bool>(
416 "sharp_face", bke::AttrDomain::Face);
417
418 if (!CustomData_has_layer(&result->face_data, CD_ORIGINDEX)) {
419 CustomData_add_layer(&result->face_data, CD_ORIGINDEX, CD_SET_DEFAULT, int(maxPolys));
420 }
421
422 int *origindex = static_cast<int *>(
423 CustomData_get_layer_for_write(&result->face_data, CD_ORIGINDEX, result->faces_num));
424
425 CustomData_copy_data(&mesh->vert_data, &result->vert_data, 0, 0, int(totvert));
426
427 if (mloopuv_layers_tot) {
428 const float zero_co[3] = {0};
429 plane_from_point_normal_v3(uv_axis_plane, zero_co, axis_vec);
430 }
431
432 if (mloopuv_layers_tot) {
433 uint uv_lay;
434 for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
435 mloopuv_layers[uv_lay] = static_cast<blender::float2 *>(CustomData_get_layer_n_for_write(
436 &result->corner_data, CD_PROP_FLOAT2, int(uv_lay), result->corners_num));
437 }
438
439 if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
440 for (uint i = 0; i < totvert; i++) {
441 const float v = dist_signed_squared_to_plane_v3(vert_positions_orig[i], uv_axis_plane);
442 uv_v_minmax[0] = min_ff(v, uv_v_minmax[0]);
443 uv_v_minmax[1] = max_ff(v, uv_v_minmax[1]);
444 }
445 uv_v_minmax[0] = sqrtf_signed(uv_v_minmax[0]);
446 uv_v_minmax[1] = sqrtf_signed(uv_v_minmax[1]);
447 }
448
449 uv_v_range_inv = uv_v_minmax[1] - uv_v_minmax[0];
450 uv_v_range_inv = uv_v_range_inv ? 1.0f / uv_v_range_inv : 0.0f;
451 }
452
453 /* Set the locations of the first set of verts */
454
455 /* Copy the first set of edges */
456 const blender::int2 *edge_orig = edges_orig.data();
457 edge_new = edges_new.data();
458 for (uint i = 0; i < totedge; i++, edge_orig++, edge_new++) {
459 *edge_new = *edge_orig;
460 }
461
462 /* build face -> edge map */
463 if (faces_num) {
464
465 edge_face_map = static_cast<uint *>(
466 MEM_malloc_arrayN(totedge, sizeof(*edge_face_map), __func__));
467 memset(edge_face_map, 0xff, sizeof(*edge_face_map) * totedge);
468
469 vert_loop_map = static_cast<uint *>(
470 MEM_malloc_arrayN(totvert, sizeof(*vert_loop_map), __func__));
471 memset(vert_loop_map, 0xff, sizeof(*vert_loop_map) * totvert);
472
473 for (const int64_t i : faces_orig.index_range()) {
474 for (const int64_t corner : faces_orig[i]) {
475 const int vert_i = corner_verts_orig[corner];
476 const int edge_i = corner_edges_orig[corner];
477 edge_face_map[edge_i] = uint(i);
478 vert_loop_map[vert_i] = uint(corner);
479
480 /* also order edges based on faces */
481 if (edges_new[edge_i][0] != vert_i) {
482 std::swap(edges_new[edge_i][0], edges_new[edge_i][1]);
483 }
484 }
485 }
486 }
487
488 if (ltmd->flag & MOD_SCREW_NORMAL_CALC) {
489
490 /* Normal Calculation (for face flipping)
491 * Sort edge verts for correct face flipping
492 * NOT REALLY NEEDED but face flipping is nice. */
493
494 vert_connect = static_cast<ScrewVertConnect *>(
495 MEM_malloc_arrayN(totvert, sizeof(ScrewVertConnect), __func__));
496 /* skip the first slice of verts. */
497 // vert_connect = (ScrewVertConnect *) &medge_new[totvert];
498 vc = vert_connect;
499
500 /* Copy Vert Locations */
501 if (totedge != 0) {
502 // printf("\n\n\n\n\nStarting Modifier\n");
503 /* set edge users */
504 edge_new = edges_new.data();
505
506 if (ob_axis != nullptr) {
507 /* `mtx_tx` is initialized early on. */
508 for (uint i = 0; i < totvert; i++, vc++) {
509 vc->co[0] = vert_positions_new[i][0] = vert_positions_orig[i][0];
510 vc->co[1] = vert_positions_new[i][1] = vert_positions_orig[i][1];
511 vc->co[2] = vert_positions_new[i][2] = vert_positions_orig[i][2];
512
513 vc->flag = 0;
514 vc->e[0] = vc->e[1] = nullptr;
515 vc->v[0] = vc->v[1] = SV_UNUSED;
516
517 mul_m4_v3(mtx_tx, vc->co);
518 /* Length in 2D, don't `sqrt` because this is only for comparison. */
519 vc->dist_sq = vc->co[other_axis_1] * vc->co[other_axis_1] +
520 vc->co[other_axis_2] * vc->co[other_axis_2];
521
522 // printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist_sq);
523 }
524 }
525 else {
526 for (uint i = 0; i < totvert; i++, vc++) {
527 vc->co[0] = vert_positions_new[i][0] = vert_positions_orig[i][0];
528 vc->co[1] = vert_positions_new[i][1] = vert_positions_orig[i][1];
529 vc->co[2] = vert_positions_new[i][2] = vert_positions_orig[i][2];
530
531 vc->flag = 0;
532 vc->e[0] = vc->e[1] = nullptr;
533 vc->v[0] = vc->v[1] = SV_UNUSED;
534
535 /* Length in 2D, don't `sqrt` because this is only for comparison. */
536 vc->dist_sq = vc->co[other_axis_1] * vc->co[other_axis_1] +
537 vc->co[other_axis_2] * vc->co[other_axis_2];
538
539 // printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist_sq);
540 }
541 }
542
543 /* this loop builds connectivity info for verts */
544 for (uint i = 0; i < totedge; i++, edge_new++) {
545 vc = &vert_connect[(*edge_new)[0]];
546
547 if (vc->v[0] == SV_UNUSED) { /* unused */
548 vc->v[0] = uint((*edge_new)[1]);
549 vc->e[0] = edge_new;
550 }
551 else if (vc->v[1] == SV_UNUSED) {
552 vc->v[1] = uint((*edge_new)[1]);
553 vc->e[1] = edge_new;
554 }
555 else {
556 vc->v[0] = vc->v[1] = SV_INVALID; /* error value - don't use, 3 edges on vert */
557 }
558
559 vc = &vert_connect[(*edge_new)[1]];
560
561 /* same as above but swap v1/2 */
562 if (vc->v[0] == SV_UNUSED) { /* unused */
563 vc->v[0] = uint((*edge_new)[0]);
564 vc->e[0] = edge_new;
565 }
566 else if (vc->v[1] == SV_UNUSED) {
567 vc->v[1] = uint((*edge_new)[0]);
568 vc->e[1] = edge_new;
569 }
570 else {
571 vc->v[0] = vc->v[1] = SV_INVALID; /* error value - don't use, 3 edges on vert */
572 }
573 }
574
575 /* find the first vert */
576 vc = vert_connect;
577 for (uint i = 0; i < totvert; i++, vc++) {
578 /* Now do search for connected verts, order all edges and flip them
579 * so resulting faces are flipped the right way */
580 vc_tot_linked = 0; /* count the number of linked verts for this loop */
581 if (vc->flag == 0) {
582 uint v_best = SV_UNUSED, ed_loop_closed = 0; /* vert and vert new */
583 ScrewVertIter lt_iter;
584 float fl = -1.0f;
585
586 /* compiler complains if not initialized, but it should be initialized below */
587 bool ed_loop_flip = false;
588
589 // printf("Loop on connected vert: %i\n", i);
590
591 for (j = 0; j < 2; j++) {
592 // printf("\tSide: %i\n", j);
593 screwvert_iter_init(&lt_iter, vert_connect, i, j);
594 if (j == 1) {
595 screwvert_iter_step(&lt_iter);
596 }
597 while (lt_iter.v_poin) {
598 // printf("\t\tVERT: %i\n", lt_iter.v);
599 if (lt_iter.v_poin->flag) {
600 // printf("\t\t\tBreaking Found end\n");
601 // endpoints[0] = endpoints[1] = SV_UNUSED;
602 ed_loop_closed = 1; /* circle */
603 break;
604 }
605 lt_iter.v_poin->flag = 1;
606 vc_tot_linked++;
607 // printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist_sq);
608 if (fl <= lt_iter.v_poin->dist_sq) {
609 fl = lt_iter.v_poin->dist_sq;
610 v_best = lt_iter.v;
611 // printf("\t\t\tVERT BEST: %i\n", v_best);
612 }
613 screwvert_iter_step(&lt_iter);
614 if (!lt_iter.v_poin) {
615 // printf("\t\t\tFound End Also Num %i\n", j);
616 // endpoints[j] = lt_iter.v_other; /* other is still valid */
617 break;
618 }
619 }
620 }
621
622 /* Now we have a collection of used edges. flip their edges the right way. */
623 /* if (v_best != SV_UNUSED) - */
624
625 // printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);
626
627 if (vc_tot_linked > 1) {
628 float vf_1, vf_2, vf_best;
629
630 vc_tmp = &vert_connect[v_best];
631
632 tmpf1 = vert_connect[vc_tmp->v[0]].co;
633 tmpf2 = vert_connect[vc_tmp->v[1]].co;
634
635 /* edge connects on each side! */
636 if (SV_IS_VALID(vc_tmp->v[0]) && SV_IS_VALID(vc_tmp->v[1])) {
637 // printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);
638 /* Find out which is higher. */
639
640 vf_1 = tmpf1[ltmd->axis];
641 vf_2 = tmpf2[ltmd->axis];
642 vf_best = vc_tmp->co[ltmd->axis];
643
644 if (vf_1 < vf_best && vf_best < vf_2) {
645 ed_loop_flip = false;
646 }
647 else if (vf_1 > vf_best && vf_best > vf_2) {
648 ed_loop_flip = true;
649 }
650 else {
651 /* not so simple to work out which edge is higher */
652 sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co);
653 sub_v3_v3v3(tmp_vec2, tmpf2, vc_tmp->co);
654 normalize_v3(tmp_vec1);
655 normalize_v3(tmp_vec2);
656
657 if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) {
658 ed_loop_flip = true;
659 }
660 else {
661 ed_loop_flip = false;
662 }
663 }
664 }
665 else if (SV_IS_VALID(vc_tmp->v[0])) { /* Vertex only connected on 1 side. */
666 // printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);
667 if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
668 ed_loop_flip = true;
669 }
670 else { /* best is below or even... in even case we can't know what to do. */
671 ed_loop_flip = false;
672 }
673 }
674#if 0
675 else {
676 printf("No Connected ___\n");
677 }
678#endif
679
680 // printf("flip direction %i\n", ed_loop_flip);
681
682 /* Switch the flip option if set
683 * NOTE: flip is now done at face level so copying group slices is easier. */
684#if 0
685 if (do_flip) {
686 ed_loop_flip = !ed_loop_flip;
687 }
688#endif
689
690 if (angle < 0.0f) {
691 ed_loop_flip = !ed_loop_flip;
692 }
693
694 /* if its closed, we only need 1 loop */
695 for (j = ed_loop_closed; j < 2; j++) {
696 // printf("Ordering Side J %i\n", j);
697
698 screwvert_iter_init(&lt_iter, vert_connect, v_best, j);
699 // printf("\n\nStarting - Loop\n");
700 lt_iter.v_poin->flag = 1; /* so a non loop will traverse the other side */
701
702 /* If this is the vert off the best vert and
703 * the best vert has 2 edges connected too it
704 * then swap the flip direction */
705 if (j == 1 && SV_IS_VALID(vc_tmp->v[0]) && SV_IS_VALID(vc_tmp->v[1])) {
706 ed_loop_flip = !ed_loop_flip;
707 }
708
709 while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
710 // printf("\tOrdering Vert V %i\n", lt_iter.v);
711
712 lt_iter.v_poin->flag = 2;
713 if (lt_iter.e) {
714 if (lt_iter.v == uint((*lt_iter.e)[0])) {
715 if (ed_loop_flip == 0) {
716 // printf("\t\t\tFlipping 0\n");
717 std::swap((*lt_iter.e)[0], (*lt_iter.e)[1]);
718 }
719#if 0
720 else {
721 printf("\t\t\tFlipping Not 0\n");
722 }
723#endif
724 }
725 else if (lt_iter.v == uint((*lt_iter.e)[1])) {
726 if (ed_loop_flip == 1) {
727 // printf("\t\t\tFlipping 1\n");
728 std::swap((*lt_iter.e)[0], (*lt_iter.e)[1]);
729 }
730#if 0
731 else {
732 printf("\t\t\tFlipping Not 1\n");
733 }
734#endif
735 }
736#if 0
737 else {
738 printf("\t\tIncorrect edge topology");
739 }
740#endif
741 }
742#if 0
743 else {
744 printf("\t\tNo Edge at this point\n");
745 }
746#endif
747 screwvert_iter_step(&lt_iter);
748 }
749 }
750 }
751 }
752 }
753 }
754 }
755 else {
756 for (uint i = 0; i < totvert; i++) {
757 copy_v3_v3(vert_positions_new[i], vert_positions_orig[i]);
758 }
759 }
760 /* done with edge connectivity based normal flipping */
761
762 /* Add Faces */
763 for (step = 1; step < step_tot; step++) {
764 const uint varray_stride = totvert * step;
765 float step_angle;
766 float mat[4][4];
767 /* Rotation Matrix */
768 step_angle = (angle / float(step_tot - (!close))) * float(step);
769
770 if (ob_axis != nullptr) {
771 axis_angle_normalized_to_mat3(mat3, axis_vec, step_angle);
772 }
773 else {
774 axis_angle_to_mat3_single(mat3, axis_char, step_angle);
775 }
776 copy_m4_m3(mat, mat3);
777
778 if (screw_ofs) {
779 madd_v3_v3fl(mat[3], axis_vec, screw_ofs * (float(step) / float(step_tot - 1)));
780 }
781
782 /* copy a slice */
784 &mesh->vert_data, &result->vert_data, 0, int(varray_stride), int(totvert));
785
786 /* set location */
787 for (j = 0; j < totvert; j++) {
788 const int vert_new = int(varray_stride) + int(j);
789
790 copy_v3_v3(vert_positions_new[vert_new], vert_positions_new[j]);
791
792 /* only need to set these if using non cleared memory */
793 // mv_new->mat_nr = mv_new->flag = 0;
794
795 if (ob_axis != nullptr) {
796 sub_v3_v3(vert_positions_new[vert_new], mtx_tx[3]);
797
798 mul_m4_v3(mat, vert_positions_new[vert_new]);
799
800 add_v3_v3(vert_positions_new[vert_new], mtx_tx[3]);
801 }
802 else {
803 mul_m4_v3(mat, vert_positions_new[vert_new]);
804 }
805
806 /* add the new edge */
807 (*edge_new)[0] = int(varray_stride + j);
808 (*edge_new)[1] = (*edge_new)[0] - int(totvert);
809 edge_new++;
810 }
811 }
812
813 /* we can avoid if using vert alloc trick */
814 if (vert_connect) {
815 MEM_freeN(vert_connect);
816 vert_connect = nullptr;
817 }
818
819 if (close) {
820 /* last loop of edges, previous loop doesn't account for the last set of edges */
821 const uint varray_stride = (step_tot - 1) * totvert;
822
823 for (uint i = 0; i < totvert; i++) {
824 (*edge_new)[0] = int(i);
825 (*edge_new)[1] = int(varray_stride + i);
826 edge_new++;
827 }
828 }
829
830 int new_loop_index = 0;
831 med_new_firstloop = edges_new.data();
832
833 /* more of an offset in this case */
834 edge_offset = totedge + (totvert * (step_tot - (close ? 0 : 1)));
835
836 const bke::AttributeAccessor src_attributes = mesh->attributes();
837 const VArraySpan src_material_index = *src_attributes.lookup<int>("material_index",
838 bke::AttrDomain::Face);
839
840 bke::MutableAttributeAccessor dst_attributes = result->attributes_for_write();
841 bke::SpanAttributeWriter dst_material_index = dst_attributes.lookup_or_add_for_write_span<int>(
842 "material_index", bke::AttrDomain::Face);
843
844 for (uint i = 0; i < totedge; i++, med_new_firstloop++) {
845 const uint step_last = step_tot - (close ? 1 : 2);
846 const uint face_index_orig = faces_num ? edge_face_map[i] : UINT_MAX;
847 const bool has_mpoly_orig = (face_index_orig != UINT_MAX);
848 float uv_v_offset_a, uv_v_offset_b;
849
850 const uint mloop_index_orig[2] = {
851 vert_loop_map ? vert_loop_map[edges_new[i][0]] : UINT_MAX,
852 vert_loop_map ? vert_loop_map[edges_new[i][1]] : UINT_MAX,
853 };
854 const bool has_mloop_orig = mloop_index_orig[0] != UINT_MAX;
855
856 int mat_nr;
857
858 /* for each edge, make a cylinder of quads */
859 i1 = uint((*med_new_firstloop)[0]);
860 i2 = uint((*med_new_firstloop)[1]);
861
862 if (has_mpoly_orig) {
863 mat_nr = src_material_index.is_empty() ? 0 : src_material_index[face_index_orig];
864 }
865 else {
866 mat_nr = 0;
867 }
868
869 if (has_mloop_orig == false && mloopuv_layers_tot) {
870 uv_v_offset_a = dist_signed_to_plane_v3(vert_positions_new[edges_new[i][0]], uv_axis_plane);
871 uv_v_offset_b = dist_signed_to_plane_v3(vert_positions_new[edges_new[i][1]], uv_axis_plane);
872
873 if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
874 uv_v_offset_a = (uv_v_offset_a - uv_v_minmax[0]) * uv_v_range_inv;
875 uv_v_offset_b = (uv_v_offset_b - uv_v_minmax[0]) * uv_v_range_inv;
876 }
877 }
878
879 for (step = 0; step <= step_last; step++) {
880
881 /* Polygon */
882 if (has_mpoly_orig) {
884 &mesh->face_data, &result->face_data, int(face_index_orig), int(face_index), 1);
885 origindex[face_index] = int(face_index_orig);
886 }
887 else {
888 origindex[face_index] = ORIGINDEX_NONE;
889 dst_material_index.span[face_index] = mat_nr;
890 sharp_faces.span[face_index] = use_flat_shading;
891 }
892 face_offests_new[face_index] = face_index * 4;
893
894 /* Loop-Custom-Data */
895 if (has_mloop_orig) {
896
897 CustomData_copy_data(&mesh->corner_data,
898 &result->corner_data,
899 int(mloop_index_orig[0]),
900 new_loop_index + 0,
901 1);
902 CustomData_copy_data(&mesh->corner_data,
903 &result->corner_data,
904 int(mloop_index_orig[1]),
905 new_loop_index + 1,
906 1);
907 CustomData_copy_data(&mesh->corner_data,
908 &result->corner_data,
909 int(mloop_index_orig[1]),
910 new_loop_index + 2,
911 1);
912 CustomData_copy_data(&mesh->corner_data,
913 &result->corner_data,
914 int(mloop_index_orig[0]),
915 new_loop_index + 3,
916 1);
917
918 if (mloopuv_layers_tot) {
919 uint uv_lay;
920 const float uv_u_offset_a = float(step) * uv_u_scale;
921 const float uv_u_offset_b = float(step + 1) * uv_u_scale;
922 for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
923 blender::float2 *mluv = &mloopuv_layers[uv_lay][new_loop_index];
924
925 mluv[quad_ord[0]][0] += uv_u_offset_a;
926 mluv[quad_ord[1]][0] += uv_u_offset_a;
927 mluv[quad_ord[2]][0] += uv_u_offset_b;
928 mluv[quad_ord[3]][0] += uv_u_offset_b;
929 }
930 }
931 }
932 else {
933 if (mloopuv_layers_tot) {
934 uint uv_lay;
935 const float uv_u_offset_a = float(step) * uv_u_scale;
936 const float uv_u_offset_b = float(step + 1) * uv_u_scale;
937 for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
938 blender::float2 *mluv = &mloopuv_layers[uv_lay][new_loop_index];
939
940 copy_v2_fl2(mluv[quad_ord[0]], uv_u_offset_a, uv_v_offset_a);
941 copy_v2_fl2(mluv[quad_ord[1]], uv_u_offset_a, uv_v_offset_b);
942 copy_v2_fl2(mluv[quad_ord[2]], uv_u_offset_b, uv_v_offset_b);
943 copy_v2_fl2(mluv[quad_ord[3]], uv_u_offset_b, uv_v_offset_a);
944 }
945 }
946 }
947
948 /* Loop-Data */
949 if (!(close && step == step_last)) {
950 /* regular segments */
951 corner_verts_new[new_loop_index + quad_ord[0]] = int(i1);
952 corner_verts_new[new_loop_index + quad_ord[1]] = int(i2);
953 corner_verts_new[new_loop_index + quad_ord[2]] = int(i2 + totvert);
954 corner_verts_new[new_loop_index + quad_ord[3]] = int(i1 + totvert);
955
956 corner_edges_new[new_loop_index + quad_ord_ofs[0]] = int(
957 step == 0 ? i : (edge_offset + step + (i * (step_tot - 1))) - 1);
958 corner_edges_new[new_loop_index + quad_ord_ofs[1]] = int(totedge + i2);
959 corner_edges_new[new_loop_index + quad_ord_ofs[2]] = int(edge_offset + step +
960 (i * (step_tot - 1)));
961 corner_edges_new[new_loop_index + quad_ord_ofs[3]] = int(totedge + i1);
962
963 /* new vertical edge */
964 if (step) { /* The first set is already done */
965 (*edge_new)[0] = int(i1);
966 (*edge_new)[1] = int(i2);
967 edge_new++;
968 }
969 i1 += totvert;
970 i2 += totvert;
971 }
972 else {
973 /* last segment */
974 corner_verts_new[new_loop_index + quad_ord[0]] = int(i1);
975 corner_verts_new[new_loop_index + quad_ord[1]] = int(i2);
976 corner_verts_new[new_loop_index + quad_ord[2]] = int((*med_new_firstloop)[1]);
977 corner_verts_new[new_loop_index + quad_ord[3]] = int((*med_new_firstloop)[0]);
978
979 corner_edges_new[new_loop_index + quad_ord_ofs[0]] = int(
980 (edge_offset + step + (i * (step_tot - 1))) - 1);
981 corner_edges_new[new_loop_index + quad_ord_ofs[1]] = int(totedge + i2);
982 corner_edges_new[new_loop_index + quad_ord_ofs[2]] = int(i);
983 corner_edges_new[new_loop_index + quad_ord_ofs[3]] = int(totedge + i1);
984 }
985
986 new_loop_index += 4;
987 face_index++;
988 }
989
990 /* new vertical edge */
991 (*edge_new)[0] = int(i1);
992 (*edge_new)[1] = int(i2);
993 edge_new++;
994 }
995
996/* validate loop edges */
997#if 0
998 {
999 uint i = 0;
1000 printf("\n");
1001 for (; i < maxPolys * 4; i += 4) {
1002 uint ii;
1003 ml_new = mloop_new + i;
1004 ii = findEd(edges_new, maxEdges, ml_new[0].v, ml_new[1].v);
1005 printf("%d %d -- ", ii, ml_new[0].e);
1006 ml_new[0].e = ii;
1007
1008 ii = findEd(edges_new, maxEdges, ml_new[1].v, ml_new[2].v);
1009 printf("%d %d -- ", ii, ml_new[1].e);
1010 ml_new[1].e = ii;
1011
1012 ii = findEd(edges_new, maxEdges, ml_new[2].v, ml_new[3].v);
1013 printf("%d %d -- ", ii, ml_new[2].e);
1014 ml_new[2].e = ii;
1015
1016 ii = findEd(edges_new, maxEdges, ml_new[3].v, ml_new[0].v);
1017 printf("%d %d\n", ii, ml_new[3].e);
1018 ml_new[3].e = ii;
1019 }
1020 }
1021#endif
1022
1023 sharp_faces.finish();
1024
1025 if (edge_face_map) {
1026 MEM_freeN(edge_face_map);
1027 }
1028
1029 if (vert_loop_map) {
1030 MEM_freeN(vert_loop_map);
1031 }
1032
1033 if (do_remove_doubles) {
1034 result = mesh_remove_doubles_on_axis(result,
1035 vert_positions_new,
1036 totvert,
1037 step_tot,
1038 axis_vec,
1039 ob_axis != nullptr ? mtx_tx[3] : nullptr,
1040 ltmd->merge_dist);
1041 }
1042
1043 dst_material_index.finish();
1044
1045 return result;
1046}
1047
1049{
1051 if (ltmd->ob_axis != nullptr) {
1052 DEG_add_object_relation(ctx->node, ltmd->ob_axis, DEG_OB_COMP_TRANSFORM, "Screw Modifier");
1053 DEG_add_depends_on_transform_relation(ctx->node, "Screw Modifier");
1054 }
1055}
1056
1057static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
1058{
1060
1061 walk(user_data, ob, (ID **)&ltmd->ob_axis, IDWALK_CB_NOP);
1062}
1063
1064static void panel_draw(const bContext * /*C*/, Panel *panel)
1065{
1066 uiLayout *sub, *row, *col;
1067 uiLayout *layout = panel->layout;
1069
1071
1072 PointerRNA screw_obj_ptr = RNA_pointer_get(ptr, "object");
1073
1074 uiLayoutSetPropSep(layout, true);
1075
1076 col = uiLayoutColumn(layout, false);
1077 uiItemR(col, ptr, "angle", UI_ITEM_NONE, nullptr, ICON_NONE);
1078 row = uiLayoutRow(col, false);
1080 RNA_pointer_is_null(&screw_obj_ptr) ||
1081 !RNA_boolean_get(ptr, "use_object_screw_offset"));
1082 uiItemR(row, ptr, "screw_offset", UI_ITEM_NONE, nullptr, ICON_NONE);
1083 uiItemR(col, ptr, "iterations", UI_ITEM_NONE, nullptr, ICON_NONE);
1084
1085 uiItemS(layout);
1086 col = uiLayoutColumn(layout, false);
1087 row = uiLayoutRow(col, false);
1088 uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
1089 uiItemR(col, ptr, "object", UI_ITEM_NONE, IFACE_("Axis Object"), ICON_NONE);
1090 sub = uiLayoutColumn(col, false);
1091 uiLayoutSetActive(sub, !RNA_pointer_is_null(&screw_obj_ptr));
1092 uiItemR(sub, ptr, "use_object_screw_offset", UI_ITEM_NONE, nullptr, ICON_NONE);
1093
1094 uiItemS(layout);
1095
1096 col = uiLayoutColumn(layout, true);
1097 uiItemR(col, ptr, "steps", UI_ITEM_NONE, IFACE_("Steps Viewport"), ICON_NONE);
1098 uiItemR(col, ptr, "render_steps", UI_ITEM_NONE, IFACE_("Render"), ICON_NONE);
1099
1100 uiItemS(layout);
1101
1102 row = uiLayoutRowWithHeading(layout, true, IFACE_("Merge"));
1103 uiItemR(row, ptr, "use_merge_vertices", UI_ITEM_NONE, "", ICON_NONE);
1104 sub = uiLayoutRow(row, true);
1105 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_merge_vertices"));
1106 uiItemR(sub, ptr, "merge_threshold", UI_ITEM_NONE, "", ICON_NONE);
1107
1108 uiItemS(layout);
1109
1110 row = uiLayoutRowWithHeading(layout, true, IFACE_("Stretch UVs"));
1111 uiItemR(row, ptr, "use_stretch_u", toggles_flag, IFACE_("U"), ICON_NONE);
1112 uiItemR(row, ptr, "use_stretch_v", toggles_flag, IFACE_("V"), ICON_NONE);
1113
1114 modifier_panel_end(layout, ptr);
1115}
1116
1117static void normals_panel_draw(const bContext * /*C*/, Panel *panel)
1118{
1119 uiLayout *col;
1120 uiLayout *layout = panel->layout;
1121
1123
1124 uiLayoutSetPropSep(layout, true);
1125
1126 col = uiLayoutColumn(layout, false);
1127 uiItemR(col, ptr, "use_smooth_shade", UI_ITEM_NONE, nullptr, ICON_NONE);
1128 uiItemR(col, ptr, "use_normal_calculate", UI_ITEM_NONE, nullptr, ICON_NONE);
1129 uiItemR(col, ptr, "use_normal_flip", UI_ITEM_NONE, nullptr, ICON_NONE);
1130}
1131
1132static void panel_register(ARegionType *region_type)
1133{
1136 region_type, "normals", "Normals", nullptr, normals_panel_draw, panel_type);
1137}
1138
1140 /*idname*/ "Screw",
1141 /*name*/ N_("Screw"),
1142 /*struct_name*/ "ScrewModifierData",
1143 /*struct_size*/ sizeof(ScrewModifierData),
1144 /*srna*/ &RNA_ScrewModifier,
1146
1149 /*icon*/ ICON_MOD_SCREW,
1150
1151 /*copy_data*/ BKE_modifier_copydata_generic,
1152
1153 /*deform_verts*/ nullptr,
1154 /*deform_matrices*/ nullptr,
1155 /*deform_verts_EM*/ nullptr,
1156 /*deform_matrices_EM*/ nullptr,
1157 /*modify_mesh*/ modify_mesh,
1158 /*modify_geometry_set*/ nullptr,
1159
1160 /*init_data*/ init_data,
1161 /*required_data_mask*/ nullptr,
1162 /*free_data*/ nullptr,
1163 /*is_disabled*/ nullptr,
1164 /*update_depsgraph*/ update_depsgraph,
1165 /*depends_on_time*/ nullptr,
1166 /*depends_on_normals*/ nullptr,
1167 /*foreach_ID_link*/ foreach_ID_link,
1168 /*foreach_tex_link*/ nullptr,
1169 /*free_runtime_data*/ nullptr,
1170 /*panel_register*/ panel_register,
1171 /*blend_write*/ nullptr,
1172 /*blend_read*/ nullptr,
1173 /*foreach_cache*/ nullptr,
1174};
CustomData interface, see also DNA_customdata_types.h.
@ CD_SET_DEFAULT
void CustomData_free_layers(CustomData *data, eCustomDataType type, int totelem)
#define ORIGINDEX_NONE
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
void * CustomData_get_layer_n_for_write(CustomData *data, eCustomDataType type, int n, int totelem)
void BKE_id_free(Main *bmain, void *idv)
@ IDWALK_CB_NOP
Mesh * BKE_mesh_new_nomain_from_template(const Mesh *me_src, int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
void(*)(void *user_data, Object *ob, ID **idpoin, int cb_flag) IDWalkFunc
@ MOD_APPLY_RENDER
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:41
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:65
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition BLI_bitmap.h:82
unsigned int BLI_bitmap
Definition BLI_bitmap.h:17
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE float square_f(float a)
MINLINE float sqrtf_signed(float f)
#define M_PI
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:215
float dist_signed_to_plane_v3(const float p[3], const float plane[4])
Definition math_geom.cc:493
float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
float dist_signed_squared_to_plane_v3(const float p[3], const float plane[4])
Definition math_geom.cc:461
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void axis_angle_to_mat3_single(float R[3][3], char axis, float angle)
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void copy_v2_fl2(float v[2], float x, float y)
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_proj[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
void copy_vn_i(int *array_tar, int size, int val)
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
void DEG_add_depends_on_transform_relation(DepsNodeHandle *node_handle, const char *description)
void DEG_add_object_relation(DepsNodeHandle *node_handle, Object *object, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_TRANSFORM
@ CD_PROP_FLOAT2
#define DNA_struct_default_get(struct_name)
@ MOD_SCREW_NORMAL_CALC
@ MOD_SCREW_SMOOTH_SHADING
@ MOD_SCREW_UV_STRETCH_V
@ MOD_SCREW_MERGE
@ MOD_SCREW_UV_STRETCH_U
@ MOD_SCREW_NORMAL_FLIP
@ MOD_SCREW_OBJECT_OFFSET
@ eModifierType_Screw
struct ScrewModifierData ScrewModifierData
Object is a sort of wrapper for general info.
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, uint v_init, uint dir)
Definition MOD_screw.cc:86
#define SV_INVALID
Definition MOD_screw.cc:83
#define SV_UNUSED
Definition MOD_screw.cc:82
static void normals_panel_draw(const bContext *, Panel *panel)
static Mesh * mesh_remove_doubles_on_axis(Mesh *result, blender::MutableSpan< blender::float3 > vert_positions_new, const uint totvert, const uint step_tot, const float axis_vec[3], const float axis_offset[3], const float merge_threshold)
Definition MOD_screw.cc:125
ModifierTypeInfo modifierType_Screw
static void screwvert_iter_step(ScrewVertIter *iter)
Definition MOD_screw.cc:105
#define SV_IS_VALID(v)
Definition MOD_screw.cc:84
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
#define UI_ITEM_NONE
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
eUI_Item_Flag
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
@ UI_ITEM_R_EXPAND
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr T * data() const
Definition BLI_span.hh:540
constexpr const T * data() const
Definition BLI_span.hh:216
constexpr bool is_empty() const
Definition BLI_span.hh:261
#define printf
#define fabsf(x)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
#define UINT_MAX
Definition hash_md5.cc:44
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static void init_data(ModifierData *md)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void panel_draw(const bContext *C, Panel *panel)
static void panel_register(ARegionType *region_type)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
bool RNA_pointer_is_null(const PointerRNA *ptr)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
#define FLT_MAX
Definition stdcycles.h:14
__int64 int64_t
Definition stdint.h:89
Definition DNA_ID.h:413
ModifierApplyFlag flag
struct uiLayout * layout
struct Object * ob_axis
blender::int2 * e[2]
Definition MOD_screw.cc:71
blender::int2 * e
Definition MOD_screw.cc:79
ScrewVertConnect * v_array
Definition MOD_screw.cc:76
ScrewVertConnect * v_poin
Definition MOD_screw.cc:77
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126