Blender  V3.3
MOD_screw.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. All rights reserved. */
3 
8 /* Screw modifier: revolves the edges about an axis */
9 #include <limits.h>
10 
11 #include "BLI_utildefines.h"
12 
13 #include "BLI_alloca.h"
14 #include "BLI_bitmap.h"
15 #include "BLI_math.h"
16 
17 #include "BLT_translation.h"
18 
19 #include "DNA_defaults.h"
20 #include "DNA_mesh_types.h"
21 #include "DNA_meshdata_types.h"
22 #include "DNA_object_types.h"
23 #include "DNA_screen_types.h"
24 
25 #include "BKE_context.h"
26 #include "BKE_lib_query.h"
27 #include "BKE_mesh.h"
28 #include "BKE_screen.h"
29 
30 #include "UI_interface.h"
31 #include "UI_resources.h"
32 
33 #include "RNA_access.h"
34 #include "RNA_prototypes.h"
35 
36 #include "DEG_depsgraph_build.h"
37 #include "DEG_depsgraph_query.h"
38 
39 #include "MEM_guardedalloc.h"
40 
41 #include "MOD_modifiertypes.h"
42 #include "MOD_ui_common.h"
43 
44 static void initData(ModifierData *md)
45 {
47 
48  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(ltmd, modifier));
49 
51 }
52 
53 #include "BLI_strict_flags.h"
54 
55 /* used for gathering edge connectivity */
56 typedef struct ScrewVertConnect {
57  float dist; /* distance from the center axis */
58  float co[3]; /* location relative to the transformed axis */
59  uint v[2]; /* 2 verts on either side of this one */
60  MEdge *e[2]; /* edges on either side, a bit of a waste since each edge ref's 2 edges */
61  char flag;
63 
64 typedef struct ScrewVertIter {
68  MEdge *e;
70 
71 #define SV_UNUSED (UINT_MAX)
72 #define SV_INVALID ((UINT_MAX)-1)
73 #define SV_IS_VALID(v) ((v) < SV_INVALID)
74 
77  uint v_init,
78  uint dir)
79 {
80  iter->v_array = array;
81  iter->v = v_init;
82 
83  if (SV_IS_VALID(v_init)) {
84  iter->v_poin = &array[v_init];
85  iter->v_other = iter->v_poin->v[dir];
86  iter->e = iter->v_poin->e[!dir];
87  }
88  else {
89  iter->v_poin = NULL;
90  iter->e = NULL;
91  }
92 }
93 
95 {
96  if (iter->v_poin->v[0] == iter->v_other) {
97  iter->v_other = iter->v;
98  iter->v = iter->v_poin->v[1];
99  }
100  else if (iter->v_poin->v[1] == iter->v_other) {
101  iter->v_other = iter->v;
102  iter->v = iter->v_poin->v[0];
103  }
104  if (SV_IS_VALID(iter->v)) {
105  iter->v_poin = &iter->v_array[iter->v];
106  iter->e = iter->v_poin->e[(iter->v_poin->e[0] == iter->e)];
107  }
108  else {
109  iter->e = NULL;
110  iter->v_poin = NULL;
111  }
112 }
113 
115  MVert *mvert_new,
116  const uint totvert,
117  const uint step_tot,
118  const float axis_vec[3],
119  const float axis_offset[3],
120  const float merge_threshold)
121 {
122  BLI_bitmap *vert_tag = BLI_BITMAP_NEW(totvert, __func__);
123 
124  const float merge_threshold_sq = square_f(merge_threshold);
125  const bool use_offset = axis_offset != NULL;
126  uint tot_doubles = 0;
127  for (uint i = 0; i < totvert; i += 1) {
128  float axis_co[3];
129  if (use_offset) {
130  float offset_co[3];
131  sub_v3_v3v3(offset_co, mvert_new[i].co, axis_offset);
132  project_v3_v3v3_normalized(axis_co, offset_co, axis_vec);
133  add_v3_v3(axis_co, axis_offset);
134  }
135  else {
136  project_v3_v3v3_normalized(axis_co, mvert_new[i].co, axis_vec);
137  }
138  const float dist_sq = len_squared_v3v3(axis_co, mvert_new[i].co);
139  if (dist_sq <= merge_threshold_sq) {
140  BLI_BITMAP_ENABLE(vert_tag, i);
141  tot_doubles += 1;
142  copy_v3_v3(mvert_new[i].co, axis_co);
143  }
144  }
145 
146  if (tot_doubles != 0) {
147  uint tot = totvert * step_tot;
148  int *full_doubles_map = MEM_malloc_arrayN(tot, sizeof(int), __func__);
149  copy_vn_i(full_doubles_map, (int)tot, -1);
150 
151  uint tot_doubles_left = tot_doubles;
152  for (uint i = 0; i < totvert; i += 1) {
153  if (BLI_BITMAP_TEST(vert_tag, i)) {
154  int *doubles_map = &full_doubles_map[totvert + i];
155  for (uint step = 1; step < step_tot; step += 1) {
156  *doubles_map = (int)i;
157  doubles_map += totvert;
158  }
159  tot_doubles_left -= 1;
160  if (tot_doubles_left == 0) {
161  break;
162  }
163  }
164  }
166  full_doubles_map,
167  (int)(tot_doubles * (step_tot - 1)),
169  MEM_freeN(full_doubles_map);
170  }
171 
172  MEM_freeN(vert_tag);
173 
174  return result;
175 }
176 
177 static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
178 {
179  Mesh *mesh = meshData;
180  Mesh *result;
181  ScrewModifierData *ltmd = (ScrewModifierData *)md;
182  const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER) != 0;
183 
184  int mpoly_index = 0;
185  uint step;
186  uint i, j;
187  uint i1, i2;
188  uint step_tot = use_render_params ? ltmd->render_steps : ltmd->steps;
189  const bool do_flip = (ltmd->flag & MOD_SCREW_NORMAL_FLIP) != 0;
190 
191  const int quad_ord[4] = {
192  do_flip ? 3 : 0,
193  do_flip ? 2 : 1,
194  do_flip ? 1 : 2,
195  do_flip ? 0 : 3,
196  };
197  const int quad_ord_ofs[4] = {
198  do_flip ? 2 : 0,
199  1,
200  do_flip ? 0 : 2,
201  3,
202  };
203 
204  uint maxVerts = 0, maxEdges = 0, maxPolys = 0;
205  const uint totvert = (uint)mesh->totvert;
206  const uint totedge = (uint)mesh->totedge;
207  const uint totpoly = (uint)mesh->totpoly;
208 
209  uint *edge_poly_map = NULL; /* orig edge to orig poly */
210  uint *vert_loop_map = NULL; /* orig vert to orig loop */
211 
212  /* UV Coords */
213  const uint mloopuv_layers_tot = (uint)CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
214  MLoopUV **mloopuv_layers = BLI_array_alloca(mloopuv_layers, mloopuv_layers_tot);
215  float uv_u_scale;
216  float uv_v_minmax[2] = {FLT_MAX, -FLT_MAX};
217  float uv_v_range_inv;
218  float uv_axis_plane[4];
219 
220  char axis_char = 'X';
221  bool close;
222  float angle = ltmd->angle;
223  float screw_ofs = ltmd->screw_ofs;
224  float axis_vec[3] = {0.0f, 0.0f, 0.0f};
225  float tmp_vec1[3], tmp_vec2[3];
226  float mat3[3][3];
227  /* transform the coords by an object relative to this objects transformation */
228  float mtx_tx[4][4];
229  float mtx_tx_inv[4][4]; /* inverted */
230  float mtx_tmp_a[4][4];
231 
232  uint vc_tot_linked = 0;
233  short other_axis_1, other_axis_2;
234  const float *tmpf1, *tmpf2;
235 
236  uint edge_offset;
237 
238  MPoly *mpoly_orig, *mpoly_new, *mp_new;
239  MLoop *mloop_orig, *mloop_new, *ml_new;
240  MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
241  MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;
242 
243  Object *ob_axis = ltmd->ob_axis;
244 
245  ScrewVertConnect *vc, *vc_tmp, *vert_connect = NULL;
246 
247  const char mpoly_flag = (ltmd->flag & MOD_SCREW_SMOOTH_SHADING) ? ME_SMOOTH : 0;
248 
249  /* don't do anything? */
250  if (!totvert) {
251  return BKE_mesh_new_nomain_from_template(mesh, 0, 0, 0, 0, 0);
252  }
253 
254  switch (ltmd->axis) {
255  case 0:
256  other_axis_1 = 1;
257  other_axis_2 = 2;
258  break;
259  case 1:
260  other_axis_1 = 0;
261  other_axis_2 = 2;
262  break;
263  default: /* 2, use default to quiet warnings */
264  other_axis_1 = 0;
265  other_axis_2 = 1;
266  break;
267  }
268 
269  axis_vec[ltmd->axis] = 1.0f;
270 
271  if (ob_axis != NULL) {
272  /* calc the matrix relative to the axis object */
273  invert_m4_m4(mtx_tmp_a, ctx->object->obmat);
274  copy_m4_m4(mtx_tx_inv, ob_axis->obmat);
275  mul_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv);
276 
277  /* calc the axis vec */
278  mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */
279  normalize_v3(axis_vec);
280 
281  /* screw */
282  if (ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
283  /* find the offset along this axis relative to this objects matrix */
284  float totlen = len_v3(mtx_tx[3]);
285 
286  if (totlen != 0.0f) {
287  const float zero[3] = {0.0f, 0.0f, 0.0f};
288  float cp[3];
289  screw_ofs = closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
290  }
291  else {
292  screw_ofs = 0.0f;
293  }
294  }
295 
296  /* angle */
297 
298 #if 0 /* can't include this, not predictable enough, though quite fun. */
299  if (ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
300  float mtx3_tx[3][3];
301  copy_m3_m4(mtx3_tx, mtx_tx);
302 
303  float vec[3] = {0, 1, 0};
304  float cross1[3];
305  float cross2[3];
306  cross_v3_v3v3(cross1, vec, axis_vec);
307 
308  mul_v3_m3v3(cross2, mtx3_tx, cross1);
309  {
310  float c1[3];
311  float c2[3];
312  float axis_tmp[3];
313 
314  cross_v3_v3v3(c1, cross2, axis_vec);
315  cross_v3_v3v3(c2, axis_vec, c1);
316 
317  angle = angle_v3v3(cross1, c2);
318 
319  cross_v3_v3v3(axis_tmp, cross1, c2);
320  normalize_v3(axis_tmp);
321 
322  if (len_v3v3(axis_tmp, axis_vec) > 1.0f) {
323  angle = -angle;
324  }
325  }
326  }
327 #endif
328  }
329  else {
330  axis_char = (char)(axis_char + ltmd->axis); /* 'X' + axis */
331 
332  /* useful to be able to use the axis vec in some cases still */
333  zero_v3(axis_vec);
334  axis_vec[ltmd->axis] = 1.0f;
335  }
336 
337  /* apply the multiplier */
338  angle *= (float)ltmd->iter;
339  screw_ofs *= (float)ltmd->iter;
340  uv_u_scale = 1.0f / (float)(step_tot);
341 
342  /* multiplying the steps is a bit tricky, this works best */
343  step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
344 
345  /* Will the screw be closed?
346  * NOTE: smaller than `FLT_EPSILON * 100`
347  * gives problems with float precision so its never closed. */
348  if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) &&
349  fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f) && step_tot > 3) {
350  close = 1;
351  step_tot--;
352 
353  maxVerts = totvert * step_tot; /* -1 because we're joining back up */
354  maxEdges = (totvert * step_tot) + /* these are the edges between new verts */
355  (totedge * step_tot); /* -1 because vert edges join */
356  maxPolys = totedge * step_tot;
357 
358  screw_ofs = 0.0f;
359  }
360  else {
361  close = 0;
362  if (step_tot < 2) {
363  step_tot = 2;
364  }
365 
366  maxVerts = totvert * step_tot; /* -1 because we're joining back up */
367  maxEdges = (totvert * (step_tot - 1)) + /* these are the edges between new verts */
368  (totedge * step_tot); /* -1 because vert edges join */
369  maxPolys = totedge * (step_tot - 1);
370  }
371 
372  if ((ltmd->flag & MOD_SCREW_UV_STRETCH_U) == 0) {
373  uv_u_scale = (uv_u_scale / (float)ltmd->iter) * (angle / ((float)M_PI * 2.0f));
374  }
375 
376  /* The `screw_ofs` cannot change from now on. */
377  const bool do_remove_doubles = (ltmd->flag & MOD_SCREW_MERGE) && (screw_ofs == 0.0f);
378 
380  mesh, (int)maxVerts, (int)maxEdges, 0, (int)maxPolys * 4, (int)maxPolys);
381 
382  /* copy verts from mesh */
383  mvert_orig = mesh->mvert;
384  medge_orig = mesh->medge;
385 
386  mvert_new = result->mvert;
387  mpoly_new = result->mpoly;
388  mloop_new = result->mloop;
389  medge_new = result->medge;
390 
391  if (!CustomData_has_layer(&result->pdata, CD_ORIGINDEX)) {
392  CustomData_add_layer(&result->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, (int)maxPolys);
393  }
394 
395  int *origindex = CustomData_get_layer(&result->pdata, CD_ORIGINDEX);
396 
397  CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)totvert);
398 
399  if (mloopuv_layers_tot) {
400  const float zero_co[3] = {0};
401  plane_from_point_normal_v3(uv_axis_plane, zero_co, axis_vec);
402  }
403 
404  if (mloopuv_layers_tot) {
405  uint uv_lay;
406  for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
407  mloopuv_layers[uv_lay] = CustomData_get_layer_n(&result->ldata, CD_MLOOPUV, (int)uv_lay);
408  }
409 
410  if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
411  for (i = 0, mv_orig = mvert_orig; i < totvert; i++, mv_orig++) {
412  const float v = dist_signed_squared_to_plane_v3(mv_orig->co, uv_axis_plane);
413  uv_v_minmax[0] = min_ff(v, uv_v_minmax[0]);
414  uv_v_minmax[1] = max_ff(v, uv_v_minmax[1]);
415  }
416  uv_v_minmax[0] = sqrtf_signed(uv_v_minmax[0]);
417  uv_v_minmax[1] = sqrtf_signed(uv_v_minmax[1]);
418  }
419 
420  uv_v_range_inv = uv_v_minmax[1] - uv_v_minmax[0];
421  uv_v_range_inv = uv_v_range_inv ? 1.0f / uv_v_range_inv : 0.0f;
422  }
423 
424  /* Set the locations of the first set of verts */
425 
426  mv_new = mvert_new;
427  mv_orig = mvert_orig;
428 
429  BLI_bitmap *vert_tag = BLI_BITMAP_NEW(totvert, __func__);
430 
431  /* Copy the first set of edges */
432  med_orig = medge_orig;
433  med_new = medge_new;
434  for (i = 0; i < totedge; i++, med_orig++, med_new++) {
435  med_new->v1 = med_orig->v1;
436  med_new->v2 = med_orig->v2;
437  med_new->crease = med_orig->crease;
438  med_new->flag = med_orig->flag & ~ME_LOOSEEDGE;
439 
440  /* Tag mvert as not loose. */
441  BLI_BITMAP_ENABLE(vert_tag, med_orig->v1);
442  BLI_BITMAP_ENABLE(vert_tag, med_orig->v2);
443  }
444 
445  /* build polygon -> edge map */
446  if (totpoly) {
447  MPoly *mp_orig;
448 
449  mpoly_orig = mesh->mpoly;
450  mloop_orig = mesh->mloop;
451  edge_poly_map = MEM_malloc_arrayN(totedge, sizeof(*edge_poly_map), __func__);
452  memset(edge_poly_map, 0xff, sizeof(*edge_poly_map) * totedge);
453 
454  vert_loop_map = MEM_malloc_arrayN(totvert, sizeof(*vert_loop_map), __func__);
455  memset(vert_loop_map, 0xff, sizeof(*vert_loop_map) * totvert);
456 
457  for (i = 0, mp_orig = mpoly_orig; i < totpoly; i++, mp_orig++) {
458  uint loopstart = (uint)mp_orig->loopstart;
459  uint loopend = loopstart + (uint)mp_orig->totloop;
460 
461  MLoop *ml_orig = &mloop_orig[loopstart];
462  uint k;
463  for (k = loopstart; k < loopend; k++, ml_orig++) {
464  edge_poly_map[ml_orig->e] = i;
465  vert_loop_map[ml_orig->v] = k;
466 
467  /* also order edges based on faces */
468  if (medge_new[ml_orig->e].v1 != ml_orig->v) {
469  SWAP(uint, medge_new[ml_orig->e].v1, medge_new[ml_orig->e].v2);
470  }
471  }
472  }
473  }
474 
475  if (ltmd->flag & MOD_SCREW_NORMAL_CALC) {
476 
477  /*
478  * Normal Calculation (for face flipping)
479  * Sort edge verts for correct face flipping
480  * NOT REALLY NEEDED but face flipping is nice. */
481 
482  /* Notice!
483  *
484  * Since we are only ordering the edges here it can avoid mallocing the
485  * extra space by abusing the vert array before its filled with new verts.
486  * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert
487  * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3
488  * so its safe to use the second 2 thirds of MVert the array for vert_connect,
489  * just make sure ScrewVertConnect struct is no more than twice as big as MVert,
490  * at the moment there is no chance of that being a problem,
491  * unless MVert becomes half its current size.
492  *
493  * once the edges are ordered, vert_connect is not needed and it can be used for verts
494  *
495  * This makes the modifier faster with one less alloc.
496  */
497 
498  vert_connect = MEM_malloc_arrayN(totvert, sizeof(ScrewVertConnect), "ScrewVertConnect");
499  /* skip the first slice of verts. */
500  // vert_connect = (ScrewVertConnect *) &medge_new[totvert];
501  vc = vert_connect;
502 
503  /* Copy Vert Locations */
504  if (totedge != 0) {
505  // printf("\n\n\n\n\nStarting Modifier\n");
506  /* set edge users */
507  med_new = medge_new;
508  mv_new = mvert_new;
509 
510  if (ob_axis != NULL) {
511  /* `mtx_tx` is initialized early on. */
512  for (i = 0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
513  vc->co[0] = mv_new->co[0] = mv_orig->co[0];
514  vc->co[1] = mv_new->co[1] = mv_orig->co[1];
515  vc->co[2] = mv_new->co[2] = mv_orig->co[2];
516 
517  vc->flag = 0;
518  vc->e[0] = vc->e[1] = NULL;
519  vc->v[0] = vc->v[1] = SV_UNUSED;
520 
521  mul_m4_v3(mtx_tx, vc->co);
522  /* length in 2d, don't sqrt because this is only for comparison */
523  vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] +
524  vc->co[other_axis_2] * vc->co[other_axis_2];
525 
526  // printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);
527  }
528  }
529  else {
530  for (i = 0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
531  vc->co[0] = mv_new->co[0] = mv_orig->co[0];
532  vc->co[1] = mv_new->co[1] = mv_orig->co[1];
533  vc->co[2] = mv_new->co[2] = mv_orig->co[2];
534 
535  vc->flag = 0;
536  vc->e[0] = vc->e[1] = NULL;
537  vc->v[0] = vc->v[1] = SV_UNUSED;
538 
539  /* length in 2d, don't sqrt because this is only for comparison */
540  vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] +
541  vc->co[other_axis_2] * vc->co[other_axis_2];
542 
543  // printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);
544  }
545  }
546 
547  /* this loop builds connectivity info for verts */
548  for (i = 0; i < totedge; i++, med_new++) {
549  vc = &vert_connect[med_new->v1];
550 
551  if (vc->v[0] == SV_UNUSED) { /* unused */
552  vc->v[0] = med_new->v2;
553  vc->e[0] = med_new;
554  }
555  else if (vc->v[1] == SV_UNUSED) {
556  vc->v[1] = med_new->v2;
557  vc->e[1] = med_new;
558  }
559  else {
560  vc->v[0] = vc->v[1] = SV_INVALID; /* error value - don't use, 3 edges on vert */
561  }
562 
563  vc = &vert_connect[med_new->v2];
564 
565  /* same as above but swap v1/2 */
566  if (vc->v[0] == SV_UNUSED) { /* unused */
567  vc->v[0] = med_new->v1;
568  vc->e[0] = med_new;
569  }
570  else if (vc->v[1] == SV_UNUSED) {
571  vc->v[1] = med_new->v1;
572  vc->e[1] = med_new;
573  }
574  else {
575  vc->v[0] = vc->v[1] = SV_INVALID; /* error value - don't use, 3 edges on vert */
576  }
577  }
578 
579  /* find the first vert */
580  vc = vert_connect;
581  for (i = 0; i < totvert; i++, vc++) {
582  /* Now do search for connected verts, order all edges and flip them
583  * so resulting faces are flipped the right way */
584  vc_tot_linked = 0; /* count the number of linked verts for this loop */
585  if (vc->flag == 0) {
586  uint v_best = SV_UNUSED, ed_loop_closed = 0; /* vert and vert new */
587  ScrewVertIter lt_iter;
588  float fl = -1.0f;
589 
590  /* compiler complains if not initialized, but it should be initialized below */
591  bool ed_loop_flip = false;
592 
593  // printf("Loop on connected vert: %i\n", i);
594 
595  for (j = 0; j < 2; j++) {
596  // printf("\tSide: %i\n", j);
597  screwvert_iter_init(&lt_iter, vert_connect, i, j);
598  if (j == 1) {
599  screwvert_iter_step(&lt_iter);
600  }
601  while (lt_iter.v_poin) {
602  // printf("\t\tVERT: %i\n", lt_iter.v);
603  if (lt_iter.v_poin->flag) {
604  // printf("\t\t\tBreaking Found end\n");
605  // endpoints[0] = endpoints[1] = SV_UNUSED;
606  ed_loop_closed = 1; /* circle */
607  break;
608  }
609  lt_iter.v_poin->flag = 1;
610  vc_tot_linked++;
611  // printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);
612  if (fl <= lt_iter.v_poin->dist) {
613  fl = lt_iter.v_poin->dist;
614  v_best = lt_iter.v;
615  // printf("\t\t\tVERT BEST: %i\n", v_best);
616  }
617  screwvert_iter_step(&lt_iter);
618  if (!lt_iter.v_poin) {
619  // printf("\t\t\tFound End Also Num %i\n", j);
620  // endpoints[j] = lt_iter.v_other; /* other is still valid */
621  break;
622  }
623  }
624  }
625 
626  /* Now we have a collection of used edges. flip their edges the right way. */
627  /* if (v_best != SV_UNUSED) - */
628 
629  // printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);
630 
631  if (vc_tot_linked > 1) {
632  float vf_1, vf_2, vf_best;
633 
634  vc_tmp = &vert_connect[v_best];
635 
636  tmpf1 = vert_connect[vc_tmp->v[0]].co;
637  tmpf2 = vert_connect[vc_tmp->v[1]].co;
638 
639  /* edge connects on each side! */
640  if (SV_IS_VALID(vc_tmp->v[0]) && SV_IS_VALID(vc_tmp->v[1])) {
641  // printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);
642  /* Find out which is higher. */
643 
644  vf_1 = tmpf1[ltmd->axis];
645  vf_2 = tmpf2[ltmd->axis];
646  vf_best = vc_tmp->co[ltmd->axis];
647 
648  if (vf_1 < vf_best && vf_best < vf_2) {
649  ed_loop_flip = 0;
650  }
651  else if (vf_1 > vf_best && vf_best > vf_2) {
652  ed_loop_flip = 1;
653  }
654  else {
655  /* not so simple to work out which edge is higher */
656  sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co);
657  sub_v3_v3v3(tmp_vec2, tmpf2, vc_tmp->co);
658  normalize_v3(tmp_vec1);
659  normalize_v3(tmp_vec2);
660 
661  if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) {
662  ed_loop_flip = 1;
663  }
664  else {
665  ed_loop_flip = 0;
666  }
667  }
668  }
669  else if (SV_IS_VALID(vc_tmp->v[0])) { /* Vertex only connected on 1 side. */
670  // printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);
671  if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
672  ed_loop_flip = 1;
673  }
674  else { /* best is below or even... in even case we can't know what to do. */
675  ed_loop_flip = 0;
676  }
677  }
678 #if 0
679  else {
680  printf("No Connected ___\n");
681  }
682 #endif
683 
684  // printf("flip direction %i\n", ed_loop_flip);
685 
686  /* Switch the flip option if set
687  * NOTE: flip is now done at face level so copying group slices is easier. */
688 #if 0
689  if (do_flip) {
690  ed_loop_flip = !ed_loop_flip;
691  }
692 #endif
693 
694  if (angle < 0.0f) {
695  ed_loop_flip = !ed_loop_flip;
696  }
697 
698  /* if its closed, we only need 1 loop */
699  for (j = ed_loop_closed; j < 2; j++) {
700  // printf("Ordering Side J %i\n", j);
701 
702  screwvert_iter_init(&lt_iter, vert_connect, v_best, j);
703  // printf("\n\nStarting - Loop\n");
704  lt_iter.v_poin->flag = 1; /* so a non loop will traverse the other side */
705 
706  /* If this is the vert off the best vert and
707  * the best vert has 2 edges connected too it
708  * then swap the flip direction */
709  if (j == 1 && SV_IS_VALID(vc_tmp->v[0]) && SV_IS_VALID(vc_tmp->v[1])) {
710  ed_loop_flip = !ed_loop_flip;
711  }
712 
713  while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
714  // printf("\tOrdering Vert V %i\n", lt_iter.v);
715 
716  lt_iter.v_poin->flag = 2;
717  if (lt_iter.e) {
718  if (lt_iter.v == lt_iter.e->v1) {
719  if (ed_loop_flip == 0) {
720  // printf("\t\t\tFlipping 0\n");
721  SWAP(uint, lt_iter.e->v1, lt_iter.e->v2);
722  }
723 #if 0
724  else {
725  printf("\t\t\tFlipping Not 0\n");
726  }
727 #endif
728  }
729  else if (lt_iter.v == lt_iter.e->v2) {
730  if (ed_loop_flip == 1) {
731  // printf("\t\t\tFlipping 1\n");
732  SWAP(uint, lt_iter.e->v1, lt_iter.e->v2);
733  }
734 #if 0
735  else {
736  printf("\t\t\tFlipping Not 1\n");
737  }
738 #endif
739  }
740 #if 0
741  else {
742  printf("\t\tIncorrect edge topology");
743  }
744 #endif
745  }
746 #if 0
747  else {
748  printf("\t\tNo Edge at this point\n");
749  }
750 #endif
751  screwvert_iter_step(&lt_iter);
752  }
753  }
754  }
755  }
756  }
757  }
758  }
759  else {
760  mv_orig = mvert_orig;
761  mv_new = mvert_new;
762 
763  for (i = 0; i < totvert; i++, mv_new++, mv_orig++) {
764  copy_v3_v3(mv_new->co, mv_orig->co);
765  }
766  }
767  /* done with edge connectivity based normal flipping */
768 
769  /* Add Faces */
770  for (step = 1; step < step_tot; step++) {
771  const uint varray_stride = totvert * step;
772  float step_angle;
773  float mat[4][4];
774  /* Rotation Matrix */
775  step_angle = (angle / (float)(step_tot - (!close))) * (float)step;
776 
777  if (ob_axis != NULL) {
778  axis_angle_normalized_to_mat3(mat3, axis_vec, step_angle);
779  }
780  else {
781  axis_angle_to_mat3_single(mat3, axis_char, step_angle);
782  }
783  copy_m4_m3(mat, mat3);
784 
785  if (screw_ofs) {
786  madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)step / (float)(step_tot - 1)));
787  }
788 
789  /* copy a slice */
790  CustomData_copy_data(&mesh->vdata, &result->vdata, 0, (int)varray_stride, (int)totvert);
791 
792  mv_new_base = mvert_new;
793  mv_new = &mvert_new[varray_stride]; /* advance to the next slice */
794 
795  for (j = 0; j < totvert; j++, mv_new_base++, mv_new++) {
796  /* set location */
797  copy_v3_v3(mv_new->co, mv_new_base->co);
798 
799  /* only need to set these if using non cleared memory */
800  // mv_new->mat_nr = mv_new->flag = 0;
801 
802  if (ob_axis != NULL) {
803  sub_v3_v3(mv_new->co, mtx_tx[3]);
804 
805  mul_m4_v3(mat, mv_new->co);
806 
807  add_v3_v3(mv_new->co, mtx_tx[3]);
808  }
809  else {
810  mul_m4_v3(mat, mv_new->co);
811  }
812 
813  /* add the new edge */
814  med_new->v1 = varray_stride + j;
815  med_new->v2 = med_new->v1 - totvert;
816  med_new->flag = ME_EDGEDRAW | ME_EDGERENDER;
817  if (!BLI_BITMAP_TEST(vert_tag, j)) {
818  med_new->flag |= ME_LOOSEEDGE;
819  }
820  med_new++;
821  }
822  }
823 
824  /* we can avoid if using vert alloc trick */
825  if (vert_connect) {
826  MEM_freeN(vert_connect);
827  vert_connect = NULL;
828  }
829 
830  if (close) {
831  /* last loop of edges, previous loop doesn't account for the last set of edges */
832  const uint varray_stride = (step_tot - 1) * totvert;
833 
834  for (i = 0; i < totvert; i++) {
835  med_new->v1 = i;
836  med_new->v2 = varray_stride + i;
837  med_new->flag = ME_EDGEDRAW | ME_EDGERENDER;
838  if (!BLI_BITMAP_TEST(vert_tag, i)) {
839  med_new->flag |= ME_LOOSEEDGE;
840  }
841  med_new++;
842  }
843  }
844 
845  mp_new = mpoly_new;
846  ml_new = mloop_new;
847  med_new_firstloop = medge_new;
848 
849  /* more of an offset in this case */
850  edge_offset = totedge + (totvert * (step_tot - (close ? 0 : 1)));
851 
852  for (i = 0; i < totedge; i++, med_new_firstloop++) {
853  const uint step_last = step_tot - (close ? 1 : 2);
854  const uint mpoly_index_orig = totpoly ? edge_poly_map[i] : UINT_MAX;
855  const bool has_mpoly_orig = (mpoly_index_orig != UINT_MAX);
856  float uv_v_offset_a, uv_v_offset_b;
857 
858  const uint mloop_index_orig[2] = {
859  vert_loop_map ? vert_loop_map[medge_new[i].v1] : UINT_MAX,
860  vert_loop_map ? vert_loop_map[medge_new[i].v2] : UINT_MAX,
861  };
862  const bool has_mloop_orig = mloop_index_orig[0] != UINT_MAX;
863 
864  short mat_nr;
865 
866  /* for each edge, make a cylinder of quads */
867  i1 = med_new_firstloop->v1;
868  i2 = med_new_firstloop->v2;
869 
870  if (has_mpoly_orig) {
871  mat_nr = mpoly_orig[mpoly_index_orig].mat_nr;
872  }
873  else {
874  mat_nr = 0;
875  }
876 
877  if (has_mloop_orig == false && mloopuv_layers_tot) {
878  uv_v_offset_a = dist_signed_to_plane_v3(mvert_new[medge_new[i].v1].co, uv_axis_plane);
879  uv_v_offset_b = dist_signed_to_plane_v3(mvert_new[medge_new[i].v2].co, uv_axis_plane);
880 
881  if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
882  uv_v_offset_a = (uv_v_offset_a - uv_v_minmax[0]) * uv_v_range_inv;
883  uv_v_offset_b = (uv_v_offset_b - uv_v_minmax[0]) * uv_v_range_inv;
884  }
885  }
886 
887  for (step = 0; step <= step_last; step++) {
888 
889  /* Polygon */
890  if (has_mpoly_orig) {
892  &mesh->pdata, &result->pdata, (int)mpoly_index_orig, (int)mpoly_index, 1);
893  origindex[mpoly_index] = (int)mpoly_index_orig;
894  }
895  else {
896  origindex[mpoly_index] = ORIGINDEX_NONE;
897  mp_new->flag = mpoly_flag;
898  mp_new->mat_nr = mat_nr;
899  }
900  mp_new->loopstart = mpoly_index * 4;
901  mp_new->totloop = 4;
902 
903  /* Loop-Custom-Data */
904  if (has_mloop_orig) {
905  int l_index = (int)(ml_new - mloop_new);
906 
908  &mesh->ldata, &result->ldata, (int)mloop_index_orig[0], l_index + 0, 1);
910  &mesh->ldata, &result->ldata, (int)mloop_index_orig[1], l_index + 1, 1);
912  &mesh->ldata, &result->ldata, (int)mloop_index_orig[1], l_index + 2, 1);
914  &mesh->ldata, &result->ldata, (int)mloop_index_orig[0], l_index + 3, 1);
915 
916  if (mloopuv_layers_tot) {
917  uint uv_lay;
918  const float uv_u_offset_a = (float)(step)*uv_u_scale;
919  const float uv_u_offset_b = (float)(step + 1) * uv_u_scale;
920  for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
921  MLoopUV *mluv = &mloopuv_layers[uv_lay][l_index];
922 
923  mluv[quad_ord[0]].uv[0] += uv_u_offset_a;
924  mluv[quad_ord[1]].uv[0] += uv_u_offset_a;
925  mluv[quad_ord[2]].uv[0] += uv_u_offset_b;
926  mluv[quad_ord[3]].uv[0] += uv_u_offset_b;
927  }
928  }
929  }
930  else {
931  if (mloopuv_layers_tot) {
932  int l_index = (int)(ml_new - mloop_new);
933 
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  MLoopUV *mluv = &mloopuv_layers[uv_lay][l_index];
939 
940  copy_v2_fl2(mluv[quad_ord[0]].uv, uv_u_offset_a, uv_v_offset_a);
941  copy_v2_fl2(mluv[quad_ord[1]].uv, uv_u_offset_a, uv_v_offset_b);
942  copy_v2_fl2(mluv[quad_ord[2]].uv, uv_u_offset_b, uv_v_offset_b);
943  copy_v2_fl2(mluv[quad_ord[3]].uv, 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  ml_new[quad_ord[0]].v = i1;
952  ml_new[quad_ord[1]].v = i2;
953  ml_new[quad_ord[2]].v = i2 + totvert;
954  ml_new[quad_ord[3]].v = i1 + totvert;
955 
956  ml_new[quad_ord_ofs[0]].e = step == 0 ? i :
957  (edge_offset + step + (i * (step_tot - 1))) - 1;
958  ml_new[quad_ord_ofs[1]].e = totedge + i2;
959  ml_new[quad_ord_ofs[2]].e = edge_offset + step + (i * (step_tot - 1));
960  ml_new[quad_ord_ofs[3]].e = totedge + i1;
961 
962  /* new vertical edge */
963  if (step) { /* The first set is already done */
964  med_new->v1 = i1;
965  med_new->v2 = i2;
966  med_new->flag = med_new_firstloop->flag;
967  med_new->crease = med_new_firstloop->crease;
968  med_new++;
969  }
970  i1 += totvert;
971  i2 += totvert;
972  }
973  else {
974  /* last segment */
975  ml_new[quad_ord[0]].v = i1;
976  ml_new[quad_ord[1]].v = i2;
977  ml_new[quad_ord[2]].v = med_new_firstloop->v2;
978  ml_new[quad_ord[3]].v = med_new_firstloop->v1;
979 
980  ml_new[quad_ord_ofs[0]].e = (edge_offset + step + (i * (step_tot - 1))) - 1;
981  ml_new[quad_ord_ofs[1]].e = totedge + i2;
982  ml_new[quad_ord_ofs[2]].e = i;
983  ml_new[quad_ord_ofs[3]].e = totedge + i1;
984  }
985 
986  mp_new++;
987  ml_new += 4;
988  mpoly_index++;
989  }
990 
991  /* new vertical edge */
992  med_new->v1 = i1;
993  med_new->v2 = i2;
994  med_new->flag = med_new_firstloop->flag & ~ME_LOOSEEDGE;
995  med_new->crease = med_new_firstloop->crease;
996  med_new++;
997  }
998 
999  /* validate loop edges */
1000 #if 0
1001  {
1002  uint i = 0;
1003  printf("\n");
1004  for (; i < maxPolys * 4; i += 4) {
1005  uint ii;
1006  ml_new = mloop_new + i;
1007  ii = findEd(medge_new, maxEdges, ml_new[0].v, ml_new[1].v);
1008  printf("%d %d -- ", ii, ml_new[0].e);
1009  ml_new[0].e = ii;
1010 
1011  ii = findEd(medge_new, maxEdges, ml_new[1].v, ml_new[2].v);
1012  printf("%d %d -- ", ii, ml_new[1].e);
1013  ml_new[1].e = ii;
1014 
1015  ii = findEd(medge_new, maxEdges, ml_new[2].v, ml_new[3].v);
1016  printf("%d %d -- ", ii, ml_new[2].e);
1017  ml_new[2].e = ii;
1018 
1019  ii = findEd(medge_new, maxEdges, ml_new[3].v, ml_new[0].v);
1020  printf("%d %d\n", ii, ml_new[3].e);
1021  ml_new[3].e = ii;
1022  }
1023  }
1024 #endif
1025 
1026  MEM_freeN(vert_tag);
1027 
1028  if (edge_poly_map) {
1029  MEM_freeN(edge_poly_map);
1030  }
1031 
1032  if (vert_loop_map) {
1033  MEM_freeN(vert_loop_map);
1034  }
1035 
1036  if (do_remove_doubles) {
1038  mvert_new,
1039  totvert,
1040  step_tot,
1041  axis_vec,
1042  ob_axis != NULL ? mtx_tx[3] : NULL,
1043  ltmd->merge_dist);
1044  }
1045 
1046  return result;
1047 }
1048 
1050 {
1051  ScrewModifierData *ltmd = (ScrewModifierData *)md;
1052  if (ltmd->ob_axis != NULL) {
1053  DEG_add_object_relation(ctx->node, ltmd->ob_axis, DEG_OB_COMP_TRANSFORM, "Screw Modifier");
1054  DEG_add_modifier_to_transform_relation(ctx->node, "Screw Modifier");
1055  }
1056 }
1057 
1058 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
1059 {
1060  ScrewModifierData *ltmd = (ScrewModifierData *)md;
1061 
1062  walk(userData, ob, (ID **)&ltmd->ob_axis, IDWALK_CB_NOP);
1063 }
1064 
1065 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
1066 {
1067  uiLayout *sub, *row, *col;
1068  uiLayout *layout = panel->layout;
1069  int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
1070 
1072 
1073  PointerRNA screw_obj_ptr = RNA_pointer_get(ptr, "object");
1074 
1075  uiLayoutSetPropSep(layout, true);
1076 
1077  col = uiLayoutColumn(layout, false);
1078  uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
1079  row = uiLayoutRow(col, false);
1080  uiLayoutSetActive(row,
1081  RNA_pointer_is_null(&screw_obj_ptr) ||
1082  !RNA_boolean_get(ptr, "use_object_screw_offset"));
1083  uiItemR(row, ptr, "screw_offset", 0, NULL, ICON_NONE);
1084  uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE);
1085 
1086  uiItemS(layout);
1087  col = uiLayoutColumn(layout, false);
1088  row = uiLayoutRow(col, false);
1089  uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1090  uiItemR(col, ptr, "object", 0, IFACE_("Axis Object"), ICON_NONE);
1091  sub = uiLayoutColumn(col, false);
1092  uiLayoutSetActive(sub, !RNA_pointer_is_null(&screw_obj_ptr));
1093  uiItemR(sub, ptr, "use_object_screw_offset", 0, NULL, ICON_NONE);
1094 
1095  uiItemS(layout);
1096 
1097  col = uiLayoutColumn(layout, true);
1098  uiItemR(col, ptr, "steps", 0, IFACE_("Steps Viewport"), ICON_NONE);
1099  uiItemR(col, ptr, "render_steps", 0, IFACE_("Render"), ICON_NONE);
1100 
1101  uiItemS(layout);
1102 
1103  row = uiLayoutRowWithHeading(layout, true, IFACE_("Merge"));
1104  uiItemR(row, ptr, "use_merge_vertices", 0, "", ICON_NONE);
1105  sub = uiLayoutRow(row, true);
1106  uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_merge_vertices"));
1107  uiItemR(sub, ptr, "merge_threshold", 0, "", ICON_NONE);
1108 
1109  uiItemS(layout);
1110 
1111  row = uiLayoutRowWithHeading(layout, true, IFACE_("Stretch UVs"));
1112  uiItemR(row, ptr, "use_stretch_u", toggles_flag, IFACE_("U"), ICON_NONE);
1113  uiItemR(row, ptr, "use_stretch_v", toggles_flag, IFACE_("V"), ICON_NONE);
1114 
1115  modifier_panel_end(layout, ptr);
1116 }
1117 
1118 static void normals_panel_draw(const bContext *UNUSED(C), Panel *panel)
1119 {
1120  uiLayout *col;
1121  uiLayout *layout = panel->layout;
1122 
1124 
1125  uiLayoutSetPropSep(layout, true);
1126 
1127  col = uiLayoutColumn(layout, false);
1128  uiItemR(col, ptr, "use_smooth_shade", 0, NULL, ICON_NONE);
1129  uiItemR(col, ptr, "use_normal_calculate", 0, NULL, ICON_NONE);
1130  uiItemR(col, ptr, "use_normal_flip", 0, NULL, ICON_NONE);
1131 }
1132 
1133 static void panelRegister(ARegionType *region_type)
1134 {
1135  PanelType *panel_type = modifier_panel_register(region_type, eModifierType_Screw, panel_draw);
1137  region_type, "normals", "Normals", NULL, normals_panel_draw, panel_type);
1138 }
1139 
1141  /* name */ N_("Screw"),
1142  /* structName */ "ScrewModifierData",
1143  /* structSize */ sizeof(ScrewModifierData),
1144  /* srna */ &RNA_ScrewModifier,
1145  /* type */ eModifierTypeType_Constructive,
1146 
1149  /* icon */ ICON_MOD_SCREW,
1150 
1151  /* copyData */ BKE_modifier_copydata_generic,
1152 
1153  /* deformVerts */ NULL,
1154  /* deformMatrices */ NULL,
1155  /* deformVertsEM */ NULL,
1156  /* deformMatricesEM */ NULL,
1157  /* modifyMesh */ modifyMesh,
1158  /* modifyGeometrySet */ NULL,
1159 
1160  /* initData */ initData,
1161  /* requiredDataMask */ NULL,
1162  /* freeData */ NULL,
1163  /* isDisabled */ NULL,
1164  /* updateDepsgraph */ updateDepsgraph,
1165  /* dependsOnTime */ NULL,
1166  /* dependsOnNormals */ NULL,
1167  /* foreachIDLink */ foreachIDLink,
1168  /* foreachTexLink */ NULL,
1169  /* freeRuntimeData */ NULL,
1170  /* panelRegister */ panelRegister,
1171  /* blendWrite */ NULL,
1172  /* blendRead */ NULL,
1173 };
typedef float(TangentPoint)[2]
int CustomData_number_of_layers(const struct CustomData *data, int type)
@ CD_CALLOC
bool CustomData_has_layer(const struct CustomData *data, int type)
#define ORIGINDEX_NONE
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
@ MESH_MERGE_VERTS_DUMP_IF_MAPPED
Definition: BKE_mesh.h:818
struct Mesh * BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
struct Mesh * BKE_mesh_merge_verts(struct Mesh *mesh, const int *vtargetmap, int tot_vtargetmap, int merge_mode)
Definition: mesh_merge.c:192
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:107
@ eModifierTypeFlag_AcceptsCVs
Definition: BKE_modifier.h:67
@ eModifierTypeFlag_EnableInEditmode
Definition: BKE_modifier.h:78
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:69
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_Constructive
Definition: BKE_modifier.h:47
@ MOD_APPLY_RENDER
Definition: BKE_modifier.h:115
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:64
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:81
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
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
Definition: BLI_math_base.h:20
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:209
float dist_signed_to_plane_v3(const float p[3], const float plane[4])
Definition: math_geom.c:461
float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3176
float dist_signed_squared_to_plane_v3(const float p[3], const float plane[4])
Definition: math_geom.c:429
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:790
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:897
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
Definition: math_vector.c:385
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 float normalize_v3(float r[3])
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])
Definition: math_vector.c:630
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)
Definition: math_vector.c:1223
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
unsigned int uint
Definition: BLI_sys_types.h:67
#define SWAP(type, a, b)
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
@ DEG_OB_COMP_TRANSFORM
@ CD_ORIGINDEX
@ CD_MLOOPUV
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ ME_SMOOTH
@ ME_EDGEDRAW
@ ME_EDGERENDER
@ ME_LOOSEEDGE
@ 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.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint i1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
struct ScrewVertConnect ScrewVertConnect
static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, uint v_init, uint dir)
Definition: MOD_screw.c:75
#define SV_INVALID
Definition: MOD_screw.c:72
static Mesh * mesh_remove_doubles_on_axis(Mesh *result, MVert *mvert_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.c:114
#define SV_UNUSED
Definition: MOD_screw.c:71
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
Definition: MOD_screw.c:1049
struct ScrewVertIter ScrewVertIter
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
Definition: MOD_screw.c:177
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
Definition: MOD_screw.c:1058
static void normals_panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_screw.c:1118
ModifierTypeInfo modifierType_Screw
Definition: MOD_screw.c:1140
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_screw.c:1065
static void initData(ModifierData *md)
Definition: MOD_screw.c:44
static void panelRegister(ARegionType *region_type)
Definition: MOD_screw.c:1133
static void screwvert_iter_step(ScrewVertIter *iter)
Definition: MOD_screw.c:94
#define SV_IS_VALID(v)
Definition: MOD_screw.c:73
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
Definition: MOD_ui_common.c:91
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
#define C
Definition: RandGen.cpp:25
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
@ UI_ITEM_R_EXPAND
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
uint col
#define UINT_MAX
Definition: hash_md5.c:43
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
#define fabsf(x)
Definition: metal/compat.h:219
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5167
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:164
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
Definition: DNA_ID.h:368
unsigned int v1
unsigned int v2
unsigned int e
unsigned int v
short mat_nr
float co[3]
struct MEdge * medge
CustomData vdata
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
CustomData pdata
int totpoly
struct MPoly * mpoly
CustomData ldata
ModifierApplyFlag flag
Definition: BKE_modifier.h:142
struct Object * object
Definition: BKE_modifier.h:141
struct DepsNodeHandle * node
Definition: BKE_modifier.h:134
float obmat[4][4]
struct uiLayout * layout
struct Object * ob_axis
MEdge * e[2]
Definition: MOD_screw.c:60
float co[3]
Definition: MOD_screw.c:58
ScrewVertConnect * v_array
Definition: MOD_screw.c:65
uint v_other
Definition: MOD_screw.c:67
MEdge * e
Definition: MOD_screw.c:68
ScrewVertConnect * v_poin
Definition: MOD_screw.c:66
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480