Blender  V2.93
curve.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include <math.h> /* floor */
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "BLI_blenlib.h"
31 #include "BLI_endian_switch.h"
32 #include "BLI_ghash.h"
33 #include "BLI_math.h"
34 #include "BLI_utildefines.h"
35 
36 #include "BLT_translation.h"
37 
38 /* Allow using deprecated functionality for .blend file I/O. */
39 #define DNA_DEPRECATED_ALLOW
40 
41 #include "DNA_anim_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_defaults.h"
44 #include "DNA_material_types.h"
45 
46 /* for dereferencing pointers */
47 #include "DNA_key_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_vfont_types.h"
50 
51 #include "BKE_anim_data.h"
52 #include "BKE_curve.h"
53 #include "BKE_curveprofile.h"
54 #include "BKE_displist.h"
55 #include "BKE_font.h"
56 #include "BKE_idtype.h"
57 #include "BKE_key.h"
58 #include "BKE_lib_id.h"
59 #include "BKE_lib_query.h"
60 #include "BKE_main.h"
61 #include "BKE_object.h"
62 
63 #include "DEG_depsgraph.h"
64 #include "DEG_depsgraph_query.h"
65 
66 #include "CLG_log.h"
67 
68 #include "BLO_read_write.h"
69 
70 /* globals */
71 
72 /* local */
73 static CLG_LogRef LOG = {"bke.curve"};
74 
75 static void curve_init_data(ID *id)
76 {
77  Curve *curve = (Curve *)id;
78 
80 
82 }
83 
84 static void curve_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
85 {
86  Curve *curve_dst = (Curve *)id_dst;
87  const Curve *curve_src = (const Curve *)id_src;
88 
89  BLI_listbase_clear(&curve_dst->nurb);
90  BKE_nurbList_duplicate(&(curve_dst->nurb), &(curve_src->nurb));
91 
92  curve_dst->mat = MEM_dupallocN(curve_src->mat);
93 
94  curve_dst->str = MEM_dupallocN(curve_src->str);
95  curve_dst->strinfo = MEM_dupallocN(curve_src->strinfo);
96  curve_dst->tb = MEM_dupallocN(curve_src->tb);
97  curve_dst->batch_cache = NULL;
98 
99  curve_dst->bevel_profile = BKE_curveprofile_copy(curve_src->bevel_profile);
100 
101  if (curve_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
102  BKE_id_copy_ex(bmain, &curve_src->key->id, (ID **)&curve_dst->key, flag);
103  /* XXX This is not nice, we need to make BKE_id_copy_ex fully re-entrant... */
104  curve_dst->key->from = &curve_dst->id;
105  }
106 
107  curve_dst->editnurb = NULL;
108  curve_dst->editfont = NULL;
109 }
110 
111 static void curve_free_data(ID *id)
112 {
113  Curve *curve = (Curve *)id;
114 
116 
119 
121 
123 
128 }
129 
131 {
132  Curve *curve = (Curve *)id;
137  for (int i = 0; i < curve->totcol; i++) {
139  }
144 }
145 
146 static void curve_blend_write(BlendWriter *writer, ID *id, const void *id_address)
147 {
148  Curve *cu = (Curve *)id;
149  if (cu->id.us > 0 || BLO_write_is_undo(writer)) {
150  /* Clean up, important in undo case to reduce false detection of changed datablocks. */
151  cu->editnurb = NULL;
152  cu->editfont = NULL;
153  cu->batch_cache = NULL;
154 
155  /* write LibData */
156  BLO_write_id_struct(writer, Curve, id_address, &cu->id);
157  BKE_id_blend_write(writer, &cu->id);
158 
159  /* direct data */
160  BLO_write_pointer_array(writer, cu->totcol, cu->mat);
161  if (cu->adt) {
162  BKE_animdata_blend_write(writer, cu->adt);
163  }
164 
165  if (cu->vfont) {
166  BLO_write_raw(writer, cu->len + 1, cu->str);
167  BLO_write_struct_array(writer, CharInfo, cu->len_char32 + 1, cu->strinfo);
168  BLO_write_struct_array(writer, TextBox, cu->totbox, cu->tb);
169  }
170  else {
171  /* is also the order of reading */
172  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
173  BLO_write_struct(writer, Nurb, nu);
174  }
175  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
176  if (nu->type == CU_BEZIER) {
177  BLO_write_struct_array(writer, BezTriple, nu->pntsu, nu->bezt);
178  }
179  else {
180  BLO_write_struct_array(writer, BPoint, nu->pntsu * nu->pntsv, nu->bp);
181  if (nu->knotsu) {
182  BLO_write_float_array(writer, KNOTSU(nu), nu->knotsu);
183  }
184  if (nu->knotsv) {
185  BLO_write_float_array(writer, KNOTSV(nu), nu->knotsv);
186  }
187  }
188  }
189  }
190 
191  if (cu->bevel_profile != NULL) {
193  }
194  }
195 }
196 
197 static void switch_endian_knots(Nurb *nu)
198 {
199  if (nu->knotsu) {
201  }
202  if (nu->knotsv) {
204  }
205 }
206 
207 static void curve_blend_read_data(BlendDataReader *reader, ID *id)
208 {
209  Curve *cu = (Curve *)id;
210  BLO_read_data_address(reader, &cu->adt);
211  BKE_animdata_blend_read_data(reader, cu->adt);
212 
213  /* Protect against integer overflow vulnerability. */
214  CLAMP(cu->len_char32, 0, INT_MAX - 4);
215 
216  BLO_read_pointer_array(reader, (void **)&cu->mat);
217 
218  BLO_read_data_address(reader, &cu->str);
219  BLO_read_data_address(reader, &cu->strinfo);
220  BLO_read_data_address(reader, &cu->tb);
221 
222  if (cu->vfont == NULL) {
223  BLO_read_list(reader, &(cu->nurb));
224  }
225  else {
226  cu->nurb.first = cu->nurb.last = NULL;
227 
228  TextBox *tb = MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "TextBoxread");
229  if (cu->tb) {
230  memcpy(tb, cu->tb, cu->totbox * sizeof(TextBox));
231  MEM_freeN(cu->tb);
232  cu->tb = tb;
233  }
234  else {
235  cu->totbox = 1;
236  cu->actbox = 1;
237  cu->tb = tb;
238  cu->tb[0].w = cu->linewidth;
239  }
240  if (cu->wordspace == 0.0f) {
241  cu->wordspace = 1.0f;
242  }
243  }
244 
245  cu->editnurb = NULL;
246  cu->editfont = NULL;
247  cu->batch_cache = NULL;
248 
249  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
250  BLO_read_data_address(reader, &nu->bezt);
251  BLO_read_data_address(reader, &nu->bp);
252  BLO_read_data_address(reader, &nu->knotsu);
253  BLO_read_data_address(reader, &nu->knotsv);
254  if (cu->vfont == NULL) {
255  nu->charidx = 0;
256  }
257 
258  if (BLO_read_requires_endian_switch(reader)) {
260  }
261  }
263 
264  BLO_read_data_address(reader, &cu->bevel_profile);
265  if (cu->bevel_profile != NULL) {
267  }
268 }
269 
270 static void curve_blend_read_lib(BlendLibReader *reader, ID *id)
271 {
272  Curve *cu = (Curve *)id;
273  for (int a = 0; a < cu->totcol; a++) {
274  BLO_read_id_address(reader, cu->id.lib, &cu->mat[a]);
275  }
276 
277  BLO_read_id_address(reader, cu->id.lib, &cu->bevobj);
278  BLO_read_id_address(reader, cu->id.lib, &cu->taperobj);
279  BLO_read_id_address(reader, cu->id.lib, &cu->textoncurve);
280  BLO_read_id_address(reader, cu->id.lib, &cu->vfont);
281  BLO_read_id_address(reader, cu->id.lib, &cu->vfontb);
282  BLO_read_id_address(reader, cu->id.lib, &cu->vfonti);
283  BLO_read_id_address(reader, cu->id.lib, &cu->vfontbi);
284 
285  BLO_read_id_address(reader, cu->id.lib, &cu->ipo); /* XXX deprecated - old animation system */
286  BLO_read_id_address(reader, cu->id.lib, &cu->key);
287 }
288 
289 static void curve_blend_read_expand(BlendExpander *expander, ID *id)
290 {
291  Curve *cu = (Curve *)id;
292  for (int a = 0; a < cu->totcol; a++) {
293  BLO_expand(expander, cu->mat[a]);
294  }
295 
296  BLO_expand(expander, cu->vfont);
297  BLO_expand(expander, cu->vfontb);
298  BLO_expand(expander, cu->vfonti);
299  BLO_expand(expander, cu->vfontbi);
300  BLO_expand(expander, cu->key);
301  BLO_expand(expander, cu->ipo); /* XXX deprecated - old animation system */
302  BLO_expand(expander, cu->bevobj);
303  BLO_expand(expander, cu->taperobj);
304  BLO_expand(expander, cu->textoncurve);
305 }
306 
308  .id_code = ID_CU,
309  .id_filter = FILTER_ID_CU,
310  .main_listbase_index = INDEX_ID_CU,
311  .struct_size = sizeof(Curve),
312  .name = "Curve",
313  .name_plural = "curves",
314  .translation_context = BLT_I18NCONTEXT_ID_CURVE,
315  .flags = 0,
316 
318  .copy_data = curve_copy_data,
319  .free_data = curve_free_data,
320  .make_local = NULL,
321  .foreach_id = curve_foreach_id,
322  .foreach_cache = NULL,
323  .owner_get = NULL,
324 
325  .blend_write = curve_blend_write,
326  .blend_read_data = curve_blend_read_data,
327  .blend_read_lib = curve_blend_read_lib,
328  .blend_read_expand = curve_blend_read_expand,
329 
330  .blend_read_undo_preserve = NULL,
331 
332  .lib_override_apply_post = NULL,
333 };
334 
335 static int cu_isectLL(const float v1[3],
336  const float v2[3],
337  const float v3[3],
338  const float v4[3],
339  short cox,
340  short coy,
341  float *lambda,
342  float *mu,
343  float vec[3]);
344 
345 /* frees editcurve entirely */
347 {
348  if (cu->editfont) {
349  EditFont *ef = cu->editfont;
350 
351  if (ef->textbuf) {
352  MEM_freeN(ef->textbuf);
353  }
354  if (ef->textbufinfo) {
355  MEM_freeN(ef->textbufinfo);
356  }
357  if (ef->selboxes) {
358  MEM_freeN(ef->selboxes);
359  }
360 
361  MEM_freeN(ef);
362  cu->editfont = NULL;
363  }
364 }
365 
367 {
368  CVKeyIndex *index = val;
369  MEM_freeN(index->orig_cv);
370  MEM_freeN(val);
371 }
372 
373 void BKE_curve_editNurb_keyIndex_delCV(GHash *keyindex, const void *cv)
374 {
375  BLI_assert(keyindex != NULL);
377 }
378 
380 {
381  if (!(*keyindex)) {
382  return;
383  }
385  *keyindex = NULL;
386 }
387 
389 {
390  if (cu->editnurb) {
393  MEM_freeN(cu->editnurb);
394  cu->editnurb = NULL;
395  }
396 }
397 
398 void BKE_curve_init(Curve *cu, const short curve_type)
399 {
400  curve_init_data(&cu->id);
401 
402  cu->type = curve_type;
403 
404  if (cu->type == OB_FONT) {
405  cu->flag |= CU_FRONT | CU_BACK;
406  cu->vfont = cu->vfontb = cu->vfonti = cu->vfontbi = BKE_vfont_builtin_get();
407  cu->vfont->id.us += 4;
408  cu->str = MEM_malloc_arrayN(12, sizeof(unsigned char), "str");
409  BLI_strncpy(cu->str, "Text", 12);
410  cu->len = cu->len_char32 = cu->pos = 4;
411  cu->strinfo = MEM_calloc_arrayN(12, sizeof(CharInfo), "strinfo new");
412  cu->totbox = cu->actbox = 1;
413  cu->tb = MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "textbox");
414  cu->tb[0].w = cu->tb[0].h = 0.0;
415  }
416  else if (cu->type == OB_SURF) {
417  cu->flag |= CU_3D;
418  cu->resolu = 4;
419  cu->resolv = 4;
420  }
421  cu->bevel_profile = NULL;
422 }
423 
424 Curve *BKE_curve_add(Main *bmain, const char *name, int type)
425 {
426  Curve *cu;
427 
428  /* We cannot use #BKE_id_new here as we need some custom initialization code. */
429  cu = BKE_libblock_alloc(bmain, ID_CU, name, 0);
430 
431  BKE_curve_init(cu, type);
432 
433  return cu;
434 }
435 
436 /* Get list of nurbs from editnurbs structure */
438 {
439  if (cu->editnurb) {
440  return &cu->editnurb->nurbs;
441  }
442 
443  return NULL;
444 }
445 
446 short BKE_curve_type_get(const Curve *cu)
447 {
448  int type = cu->type;
449 
450  if (cu->vfont) {
451  return OB_FONT;
452  }
453 
454  if (!cu->type) {
455  type = OB_CURVE;
456 
457  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
458  if (nu->pntsv > 1) {
459  type = OB_SURF;
460  }
461  }
462  }
463 
464  return type;
465 }
466 
468 {
469  ListBase *nurbs = BKE_curve_nurbs_get(cu);
470  bool is_2d = CU_IS_2D(cu);
471 
472  LISTBASE_FOREACH (Nurb *, nu, nurbs) {
473  if (is_2d) {
475  }
476 
477  /* since the handles are moved they need to be auto-located again */
478  if (nu->type == CU_BEZIER) {
480  }
481  }
482 }
483 
485 {
486  ob->type = BKE_curve_type_get(ob->data);
487 
488  if (ob->type == OB_CURVE) {
489  Curve *cu = ob->data;
490  if (CU_IS_2D(cu)) {
492  }
493  }
494 }
495 
497 {
498  /* This is Object-level data access,
499  * DO NOT touch to Mesh's bb, would be totally thread-unsafe. */
500  if (ob->runtime.bb == NULL || ob->runtime.bb->flag & BOUNDBOX_DIRTY) {
501  Curve *cu = ob->data;
502  float min[3], max[3];
503 
504  INIT_MINMAX(min, max);
505  BKE_curve_minmax(cu, true, min, max);
506 
507  if (ob->runtime.bb == NULL) {
508  ob->runtime.bb = MEM_mallocN(sizeof(*ob->runtime.bb), __func__);
509  }
511  ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
512  }
513 
514  return ob->runtime.bb;
515 }
516 
518 {
519  if (cu->texflag & CU_AUTOSPACE) {
520  float min[3], max[3];
521 
522  INIT_MINMAX(min, max);
523  if (!BKE_curve_minmax(cu, true, min, max)) {
524  min[0] = min[1] = min[2] = -1.0f;
525  max[0] = max[1] = max[2] = 1.0f;
526  }
527 
528  float loc[3], size[3];
529  mid_v3_v3v3(loc, min, max);
530 
531  size[0] = (max[0] - min[0]) / 2.0f;
532  size[1] = (max[1] - min[1]) / 2.0f;
533  size[2] = (max[2] - min[2]) / 2.0f;
534 
535  for (int a = 0; a < 3; a++) {
536  if (size[a] == 0.0f) {
537  size[a] = 1.0f;
538  }
539  else if (size[a] > 0.0f && size[a] < 0.00001f) {
540  size[a] = 0.00001f;
541  }
542  else if (size[a] < 0.0f && size[a] > -0.00001f) {
543  size[a] = -0.00001f;
544  }
545  }
546 
547  copy_v3_v3(cu->loc, loc);
548  copy_v3_v3(cu->size, size);
549 
551  }
552 }
553 
555 {
556  if ((cu->texflag & CU_AUTOSPACE) && !(cu->texflag & CU_AUTOSPACE_EVALUATED)) {
558  }
559 }
560 
561 void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_size[3])
562 {
564 
565  if (r_loc) {
566  copy_v3_v3(r_loc, cu->loc);
567  }
568  if (r_size) {
569  copy_v3_v3(r_size, cu->size);
570  }
571 }
572 
573 bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
574 {
575  int tot = 0;
576 
577  LISTBASE_FOREACH (Nurb *, nu, nurb) {
578  int tot_nu;
579  if (nu->type == CU_BEZIER) {
580  tot_nu = nu->pntsu;
581  if (index - tot < tot_nu) {
582  copy_v3_v3(r_co, nu->bezt[index - tot].vec[1]);
583  return true;
584  }
585  }
586  else {
587  tot_nu = nu->pntsu * nu->pntsv;
588  if (index - tot < tot_nu) {
589  copy_v3_v3(r_co, nu->bp[index - tot].vec);
590  return true;
591  }
592  }
593  tot += tot_nu;
594  }
595 
596  return false;
597 }
598 
600 {
601  int tot = 0;
602 
603  LISTBASE_FOREACH (const Nurb *, nu, nurb) {
604  if (nu->bezt) {
605  tot += 3 * nu->pntsu;
606  }
607  else if (nu->bp) {
608  tot += nu->pntsu * nu->pntsv;
609  }
610  }
611 
612  return tot;
613 }
614 
616 {
617  int tot = 0;
618 
619  LISTBASE_FOREACH (Nurb *, nu, nurb) {
620  if (nu->bezt) {
621  tot += nu->pntsu;
622  }
623  else if (nu->bp) {
624  tot += nu->pntsu * nu->pntsv;
625  }
626  }
627 
628  return tot;
629 }
630 
631 /* **************** NURBS ROUTINES ******************** */
632 
634 {
635  if (nu == NULL) {
636  return;
637  }
638 
639  if (nu->bezt) {
640  MEM_freeN(nu->bezt);
641  }
642  nu->bezt = NULL;
643  if (nu->bp) {
644  MEM_freeN(nu->bp);
645  }
646  nu->bp = NULL;
647  if (nu->knotsu) {
648  MEM_freeN(nu->knotsu);
649  }
650  nu->knotsu = NULL;
651  if (nu->knotsv) {
652  MEM_freeN(nu->knotsv);
653  }
654  nu->knotsv = NULL;
655  /* if (nu->trim.first) freeNurblist(&(nu->trim)); */
656 
657  MEM_freeN(nu);
658 }
659 
661 {
662  if (lb == NULL) {
663  return;
664  }
665 
666  LISTBASE_FOREACH_MUTABLE (Nurb *, nu, lb) {
667  BKE_nurb_free(nu);
668  }
669  BLI_listbase_clear(lb);
670 }
671 
673 {
674  Nurb *newnu;
675  int len;
676 
677  newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "duplicateNurb");
678  if (newnu == NULL) {
679  return NULL;
680  }
681  memcpy(newnu, nu, sizeof(Nurb));
682 
683  if (nu->bezt) {
684  newnu->bezt = (BezTriple *)MEM_malloc_arrayN(nu->pntsu, sizeof(BezTriple), "duplicateNurb2");
685  memcpy(newnu->bezt, nu->bezt, nu->pntsu * sizeof(BezTriple));
686  }
687  else {
688  len = nu->pntsu * nu->pntsv;
689  newnu->bp = (BPoint *)MEM_malloc_arrayN(len, sizeof(BPoint), "duplicateNurb3");
690  memcpy(newnu->bp, nu->bp, len * sizeof(BPoint));
691 
692  newnu->knotsu = newnu->knotsv = NULL;
693 
694  if (nu->knotsu) {
695  len = KNOTSU(nu);
696  if (len) {
697  newnu->knotsu = MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb4");
698  memcpy(newnu->knotsu, nu->knotsu, sizeof(float) * len);
699  }
700  }
701  if (nu->pntsv > 1 && nu->knotsv) {
702  len = KNOTSV(nu);
703  if (len) {
704  newnu->knotsv = MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb5");
705  memcpy(newnu->knotsv, nu->knotsv, sizeof(float) * len);
706  }
707  }
708  }
709  return newnu;
710 }
711 
712 /* copy the nurb but allow for different number of points (to be copied after this) */
713 Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
714 {
715  Nurb *newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "copyNurb");
716  memcpy(newnu, src, sizeof(Nurb));
717 
718  if (pntsu == 1) {
719  SWAP(int, pntsu, pntsv);
720  }
721  newnu->pntsu = pntsu;
722  newnu->pntsv = pntsv;
723 
724  /* caller can manually handle these arrays */
725  newnu->knotsu = NULL;
726  newnu->knotsv = NULL;
727 
728  if (src->bezt) {
729  newnu->bezt = (BezTriple *)MEM_malloc_arrayN(pntsu * pntsv, sizeof(BezTriple), "copyNurb2");
730  }
731  else {
732  newnu->bp = (BPoint *)MEM_malloc_arrayN(pntsu * pntsv, sizeof(BPoint), "copyNurb3");
733  }
734 
735  return newnu;
736 }
737 
739 {
740  BKE_nurbList_free(lb1);
741 
742  LISTBASE_FOREACH (const Nurb *, nu, lb2) {
743  Nurb *nurb_new = BKE_nurb_duplicate(nu);
744  BLI_addtail(lb1, nurb_new);
745  }
746 }
747 
749 {
750  BezTriple *bezt;
751  BPoint *bp;
752  int a;
753 
754  if (nu->type == CU_BEZIER) {
755  a = nu->pntsu;
756  bezt = nu->bezt;
757  while (a--) {
758  bezt->vec[0][2] = 0.0;
759  bezt->vec[1][2] = 0.0;
760  bezt->vec[2][2] = 0.0;
761  bezt++;
762  }
763  }
764  else {
765  a = nu->pntsu * nu->pntsv;
766  bp = nu->bp;
767  while (a--) {
768  bp->vec[2] = 0.0;
769  bp++;
770  }
771  }
772 }
773 
778 void BKE_nurb_minmax(const Nurb *nu, bool use_radius, float min[3], float max[3])
779 {
780  BezTriple *bezt;
781  BPoint *bp;
782  int a;
783  float point[3];
784 
785  if (nu->type == CU_BEZIER) {
786  a = nu->pntsu;
787  bezt = nu->bezt;
788  while (a--) {
789  if (use_radius) {
790  float radius_vector[3];
791  radius_vector[0] = radius_vector[1] = radius_vector[2] = bezt->radius;
792 
793  add_v3_v3v3(point, bezt->vec[1], radius_vector);
794  minmax_v3v3_v3(min, max, point);
795 
796  sub_v3_v3v3(point, bezt->vec[1], radius_vector);
797  minmax_v3v3_v3(min, max, point);
798  }
799  else {
800  minmax_v3v3_v3(min, max, bezt->vec[1]);
801  }
802  minmax_v3v3_v3(min, max, bezt->vec[0]);
803  minmax_v3v3_v3(min, max, bezt->vec[2]);
804  bezt++;
805  }
806  }
807  else {
808  a = nu->pntsu * nu->pntsv;
809  bp = nu->bp;
810  while (a--) {
811  if (nu->pntsv == 1 && use_radius) {
812  float radius_vector[3];
813  radius_vector[0] = radius_vector[1] = radius_vector[2] = bp->radius;
814 
815  add_v3_v3v3(point, bp->vec, radius_vector);
816  minmax_v3v3_v3(min, max, point);
817 
818  sub_v3_v3v3(point, bp->vec, radius_vector);
819  minmax_v3v3_v3(min, max, point);
820  }
821  else {
822  /* Surfaces doesn't use bevel, so no need to take radius into account. */
823  minmax_v3v3_v3(min, max, bp->vec);
824  }
825  bp++;
826  }
827  }
828 }
829 
830 float BKE_nurb_calc_length(const Nurb *nu, int resolution)
831 {
832  BezTriple *bezt, *prevbezt;
833  BPoint *bp, *prevbp;
834  int a, b;
835  float length = 0.0f;
836  int resolu = resolution ? resolution : nu->resolu;
837  int pntsu = nu->pntsu;
838  float *points, *pntsit, *prevpntsit;
839 
840  if (nu->type == CU_POLY) {
841  a = nu->pntsu - 1;
842  bp = nu->bp;
843  if (nu->flagu & CU_NURB_CYCLIC) {
844  a++;
845  prevbp = nu->bp + (nu->pntsu - 1);
846  }
847  else {
848  prevbp = bp;
849  bp++;
850  }
851 
852  while (a--) {
853  length += len_v3v3(prevbp->vec, bp->vec);
854  prevbp = bp;
855  bp++;
856  }
857  }
858  else if (nu->type == CU_BEZIER) {
859  points = MEM_mallocN(sizeof(float[3]) * (resolu + 1), "getLength_bezier");
860  a = nu->pntsu - 1;
861  bezt = nu->bezt;
862  if (nu->flagu & CU_NURB_CYCLIC) {
863  a++;
864  prevbezt = nu->bezt + (nu->pntsu - 1);
865  }
866  else {
867  prevbezt = bezt;
868  bezt++;
869  }
870 
871  while (a--) {
872  if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
873  length += len_v3v3(prevbezt->vec[1], bezt->vec[1]);
874  }
875  else {
876  for (int j = 0; j < 3; j++) {
877  BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
878  prevbezt->vec[2][j],
879  bezt->vec[0][j],
880  bezt->vec[1][j],
881  points + j,
882  resolu,
883  sizeof(float[3]));
884  }
885 
886  prevpntsit = pntsit = points;
887  b = resolu;
888  while (b--) {
889  pntsit += 3;
890  length += len_v3v3(prevpntsit, pntsit);
891  prevpntsit = pntsit;
892  }
893  }
894  prevbezt = bezt;
895  bezt++;
896  }
897 
898  MEM_freeN(points);
899  }
900  else if (nu->type == CU_NURBS) {
901  if (nu->pntsv == 1) {
902  /* important to zero for BKE_nurb_makeCurve. */
903  points = MEM_callocN(sizeof(float[3]) * pntsu * resolu, "getLength_nurbs");
904 
905  BKE_nurb_makeCurve(nu, points, NULL, NULL, NULL, resolu, sizeof(float[3]));
906 
907  if (nu->flagu & CU_NURB_CYCLIC) {
908  b = pntsu * resolu + 1;
909  prevpntsit = points + 3 * (pntsu * resolu - 1);
910  pntsit = points;
911  }
912  else {
913  b = (pntsu - 1) * resolu;
914  prevpntsit = points;
915  pntsit = points + 3;
916  }
917 
918  while (--b > 0) {
919  length += len_v3v3(prevpntsit, pntsit);
920  prevpntsit = pntsit;
921  pntsit += 3;
922  }
923 
924  MEM_freeN(points);
925  }
926  }
927 
928  return length;
929 }
930 
931 /* be sure to call makeknots after this */
932 void BKE_nurb_points_add(Nurb *nu, int number)
933 {
934  nu->bp = MEM_recallocN(nu->bp, (nu->pntsu + number) * sizeof(BPoint));
935 
936  BPoint *bp;
937  int i;
938  for (i = 0, bp = &nu->bp[nu->pntsu]; i < number; i++, bp++) {
939  bp->radius = 1.0f;
940  }
941 
942  nu->pntsu += number;
943 }
944 
945 void BKE_nurb_bezierPoints_add(Nurb *nu, int number)
946 {
947  BezTriple *bezt;
948  int i;
949 
950  nu->bezt = MEM_recallocN(nu->bezt, (nu->pntsu + number) * sizeof(BezTriple));
951 
952  for (i = 0, bezt = &nu->bezt[nu->pntsu]; i < number; i++, bezt++) {
953  bezt->radius = 1.0f;
954  }
955 
956  nu->pntsu += number;
957 }
958 
959 int BKE_nurb_index_from_uv(Nurb *nu, int u, int v)
960 {
961  const int totu = nu->pntsu;
962  const int totv = nu->pntsv;
963 
964  if (nu->flagu & CU_NURB_CYCLIC) {
965  u = mod_i(u, totu);
966  }
967  else if (u < 0 || u >= totu) {
968  return -1;
969  }
970 
971  if (nu->flagv & CU_NURB_CYCLIC) {
972  v = mod_i(v, totv);
973  }
974  else if (v < 0 || v >= totv) {
975  return -1;
976  }
977 
978  return (v * totu) + u;
979 }
980 
981 void BKE_nurb_index_to_uv(Nurb *nu, int index, int *r_u, int *r_v)
982 {
983  const int totu = nu->pntsu;
984  const int totv = nu->pntsv;
985  BLI_assert(index >= 0 && index < (nu->pntsu * nu->pntsv));
986  *r_u = (index % totu);
987  *r_v = (index / totu) % totv;
988 }
989 
991 {
992  BezTriple *bezt_next;
993 
994  BLI_assert(ARRAY_HAS_ITEM(bezt, nu->bezt, nu->pntsu));
995 
996  if (bezt == &nu->bezt[nu->pntsu - 1]) {
997  if (nu->flagu & CU_NURB_CYCLIC) {
998  bezt_next = nu->bezt;
999  }
1000  else {
1001  bezt_next = NULL;
1002  }
1003  }
1004  else {
1005  bezt_next = bezt + 1;
1006  }
1007 
1008  return bezt_next;
1009 }
1010 
1012 {
1013  BPoint *bp_next;
1014 
1015  BLI_assert(ARRAY_HAS_ITEM(bp, nu->bp, nu->pntsu));
1016 
1017  if (bp == &nu->bp[nu->pntsu - 1]) {
1018  if (nu->flagu & CU_NURB_CYCLIC) {
1019  bp_next = nu->bp;
1020  }
1021  else {
1022  bp_next = NULL;
1023  }
1024  }
1025  else {
1026  bp_next = bp + 1;
1027  }
1028 
1029  return bp_next;
1030 }
1031 
1033 {
1034  BezTriple *bezt_prev;
1035 
1036  BLI_assert(ARRAY_HAS_ITEM(bezt, nu->bezt, nu->pntsu));
1037  BLI_assert(nu->pntsv <= 1);
1038 
1039  if (bezt == nu->bezt) {
1040  if (nu->flagu & CU_NURB_CYCLIC) {
1041  bezt_prev = &nu->bezt[nu->pntsu - 1];
1042  }
1043  else {
1044  bezt_prev = NULL;
1045  }
1046  }
1047  else {
1048  bezt_prev = bezt - 1;
1049  }
1050 
1051  return bezt_prev;
1052 }
1053 
1055 {
1056  BPoint *bp_prev;
1057 
1058  BLI_assert(ARRAY_HAS_ITEM(bp, nu->bp, nu->pntsu));
1059  BLI_assert(nu->pntsv == 1);
1060 
1061  if (bp == nu->bp) {
1062  if (nu->flagu & CU_NURB_CYCLIC) {
1063  bp_prev = &nu->bp[nu->pntsu - 1];
1064  }
1065  else {
1066  bp_prev = NULL;
1067  }
1068  }
1069  else {
1070  bp_prev = bp - 1;
1071  }
1072 
1073  return bp_prev;
1074 }
1075 
1076 void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), BezTriple *bezt, float r_normal[3])
1077 {
1078  /* calculate the axis matrix from the spline */
1079  float dir_prev[3], dir_next[3];
1080 
1081  sub_v3_v3v3(dir_prev, bezt->vec[0], bezt->vec[1]);
1082  sub_v3_v3v3(dir_next, bezt->vec[1], bezt->vec[2]);
1083 
1084  normalize_v3(dir_prev);
1085  normalize_v3(dir_next);
1086 
1087  add_v3_v3v3(r_normal, dir_prev, dir_next);
1088  normalize_v3(r_normal);
1089 }
1090 
1091 void BKE_nurb_bezt_calc_plane(struct Nurb *nu, BezTriple *bezt, float r_plane[3])
1092 {
1093  float dir_prev[3], dir_next[3];
1094 
1095  sub_v3_v3v3(dir_prev, bezt->vec[0], bezt->vec[1]);
1096  sub_v3_v3v3(dir_next, bezt->vec[1], bezt->vec[2]);
1097 
1098  normalize_v3(dir_prev);
1099  normalize_v3(dir_next);
1100 
1101  cross_v3_v3v3(r_plane, dir_prev, dir_next);
1102  if (normalize_v3(r_plane) < FLT_EPSILON) {
1103  BezTriple *bezt_prev = BKE_nurb_bezt_get_prev(nu, bezt);
1104  BezTriple *bezt_next = BKE_nurb_bezt_get_next(nu, bezt);
1105 
1106  if (bezt_prev) {
1107  sub_v3_v3v3(dir_prev, bezt_prev->vec[1], bezt->vec[1]);
1108  normalize_v3(dir_prev);
1109  }
1110  if (bezt_next) {
1111  sub_v3_v3v3(dir_next, bezt->vec[1], bezt_next->vec[1]);
1112  normalize_v3(dir_next);
1113  }
1114  cross_v3_v3v3(r_plane, dir_prev, dir_next);
1115  }
1116 
1117  /* matches with bones more closely */
1118  {
1119  float dir_mid[3], tvec[3];
1120  add_v3_v3v3(dir_mid, dir_prev, dir_next);
1121  cross_v3_v3v3(tvec, r_plane, dir_mid);
1122  copy_v3_v3(r_plane, tvec);
1123  }
1124 
1125  normalize_v3(r_plane);
1126 }
1127 
1128 void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, BPoint *bp, float r_normal[3])
1129 {
1130  BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
1131  BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
1132 
1133  zero_v3(r_normal);
1134 
1135  if (bp_prev) {
1136  float dir_prev[3];
1137  sub_v3_v3v3(dir_prev, bp_prev->vec, bp->vec);
1138  normalize_v3(dir_prev);
1139  add_v3_v3(r_normal, dir_prev);
1140  }
1141  if (bp_next) {
1142  float dir_next[3];
1143  sub_v3_v3v3(dir_next, bp->vec, bp_next->vec);
1144  normalize_v3(dir_next);
1145  add_v3_v3(r_normal, dir_next);
1146  }
1147 
1148  normalize_v3(r_normal);
1149 }
1150 
1151 void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3])
1152 {
1153  BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
1154  BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
1155 
1156  float dir_prev[3] = {0.0f}, dir_next[3] = {0.0f};
1157 
1158  if (bp_prev) {
1159  sub_v3_v3v3(dir_prev, bp_prev->vec, bp->vec);
1160  normalize_v3(dir_prev);
1161  }
1162  if (bp_next) {
1163  sub_v3_v3v3(dir_next, bp->vec, bp_next->vec);
1164  normalize_v3(dir_next);
1165  }
1166  cross_v3_v3v3(r_plane, dir_prev, dir_next);
1167 
1168  /* matches with bones more closely */
1169  {
1170  float dir_mid[3], tvec[3];
1171  add_v3_v3v3(dir_mid, dir_prev, dir_next);
1172  cross_v3_v3v3(tvec, r_plane, dir_mid);
1173  copy_v3_v3(r_plane, tvec);
1174  }
1175 
1176  normalize_v3(r_plane);
1177 }
1178 
1179 /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */
1180 
1181 static void calcknots(float *knots, const int pnts, const short order, const short flag)
1182 {
1183  /* knots: number of pnts NOT corrected for cyclic */
1184  const int pnts_order = pnts + order;
1185  float k;
1186  int a;
1187 
1188  switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) {
1189  case CU_NURB_ENDPOINT:
1190  k = 0.0;
1191  for (a = 1; a <= pnts_order; a++) {
1192  knots[a - 1] = k;
1193  if (a >= order && a <= pnts) {
1194  k += 1.0f;
1195  }
1196  }
1197  break;
1198  case CU_NURB_BEZIER:
1199  /* Warning, the order MUST be 2 or 4,
1200  * if this is not enforced, the displist will be corrupt */
1201  if (order == 4) {
1202  k = 0.34;
1203  for (a = 0; a < pnts_order; a++) {
1204  knots[a] = floorf(k);
1205  k += (1.0f / 3.0f);
1206  }
1207  }
1208  else if (order == 3) {
1209  k = 0.6f;
1210  for (a = 0; a < pnts_order; a++) {
1211  if (a >= order && a <= pnts) {
1212  k += 0.5f;
1213  }
1214  knots[a] = floorf(k);
1215  }
1216  }
1217  else {
1218  CLOG_ERROR(&LOG, "bez nurb curve order is not 3 or 4, should never happen");
1219  }
1220  break;
1221  default:
1222  for (a = 0; a < pnts_order; a++) {
1223  knots[a] = (float)a;
1224  }
1225  break;
1226  }
1227 }
1228 
1229 static void makecyclicknots(float *knots, int pnts, short order)
1230 /* pnts, order: number of pnts NOT corrected for cyclic */
1231 {
1232  int a, b, order2, c;
1233 
1234  if (knots == NULL) {
1235  return;
1236  }
1237 
1238  order2 = order - 1;
1239 
1240  /* do first long rows (order -1), remove identical knots at endpoints */
1241  if (order > 2) {
1242  b = pnts + order2;
1243  for (a = 1; a < order2; a++) {
1244  if (knots[b] != knots[b - a]) {
1245  break;
1246  }
1247  }
1248  if (a == order2) {
1249  knots[pnts + order - 2] += 1.0f;
1250  }
1251  }
1252 
1253  b = order;
1254  c = pnts + order + order2;
1255  for (a = pnts + order2; a < c; a++) {
1256  knots[a] = knots[a - 1] + (knots[b] - knots[b - 1]);
1257  b--;
1258  }
1259 }
1260 
1261 static void makeknots(Nurb *nu, short uv)
1262 {
1263  if (nu->type == CU_NURBS) {
1264  if (uv == 1) {
1265  if (nu->knotsu) {
1266  MEM_freeN(nu->knotsu);
1267  }
1268  if (BKE_nurb_check_valid_u(nu)) {
1269  nu->knotsu = MEM_calloc_arrayN(KNOTSU(nu) + 1, sizeof(float), "makeknots");
1270  if (nu->flagu & CU_NURB_CYCLIC) {
1271  calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0); /* cyclic should be uniform */
1272  makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
1273  }
1274  else {
1275  calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu);
1276  }
1277  }
1278  else {
1279  nu->knotsu = NULL;
1280  }
1281  }
1282  else if (uv == 2) {
1283  if (nu->knotsv) {
1284  MEM_freeN(nu->knotsv);
1285  }
1286  if (BKE_nurb_check_valid_v(nu)) {
1287  nu->knotsv = MEM_calloc_arrayN(KNOTSV(nu) + 1, sizeof(float), "makeknots");
1288  if (nu->flagv & CU_NURB_CYCLIC) {
1289  calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0); /* cyclic should be uniform */
1290  makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
1291  }
1292  else {
1293  calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv);
1294  }
1295  }
1296  else {
1297  nu->knotsv = NULL;
1298  }
1299  }
1300  }
1301 }
1302 
1304 {
1305  makeknots(nu, 1);
1306 }
1307 
1309 {
1310  makeknots(nu, 2);
1311 }
1312 
1313 static void basisNurb(
1314  float t, short order, int pnts, const float *knots, float *basis, int *start, int *end)
1315 {
1316  float d, e;
1317  int i, i1 = 0, i2 = 0, j, orderpluspnts, opp2, o2;
1318 
1319  orderpluspnts = order + pnts;
1320  opp2 = orderpluspnts - 1;
1321 
1322  /* this is for float inaccuracy */
1323  if (t < knots[0]) {
1324  t = knots[0];
1325  }
1326  else if (t > knots[opp2]) {
1327  t = knots[opp2];
1328  }
1329 
1330  /* this part is order '1' */
1331  o2 = order + 1;
1332  for (i = 0; i < opp2; i++) {
1333  if (knots[i] != knots[i + 1] && t >= knots[i] && t <= knots[i + 1]) {
1334  basis[i] = 1.0;
1335  i1 = i - o2;
1336  if (i1 < 0) {
1337  i1 = 0;
1338  }
1339  i2 = i;
1340  i++;
1341  while (i < opp2) {
1342  basis[i] = 0.0;
1343  i++;
1344  }
1345  break;
1346  }
1347 
1348  basis[i] = 0.0;
1349  }
1350  basis[i] = 0.0;
1351 
1352  /* this is order 2, 3, ... */
1353  for (j = 2; j <= order; j++) {
1354 
1355  if (i2 + j >= orderpluspnts) {
1356  i2 = opp2 - j;
1357  }
1358 
1359  for (i = i1; i <= i2; i++) {
1360  if (basis[i] != 0.0f) {
1361  d = ((t - knots[i]) * basis[i]) / (knots[i + j - 1] - knots[i]);
1362  }
1363  else {
1364  d = 0.0f;
1365  }
1366 
1367  if (basis[i + 1] != 0.0f) {
1368  e = ((knots[i + j] - t) * basis[i + 1]) / (knots[i + j] - knots[i + 1]);
1369  }
1370  else {
1371  e = 0.0;
1372  }
1373 
1374  basis[i] = d + e;
1375  }
1376  }
1377 
1378  *start = 1000;
1379  *end = 0;
1380 
1381  for (i = i1; i <= i2; i++) {
1382  if (basis[i] > 0.0f) {
1383  *end = i;
1384  if (*start == 1000) {
1385  *start = i;
1386  }
1387  }
1388  }
1389 }
1390 
1394 void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv)
1395 {
1396  BPoint *bp;
1397  float *basisu, *basis, *basisv, *sum, *fp, *in;
1398  float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv;
1399  int i, j, iofs, jofs, cycl, len, curu, curv;
1400  int istart, iend, jsta, jen, *jstart, *jend, ratcomp;
1401 
1402  int totu = nu->pntsu * resolu, totv = nu->pntsv * resolv;
1403 
1404  if (nu->knotsu == NULL || nu->knotsv == NULL) {
1405  return;
1406  }
1407  if (nu->orderu > nu->pntsu) {
1408  return;
1409  }
1410  if (nu->orderv > nu->pntsv) {
1411  return;
1412  }
1413  if (coord_array == NULL) {
1414  return;
1415  }
1416 
1417  /* allocate and initialize */
1418  len = totu * totv;
1419  if (len == 0) {
1420  return;
1421  }
1422 
1423  sum = (float *)MEM_calloc_arrayN(len, sizeof(float), "makeNurbfaces1");
1424 
1425  bp = nu->bp;
1426  i = nu->pntsu * nu->pntsv;
1427  ratcomp = 0;
1428  while (i--) {
1429  if (bp->vec[3] != 1.0f) {
1430  ratcomp = 1;
1431  break;
1432  }
1433  bp++;
1434  }
1435 
1436  fp = nu->knotsu;
1437  ustart = fp[nu->orderu - 1];
1438  if (nu->flagu & CU_NURB_CYCLIC) {
1439  uend = fp[nu->pntsu + nu->orderu - 1];
1440  }
1441  else {
1442  uend = fp[nu->pntsu];
1443  }
1444  ustep = (uend - ustart) / ((nu->flagu & CU_NURB_CYCLIC) ? totu : totu - 1);
1445 
1446  basisu = (float *)MEM_malloc_arrayN(KNOTSU(nu), sizeof(float), "makeNurbfaces3");
1447 
1448  fp = nu->knotsv;
1449  vstart = fp[nu->orderv - 1];
1450 
1451  if (nu->flagv & CU_NURB_CYCLIC) {
1452  vend = fp[nu->pntsv + nu->orderv - 1];
1453  }
1454  else {
1455  vend = fp[nu->pntsv];
1456  }
1457  vstep = (vend - vstart) / ((nu->flagv & CU_NURB_CYCLIC) ? totv : totv - 1);
1458 
1459  len = KNOTSV(nu);
1460  basisv = (float *)MEM_malloc_arrayN(len * totv, sizeof(float), "makeNurbfaces3");
1461  jstart = (int *)MEM_malloc_arrayN(totv, sizeof(float), "makeNurbfaces4");
1462  jend = (int *)MEM_malloc_arrayN(totv, sizeof(float), "makeNurbfaces5");
1463 
1464  /* precalculation of basisv and jstart, jend */
1465  if (nu->flagv & CU_NURB_CYCLIC) {
1466  cycl = nu->orderv - 1;
1467  }
1468  else {
1469  cycl = 0;
1470  }
1471  v = vstart;
1472  basis = basisv;
1473  curv = totv;
1474  while (curv--) {
1475  basisNurb(v, nu->orderv, nu->pntsv + cycl, nu->knotsv, basis, jstart + curv, jend + curv);
1476  basis += KNOTSV(nu);
1477  v += vstep;
1478  }
1479 
1480  if (nu->flagu & CU_NURB_CYCLIC) {
1481  cycl = nu->orderu - 1;
1482  }
1483  else {
1484  cycl = 0;
1485  }
1486  in = coord_array;
1487  u = ustart;
1488  curu = totu;
1489  while (curu--) {
1490  basisNurb(u, nu->orderu, nu->pntsu + cycl, nu->knotsu, basisu, &istart, &iend);
1491 
1492  basis = basisv;
1493  curv = totv;
1494  while (curv--) {
1495  jsta = jstart[curv];
1496  jen = jend[curv];
1497 
1498  /* calculate sum */
1499  sumdiv = 0.0;
1500  fp = sum;
1501 
1502  for (j = jsta; j <= jen; j++) {
1503 
1504  if (j >= nu->pntsv) {
1505  jofs = (j - nu->pntsv);
1506  }
1507  else {
1508  jofs = j;
1509  }
1510  bp = nu->bp + nu->pntsu * jofs + istart - 1;
1511 
1512  for (i = istart; i <= iend; i++, fp++) {
1513  if (i >= nu->pntsu) {
1514  iofs = i - nu->pntsu;
1515  bp = nu->bp + nu->pntsu * jofs + iofs;
1516  }
1517  else {
1518  bp++;
1519  }
1520 
1521  if (ratcomp) {
1522  *fp = basisu[i] * basis[j] * bp->vec[3];
1523  sumdiv += *fp;
1524  }
1525  else {
1526  *fp = basisu[i] * basis[j];
1527  }
1528  }
1529  }
1530 
1531  if (ratcomp) {
1532  fp = sum;
1533  for (j = jsta; j <= jen; j++) {
1534  for (i = istart; i <= iend; i++, fp++) {
1535  *fp /= sumdiv;
1536  }
1537  }
1538  }
1539 
1540  zero_v3(in);
1541 
1542  /* one! (1.0) real point now */
1543  fp = sum;
1544  for (j = jsta; j <= jen; j++) {
1545 
1546  if (j >= nu->pntsv) {
1547  jofs = (j - nu->pntsv);
1548  }
1549  else {
1550  jofs = j;
1551  }
1552  bp = nu->bp + nu->pntsu * jofs + istart - 1;
1553 
1554  for (i = istart; i <= iend; i++, fp++) {
1555  if (i >= nu->pntsu) {
1556  iofs = i - nu->pntsu;
1557  bp = nu->bp + nu->pntsu * jofs + iofs;
1558  }
1559  else {
1560  bp++;
1561  }
1562 
1563  if (*fp != 0.0f) {
1564  madd_v3_v3fl(in, bp->vec, *fp);
1565  }
1566  }
1567  }
1568 
1569  in += 3;
1570  basis += KNOTSV(nu);
1571  }
1572  u += ustep;
1573  if (rowstride != 0) {
1574  in = (float *)(((unsigned char *)in) + (rowstride - 3 * totv * sizeof(*in)));
1575  }
1576  }
1577 
1578  /* free */
1579  MEM_freeN(sum);
1580  MEM_freeN(basisu);
1581  MEM_freeN(basisv);
1582  MEM_freeN(jstart);
1583  MEM_freeN(jend);
1584 }
1585 
1591 void BKE_nurb_makeCurve(const Nurb *nu,
1592  float *coord_array,
1593  float *tilt_array,
1594  float *radius_array,
1595  float *weight_array,
1596  int resolu,
1597  int stride)
1598 {
1599  const float eps = 1e-6f;
1600  BPoint *bp;
1601  float u, ustart, uend, ustep, sumdiv;
1602  float *basisu, *sum, *fp;
1603  float *coord_fp = coord_array, *tilt_fp = tilt_array, *radius_fp = radius_array,
1604  *weight_fp = weight_array;
1605  int i, len, istart, iend, cycl;
1606 
1607  if (nu->knotsu == NULL) {
1608  return;
1609  }
1610  if (nu->orderu > nu->pntsu) {
1611  return;
1612  }
1613  if (coord_array == NULL) {
1614  return;
1615  }
1616 
1617  /* allocate and initialize */
1618  len = nu->pntsu;
1619  if (len == 0) {
1620  return;
1621  }
1622  sum = (float *)MEM_calloc_arrayN(len, sizeof(float), "makeNurbcurve1");
1623 
1624  resolu = (resolu * SEGMENTSU(nu));
1625 
1626  if (resolu == 0) {
1627  MEM_freeN(sum);
1628  return;
1629  }
1630 
1631  fp = nu->knotsu;
1632  ustart = fp[nu->orderu - 1];
1633  if (nu->flagu & CU_NURB_CYCLIC) {
1634  uend = fp[nu->pntsu + nu->orderu - 1];
1635  }
1636  else {
1637  uend = fp[nu->pntsu];
1638  }
1639  ustep = (uend - ustart) / (resolu - ((nu->flagu & CU_NURB_CYCLIC) ? 0 : 1));
1640 
1641  basisu = (float *)MEM_malloc_arrayN(KNOTSU(nu), sizeof(float), "makeNurbcurve3");
1642 
1643  if (nu->flagu & CU_NURB_CYCLIC) {
1644  cycl = nu->orderu - 1;
1645  }
1646  else {
1647  cycl = 0;
1648  }
1649 
1650  u = ustart;
1651  while (resolu--) {
1652  basisNurb(u, nu->orderu, nu->pntsu + cycl, nu->knotsu, basisu, &istart, &iend);
1653 
1654  /* calc sum */
1655  sumdiv = 0.0;
1656  fp = sum;
1657  bp = nu->bp + istart - 1;
1658  for (i = istart; i <= iend; i++, fp++) {
1659  if (i >= nu->pntsu) {
1660  bp = nu->bp + (i - nu->pntsu);
1661  }
1662  else {
1663  bp++;
1664  }
1665 
1666  *fp = basisu[i] * bp->vec[3];
1667  sumdiv += *fp;
1668  }
1669  if ((sumdiv != 0.0f) && (sumdiv < 1.0f - eps || sumdiv > 1.0f + eps)) {
1670  /* is normalizing needed? */
1671  fp = sum;
1672  for (i = istart; i <= iend; i++, fp++) {
1673  *fp /= sumdiv;
1674  }
1675  }
1676 
1677  zero_v3(coord_fp);
1678 
1679  /* one! (1.0) real point */
1680  fp = sum;
1681  bp = nu->bp + istart - 1;
1682  for (i = istart; i <= iend; i++, fp++) {
1683  if (i >= nu->pntsu) {
1684  bp = nu->bp + (i - nu->pntsu);
1685  }
1686  else {
1687  bp++;
1688  }
1689 
1690  if (*fp != 0.0f) {
1691  madd_v3_v3fl(coord_fp, bp->vec, *fp);
1692 
1693  if (tilt_fp) {
1694  (*tilt_fp) += (*fp) * bp->tilt;
1695  }
1696 
1697  if (radius_fp) {
1698  (*radius_fp) += (*fp) * bp->radius;
1699  }
1700 
1701  if (weight_fp) {
1702  (*weight_fp) += (*fp) * bp->weight;
1703  }
1704  }
1705  }
1706 
1707  coord_fp = POINTER_OFFSET(coord_fp, stride);
1708 
1709  if (tilt_fp) {
1710  tilt_fp = POINTER_OFFSET(tilt_fp, stride);
1711  }
1712  if (radius_fp) {
1713  radius_fp = POINTER_OFFSET(radius_fp, stride);
1714  }
1715  if (weight_fp) {
1716  weight_fp = POINTER_OFFSET(weight_fp, stride);
1717  }
1718 
1719  u += ustep;
1720  }
1721 
1722  /* free */
1723  MEM_freeN(sum);
1724  MEM_freeN(basisu);
1725 }
1726 
1730 unsigned int BKE_curve_calc_coords_axis_len(const unsigned int bezt_array_len,
1731  const unsigned int resolu,
1732  const bool is_cyclic,
1733  const bool use_cyclic_duplicate_endpoint)
1734 {
1735  const unsigned int segments = bezt_array_len - (is_cyclic ? 0 : 1);
1736  const unsigned int points_len = (segments * resolu) +
1737  (is_cyclic ? (use_cyclic_duplicate_endpoint) : 1);
1738  return points_len;
1739 }
1740 
1747 void BKE_curve_calc_coords_axis(const BezTriple *bezt_array,
1748  const unsigned int bezt_array_len,
1749  const unsigned int resolu,
1750  const bool is_cyclic,
1751  const bool use_cyclic_duplicate_endpoint,
1752  /* array params */
1753  const unsigned int axis,
1754  const unsigned int stride,
1755  float *r_points)
1756 {
1757  const unsigned int points_len = BKE_curve_calc_coords_axis_len(
1758  bezt_array_len, resolu, is_cyclic, use_cyclic_duplicate_endpoint);
1759  float *r_points_offset = r_points;
1760 
1761  const unsigned int resolu_stride = resolu * stride;
1762  const unsigned int bezt_array_last = bezt_array_len - 1;
1763 
1764  for (unsigned int i = 0; i < bezt_array_last; i++) {
1765  const BezTriple *bezt_curr = &bezt_array[i];
1766  const BezTriple *bezt_next = &bezt_array[i + 1];
1767  BKE_curve_forward_diff_bezier(bezt_curr->vec[1][axis],
1768  bezt_curr->vec[2][axis],
1769  bezt_next->vec[0][axis],
1770  bezt_next->vec[1][axis],
1771  r_points_offset,
1772  (int)resolu,
1773  stride);
1774  r_points_offset = POINTER_OFFSET(r_points_offset, resolu_stride);
1775  }
1776 
1777  if (is_cyclic) {
1778  const BezTriple *bezt_curr = &bezt_array[bezt_array_last];
1779  const BezTriple *bezt_next = &bezt_array[0];
1780  BKE_curve_forward_diff_bezier(bezt_curr->vec[1][axis],
1781  bezt_curr->vec[2][axis],
1782  bezt_next->vec[0][axis],
1783  bezt_next->vec[1][axis],
1784  r_points_offset,
1785  (int)resolu,
1786  stride);
1787  r_points_offset = POINTER_OFFSET(r_points_offset, resolu_stride);
1788  if (use_cyclic_duplicate_endpoint) {
1789  *r_points_offset = *r_points;
1790  r_points_offset = POINTER_OFFSET(r_points_offset, stride);
1791  }
1792  }
1793  else {
1794  float *r_points_last = POINTER_OFFSET(r_points, bezt_array_last * resolu_stride);
1795  *r_points_last = bezt_array[bezt_array_last].vec[1][axis];
1796  r_points_offset = POINTER_OFFSET(r_points_offset, stride);
1797  }
1798 
1799  BLI_assert(POINTER_OFFSET(r_points, points_len * stride) == r_points_offset);
1800  UNUSED_VARS_NDEBUG(points_len);
1801 }
1802 
1803 /* forward differencing method for bezier curve */
1805  float q0, float q1, float q2, float q3, float *p, int it, int stride)
1806 {
1807  float rt0, rt1, rt2, rt3, f;
1808  int a;
1809 
1810  f = (float)it;
1811  rt0 = q0;
1812  rt1 = 3.0f * (q1 - q0) / f;
1813  f *= f;
1814  rt2 = 3.0f * (q0 - 2.0f * q1 + q2) / f;
1815  f *= it;
1816  rt3 = (q3 - q0 + 3.0f * (q1 - q2)) / f;
1817 
1818  q0 = rt0;
1819  q1 = rt1 + rt2 + rt3;
1820  q2 = 2 * rt2 + 6 * rt3;
1821  q3 = 6 * rt3;
1822 
1823  for (a = 0; a <= it; a++) {
1824  *p = q0;
1825  p = POINTER_OFFSET(p, stride);
1826  q0 += q1;
1827  q1 += q2;
1828  q2 += q3;
1829  }
1830 }
1831 
1832 /* forward differencing method for first derivative of cubic bezier curve */
1834  float q0, float q1, float q2, float q3, float *p, int it, int stride)
1835 {
1836  float rt0, rt1, rt2, f;
1837  int a;
1838 
1839  f = 1.0f / (float)it;
1840 
1841  rt0 = 3.0f * (q1 - q0);
1842  rt1 = f * (3.0f * (q3 - q0) + 9.0f * (q1 - q2));
1843  rt2 = 6.0f * (q0 + q2) - 12.0f * q1;
1844 
1845  q0 = rt0;
1846  q1 = f * (rt1 + rt2);
1847  q2 = 2.0f * f * rt1;
1848 
1849  for (a = 0; a <= it; a++) {
1850  *p = q0;
1851  p = POINTER_OFFSET(p, stride);
1852  q0 += q1;
1853  q1 += q2;
1854  }
1855 }
1856 
1857 static void forward_diff_bezier_cotangent(const float p0[3],
1858  const float p1[3],
1859  const float p2[3],
1860  const float p3[3],
1861  float p[3],
1862  int it,
1863  int stride)
1864 {
1865  /* note that these are not perpendicular to the curve
1866  * they need to be rotated for this,
1867  *
1868  * This could also be optimized like BKE_curve_forward_diff_bezier */
1869  for (int a = 0; a <= it; a++) {
1870  float t = (float)a / (float)it;
1871 
1872  for (int i = 0; i < 3; i++) {
1873  p[i] = (-6.0f * t + 6.0f) * p0[i] + (18.0f * t - 12.0f) * p1[i] +
1874  (-18.0f * t + 6.0f) * p2[i] + (6.0f * t) * p3[i];
1875  }
1876  normalize_v3(p);
1877  p = POINTER_OFFSET(p, stride);
1878  }
1879 }
1880 
1881 static int cu_isectLL(const float v1[3],
1882  const float v2[3],
1883  const float v3[3],
1884  const float v4[3],
1885  short cox,
1886  short coy,
1887  float *lambda,
1888  float *mu,
1889  float vec[3])
1890 {
1891  /* return:
1892  * -1: collinear
1893  * 0: no intersection of segments
1894  * 1: exact intersection of segments
1895  * 2: cross-intersection of segments
1896  */
1897  float deler;
1898 
1899  deler = (v1[cox] - v2[cox]) * (v3[coy] - v4[coy]) - (v3[cox] - v4[cox]) * (v1[coy] - v2[coy]);
1900  if (deler == 0.0f) {
1901  return -1;
1902  }
1903 
1904  *lambda = (v1[coy] - v3[coy]) * (v3[cox] - v4[cox]) - (v1[cox] - v3[cox]) * (v3[coy] - v4[coy]);
1905  *lambda = -(*lambda / deler);
1906 
1907  deler = v3[coy] - v4[coy];
1908  if (deler == 0) {
1909  deler = v3[cox] - v4[cox];
1910  *mu = -(*lambda * (v2[cox] - v1[cox]) + v1[cox] - v3[cox]) / deler;
1911  }
1912  else {
1913  *mu = -(*lambda * (v2[coy] - v1[coy]) + v1[coy] - v3[coy]) / deler;
1914  }
1915  vec[cox] = *lambda * (v2[cox] - v1[cox]) + v1[cox];
1916  vec[coy] = *lambda * (v2[coy] - v1[coy]) + v1[coy];
1917 
1918  if (*lambda >= 0.0f && *lambda <= 1.0f && *mu >= 0.0f && *mu <= 1.0f) {
1919  if (*lambda == 0.0f || *lambda == 1.0f || *mu == 0.0f || *mu == 1.0f) {
1920  return 1;
1921  }
1922  return 2;
1923  }
1924  return 0;
1925 }
1926 
1927 static bool bevelinside(const BevList *bl1, const BevList *bl2)
1928 {
1929  /* is bl2 INSIDE bl1 ? with left-right method and "lambda's" */
1930  /* returns '1' if correct hole */
1931  BevPoint *bevp, *prevbevp;
1932  float min, max, vec[3], hvec1[3], hvec2[3], lab, mu;
1933  int nr, links = 0, rechts = 0, mode;
1934 
1935  /* take first vertex of possible hole */
1936 
1937  bevp = bl2->bevpoints;
1938  hvec1[0] = bevp->vec[0];
1939  hvec1[1] = bevp->vec[1];
1940  hvec1[2] = 0.0;
1941  copy_v3_v3(hvec2, hvec1);
1942  hvec2[0] += 1000;
1943 
1944  /* test it with all edges of potential surrounding poly */
1945  /* count number of transitions left-right */
1946 
1947  bevp = bl1->bevpoints;
1948  nr = bl1->nr;
1949  prevbevp = bevp + (nr - 1);
1950 
1951  while (nr--) {
1952  min = prevbevp->vec[1];
1953  max = bevp->vec[1];
1954  if (max < min) {
1955  min = max;
1956  max = prevbevp->vec[1];
1957  }
1958  if (min != max) {
1959  if (min <= hvec1[1] && max >= hvec1[1]) {
1960  /* there's a transition, calc intersection point */
1961  mode = cu_isectLL(prevbevp->vec, bevp->vec, hvec1, hvec2, 0, 1, &lab, &mu, vec);
1962  /* if lab==0.0 or lab==1.0 then the edge intersects exactly a transition
1963  * only allow for one situation: we choose lab= 1.0
1964  */
1965  if (mode >= 0 && lab != 0.0f) {
1966  if (vec[0] < hvec1[0]) {
1967  links++;
1968  }
1969  else {
1970  rechts++;
1971  }
1972  }
1973  }
1974  }
1975  prevbevp = bevp;
1976  bevp++;
1977  }
1978 
1979  return (links & 1) && (rechts & 1);
1980 }
1981 
1982 struct BevelSort {
1984  float left;
1985  int dir;
1986 };
1987 
1988 static int vergxcobev(const void *a1, const void *a2)
1989 {
1990  const struct BevelSort *x1 = a1, *x2 = a2;
1991 
1992  if (x1->left > x2->left) {
1993  return 1;
1994  }
1995  if (x1->left < x2->left) {
1996  return -1;
1997  }
1998  return 0;
1999 }
2000 
2001 /* this function cannot be replaced with atan2, but why? */
2002 
2004  float x1, float y1, float x2, float y2, float *r_sina, float *r_cosa)
2005 {
2006  float t01, t02, x3, y3;
2007 
2008  t01 = sqrtf(x1 * x1 + y1 * y1);
2009  t02 = sqrtf(x2 * x2 + y2 * y2);
2010  if (t01 == 0.0f) {
2011  t01 = 1.0f;
2012  }
2013  if (t02 == 0.0f) {
2014  t02 = 1.0f;
2015  }
2016 
2017  x1 /= t01;
2018  y1 /= t01;
2019  x2 /= t02;
2020  y2 /= t02;
2021 
2022  t02 = x1 * x2 + y1 * y2;
2023  if (fabsf(t02) >= 1.0f) {
2024  t02 = M_PI_2;
2025  }
2026  else {
2027  t02 = (saacos(t02)) / 2.0f;
2028  }
2029 
2030  t02 = sinf(t02);
2031  if (t02 == 0.0f) {
2032  t02 = 1.0f;
2033  }
2034 
2035  x3 = x1 - x2;
2036  y3 = y1 - y2;
2037  if (x3 == 0 && y3 == 0) {
2038  x3 = y1;
2039  y3 = -x1;
2040  }
2041  else {
2042  t01 = sqrtf(x3 * x3 + y3 * y3);
2043  x3 /= t01;
2044  y3 /= t01;
2045  }
2046 
2047  *r_sina = -y3 / t02;
2048  *r_cosa = x3 / t02;
2049 }
2050 
2051 static void tilt_bezpart(const BezTriple *prevbezt,
2052  const BezTriple *bezt,
2053  Nurb *nu,
2054  float *tilt_array,
2055  float *radius_array,
2056  float *weight_array,
2057  int resolu,
2058  int stride)
2059 {
2060  const BezTriple *pprev, *next, *last;
2061  float fac, dfac, t[4];
2062  int a;
2063 
2064  if (tilt_array == NULL && radius_array == NULL) {
2065  return;
2066  }
2067 
2068  last = nu->bezt + (nu->pntsu - 1);
2069 
2070  /* returns a point */
2071  if (prevbezt == nu->bezt) {
2072  if (nu->flagu & CU_NURB_CYCLIC) {
2073  pprev = last;
2074  }
2075  else {
2076  pprev = prevbezt;
2077  }
2078  }
2079  else {
2080  pprev = prevbezt - 1;
2081  }
2082 
2083  /* next point */
2084  if (bezt == last) {
2085  if (nu->flagu & CU_NURB_CYCLIC) {
2086  next = nu->bezt;
2087  }
2088  else {
2089  next = bezt;
2090  }
2091  }
2092  else {
2093  next = bezt + 1;
2094  }
2095 
2096  fac = 0.0;
2097  dfac = 1.0f / (float)resolu;
2098 
2099  for (a = 0; a < resolu; a++, fac += dfac) {
2100  if (tilt_array) {
2101  if (nu->tilt_interp == KEY_CU_EASE) {
2102  /* May as well support for tilt also 2.47 ease interp. */
2103  *tilt_array = prevbezt->tilt +
2104  (bezt->tilt - prevbezt->tilt) * (3.0f * fac * fac - 2.0f * fac * fac * fac);
2105  }
2106  else {
2108  *tilt_array = t[0] * pprev->tilt + t[1] * prevbezt->tilt + t[2] * bezt->tilt +
2109  t[3] * next->tilt;
2110  }
2111 
2112  tilt_array = POINTER_OFFSET(tilt_array, stride);
2113  }
2114 
2115  if (radius_array) {
2116  if (nu->radius_interp == KEY_CU_EASE) {
2117  /* Support 2.47 ease interp
2118  * Note! - this only takes the 2 points into account,
2119  * giving much more localized results to changes in radius, sometimes you want that */
2120  *radius_array = prevbezt->radius + (bezt->radius - prevbezt->radius) *
2121  (3.0f * fac * fac - 2.0f * fac * fac * fac);
2122  }
2123  else {
2124 
2125  /* reuse interpolation from tilt if we can */
2126  if (tilt_array == NULL || nu->tilt_interp != nu->radius_interp) {
2128  }
2129  *radius_array = t[0] * pprev->radius + t[1] * prevbezt->radius + t[2] * bezt->radius +
2130  t[3] * next->radius;
2131  }
2132 
2133  radius_array = POINTER_OFFSET(radius_array, stride);
2134  }
2135 
2136  if (weight_array) {
2137  /* basic interpolation for now, could copy tilt interp too */
2138  *weight_array = prevbezt->weight + (bezt->weight - prevbezt->weight) *
2139  (3.0f * fac * fac - 2.0f * fac * fac * fac);
2140 
2141  weight_array = POINTER_OFFSET(weight_array, stride);
2142  }
2143  }
2144 }
2145 
2146 /* make_bevel_list_3D_* funcs, at a minimum these must
2147  * fill in the bezp->quat and bezp->dir values */
2148 
2149 /* utility for make_bevel_list_3D_* funcs */
2151 {
2152  BevPoint *bevp2, *bevp1, *bevp0;
2153  int nr;
2154  bool is_cyclic = bl->poly != -1;
2155 
2156  if (is_cyclic) {
2157  bevp2 = bl->bevpoints;
2158  bevp1 = bevp2 + (bl->nr - 1);
2159  bevp0 = bevp1 - 1;
2160  nr = bl->nr;
2161  }
2162  else {
2163  /* If spline is not cyclic, direction of first and
2164  * last bevel points matches direction of CV handle.
2165  *
2166  * This is getting calculated earlier when we know
2167  * CV's handles and here we might simply skip evaluation
2168  * of direction for this guys.
2169  */
2170 
2171  bevp0 = bl->bevpoints;
2172  bevp1 = bevp0 + 1;
2173  bevp2 = bevp1 + 1;
2174 
2175  nr = bl->nr - 2;
2176  }
2177 
2178  while (nr--) {
2179  /* totally simple */
2180  bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec);
2181 
2182  bevp0 = bevp1;
2183  bevp1 = bevp2;
2184  bevp2++;
2185  }
2186 
2187  /* In the unlikely situation that handles define a zeroed direction,
2188  * calculate it from the adjacent points, see T80742.
2189  *
2190  * Only do this as a fallback since we typically want the end-point directions
2191  * to be exactly aligned with the handles at the end-point, see T83117. */
2192  if (is_cyclic == false) {
2193  bevp0 = &bl->bevpoints[0];
2194  bevp1 = &bl->bevpoints[1];
2195  if (UNLIKELY(is_zero_v3(bevp0->dir))) {
2196  sub_v3_v3v3(bevp0->dir, bevp1->vec, bevp0->vec);
2197  if (normalize_v3(bevp0->dir) == 0.0f) {
2198  copy_v3_v3(bevp0->dir, bevp1->dir);
2199  }
2200  }
2201 
2202  bevp0 = &bl->bevpoints[bl->nr - 2];
2203  bevp1 = &bl->bevpoints[bl->nr - 1];
2204  if (UNLIKELY(is_zero_v3(bevp1->dir))) {
2205  sub_v3_v3v3(bevp1->dir, bevp1->vec, bevp0->vec);
2206  if (normalize_v3(bevp1->dir) == 0.0f) {
2207  copy_v3_v3(bevp1->dir, bevp0->dir);
2208  }
2209  }
2210  }
2211 }
2213 {
2214  BevPoint *bevp2, *bevp1, *bevp0;
2215  int nr;
2216 
2217  bevp2 = bl->bevpoints;
2218  bevp1 = bevp2 + (bl->nr - 1);
2219  bevp0 = bevp1 - 1;
2220 
2221  nr = bl->nr;
2222  while (nr--) {
2223  if (angle_normalized_v3v3(bevp0->tan, bevp1->tan) > DEG2RADF(90.0f)) {
2224  negate_v3(bevp1->tan);
2225  }
2226 
2227  bevp0 = bevp1;
2228  bevp1 = bevp2;
2229  bevp2++;
2230  }
2231 }
2232 /* apply user tilt */
2234 {
2235  BevPoint *bevp2, *bevp1;
2236  int nr;
2237  float q[4];
2238 
2239  bevp2 = bl->bevpoints;
2240  bevp1 = bevp2 + (bl->nr - 1);
2241 
2242  nr = bl->nr;
2243  while (nr--) {
2244  axis_angle_to_quat(q, bevp1->dir, bevp1->tilt);
2245  mul_qt_qtqt(bevp1->quat, q, bevp1->quat);
2246  normalize_qt(bevp1->quat);
2247 
2248  bevp1 = bevp2;
2249  bevp2++;
2250  }
2251 }
2252 /* smooth quats, this function should be optimized, it can get slow with many iterations. */
2254 {
2255  BevPoint *bevp2, *bevp1, *bevp0;
2256  int nr;
2257 
2258  float q[4];
2259  float bevp0_quat[4];
2260  int a;
2261 
2262  for (a = 0; a < smooth_iter; a++) {
2263  bevp2 = bl->bevpoints;
2264  bevp1 = bevp2 + (bl->nr - 1);
2265  bevp0 = bevp1 - 1;
2266 
2267  nr = bl->nr;
2268 
2269  if (bl->poly == -1) { /* check its not cyclic */
2270  /* skip the first point */
2271  /* bevp0 = bevp1; */
2272  bevp1 = bevp2;
2273  bevp2++;
2274  nr--;
2275 
2276  bevp0 = bevp1;
2277  bevp1 = bevp2;
2278  bevp2++;
2279  nr--;
2280  }
2281 
2282  copy_qt_qt(bevp0_quat, bevp0->quat);
2283 
2284  while (nr--) {
2285  /* interpolate quats */
2286  float zaxis[3] = {0, 0, 1}, cross[3], q2[4];
2287  interp_qt_qtqt(q, bevp0_quat, bevp2->quat, 0.5);
2288  normalize_qt(q);
2289 
2290  mul_qt_v3(q, zaxis);
2291  cross_v3_v3v3(cross, zaxis, bevp1->dir);
2292  axis_angle_to_quat(q2, cross, angle_normalized_v3v3(zaxis, bevp1->dir));
2293  normalize_qt(q2);
2294 
2295  copy_qt_qt(bevp0_quat, bevp1->quat);
2296  mul_qt_qtqt(q, q2, q);
2297  interp_qt_qtqt(bevp1->quat, bevp1->quat, q, 0.5);
2298  normalize_qt(bevp1->quat);
2299 
2300  /* bevp0 = bevp1; */ /* UNUSED */
2301  bevp1 = bevp2;
2302  bevp2++;
2303  }
2304  }
2305 }
2306 
2308 {
2309  BevPoint *bevp = bl->bevpoints;
2310  int nr = bl->nr;
2311 
2313 
2314  while (nr--) {
2315  vec_to_quat(bevp->quat, bevp->dir, 5, 1);
2316  bevp++;
2317  }
2318 }
2319 
2320 static void minimum_twist_between_two_points(BevPoint *current_point, BevPoint *previous_point)
2321 {
2322  float angle = angle_normalized_v3v3(previous_point->dir, current_point->dir);
2323  float q[4];
2324 
2325  if (angle > 0.0f) { /* otherwise we can keep as is */
2326  float cross_tmp[3];
2327  cross_v3_v3v3(cross_tmp, previous_point->dir, current_point->dir);
2328  axis_angle_to_quat(q, cross_tmp, angle);
2329  mul_qt_qtqt(current_point->quat, q, previous_point->quat);
2330  }
2331  else {
2332  copy_qt_qt(current_point->quat, previous_point->quat);
2333  }
2334 }
2335 
2337 {
2338  BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */
2339  int nr;
2340  float q[4];
2341 
2343 
2344  bevp2 = bl->bevpoints;
2345  bevp1 = bevp2 + (bl->nr - 1);
2346  bevp0 = bevp1 - 1;
2347 
2348  nr = bl->nr;
2349  while (nr--) {
2350 
2351  if (nr + 3 > bl->nr) { /* first time and second time, otherwise first point adjusts last */
2352  vec_to_quat(bevp1->quat, bevp1->dir, 5, 1);
2353  }
2354  else {
2355  minimum_twist_between_two_points(bevp1, bevp0);
2356  }
2357 
2358  bevp0 = bevp1;
2359  bevp1 = bevp2;
2360  bevp2++;
2361  }
2362 
2363  if (bl->poly != -1) { /* check for cyclic */
2364 
2365  /* Need to correct for the start/end points not matching
2366  * do this by calculating the tilt angle difference, then apply
2367  * the rotation gradually over the entire curve
2368  *
2369  * note that the split is between last and second last, rather than first/last as youd expect.
2370  *
2371  * real order is like this
2372  * 0,1,2,3,4 --> 1,2,3,4,0
2373  *
2374  * this is why we compare last with second last
2375  */
2376  float vec_1[3] = {0, 1, 0}, vec_2[3] = {0, 1, 0}, angle, ang_fac, cross_tmp[3];
2377 
2378  BevPoint *bevp_first;
2379  BevPoint *bevp_last;
2380 
2381  bevp_first = bl->bevpoints;
2382  bevp_first += bl->nr - 1;
2383  bevp_last = bevp_first;
2384  bevp_last--;
2385 
2386  /* quats and vec's are normalized, should not need to re-normalize */
2387  mul_qt_v3(bevp_first->quat, vec_1);
2388  mul_qt_v3(bevp_last->quat, vec_2);
2389  normalize_v3(vec_1);
2390  normalize_v3(vec_2);
2391 
2392  /* align the vector, can avoid this and it looks 98% OK but
2393  * better to align the angle quat roll's before comparing */
2394  {
2395  cross_v3_v3v3(cross_tmp, bevp_last->dir, bevp_first->dir);
2396  angle = angle_normalized_v3v3(bevp_first->dir, bevp_last->dir);
2397  axis_angle_to_quat(q, cross_tmp, angle);
2398  mul_qt_v3(q, vec_2);
2399  }
2400 
2401  angle = angle_normalized_v3v3(vec_1, vec_2);
2402 
2403  /* flip rotation if needs be */
2404  cross_v3_v3v3(cross_tmp, vec_1, vec_2);
2405  normalize_v3(cross_tmp);
2406  if (angle_normalized_v3v3(bevp_first->dir, cross_tmp) < DEG2RADF(90.0f)) {
2407  angle = -angle;
2408  }
2409 
2410  bevp2 = bl->bevpoints;
2411  bevp1 = bevp2 + (bl->nr - 1);
2412  bevp0 = bevp1 - 1;
2413 
2414  nr = bl->nr;
2415  while (nr--) {
2416  ang_fac = angle * (1.0f - ((float)nr / bl->nr)); /* also works */
2417 
2418  axis_angle_to_quat(q, bevp1->dir, ang_fac);
2419  mul_qt_qtqt(bevp1->quat, q, bevp1->quat);
2420 
2421  bevp0 = bevp1;
2422  bevp1 = bevp2;
2423  bevp2++;
2424  }
2425  }
2426  else {
2427  /* Need to correct quat for the first/last point,
2428  * this is so because previously it was only calculated
2429  * using its own direction, which might not correspond
2430  * the twist of neighbor point.
2431  */
2432  bevp1 = bl->bevpoints;
2433  bevp0 = bevp1 + 1;
2434  minimum_twist_between_two_points(bevp1, bevp0);
2435 
2436  bevp2 = bl->bevpoints;
2437  bevp1 = bevp2 + (bl->nr - 1);
2438  bevp0 = bevp1 - 1;
2439  minimum_twist_between_two_points(bevp1, bevp0);
2440  }
2441 }
2442 
2444 {
2445  BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */
2446  int nr;
2447 
2448  float bevp0_tan[3];
2449 
2452 
2453  /* correct the tangents */
2454  bevp2 = bl->bevpoints;
2455  bevp1 = bevp2 + (bl->nr - 1);
2456  bevp0 = bevp1 - 1;
2457 
2458  nr = bl->nr;
2459  while (nr--) {
2460  float cross_tmp[3];
2461  cross_v3_v3v3(cross_tmp, bevp1->tan, bevp1->dir);
2462  cross_v3_v3v3(bevp1->tan, cross_tmp, bevp1->dir);
2463  normalize_v3(bevp1->tan);
2464 
2465  bevp0 = bevp1;
2466  bevp1 = bevp2;
2467  bevp2++;
2468  }
2469 
2470  /* now for the real twist calc */
2471  bevp2 = bl->bevpoints;
2472  bevp1 = bevp2 + (bl->nr - 1);
2473  bevp0 = bevp1 - 1;
2474 
2475  copy_v3_v3(bevp0_tan, bevp0->tan);
2476 
2477  nr = bl->nr;
2478  while (nr--) {
2479  /* make perpendicular, modify tan in place, is ok */
2480  float cross_tmp[3];
2481  const float zero[3] = {0, 0, 0};
2482 
2483  cross_v3_v3v3(cross_tmp, bevp1->tan, bevp1->dir);
2484  normalize_v3(cross_tmp);
2485  tri_to_quat(bevp1->quat, zero, cross_tmp, bevp1->tan); /* XXX - could be faster */
2486 
2487  /* bevp0 = bevp1; */ /* UNUSED */
2488  bevp1 = bevp2;
2489  bevp2++;
2490  }
2491 }
2492 
2493 static void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode)
2494 {
2495  switch (twist_mode) {
2496  case CU_TWIST_TANGENT:
2498  break;
2499  case CU_TWIST_MINIMUM:
2501  break;
2502  default: /* CU_TWIST_Z_UP default, pre 2.49c */
2504  break;
2505  }
2506 
2507  if (smooth_iter) {
2509  }
2510 
2512 }
2513 
2514 /* only for 2 points */
2516 {
2517  float q[4];
2518 
2519  BevPoint *bevp2 = bl->bevpoints;
2520  BevPoint *bevp1 = bevp2 + 1;
2521 
2522  /* simple quat/dir */
2523  sub_v3_v3v3(bevp1->dir, bevp1->vec, bevp2->vec);
2524  normalize_v3(bevp1->dir);
2525 
2526  vec_to_quat(bevp1->quat, bevp1->dir, 5, 1);
2527  axis_angle_to_quat(q, bevp1->dir, bevp1->tilt);
2528  mul_qt_qtqt(bevp1->quat, q, bevp1->quat);
2529  normalize_qt(bevp1->quat);
2530 
2531  copy_v3_v3(bevp2->dir, bevp1->dir);
2532  vec_to_quat(bevp2->quat, bevp2->dir, 5, 1);
2533  axis_angle_to_quat(q, bevp2->dir, bevp2->tilt);
2534  mul_qt_qtqt(bevp2->quat, q, bevp2->quat);
2535  normalize_qt(bevp2->quat);
2536 }
2537 
2538 /* only for 2 points */
2540 {
2541  BevPoint *bevp2 = bl->bevpoints;
2542  BevPoint *bevp1 = bevp2 + 1;
2543 
2544  const float x1 = bevp1->vec[0] - bevp2->vec[0];
2545  const float y1 = bevp1->vec[1] - bevp2->vec[1];
2546 
2547  calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
2548  bevp2->sina = bevp1->sina;
2549  bevp2->cosa = bevp1->cosa;
2550 
2551  /* fill in dir & quat */
2553 }
2554 
2556 {
2557  /* note: bevp->dir and bevp->quat are not needed for beveling but are
2558  * used when making a path from a 2D curve, therefore they need to be set - Campbell */
2559 
2560  BevPoint *bevp0, *bevp1, *bevp2;
2561  int nr;
2562 
2563  if (bl->poly != -1) {
2564  bevp2 = bl->bevpoints;
2565  bevp1 = bevp2 + (bl->nr - 1);
2566  bevp0 = bevp1 - 1;
2567  nr = bl->nr;
2568  }
2569  else {
2570  bevp0 = bl->bevpoints;
2571  bevp1 = bevp0 + 1;
2572  bevp2 = bevp1 + 1;
2573 
2574  nr = bl->nr - 2;
2575  }
2576 
2577  while (nr--) {
2578  const float x1 = bevp1->vec[0] - bevp0->vec[0];
2579  const float x2 = bevp1->vec[0] - bevp2->vec[0];
2580  const float y1 = bevp1->vec[1] - bevp0->vec[1];
2581  const float y2 = bevp1->vec[1] - bevp2->vec[1];
2582 
2583  calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
2584 
2585  /* from: make_bevel_list_3D_zup, could call but avoid a second loop.
2586  * no need for tricky tilt calculation as with 3D curves */
2587  bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec);
2588  vec_to_quat(bevp1->quat, bevp1->dir, 5, 1);
2589  /* done with inline make_bevel_list_3D_zup */
2590 
2591  bevp0 = bevp1;
2592  bevp1 = bevp2;
2593  bevp2++;
2594  }
2595 
2596  /* correct non-cyclic cases */
2597  if (bl->poly == -1) {
2598  BevPoint *bevp;
2599  float angle;
2600 
2601  /* first */
2602  bevp = bl->bevpoints;
2603  angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)M_PI_2;
2604  bevp->sina = sinf(angle);
2605  bevp->cosa = cosf(angle);
2606  vec_to_quat(bevp->quat, bevp->dir, 5, 1);
2607 
2608  /* last */
2609  bevp = bl->bevpoints;
2610  bevp += (bl->nr - 1);
2611  angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)M_PI_2;
2612  bevp->sina = sinf(angle);
2613  bevp->cosa = cosf(angle);
2614  vec_to_quat(bevp->quat, bevp->dir, 5, 1);
2615  }
2616 }
2617 
2619 {
2620  if (nu->pntsu > 1) {
2621  BPoint *first_bp = nu->bp, *last_bp = nu->bp + (nu->pntsu - 1);
2622  BevPoint *first_bevp, *last_bevp;
2623 
2624  first_bevp = bl->bevpoints;
2625  last_bevp = first_bevp + (bl->nr - 1);
2626 
2627  sub_v3_v3v3(first_bevp->dir, (first_bp + 1)->vec, first_bp->vec);
2628  normalize_v3(first_bevp->dir);
2629 
2630  sub_v3_v3v3(last_bevp->dir, last_bp->vec, (last_bp - 1)->vec);
2631  normalize_v3(last_bevp->dir);
2632  }
2633 }
2634 
2636 {
2637  LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) {
2638  if (bl->seglen != NULL) {
2639  MEM_freeN(bl->seglen);
2640  }
2641  if (bl->segbevcount != NULL) {
2643  }
2644  if (bl->bevpoints != NULL) {
2646  }
2647  MEM_freeN(bl);
2648  }
2649 
2650  BLI_listbase_clear(bev);
2651 }
2652 
2653 void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
2654 {
2655  /*
2656  * - convert all curves to polys, with indication of resol and flags for double-vertices
2657  * - possibly; do a smart vertice removal (in case Nurb)
2658  * - separate in individual blocks with BoundBox
2659  * - AutoHole detection
2660  */
2661 
2662  /* this function needs an object, because of tflag and upflag */
2663  Curve *cu = ob->data;
2664  BezTriple *bezt, *prevbezt;
2665  BPoint *bp;
2666  BevList *blnew;
2667  BevPoint *bevp2, *bevp1 = NULL, *bevp0;
2668  const float threshold = 0.00001f;
2669  float min, inp;
2670  float *seglen = NULL;
2671  struct BevelSort *sortdata, *sd, *sd1;
2672  int a, b, nr, poly, resolu = 0, len = 0, segcount;
2673  int *segbevcount;
2674  bool do_tilt, do_radius, do_weight;
2675  bool is_editmode = false;
2676  ListBase *bev;
2677 
2678  /* segbevcount alsp requires seglen. */
2679  const bool need_seglen = ELEM(
2682 
2683  bev = &ob->runtime.curve_cache->bev;
2684 
2685 #if 0
2686  /* do we need to calculate the radius for each point? */
2687  do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 :
2688  1;
2689 #endif
2690 
2691  /* STEP 1: MAKE POLYS */
2692 
2694  if (cu->editnurb && ob->type != OB_FONT) {
2695  is_editmode = 1;
2696  }
2697 
2698  LISTBASE_FOREACH (Nurb *, nu, nurbs) {
2699  if (nu->hide && is_editmode) {
2700  continue;
2701  }
2702 
2703  /* check we are a single point? also check we are not a surface and that the orderu is sane,
2704  * enforced in the UI but can go wrong possibly */
2705  if (!BKE_nurb_check_valid_u(nu)) {
2706  BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList1");
2707  bl->bevpoints = MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1");
2708  BLI_addtail(bev, bl);
2709  bl->nr = 0;
2710  bl->charidx = nu->charidx;
2711  continue;
2712  }
2713 
2714  /* Tilt, as the rotation angle of curve control points, is only calculated for 3D curves,
2715  * (since this transformation affects the 3D space). */
2716  do_tilt = (cu->flag & CU_3D) != 0;
2717 
2718  /* Normal display uses the radius, better just to calculate them. */
2719  do_radius = CU_DO_RADIUS(cu, nu);
2720 
2721  do_weight = true;
2722 
2723  BevPoint *bevp;
2724 
2725  if (for_render && cu->resolu_ren != 0) {
2726  resolu = cu->resolu_ren;
2727  }
2728  else {
2729  resolu = nu->resolu;
2730  }
2731 
2732  segcount = SEGMENTSU(nu);
2733 
2734  if (nu->type == CU_POLY) {
2735  len = nu->pntsu;
2736  BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList2");
2737  bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints2");
2738  if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
2739  bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList2_seglen");
2740  bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelList2_segbevcount");
2741  }
2742  BLI_addtail(bev, bl);
2743 
2744  bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
2745  bl->nr = len;
2746  bl->dupe_nr = 0;
2747  bl->charidx = nu->charidx;
2748  bevp = bl->bevpoints;
2749  bevp->offset = 0;
2750  bp = nu->bp;
2751  seglen = bl->seglen;
2752  segbevcount = bl->segbevcount;
2753 
2754  while (len--) {
2755  copy_v3_v3(bevp->vec, bp->vec);
2756  bevp->tilt = bp->tilt;
2757  bevp->radius = bp->radius;
2758  bevp->weight = bp->weight;
2759  bp++;
2760  if (seglen != NULL && len != 0) {
2761  *seglen = len_v3v3(bevp->vec, bp->vec);
2762  bevp++;
2763  bevp->offset = *seglen;
2764  if (*seglen > threshold) {
2765  *segbevcount = 1;
2766  }
2767  else {
2768  *segbevcount = 0;
2769  }
2770  seglen++;
2771  segbevcount++;
2772  }
2773  else {
2774  bevp++;
2775  }
2776  }
2777 
2778  if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
2780  }
2781  }
2782  else if (nu->type == CU_BEZIER) {
2783  /* in case last point is not cyclic */
2784  len = segcount * resolu + 1;
2785 
2786  BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints");
2787  bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelBPointsPoints");
2788  if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
2789  bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelBPoints_seglen");
2790  bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelBPoints_segbevcount");
2791  }
2792  BLI_addtail(bev, bl);
2793 
2794  bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
2795  bl->charidx = nu->charidx;
2796 
2797  bevp = bl->bevpoints;
2798  seglen = bl->seglen;
2799  segbevcount = bl->segbevcount;
2800 
2801  bevp->offset = 0;
2802  if (seglen != NULL) {
2803  *seglen = 0;
2804  *segbevcount = 0;
2805  }
2806 
2807  a = nu->pntsu - 1;
2808  bezt = nu->bezt;
2809  if (nu->flagu & CU_NURB_CYCLIC) {
2810  a++;
2811  prevbezt = nu->bezt + (nu->pntsu - 1);
2812  }
2813  else {
2814  prevbezt = bezt;
2815  bezt++;
2816  }
2817 
2818  sub_v3_v3v3(bevp->dir, prevbezt->vec[2], prevbezt->vec[1]);
2819  normalize_v3(bevp->dir);
2820 
2821  BLI_assert(segcount >= a);
2822 
2823  while (a--) {
2824  if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
2825 
2826  copy_v3_v3(bevp->vec, prevbezt->vec[1]);
2827  bevp->tilt = prevbezt->tilt;
2828  bevp->radius = prevbezt->radius;
2829  bevp->weight = prevbezt->weight;
2830  bevp->dupe_tag = false;
2831  bevp++;
2832  bl->nr++;
2833  bl->dupe_nr = 1;
2834  if (seglen != NULL) {
2835  *seglen = len_v3v3(prevbezt->vec[1], bezt->vec[1]);
2836  bevp->offset = *seglen;
2837  seglen++;
2838  /* match segbevcount to the cleaned up bevel lists (see STEP 2) */
2839  if (bevp->offset > threshold) {
2840  *segbevcount = 1;
2841  }
2842  segbevcount++;
2843  }
2844  }
2845  else {
2846  /* always do all three, to prevent data hanging around */
2847  int j;
2848 
2849  /* BevPoint must stay aligned to 4 so sizeof(BevPoint)/sizeof(float) works */
2850  for (j = 0; j < 3; j++) {
2851  BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
2852  prevbezt->vec[2][j],
2853  bezt->vec[0][j],
2854  bezt->vec[1][j],
2855  &(bevp->vec[j]),
2856  resolu,
2857  sizeof(BevPoint));
2858  }
2859 
2860  /* if both arrays are NULL do nothiong */
2861  tilt_bezpart(prevbezt,
2862  bezt,
2863  nu,
2864  do_tilt ? &bevp->tilt : NULL,
2865  do_radius ? &bevp->radius : NULL,
2866  do_weight ? &bevp->weight : NULL,
2867  resolu,
2868  sizeof(BevPoint));
2869 
2870  if (cu->twist_mode == CU_TWIST_TANGENT) {
2871  forward_diff_bezier_cotangent(prevbezt->vec[1],
2872  prevbezt->vec[2],
2873  bezt->vec[0],
2874  bezt->vec[1],
2875  bevp->tan,
2876  resolu,
2877  sizeof(BevPoint));
2878  }
2879 
2880  /* seglen */
2881  if (seglen != NULL) {
2882  *seglen = 0;
2883  *segbevcount = 0;
2884  for (j = 0; j < resolu; j++) {
2885  bevp0 = bevp;
2886  bevp++;
2887  bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
2888  /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
2889  if (bevp->offset > threshold) {
2890  *seglen += bevp->offset;
2891  *segbevcount += 1;
2892  }
2893  }
2894  seglen++;
2895  segbevcount++;
2896  }
2897  else {
2898  bevp += resolu;
2899  }
2900  bl->nr += resolu;
2901  }
2902  prevbezt = bezt;
2903  bezt++;
2904  }
2905 
2906  if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic: endpoint */
2907  copy_v3_v3(bevp->vec, prevbezt->vec[1]);
2908  bevp->tilt = prevbezt->tilt;
2909  bevp->radius = prevbezt->radius;
2910  bevp->weight = prevbezt->weight;
2911 
2912  sub_v3_v3v3(bevp->dir, prevbezt->vec[1], prevbezt->vec[0]);
2913  normalize_v3(bevp->dir);
2914 
2915  bl->nr++;
2916  }
2917  }
2918  else if (nu->type == CU_NURBS) {
2919  if (nu->pntsv == 1) {
2920  len = (resolu * segcount);
2921 
2922  BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList3");
2923  bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints3");
2924  if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
2925  bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList3_seglen");
2926  bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelList3_segbevcount");
2927  }
2928  BLI_addtail(bev, bl);
2929  bl->nr = len;
2930  bl->dupe_nr = 0;
2931  bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
2932  bl->charidx = nu->charidx;
2933 
2934  bevp = bl->bevpoints;
2935  seglen = bl->seglen;
2936  segbevcount = bl->segbevcount;
2937 
2938  BKE_nurb_makeCurve(nu,
2939  &bevp->vec[0],
2940  do_tilt ? &bevp->tilt : NULL,
2941  do_radius ? &bevp->radius : NULL,
2942  do_weight ? &bevp->weight : NULL,
2943  resolu,
2944  sizeof(BevPoint));
2945 
2946  /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
2947  if (seglen != NULL) {
2948  nr = segcount;
2949  bevp0 = bevp;
2950  bevp++;
2951  while (nr) {
2952  int j;
2953  *seglen = 0;
2954  *segbevcount = 0;
2955  /* We keep last bevel segment zero-length. */
2956  for (j = 0; j < ((nr == 1) ? (resolu - 1) : resolu); j++) {
2957  bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
2958  if (bevp->offset > threshold) {
2959  *seglen += bevp->offset;
2960  *segbevcount += 1;
2961  }
2962  bevp0 = bevp;
2963  bevp++;
2964  }
2965  seglen++;
2966  segbevcount++;
2967  nr--;
2968  }
2969  }
2970 
2971  if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
2973  }
2974  }
2975  }
2976  }
2977 
2978  /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */
2979  LISTBASE_FOREACH (BevList *, bl, bev) {
2980  if (bl->nr == 0) { /* null bevel items come from single points */
2981  continue;
2982  }
2983 
2984  /* Scale the threshold so high resolution shapes don't get over reduced, see: T49850. */
2985  const float threshold_resolu = 0.00001f / resolu;
2986  bool is_cyclic = bl->poly != -1;
2987  nr = bl->nr;
2988  if (is_cyclic) {
2989  bevp1 = bl->bevpoints;
2990  bevp0 = bevp1 + (nr - 1);
2991  }
2992  else {
2993  bevp0 = bl->bevpoints;
2994  bevp0->offset = 0;
2995  bevp1 = bevp0 + 1;
2996  }
2997  nr--;
2998  while (nr--) {
2999  if (seglen != NULL) {
3000  if (fabsf(bevp1->offset) < threshold) {
3001  bevp0->dupe_tag = true;
3002  bl->dupe_nr++;
3003  }
3004  }
3005  else {
3006  if (compare_v3v3(bevp0->vec, bevp1->vec, threshold_resolu)) {
3007  bevp0->dupe_tag = true;
3008  bl->dupe_nr++;
3009  }
3010  }
3011  bevp0 = bevp1;
3012  bevp1++;
3013  }
3014  }
3015 
3016  LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) {
3017  if (bl->nr == 0 || bl->dupe_nr == 0) {
3018  continue;
3019  }
3020 
3021  nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */
3022  blnew = MEM_mallocN(sizeof(BevList), "makeBevelList4");
3023  memcpy(blnew, bl, sizeof(BevList));
3024  blnew->bevpoints = MEM_calloc_arrayN(nr, sizeof(BevPoint), "makeBevelPoints4");
3025  if (!blnew->bevpoints) {
3026  MEM_freeN(blnew);
3027  break;
3028  }
3029  blnew->segbevcount = bl->segbevcount;
3030  blnew->seglen = bl->seglen;
3031  blnew->nr = 0;
3032  BLI_remlink(bev, bl);
3033  BLI_insertlinkbefore(bev, bl->next, blnew); /* to make sure bevlist is tuned with nurblist */
3034  bevp0 = bl->bevpoints;
3035  bevp1 = blnew->bevpoints;
3036  nr = bl->nr;
3037  while (nr--) {
3038  if (bevp0->dupe_tag == 0) {
3039  memcpy(bevp1, bevp0, sizeof(BevPoint));
3040  bevp1++;
3041  blnew->nr++;
3042  }
3043  bevp0++;
3044  }
3045  if (bl->bevpoints != NULL) {
3047  }
3048  MEM_freeN(bl);
3049  blnew->dupe_nr = 0;
3050  }
3051 
3052  /* STEP 3: POLYS COUNT AND AUTOHOLE */
3053  poly = 0;
3054  LISTBASE_FOREACH (BevList *, bl, bev) {
3055  if (bl->nr && bl->poly >= 0) {
3056  poly++;
3057  bl->poly = poly;
3058  bl->hole = 0;
3059  }
3060  }
3061 
3062  /* find extreme left points, also test (turning) direction */
3063  if (poly > 0) {
3064  sd = sortdata = MEM_malloc_arrayN(poly, sizeof(struct BevelSort), "makeBevelList5");
3065  LISTBASE_FOREACH (BevList *, bl, bev) {
3066  if (bl->poly > 0) {
3067  BevPoint *bevp;
3068 
3069  bevp = bl->bevpoints;
3070  bevp1 = bl->bevpoints;
3071  min = bevp1->vec[0];
3072  nr = bl->nr;
3073  while (nr--) {
3074  if (min > bevp->vec[0]) {
3075  min = bevp->vec[0];
3076  bevp1 = bevp;
3077  }
3078  bevp++;
3079  }
3080  sd->bl = bl;
3081  sd->left = min;
3082 
3083  bevp = bl->bevpoints;
3084  if (bevp1 == bevp) {
3085  bevp0 = bevp + (bl->nr - 1);
3086  }
3087  else {
3088  bevp0 = bevp1 - 1;
3089  }
3090  bevp = bevp + (bl->nr - 1);
3091  if (bevp1 == bevp) {
3092  bevp2 = bl->bevpoints;
3093  }
3094  else {
3095  bevp2 = bevp1 + 1;
3096  }
3097 
3098  inp = ((bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) +
3099  (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0]));
3100 
3101  if (inp > 0.0f) {
3102  sd->dir = 1;
3103  }
3104  else {
3105  sd->dir = 0;
3106  }
3107 
3108  sd++;
3109  }
3110  }
3111  qsort(sortdata, poly, sizeof(struct BevelSort), vergxcobev);
3112 
3113  sd = sortdata + 1;
3114  for (a = 1; a < poly; a++, sd++) {
3115  BevList *bl = sd->bl; /* is bl a hole? */
3116  sd1 = sortdata + (a - 1);
3117  for (b = a - 1; b >= 0; b--, sd1--) { /* all polys to the left */
3118  if (sd1->bl->charidx == bl->charidx) { /* for text, only check matching char */
3119  if (bevelinside(sd1->bl, bl)) {
3120  bl->hole = 1 - sd1->bl->hole;
3121  break;
3122  }
3123  }
3124  }
3125  }
3126 
3127  /* turning direction */
3128  if (CU_IS_2D(cu)) {
3129  sd = sortdata;
3130  for (a = 0; a < poly; a++, sd++) {
3131  if (sd->bl->hole == sd->dir) {
3132  BevList *bl = sd->bl;
3133  bevp1 = bl->bevpoints;
3134  bevp2 = bevp1 + (bl->nr - 1);
3135  nr = bl->nr / 2;
3136  while (nr--) {
3137  SWAP(BevPoint, *bevp1, *bevp2);
3138  bevp1++;
3139  bevp2--;
3140  }
3141  }
3142  }
3143  }
3144  MEM_freeN(sortdata);
3145  }
3146 
3147  /* STEP 4: 2D-COSINES or 3D ORIENTATION */
3148  if (CU_IS_2D(cu)) {
3149  /* 2D Curves */
3150  LISTBASE_FOREACH (BevList *, bl, bev) {
3151  if (bl->nr < 2) {
3152  BevPoint *bevp = bl->bevpoints;
3153  unit_qt(bevp->quat);
3154  }
3155  else if (bl->nr == 2) { /* 2 pnt, treat separate */
3157  }
3158  else {
3160  }
3161  }
3162  }
3163  else {
3164  /* 3D Curves */
3165  LISTBASE_FOREACH (BevList *, bl, bev) {
3166  if (bl->nr < 2) {
3167  BevPoint *bevp = bl->bevpoints;
3168  unit_qt(bevp->quat);
3169  }
3170  else if (bl->nr == 2) { /* 2 pnt, treat separate */
3172  }
3173  else {
3174  make_bevel_list_3D(bl, (int)(resolu * cu->twist_smooth), cu->twist_mode);
3175  }
3176  }
3177  }
3178 }
3179 
3180 /* ****************** HANDLES ************** */
3181 
3183  const BezTriple *prev,
3184  const BezTriple *next,
3185  eBezTriple_Flag handle_sel_flag,
3186  bool is_fcurve,
3187  bool skip_align,
3188  char fcurve_smoothing)
3189 {
3190  /* defines to avoid confusion */
3191 #define p2_h1 ((p2)-3)
3192 #define p2_h2 ((p2) + 3)
3193 
3194  const float *p1, *p3;
3195  float *p2;
3196  float pt[3];
3197  float dvec_a[3], dvec_b[3];
3198  float len, len_a, len_b;
3199  float len_ratio;
3200  const float eps = 1e-5;
3201 
3202  /* assume normal handle until we check */
3204 
3205  if (bezt->h1 == 0 && bezt->h2 == 0) {
3206  return;
3207  }
3208 
3209  p2 = bezt->vec[1];
3210 
3211  if (prev == NULL) {
3212  p3 = next->vec[1];
3213  pt[0] = 2.0f * p2[0] - p3[0];
3214  pt[1] = 2.0f * p2[1] - p3[1];
3215  pt[2] = 2.0f * p2[2] - p3[2];
3216  p1 = pt;
3217  }
3218  else {
3219  p1 = prev->vec[1];
3220  }
3221 
3222  if (next == NULL) {
3223  pt[0] = 2.0f * p2[0] - p1[0];
3224  pt[1] = 2.0f * p2[1] - p1[1];
3225  pt[2] = 2.0f * p2[2] - p1[2];
3226  p3 = pt;
3227  }
3228  else {
3229  p3 = next->vec[1];
3230  }
3231 
3232  sub_v3_v3v3(dvec_a, p2, p1);
3233  sub_v3_v3v3(dvec_b, p3, p2);
3234 
3235  if (is_fcurve) {
3236  len_a = dvec_a[0];
3237  len_b = dvec_b[0];
3238  }
3239  else {
3240  len_a = len_v3(dvec_a);
3241  len_b = len_v3(dvec_b);
3242  }
3243 
3244  if (len_a == 0.0f) {
3245  len_a = 1.0f;
3246  }
3247  if (len_b == 0.0f) {
3248  len_b = 1.0f;
3249  }
3250 
3251  len_ratio = len_a / len_b;
3252 
3253  if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) || ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { /* auto */
3254  float tvec[3];
3255  tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a;
3256  tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a;
3257  tvec[2] = dvec_b[2] / len_b + dvec_a[2] / len_a;
3258 
3259  if (is_fcurve) {
3260  if (fcurve_smoothing != FCURVE_SMOOTH_NONE) {
3261  /* force the horizontal handle size to be 1/3 of the key interval so that
3262  * the X component of the parametric bezier curve is a linear spline */
3263  len = 6.0f / 2.5614f;
3264  }
3265  else {
3266  len = tvec[0];
3267  }
3268  }
3269  else {
3270  len = len_v3(tvec);
3271  }
3272  len *= 2.5614f;
3273 
3274  if (len != 0.0f) {
3275  /* only for fcurves */
3276  bool leftviolate = false, rightviolate = false;
3277 
3278  if (!is_fcurve || fcurve_smoothing == FCURVE_SMOOTH_NONE) {
3279  if (len_a > 5.0f * len_b) {
3280  len_a = 5.0f * len_b;
3281  }
3282  if (len_b > 5.0f * len_a) {
3283  len_b = 5.0f * len_a;
3284  }
3285  }
3286 
3287  if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {
3288  len_a /= len;
3289  madd_v3_v3v3fl(p2_h1, p2, tvec, -len_a);
3290 
3291  if ((bezt->h1 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
3292  float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
3293  float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
3294  if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) {
3295  bezt->vec[0][1] = bezt->vec[1][1];
3297  }
3298  else { /* handles should not be beyond y coord of two others */
3299  if (ydiff1 <= 0.0f) {
3300  if (prev->vec[1][1] > bezt->vec[0][1]) {
3301  bezt->vec[0][1] = prev->vec[1][1];
3302  leftviolate = 1;
3303  }
3304  }
3305  else {
3306  if (prev->vec[1][1] < bezt->vec[0][1]) {
3307  bezt->vec[0][1] = prev->vec[1][1];
3308  leftviolate = 1;
3309  }
3310  }
3311  }
3312  }
3313  }
3314  if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {
3315  len_b /= len;
3316  madd_v3_v3v3fl(p2_h2, p2, tvec, len_b);
3317 
3318  if ((bezt->h2 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
3319  float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
3320  float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
3321  if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) {
3322  bezt->vec[2][1] = bezt->vec[1][1];
3324  }
3325  else { /* handles should not be beyond y coord of two others */
3326  if (ydiff1 <= 0.0f) {
3327  if (next->vec[1][1] < bezt->vec[2][1]) {
3328  bezt->vec[2][1] = next->vec[1][1];
3329  rightviolate = 1;
3330  }
3331  }
3332  else {
3333  if (next->vec[1][1] > bezt->vec[2][1]) {
3334  bezt->vec[2][1] = next->vec[1][1];
3335  rightviolate = 1;
3336  }
3337  }
3338  }
3339  }
3340  }
3341  if (leftviolate || rightviolate) { /* align left handle */
3342  BLI_assert(is_fcurve);
3343  /* simple 2d calculation */
3344  float h1_x = p2_h1[0] - p2[0];
3345  float h2_x = p2[0] - p2_h2[0];
3346 
3347  if (leftviolate) {
3348  p2_h2[1] = p2[1] + ((p2[1] - p2_h1[1]) / h1_x) * h2_x;
3349  }
3350  else {
3351  p2_h1[1] = p2[1] + ((p2[1] - p2_h2[1]) / h2_x) * h1_x;
3352  }
3353  }
3354  }
3355  }
3356 
3357  if (bezt->h1 == HD_VECT) { /* vector */
3358  madd_v3_v3v3fl(p2_h1, p2, dvec_a, -1.0f / 3.0f);
3359  }
3360  if (bezt->h2 == HD_VECT) {
3361  madd_v3_v3v3fl(p2_h2, p2, dvec_b, 1.0f / 3.0f);
3362  }
3363 
3364  if (skip_align ||
3365  /* when one handle is free, alignming makes no sense, see: T35952 */
3366  (ELEM(HD_FREE, bezt->h1, bezt->h2)) ||
3367  /* also when no handles are aligned, skip this step */
3368  (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) {
3369  /* handles need to be updated during animation and applying stuff like hooks,
3370  * but in such situations it's quite difficult to distinguish in which order
3371  * align handles should be aligned so skip them for now */
3372  return;
3373  }
3374 
3375  len_a = len_v3v3(p2, p2_h1);
3376  len_b = len_v3v3(p2, p2_h2);
3377 
3378  if (len_a == 0.0f) {
3379  len_a = 1.0f;
3380  }
3381  if (len_b == 0.0f) {
3382  len_b = 1.0f;
3383  }
3384 
3385  len_ratio = len_a / len_b;
3386 
3387  if (bezt->f1 & handle_sel_flag) { /* order of calculation */
3388  if (ELEM(bezt->h2, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) { /* aligned */
3389  if (len_a > eps) {
3390  len = 1.0f / len_ratio;
3391  p2_h2[0] = p2[0] + len * (p2[0] - p2_h1[0]);
3392  p2_h2[1] = p2[1] + len * (p2[1] - p2_h1[1]);
3393  p2_h2[2] = p2[2] + len * (p2[2] - p2_h1[2]);
3394  }
3395  }
3396  if (ELEM(bezt->h1, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {
3397  if (len_b > eps) {
3398  len = len_ratio;
3399  p2_h1[0] = p2[0] + len * (p2[0] - p2_h2[0]);
3400  p2_h1[1] = p2[1] + len * (p2[1] - p2_h2[1]);
3401  p2_h1[2] = p2[2] + len * (p2[2] - p2_h2[2]);
3402  }
3403  }
3404  }
3405  else {
3406  if (ELEM(bezt->h1, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {
3407  if (len_b > eps) {
3408  len = len_ratio;
3409  p2_h1[0] = p2[0] + len * (p2[0] - p2_h2[0]);
3410  p2_h1[1] = p2[1] + len * (p2[1] - p2_h2[1]);
3411  p2_h1[2] = p2[2] + len * (p2[2] - p2_h2[2]);
3412  }
3413  }
3414  if (ELEM(bezt->h2, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) { /* aligned */
3415  if (len_a > eps) {
3416  len = 1.0f / len_ratio;
3417  p2_h2[0] = p2[0] + len * (p2[0] - p2_h1[0]);
3418  p2_h2[1] = p2[1] + len * (p2[1] - p2_h1[1]);
3419  p2_h2[2] = p2[2] + len * (p2[2] - p2_h1[2]);
3420  }
3421  }
3422  }
3423 
3424 #undef p2_h1
3425 #undef p2_h2
3426 }
3427 
3428 static void calchandlesNurb_intern(Nurb *nu, eBezTriple_Flag handle_sel_flag, bool skip_align)
3429 {
3430  BezTriple *bezt, *prev, *next;
3431  int a;
3432 
3433  if (nu->type != CU_BEZIER) {
3434  return;
3435  }
3436  if (nu->pntsu < 2) {
3437  return;
3438  }
3439 
3440  a = nu->pntsu;
3441  bezt = nu->bezt;
3442  if (nu->flagu & CU_NURB_CYCLIC) {
3443  prev = bezt + (a - 1);
3444  }
3445  else {
3446  prev = NULL;
3447  }
3448  next = bezt + 1;
3449 
3450  while (a--) {
3451  calchandleNurb_intern(bezt, prev, next, handle_sel_flag, 0, skip_align, 0);
3452  prev = bezt;
3453  if (a == 1) {
3454  if (nu->flagu & CU_NURB_CYCLIC) {
3455  next = nu->bezt;
3456  }
3457  else {
3458  next = NULL;
3459  }
3460  }
3461  else {
3462  next++;
3463  }
3464 
3465  bezt++;
3466  }
3467 }
3468 
3478 static void *allocate_arrays(int count, float ***floats, char ***chars, const char *name)
3479 {
3480  size_t num_floats = 0, num_chars = 0;
3481 
3482  while (floats && floats[num_floats]) {
3483  num_floats++;
3484  }
3485 
3486  while (chars && chars[num_chars]) {
3487  num_chars++;
3488  }
3489 
3490  void *buffer = (float *)MEM_malloc_arrayN(count, (sizeof(float) * num_floats + num_chars), name);
3491 
3492  if (!buffer) {
3493  return NULL;
3494  }
3495 
3496  float *fptr = buffer;
3497 
3498  for (int i = 0; i < num_floats; i++, fptr += count) {
3499  *floats[i] = fptr;
3500  }
3501 
3502  char *cptr = (char *)fptr;
3503 
3504  for (int i = 0; i < num_chars; i++, cptr += count) {
3505  *chars[i] = cptr;
3506  }
3507 
3508  return buffer;
3509 }
3510 
3511 static void free_arrays(void *buffer)
3512 {
3513  MEM_freeN(buffer);
3514 }
3515 
3516 /* computes in which direction to change h[i] to satisfy conditions better */
3517 static float bezier_relax_direction(const float *a,
3518  const float *b,
3519  const float *c,
3520  const float *d,
3521  const float *h,
3522  int i,
3523  int count)
3524 {
3525  /* current deviation between sides of the equation */
3526  float state = a[i] * h[(i + count - 1) % count] + b[i] * h[i] + c[i] * h[(i + 1) % count] - d[i];
3527 
3528  /* only the sign is meaningful */
3529  return -state * b[i];
3530 }
3531 
3532 static void bezier_lock_unknown(float *a, float *b, float *c, float *d, int i, float value)
3533 {
3534  a[i] = c[i] = 0.0f;
3535  b[i] = 1.0f;
3536  d[i] = value;
3537 }
3538 
3539 static void bezier_restore_equation(float *a,
3540  float *b,
3541  float *c,
3542  float *d,
3543  const float *a0,
3544  const float *b0,
3545  const float *c0,
3546  const float *d0,
3547  int i)
3548 {
3549  a[i] = a0[i];
3550  b[i] = b0[i];
3551  c[i] = c0[i];
3552  d[i] = d0[i];
3553 }
3554 
3556  float *b,
3557  float *c,
3558  float *d,
3559  float *h,
3560  const float *hmin,
3561  const float *hmax,
3562  int solve_count)
3563 {
3564  float *a0, *b0, *c0, *d0;
3565  float **arrays[] = {&a0, &b0, &c0, &d0, NULL};
3566  char *is_locked, *num_unlocks;
3567  char **flagarrays[] = {&is_locked, &num_unlocks, NULL};
3568 
3569  void *tmps = allocate_arrays(solve_count, arrays, flagarrays, "tridiagonal_solve_with_limits");
3570  if (!tmps) {
3571  return false;
3572  }
3573 
3574  memcpy(a0, a, sizeof(float) * solve_count);
3575  memcpy(b0, b, sizeof(float) * solve_count);
3576  memcpy(c0, c, sizeof(float) * solve_count);
3577  memcpy(d0, d, sizeof(float) * solve_count);
3578 
3579  memset(is_locked, 0, solve_count);
3580  memset(num_unlocks, 0, solve_count);
3581 
3582  bool overshoot, unlocked;
3583 
3584  do {
3585  if (!BLI_tridiagonal_solve_cyclic(a, b, c, d, h, solve_count)) {
3586  free_arrays(tmps);
3587  return false;
3588  }
3589 
3590  /* first check if any handles overshoot the limits, and lock them */
3591  bool all = false, locked = false;
3592 
3593  overshoot = unlocked = false;
3594 
3595  do {
3596  for (int i = 0; i < solve_count; i++) {
3597  if (h[i] >= hmin[i] && h[i] <= hmax[i]) {
3598  continue;
3599  }
3600 
3601  overshoot = true;
3602 
3603  float target = h[i] > hmax[i] ? hmax[i] : hmin[i];
3604 
3605  /* heuristically only lock handles that go in the right direction if there are such ones */
3606  if (target != 0.0f || all) {
3607  /* mark item locked */
3608  is_locked[i] = 1;
3609 
3610  bezier_lock_unknown(a, b, c, d, i, target);
3611  locked = true;
3612  }
3613  }
3614 
3615  all = true;
3616  } while (overshoot && !locked);
3617 
3618  /* If no handles overshot and were locked,
3619  * see if it may be a good idea to unlock some handles. */
3620  if (!locked) {
3621  for (int i = 0; i < solve_count; i++) {
3622  /* to definitely avoid infinite loops limit this to 2 times */
3623  if (!is_locked[i] || num_unlocks[i] >= 2) {
3624  continue;
3625  }
3626 
3627  /* if the handle wants to move in allowable direction, release it */
3628  float relax = bezier_relax_direction(a0, b0, c0, d0, h, i, solve_count);
3629 
3630  if ((relax > 0 && h[i] < hmax[i]) || (relax < 0 && h[i] > hmin[i])) {
3631  bezier_restore_equation(a, b, c, d, a0, b0, c0, d0, i);
3632 
3633  is_locked[i] = 0;
3634  num_unlocks[i]++;
3635  unlocked = true;
3636  }
3637  }
3638  }
3639  } while (overshoot || unlocked);
3640 
3641  free_arrays(tmps);
3642  return true;
3643 }
3644 
3645 /* Keep ascii art. */
3646 /* clang-format off */
3647 /*
3648  * This function computes the handles of a series of auto bezier points
3649  * on the basis of 'no acceleration discontinuities' at the points.
3650  * The first and last bezier points are considered 'fixed' (their handles are not touched)
3651  * The result is the smoothest possible trajectory going through intermediate points.
3652  * The difficulty is that the handles depends on their neighbors.
3653  *
3654  * The exact solution is found by solving a tridiagonal matrix equation formed
3655  * by the continuity and boundary conditions. Although theoretically handle position
3656  * is affected by all other points of the curve segment, in practice the influence
3657  * decreases exponentially with distance.
3658  *
3659  * Note: this algorithm assumes that the handle horizontal size is always 1/3 of the
3660  * of the interval to the next point. This rule ensures linear interpolation of time.
3661  *
3662  * ^ height (co 1)
3663  * | yN
3664  * | yN-1 |
3665  * | y2 | |
3666  * | y1 | | |
3667  * | y0 | | | |
3668  * | | | | | |
3669  * | | | | | |
3670  * | | | | | |
3671  * |------dx1--------dx2--------- ~ -------dxN-------------------> time (co 0)
3672  *
3673  * Notation:
3674  *
3675  * x[i], y[i] - keyframe coordinates
3676  * h[i] - right handle y offset from y[i]
3677  *
3678  * dx[i] = x[i] - x[i-1]
3679  * dy[i] = y[i] - y[i-1]
3680  *
3681  * Mathematical basis:
3682  *
3683  * 1. Handle lengths on either side of each point are connected by a factor
3684  * ensuring continuity of the first derivative:
3685  *
3686  * l[i] = dx[i+1]/dx[i]
3687  *
3688  * 2. The tridiagonal system is formed by the following equation, which is derived
3689  * by differentiating the bezier curve and specifies second derivative continuity
3690  * at every point:
3691  *
3692  * l[i]^2 * h[i-1] + (2*l[i]+2) * h[i] + 1/l[i+1] * h[i+1] = dy[i]*l[i]^2 + dy[i+1]
3693  *
3694  * 3. If this point is adjacent to a manually set handle with X size not equal to 1/3
3695  * of the horizontal interval, this equation becomes slightly more complex:
3696  *
3697  * l[i]^2 * h[i-1] + (3*(1-R[i-1])*l[i] + 3*(1-L[i+1])) * h[i] + 1/l[i+1] * h[i+1] = dy[i]*l[i]^2 + dy[i+1]
3698  *
3699  * The difference between equations amounts to this, and it's obvious that when R[i-1]
3700  * and L[i+1] are both 1/3, it becomes zero:
3701  *
3702  * ( (1-3*R[i-1])*l[i] + (1-3*L[i+1]) ) * h[i]
3703  *
3704  * 4. The equations for zero acceleration border conditions are basically the above
3705  * equation with parts omitted, so the handle size correction also applies.
3706  *
3707  * 5. The fully cyclic curve case is handled by eliminating one of the end points,
3708  * and instead of border conditions connecting the curve via a set of equations:
3709  *
3710  * l[0] = l[N] = dx[1] / dx[N]
3711  * dy[0] = dy[N]
3712  * Continuity equation (item 2) for i = 0.
3713  * Substitute h[0] for h[N] and h[N-1] for h[-1]
3714  */
3715 /* clang-format on */
3716 
3718  float *a, float *b, float *c, float *d, const float *dy, const float *l, int i)
3719 {
3720  a[i] = l[i] * l[i];
3721  b[i] = 2.0f * (l[i] + 1);
3722  c[i] = 1.0f / l[i + 1];
3723  d[i] = dy[i] * l[i] * l[i] + dy[i + 1];
3724 }
3725 
3727  float *a, float *b, float *c, float *d, const float *dy, const float *l, int i)
3728 {
3729  a[i] = 0.0f;
3730  b[i] = 2.0f;
3731  c[i] = 1.0f / l[i + 1];
3732  d[i] = dy[i + 1];
3733 }
3734 
3736  float *a, float *b, float *c, float *d, const float *dy, const float *l, int i)
3737 {
3738  a[i] = l[i] * l[i];
3739  b[i] = 2.0f * l[i];
3740  c[i] = 0.0f;
3741  d[i] = dy[i] * l[i] * l[i];
3742 }
3743 
3744 /* auto clamp prevents its own point going the wrong way, and adjacent handles overshooting */
3745 static void bezier_clamp(
3746  float *hmax, float *hmin, int i, float dy, bool no_reverse, bool no_overshoot)
3747 {
3748  if (dy > 0) {
3749  if (no_overshoot) {
3750  hmax[i] = min_ff(hmax[i], dy);
3751  }
3752  if (no_reverse) {
3753  hmin[i] = 0.0f;
3754  }
3755  }
3756  else if (dy < 0) {
3757  if (no_reverse) {
3758  hmax[i] = 0.0f;
3759  }
3760  if (no_overshoot) {
3761  hmin[i] = max_ff(hmin[i], dy);
3762  }
3763  }
3764  else if (no_reverse || no_overshoot) {
3765  hmax[i] = hmin[i] = 0.0f;
3766  }
3767 }
3768 
3769 /* write changes to a bezier handle */
3771  bool right,
3772  const float newval[3],
3773  bool endpoint)
3774 {
3775  float tmp[3];
3776 
3777  int idx = right ? 2 : 0;
3778  char hr = right ? bezt->h2 : bezt->h1;
3779  char hm = right ? bezt->h1 : bezt->h2;
3780 
3781  /* only assign Auto/Vector handles */
3782  if (!ELEM(hr, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) {
3783  return;
3784  }
3785 
3786  copy_v3_v3(bezt->vec[idx], newval);
3787 
3788  /* fix up the Align handle if any */
3789  if (ELEM(hm, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {
3790  float hlen = len_v3v3(bezt->vec[1], bezt->vec[2 - idx]);
3791  float h2len = len_v3v3(bezt->vec[1], bezt->vec[idx]);
3792 
3793  sub_v3_v3v3(tmp, bezt->vec[1], bezt->vec[idx]);
3794  madd_v3_v3v3fl(bezt->vec[2 - idx], bezt->vec[1], tmp, hlen / h2len);
3795  }
3796  /* at end points of the curve, mirror handle to the other side */
3797  else if (endpoint && ELEM(hm, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) {
3798  sub_v3_v3v3(tmp, bezt->vec[1], bezt->vec[idx]);
3799  add_v3_v3v3(bezt->vec[2 - idx], bezt->vec[1], tmp);
3800  }
3801 }
3802 
3803 static void bezier_output_handle(BezTriple *bezt, bool right, float dy, bool endpoint)
3804 {
3805  float tmp[3];
3806 
3807  copy_v3_v3(tmp, bezt->vec[right ? 2 : 0]);
3808 
3809  tmp[1] = bezt->vec[1][1] + dy;
3810 
3811  bezier_output_handle_inner(bezt, right, tmp, endpoint);
3812 }
3813 
3814 static bool bezier_check_solve_end_handle(BezTriple *bezt, char htype, bool end)
3815 {
3816  return (htype == HD_VECT) || (end && ELEM(htype, HD_AUTO, HD_AUTO_ANIM) &&
3818 }
3819 
3820 static float bezier_calc_handle_adj(float hsize[2], float dx)
3821 {
3822  /* if handles intersect in x direction, they are scaled to fit */
3823  float fac = dx / (hsize[0] + dx / 3.0f);
3824  if (fac < 1.0f) {
3825  mul_v2_fl(hsize, fac);
3826  }
3827  return 1.0f - 3.0f * hsize[0] / dx;
3828 }
3829 
3831  BezTriple *bezt, int total, int start, int count, bool cycle)
3832 {
3833  float *dx, *dy, *l, *a, *b, *c, *d, *h, *hmax, *hmin;
3834  float **arrays[] = {&dx, &dy, &l, &a, &b, &c, &d, &h, &hmax, &hmin, NULL};
3835 
3836  int solve_count = count;
3837 
3838  /* verify index ranges */
3839 
3840  if (count < 2) {
3841  return;
3842  }
3843 
3844  BLI_assert(start < total - 1 && count <= total);
3845  BLI_assert(start + count <= total || cycle);
3846 
3847  bool full_cycle = (start == 0 && count == total && cycle);
3848 
3849  BezTriple *bezt_first = &bezt[start];
3850  BezTriple *bezt_last =
3851  &bezt[(start + count > total) ? start + count - total : start + count - 1];
3852 
3853  bool solve_first = bezier_check_solve_end_handle(bezt_first, bezt_first->h2, start == 0);
3854  bool solve_last = bezier_check_solve_end_handle(
3855  bezt_last, bezt_last->h1, start + count == total);
3856 
3857  if (count == 2 && !full_cycle && solve_first == solve_last) {
3858  return;
3859  }
3860 
3861  /* allocate all */
3862 
3863  void *tmp_buffer = allocate_arrays(count, arrays, NULL, "bezier_calc_smooth_tmp");
3864  if (!tmp_buffer) {
3865  return;
3866  }
3867 
3868  /* point locations */
3869 
3870  dx[0] = dy[0] = NAN_FLT;
3871 
3872  for (int i = 1, j = start + 1; i < count; i++, j++) {
3873  dx[i] = bezt[j].vec[1][0] - bezt[j - 1].vec[1][0];
3874  dy[i] = bezt[j].vec[1][1] - bezt[j - 1].vec[1][1];
3875 
3876  /* when cyclic, jump from last point to first */
3877  if (cycle && j == total - 1) {
3878  j = 0;
3879  }
3880  }
3881 
3882  /* ratio of x intervals */
3883 
3884  if (full_cycle) {
3885  dx[0] = dx[count - 1];
3886  dy[0] = dy[count - 1];
3887 
3888  l[0] = l[count - 1] = dx[1] / dx[0];
3889  }
3890  else {
3891  l[0] = l[count - 1] = 1.0f;
3892  }
3893 
3894  for (int i = 1; i < count - 1; i++) {
3895  l[i] = dx[i + 1] / dx[i];
3896  }
3897 
3898  /* compute handle clamp ranges */
3899 
3900  bool clamped_prev = false, clamped_cur = ELEM(HD_AUTO_ANIM, bezt_first->h1, bezt_first->h2);
3901 
3902  for (int i = 0; i < count; i++) {
3903  hmax[i] = FLT_MAX;
3904  hmin[i] = -FLT_MAX;
3905  }
3906 
3907  for (int i = 1, j = start + 1; i < count; i++, j++) {
3908  clamped_prev = clamped_cur;
3909  clamped_cur = ELEM(HD_AUTO_ANIM, bezt[j].h1, bezt[j].h2);
3910 
3911  if (cycle && j == total - 1) {
3912  j = 0;
3913  clamped_cur = clamped_cur || ELEM(HD_AUTO_ANIM, bezt[j].h1, bezt[j].h2);
3914  }
3915 
3916  bezier_clamp(hmax, hmin, i - 1, dy[i], clamped_prev, clamped_prev);
3917  bezier_clamp(hmax, hmin, i, dy[i] * l[i], clamped_cur, clamped_cur);
3918  }
3919 
3920  /* full cycle merges first and last points into continuous loop */
3921 
3922  float first_handle_adj = 0.0f, last_handle_adj = 0.0f;
3923 
3924  if (full_cycle) {
3925  /* reduce the number of unknowns by one */
3926  int i = solve_count = count - 1;
3927 
3928  hmin[0] = max_ff(hmin[0], hmin[i]);
3929  hmax[0] = min_ff(hmax[0], hmax[i]);
3930 
3931  solve_first = solve_last = true;
3932 
3933  bezier_eq_continuous(a, b, c, d, dy, l, 0);
3934  }
3935  else {
3936  float tmp[2];
3937 
3938  /* boundary condition: fixed handles or zero curvature */
3939  if (!solve_first) {
3940  sub_v2_v2v2(tmp, bezt_first->vec[2], bezt_first->vec[1]);
3941  first_handle_adj = bezier_calc_handle_adj(tmp, dx[1]);
3942 
3943  bezier_lock_unknown(a, b, c, d, 0, tmp[1]);
3944  }
3945  else {
3946  bezier_eq_noaccel_right(a, b, c, d, dy, l, 0);
3947  }
3948 
3949  if (!solve_last) {
3950  sub_v2_v2v2(tmp, bezt_last->vec[1], bezt_last->vec[0]);
3951  last_handle_adj = bezier_calc_handle_adj(tmp, dx[count - 1]);
3952 
3953  bezier_lock_unknown(a, b, c, d, count - 1, tmp[1]);
3954  }
3955  else {
3956  bezier_eq_noaccel_left(a, b, c, d, dy, l, count - 1);
3957  }
3958  }
3959 
3960  /* main tridiagonal system of equations */
3961 
3962  for (int i = 1; i < count - 1; i++) {
3963  bezier_eq_continuous(a, b, c, d, dy, l, i);
3964  }
3965 
3966  /* apply correction for user-defined handles with nonstandard x positions */
3967 
3968  if (!full_cycle) {
3969  if (count > 2 || solve_last) {
3970  b[1] += l[1] * first_handle_adj;
3971  }
3972 
3973  if (count > 2 || solve_first) {
3974  b[count - 2] += last_handle_adj;
3975  }
3976  }
3977 
3978  /* solve and output results */
3979 
3980  if (tridiagonal_solve_with_limits(a, b, c, d, h, hmin, hmax, solve_count)) {
3981  if (full_cycle) {
3982  h[count - 1] = h[0];
3983  }
3984 
3985  for (int i = 1, j = start + 1; i < count - 1; i++, j++) {
3986  bool end = (j == total - 1);
3987 
3988  bezier_output_handle(&bezt[j], false, -h[i] / l[i], end);
3989 
3990  if (end) {
3991  j = 0;
3992  }
3993 
3994  bezier_output_handle(&bezt[j], true, h[i], end);
3995  }
3996 
3997  if (solve_first) {
3998  bezier_output_handle(bezt_first, true, h[0], start == 0);
3999  }
4000 
4001  if (solve_last) {
4002  bezier_output_handle(bezt_last, false, -h[count - 1] / l[count - 1], start + count == total);
4003  }
4004  }
4005 
4006  /* free all */
4007 
4008  free_arrays(tmp_buffer);
4009 }
4010 
4011 static bool is_free_auto_point(BezTriple *bezt)
4012 {
4013  return BEZT_IS_AUTOH(bezt) && bezt->auto_handle_type == HD_AUTOTYPE_NORMAL;
4014 }
4015 
4016 void BKE_nurb_handle_smooth_fcurve(BezTriple *bezt, int total, bool cyclic)
4017 {
4018  /* ignore cyclic extrapolation if end points are locked */
4019  cyclic = cyclic && is_free_auto_point(&bezt[0]) && is_free_auto_point(&bezt[total - 1]);
4020 
4021  /* if cyclic, try to find a sequence break point */
4022  int search_base = 0;
4023 
4024  if (cyclic) {
4025  for (int i = 1; i < total - 1; i++) {
4026  if (!is_free_auto_point(&bezt[i])) {
4027  search_base = i;
4028  break;
4029  }
4030  }
4031 
4032  /* all points of the curve are freely changeable auto handles - solve as full cycle */
4033  if (search_base == 0) {
4034  bezier_handle_calc_smooth_fcurve(bezt, total, 0, total, cyclic);
4035  return;
4036  }
4037  }
4038 
4039  /* Find continuous subsequences of free auto handles and smooth them, starting at
4040  * search_base. In cyclic mode these subsequences can span the cycle boundary. */
4041  int start = search_base, count = 1;
4042 
4043  for (int i = 1, j = start + 1; i < total; i++, j++) {
4044  /* in cyclic mode: jump from last to first point when necessary */
4045  if (j == total - 1 && cyclic) {
4046  j = 0;
4047  }
4048 
4049  /* non auto handle closes the list (we come here at least for the last handle, see above) */
4050  if (!is_free_auto_point(&bezt[j])) {
4051  bezier_handle_calc_smooth_fcurve(bezt, total, start, count + 1, cyclic);
4052  start = j;
4053  count = 1;
4054  }
4055  else {
4056  count++;
4057  }
4058  }
4059 
4060  if (count > 1) {
4061  bezier_handle_calc_smooth_fcurve(bezt, total, start, count, cyclic);
4062  }
4063 }
4064 
4070  BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve, const char smoothing)
4071 {
4072  calchandleNurb_intern(bezt, prev, next, SELECT, is_fcurve, false, smoothing);
4073 }
4074 
4083  BezTriple *prev,
4084  BezTriple *next,
4085  const eBezTriple_Flag__Alias handle_sel_flag,
4086  const bool is_fcurve,
4087  const char smoothing)
4088 {
4089  calchandleNurb_intern(bezt, prev, next, handle_sel_flag, is_fcurve, false, smoothing);
4090 }
4091 
4092 void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */
4093 {
4094  calchandlesNurb_intern(nu, SELECT, false);
4095 }
4096 
4102 {
4103  BezTriple *bezt;
4104  int i;
4105 
4106  for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
4107  if ((bezt->f1 & SELECT) != (bezt->f3 & SELECT)) {
4108  bezt->f1 ^= SELECT;
4109  bezt->f3 ^= SELECT;
4110  }
4111  }
4112 }
4113 
4114 /* internal use only (weak) */
4116 {
4120 }
4121 
4122 /* similar to BKE_nurb_handle_calc but for curves and
4123  * figures out the previous and next for us */
4125 {
4126  if (nu->pntsu > 1) {
4127  BezTriple *prev = BKE_nurb_bezt_get_prev(nu, bezt);
4128  BezTriple *next = BKE_nurb_bezt_get_next(nu, bezt);
4129  BKE_nurb_handle_calc(bezt, prev, next, 0, 0);
4130  }
4131 }
4132 
4134 {
4135  if (nu->pntsu > 1) {
4136  const char h1_back = bezt->h1, h2_back = bezt->h2;
4137 
4138  bezt->h1 = bezt->h2 = HD_AUTO;
4139 
4140  /* Override handle types to HD_AUTO and recalculate */
4141  BKE_nurb_handle_calc_simple(nu, bezt);
4142 
4143  bezt->h1 = h1_back;
4144  bezt->h2 = h2_back;
4145  }
4146 }
4147 
4162  const eBezTriple_Flag__Alias sel_flag,
4163  const bool use_handle,
4164  const bool use_around_local)
4165 {
4166  short flag = 0;
4167 
4168 #define SEL_F1 (1 << 0)
4169 #define SEL_F2 (1 << 1)
4170 #define SEL_F3 (1 << 2)
4171 
4172  if (use_handle) {
4173  if (bezt->f1 & sel_flag) {
4174  flag |= SEL_F1;
4175  }
4176  if (bezt->f2 & sel_flag) {
4177  flag |= SEL_F2;
4178  }
4179  if (bezt->f3 & sel_flag) {
4180  flag |= SEL_F3;
4181  }
4182  }
4183  else {
4184  flag = (bezt->f2 & sel_flag) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
4185  }
4186 
4187  if (use_around_local) {
4188  flag &= ~SEL_F2;
4189  }
4190 
4191  /* check for partial selection */
4192  if (!ELEM(flag, 0, SEL_F1 | SEL_F2 | SEL_F3)) {
4193  if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {
4194  bezt->h1 = HD_ALIGN;
4195  }
4196  if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {
4197  bezt->h2 = HD_ALIGN;
4198  }
4199 
4200  if (bezt->h1 == HD_VECT) {
4201  if ((!(flag & SEL_F1)) != (!(flag & SEL_F2))) {
4202  bezt->h1 = HD_FREE;
4203  }
4204  }
4205  if (bezt->h2 == HD_VECT) {
4206  if ((!(flag & SEL_F3)) != (!(flag & SEL_F2))) {
4207  bezt->h2 = HD_FREE;
4208  }
4209  }
4210  }
4211 
4212 #undef SEL_F1
4213 #undef SEL_F2
4214 #undef SEL_F3
4215 }
4216 
4217 void BKE_nurb_handles_test(Nurb *nu, const bool use_handle, const bool use_around_local)
4218 {
4219  BezTriple *bezt;
4220  int a;
4221 
4222  if (nu->type != CU_BEZIER) {
4223  return;
4224  }
4225 
4226  bezt = nu->bezt;
4227  a = nu->pntsu;
4228  while (a--) {
4229  BKE_nurb_bezt_handle_test(bezt, SELECT, use_handle, use_around_local);
4230  bezt++;
4231  }
4232 
4234 }
4235 
4237 {
4238  /* checks handle coordinates and calculates type */
4239  const float eps = 0.0001f;
4240  const float eps_sq = eps * eps;
4241 
4242  if (nu == NULL || nu->bezt == NULL) {
4243  return;
4244  }
4245 
4246  BezTriple *bezt2 = nu->bezt;
4247  BezTriple *bezt1 = bezt2 + (nu->pntsu - 1);
4248  BezTriple *bezt0 = bezt1 - 1;
4249  int i = nu->pntsu;
4250 
4251  while (i--) {
4252  bool align = false, leftsmall = false, rightsmall = false;
4253 
4254  /* left handle: */
4255  if (flag == 0 || (bezt1->f1 & flag)) {
4256  bezt1->h1 = HD_FREE;
4257  /* distance too short: vectorhandle */
4258  if (len_squared_v3v3(bezt1->vec[1], bezt0->vec[1]) < eps_sq) {
4259  bezt1->h1 = HD_VECT;
4260  leftsmall = true;
4261  }
4262  else {
4263  /* aligned handle? */
4264  if (dist_squared_to_line_v3(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < eps_sq) {
4265  align = true;
4266  bezt1->h1 = HD_ALIGN;
4267  }
4268  /* or vector handle? */
4269  if (dist_squared_to_line_v3(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < eps_sq) {
4270  bezt1->h1 = HD_VECT;
4271  }
4272  }
4273  }
4274  /* right handle: */
4275  if (flag == 0 || (bezt1->f3 & flag)) {
4276  bezt1->h2 = HD_FREE;
4277  /* distance too short: vectorhandle */
4278  if (len_squared_v3v3(bezt1->vec[1], bezt2->vec[1]) < eps_sq) {
4279  bezt1->h2 = HD_VECT;
4280  rightsmall = true;
4281  }
4282  else {
4283  /* aligned handle? */
4284  if (align) {
4285  bezt1->h2 = HD_ALIGN;
4286  }
4287 
4288  /* or vector handle? */
4289  if (dist_squared_to_line_v3(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < eps_sq) {
4290  bezt1->h2 = HD_VECT;
4291  }
4292  }
4293  }
4294  if (leftsmall && bezt1->h2 == HD_ALIGN) {
4295  bezt1->h2 = HD_FREE;
4296  }
4297  if (rightsmall && bezt1->h1 == HD_ALIGN) {
4298  bezt1->h1 = HD_FREE;
4299  }
4300 
4301  /* undesired combination: */
4302  if (bezt1->h1 == HD_ALIGN && bezt1->h2 == HD_VECT) {
4303  bezt1->h1 = HD_FREE;
4304  }
4305  if (bezt1->h2 == HD_ALIGN && bezt1->h1 == HD_VECT) {
4306  bezt1->h2 = HD_FREE;
4307  }
4308 
4309  bezt0 = bezt1;
4310  bezt1 = bezt2;
4311  bezt2++;
4312  }
4313 
4315 }
4316 
4318 {
4319  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
4320  BKE_nurb_handles_autocalc(nu, flag);
4321  }
4322 }
4323 
4333 void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
4334 {
4335  BezTriple *bezt;
4336  int a;
4337 
4338  if (ELEM(code, HD_AUTO, HD_VECT)) {
4339  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
4340  if (nu->type == CU_BEZIER) {
4341  bezt = nu->bezt;
4342  a = nu->pntsu;
4343  while (a--) {
4344  if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
4345  if (bezt->f1 & SELECT) {
4346  bezt->h1 = code;
4347  }
4348  if (bezt->f3 & SELECT) {
4349  bezt->h2 = code;
4350  }
4351  if (bezt->h1 != bezt->h2) {
4352  if (ELEM(bezt->h1, HD_ALIGN, HD_AUTO)) {
4353  bezt->h1 = HD_FREE;
4354  }
4355  if (ELEM(bezt->h2, HD_ALIGN, HD_AUTO)) {
4356  bezt->h2 = HD_FREE;
4357  }
4358  }
4359  }
4360  bezt++;
4361  }
4362 
4363  /* like BKE_nurb_handles_calc but moves selected */
4365  }
4366  }
4367  }
4368  else {
4369  char h_new = HD_FREE;
4370 
4371  /* there is 1 handle not FREE: FREE it all, else make ALIGNED */
4372  if (code == 5) {
4373  h_new = HD_ALIGN;
4374  }
4375  else if (code == 6) {
4376  h_new = HD_FREE;
4377  }
4378  else {
4379  /* Toggle */
4380  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
4381  if (nu->type == CU_BEZIER) {
4382  bezt = nu->bezt;
4383  a = nu->pntsu;
4384  while (a--) {
4385  if (((bezt->f1 & SELECT) && bezt->h1 != HD_FREE) ||
4386  ((bezt->f3 & SELECT) && bezt->h2 != HD_FREE)) {
4387  h_new = HD_AUTO;
4388  break;
4389  }
4390  bezt++;
4391  }
4392  }
4393  }
4394  h_new = (h_new == HD_FREE) ? HD_ALIGN : HD_FREE;
4395  }
4396  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
4397  if (nu->type == CU_BEZIER) {
4398  bezt = nu->bezt;
4399  a = nu->pntsu;
4400  while (a--) {
4401  if (bezt->f1 & SELECT) {
4402  bezt->h1 = h_new;
4403  }
4404  if (bezt->f3 & SELECT) {
4405  bezt->h2 = h_new;
4406  }
4407 
4408  bezt++;
4409  }
4410 
4411  /* like BKE_nurb_handles_calc but moves selected */
4413  }
4414  }
4415  }
4416 }
4417 
4419  const bool calc_length,
4420  const uint8_t flag)
4421 {
4422  BezTriple *bezt;
4423  int a;
4424 
4425  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
4426  if (nu->type != CU_BEZIER) {
4427  continue;
4428  }
4429 
4430  bool changed = false;
4431 
4432  for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) {
4433 
4434  const bool h1_select = (bezt->f1 & flag) == flag;
4435  const bool h2_select = (bezt->f3 & flag) == flag;
4436 
4437  if (h1_select || h2_select) {
4438 
4439  float co1_back[3], co2_back[3];
4440 
4441  copy_v3_v3(co1_back, bezt->vec[0]);
4442  copy_v3_v3(co2_back, bezt->vec[2]);
4443 
4445 
4446  if (h1_select) {
4447  if (!calc_length) {
4448  dist_ensure_v3_v3fl(bezt->vec[0], bezt->vec[1], len_v3v3(co1_back, bezt->vec[1]));
4449  }
4450  }
4451  else {
4452  copy_v3_v3(bezt->vec[0], co1_back);
4453  }
4454 
4455  if (h2_select) {
4456  if (!calc_length) {
4457  dist_ensure_v3_v3fl(bezt->vec[2], bezt->vec[1], len_v3v3(co2_back, bezt->vec[1]));
4458  }
4459  }
4460  else {
4461  copy_v3_v3(bezt->vec[2], co2_back);
4462  }
4463 
4464  changed = true;
4465  }
4466  }
4467 
4468  if (changed) {
4469  /* Recalculate the whole curve */
4471  }
4472  }
4473 }
4474 
4475 void BKE_nurbList_flag_set(ListBase *editnurb, uint8_t flag, bool set)
4476 {
4477  BezTriple *bezt;
4478  BPoint *bp;
4479  int a;
4480 
4481  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
4482  if (nu->type == CU_BEZIER) {
4483  a = nu->pntsu;
4484  bezt = nu->bezt;
4485  while (a--) {
4486  if (set) {
4487  bezt->f1 |= flag;
4488  bezt->f2 |= flag;
4489  bezt->f3 |= flag;
4490  }
4491  else {
4492  bezt->f1 &= ~flag;
4493  bezt->f2 &= ~flag;
4494  bezt->f3 &= ~flag;
4495  }
4496  bezt++;
4497  }
4498  }
4499  else {
4500  a = nu->pntsu * nu->pntsv;
4501  bp = nu->bp;
4502  while (a--) {
4503  SET_FLAG_FROM_TEST(bp->f1, set, flag);
4504  bp++;
4505  }
4506  }
4507  }
4508 }
4509 
4514 {
4515  bool changed = false;
4516 
4517  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
4518  if (nu->type == CU_BEZIER) {
4519  for (int i = 0; i < nu->pntsu; i++) {
4520  BezTriple *bezt = &nu->bezt[i];
4521  uint8_t old_f1 = bezt->f1, old_f2 = bezt->f2, old_f3 = bezt->f3;
4522 
4523  SET_FLAG_FROM_TEST(bezt->f1, bezt->f1 & from_flag, flag);
4524  SET_FLAG_FROM_TEST(bezt->f2, bezt->f2 & from_flag, flag);
4525  SET_FLAG_FROM_TEST(bezt->f3, bezt->f3 & from_flag, flag);
4526 
4527  changed |= (old_f1 != bezt->f1) || (old_f2 != bezt->f2) || (old_f3 != bezt->f3);
4528  }
4529  }
4530  else {
4531  for (int i = 0; i < nu->pntsu * nu->pntsv; i++) {
4532  BPoint *bp = &nu->bp[i];
4533  uint8_t old_f1 = bp->f1;
4534 
4535  SET_FLAG_FROM_TEST(bp->f1, bp->f1 & from_flag, flag);
4536  changed |= (old_f1 != bp->f1);
4537  }
4538  }
4539  }
4540 
4541  return changed;
4542 }
4543 
4545 {
4546  BezTriple *bezt1, *bezt2;
4547  BPoint *bp1, *bp2;
4548  float *fp1, *fp2, *tempf;
4549  int a, b;
4550 
4551  if (nu->pntsu == 1 && nu->pntsv == 1) {
4552  return;
4553  }
4554 
4555  if (nu->type == CU_BEZIER) {
4556  a = nu->pntsu;
4557  bezt1 = nu->bezt;
4558  bezt2 = bezt1 + (a - 1);
4559  if (a & 1) {
4560  a += 1; /* if odd, also swap middle content */
4561  }
4562  a /= 2;
4563  while (a > 0) {
4564  if (bezt1 != bezt2) {
4565  SWAP(BezTriple, *bezt1, *bezt2);
4566  }
4567 
4568  swap_v3_v3(bezt1->vec[0], bezt1->vec[2]);
4569 
4570  if (bezt1 != bezt2) {
4571  swap_v3_v3(bezt2->vec[0], bezt2->vec[2]);
4572  }
4573 
4574  SWAP(uint8_t, bezt1->h1, bezt1->h2);
4575  SWAP(uint8_t, bezt1->f1, bezt1->f3);
4576 
4577  if (bezt1 != bezt2) {
4578  SWAP(uint8_t, bezt2->h1, bezt2->h2);
4579  SWAP(uint8_t, bezt2->f1, bezt2->f3);
4580  bezt1->tilt = -bezt1->tilt;
4581  bezt2->tilt = -bezt2->tilt;
4582  }
4583  else {
4584  bezt1->tilt = -bezt1->tilt;
4585  }
4586  a--;
4587  bezt1++;
4588  bezt2--;
4589  }
4590  }
4591  else if (nu->pntsv == 1) {
4592  a = nu->pntsu;
4593  bp1 = nu->bp;
4594  bp2 = bp1 + (a - 1);
4595  a /= 2;
4596  while (bp1 != bp2 && a > 0) {
4597  SWAP(BPoint, *bp1, *bp2);
4598  a--;
4599  bp1->tilt = -bp1->tilt;
4600  bp2->tilt = -bp2->tilt;
4601  bp1++;
4602  bp2--;
4603  }
4604  /* If there are odd number of points no need to touch coord of middle one,
4605  * but still need to change its tilt.
4606  */
4607  if (nu->pntsu & 1) {
4608  bp1->tilt = -bp1->tilt;
4609  }
4610  if (nu->type == CU_NURBS) {
4611  /* no knots for too short paths */
4612  if (nu->knotsu) {
4613  /* inverse knots */
4614  a = KNOTSU(nu);
4615  fp1 = nu->knotsu;
4616  fp2 = fp1 + (a - 1);
4617  a /= 2;
4618  while (fp1 != fp2 && a > 0) {
4619  SWAP(float, *fp1, *fp2);
4620  a--;
4621  fp1++;
4622  fp2--;
4623  }
4624  /* and make in increasing order again */
4625  a = KNOTSU(nu);
4626  fp1 = nu->knotsu;
4627  fp2 = tempf = MEM_malloc_arrayN(a, sizeof(float), "switchdirect");
4628  a--;
4629  fp2[a] = fp1[a];
4630  while (a--) {
4631  fp2[0] = fabsf(fp1[1] - fp1[0]);
4632  fp1++;
4633  fp2++;
4634  }
4635 
4636  a = KNOTSU(nu) - 1;
4637  fp1 = nu->knotsu;
4638  fp2 = tempf;
4639  fp1[0] = 0.0;
4640  fp1++;
4641  while (a--) {
4642  fp1[0] = fp1[-1] + fp2[0];
4643  fp1++;
4644  fp2++;
4645  }
4646  MEM_freeN(tempf);
4647  }
4648  }
4649  }
4650  else {
4651  for (b = 0; b < nu->pntsv; b++) {
4652  bp1 = nu->bp + b * nu->pntsu;
4653  a = nu->pntsu;
4654  bp2 = bp1 + (a - 1);
4655  a /= 2;
4656 
4657  while (bp1 != bp2 && a > 0) {
4658  SWAP(BPoint, *bp1, *bp2);
4659  a--;
4660  bp1++;
4661  bp2--;
4662  }
4663  }
4664  }
4665 }
4666 
4667 void BKE_curve_nurbs_vert_coords_get(const ListBase *lb, float (*vert_coords)[3], int vert_len)
4668 {
4669  float *co = vert_coords[0];
4670  LISTBASE_FOREACH (const Nurb *, nu, lb) {
4671  if (nu->type == CU_BEZIER) {
4672  const BezTriple *bezt = nu->bezt;
4673  for (int i = 0; i < nu->pntsu; i++, bezt++) {
4674  copy_v3_v3(co, bezt->vec[0]);
4675  co += 3;
4676  copy_v3_v3(co, bezt->vec[1]);
4677  co += 3;
4678  copy_v3_v3(co, bezt->vec[2]);
4679  co += 3;
4680  }
4681  }
4682  else {
4683  const BPoint *bp = nu->bp;
4684  for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
4685  copy_v3_v3(co, bp->vec);
4686  co += 3;
4687  }
4688  }
4689  }
4690  BLI_assert(co == vert_coords[vert_len]);
4691  UNUSED_VARS_NDEBUG(vert_len);
4692 }
4693 
4694 float (*BKE_curve_nurbs_vert_coords_alloc(const ListBase *lb, int *r_vert_len))[3]
4695 {
4696  const int vert_len = BKE_nurbList_verts_count(lb);
4697  float(*vert_coords)[3] = MEM_malloc_arrayN(vert_len, sizeof(*vert_coords), __func__);
4698  BKE_curve_nurbs_vert_coords_get(lb, vert_coords, vert_len);
4699  *r_vert_len = vert_len;
4700  return vert_coords;
4701 }
4702 
4704  const float (*vert_coords)[3],
4705  const float mat[4][4],
4706  const bool constrain_2d)
4707 {
4708  const float *co = vert_coords[0];
4709 
4710  LISTBASE_FOREACH (Nurb *, nu, lb) {
4711  if (nu->type == CU_BEZIER) {
4712  BezTriple *bezt = nu->bezt;
4713 
4714  for (int i = 0; i < nu->pntsu; i++, bezt++) {
4715  mul_v3_m4v3(bezt->vec[0], mat, co);
4716  co += 3;
4717  mul_v3_m4v3(bezt->vec[1], mat, co);
4718  co += 3;
4719  mul_v3_m4v3(bezt->vec[2], mat, co);
4720  co += 3;
4721  }
4722  }
4723  else {
4724  BPoint *bp = nu->bp;
4725 
4726  for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
4727  mul_v3_m4v3(bp->vec, mat, co);
4728  co += 3;
4729  }
4730  }
4731 
4732  if (constrain_2d) {
4733  BKE_nurb_project_2d(nu);
4734  }
4735 
4736  calchandlesNurb_intern(nu, SELECT, true);
4737  }
4738 }
4739 
4741  const float (*vert_coords)[3],
4742  const bool constrain_2d)
4743 {
4744  const float *co = vert_coords[0];
4745 
4746  LISTBASE_FOREACH (Nurb *, nu, lb) {
4747  if (nu->type == CU_BEZIER) {
4748  BezTriple *bezt = nu->bezt;
4749 
4750  for (int i = 0; i < nu->pntsu; i++, bezt++) {
4751  copy_v3_v3(bezt->vec[0], co);
4752  co += 3;
4753  copy_v3_v3(bezt->vec[1], co);
4754  co += 3;
4755  copy_v3_v3(bezt->vec[2], co);
4756  co += 3;
4757  }
4758  }
4759  else {
4760  BPoint *bp = nu->bp;
4761 
4762  for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
4763  copy_v3_v3(bp->vec, co);
4764  co += 3;
4765  }
4766  }
4767 
4768  if (constrain_2d) {
4769  BKE_nurb_project_2d(nu);
4770  }
4771 
4772  calchandlesNurb_intern(nu, SELECT, true);
4773  }
4774 }
4775 
4776 float (*BKE_curve_nurbs_key_vert_coords_alloc(const ListBase *lb, float *key, int *r_vert_len))[3]
4777 {
4778  int vert_len = BKE_nurbList_verts_count(lb);
4779  float(*cos)[3] = MEM_malloc_arrayN(vert_len, sizeof(*cos), __func__);
4780 
4781  float *co = cos[0];
4782  LISTBASE_FOREACH (const Nurb *, nu, lb) {
4783  if (nu->type == CU_BEZIER) {
4784  const BezTriple *bezt = nu->bezt;
4785 
4786  for (int i = 0; i < nu->pntsu; i++, bezt++) {
4787  copy_v3_v3(co, &key[0]);
4788  co += 3;
4789  copy_v3_v3(co, &key[3]);
4790  co += 3;
4791  copy_v3_v3(co, &key[6]);
4792  co += 3;
4794  }
4795  }
4796  else {
4797  const BPoint *bp = nu->bp;
4798 
4799  for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
4800  copy_v3_v3(co, key);
4801  co += 3;
4802  key += KEYELEM_FLOAT_LEN_BPOINT;
4803  }
4804  }
4805  }
4806  *r_vert_len = vert_len;
4807  return cos;
4808 }
4809 
4811 {
4812  LISTBASE_FOREACH (Nurb *, nu, lb) {
4813  if (nu->type == CU_BEZIER) {
4814  BezTriple *bezt = nu->bezt;
4815 
4816  for (int i = 0; i < nu->pntsu; i++, bezt++) {
4817  bezt->tilt = key[9];
4818  bezt->radius = key[10];
4820  }
4821  }
4822  else {
4823  BPoint *bp = nu->bp;
4824 
4825  for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
4826  bp->tilt = key[3];
4827  bp->radius = key[4];
4828  key += KEYELEM_FLOAT_LEN_BPOINT;
4829  }
4830  }
4831  }
4832 }
4833 
4835 {
4836  if (nu->pntsu <= 1) {
4837  return false;
4838  }
4839  if (nu->type != CU_NURBS) {
4840  return true; /* not a nurb, lets assume its valid */
4841  }
4842 
4843  if (nu->pntsu < nu->orderu) {
4844  return false;
4845  }
4846  if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
4847  /* Bezier U Endpoints */
4848  if (nu->orderu == 4) {
4849  if (nu->pntsu < 5) {
4850  return false; /* bezier with 4 orderu needs 5 points */
4851  }
4852  }
4853  else {
4854  if (nu->orderu != 3) {
4855  return false; /* order must be 3 or 4 */
4856  }
4857  }
4858  }
4859  return true;
4860 }
4862 {
4863  if (nu->pntsv <= 1) {
4864  return false;
4865  }
4866  if (nu->type != CU_NURBS) {
4867  return true; /* not a nurb, lets assume its valid */
4868  }
4869 
4870  if (nu->pntsv < nu->orderv) {
4871  return false;
4872  }
4873  if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
4874  /* Bezier V Endpoints */
4875  if (nu->orderv == 4) {
4876  if (nu->pntsv < 5) {
4877  return false; /* bezier with 4 orderu needs 5 points */
4878  }
4879  }
4880  else {
4881  if (nu->orderv != 3) {
4882  return false; /* order must be 3 or 4 */
4883  }
4884  }
4885  }
4886  return true;
4887 }
4888 
4890 {
4891  if (!BKE_nurb_check_valid_u(nu)) {
4892  return false;
4893  }
4894  if ((nu->pntsv > 1) && !BKE_nurb_check_valid_v(nu)) {
4895  return false;
4896  }
4897 
4898  return true;
4899 }
4900 
4902 {
4903  bool changed = false;
4904  if (nu->pntsu < nu->orderu) {
4905  nu->orderu = max_ii(2, nu->pntsu);
4906  changed = true;
4907  }
4908  if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
4909  CLAMP(nu->orderu, 3, 4);
4910  changed = true;
4911  }
4912  return changed;
4913 }
4914 
4916 {
4917  bool changed = false;
4918  if (nu->pntsv < nu->orderv) {
4919  nu->orderv = max_ii(2, nu->pntsv);
4920  changed = true;
4921  }
4922  if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
4923  CLAMP(nu->orderv, 3, 4);
4924  changed = true;
4925  }
4926  return changed;
4927 }
4928 
4933  const short type,
4934  const bool use_handles,
4935  const char **r_err_msg)
4936 {
4937  BezTriple *bezt;
4938  BPoint *bp;
4939  int a, c, nr;
4940 
4941  if (nu->type == CU_POLY) {
4942  if (type == CU_BEZIER) { /* to Bezier with vecthandles */
4943  nr = nu->pntsu;
4944  bezt = (BezTriple *)MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2");
4945  nu->bezt = bezt;
4946  a = nr;
4947  bp = nu->bp;
4948  while (a--) {
4949  copy_v3_v3(bezt->vec[1], bp->vec);
4950  bezt->f1 = bezt->f2 = bezt->f3 = bp->f1;
4951  bezt->h1 = bezt->h2 = HD_VECT;
4952  bezt->weight = bp->weight;
4953  bezt->radius = bp->radius;
4954  bp++;
4955  bezt++;
4956  }
4957  MEM_freeN(nu->bp);
4958  nu->bp = NULL;
4959  nu->pntsu = nr;
4960  nu->pntsv = 0;
4961  nu->type = CU_BEZIER;
4963  }
4964  else if (type == CU_NURBS) {
4965  nu->type = CU_NURBS;
4966  nu->orderu = 4;
4967  nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */
4969  a = nu->pntsu * nu->pntsv;
4970  bp = nu->bp;
4971  while (a--) {
4972  bp->vec[3] = 1.0;
4973  bp++;
4974  }
4975  }
4976  }
4977  else if (nu->type == CU_BEZIER) { /* Bezier */
4978  if (ELEM(type, CU_POLY, CU_NURBS)) {
4979  nr = use_handles ? (3 * nu->pntsu) : nu->pntsu;
4980  nu->bp = MEM_calloc_arrayN(nr, sizeof(BPoint), "setsplinetype");
4981  a = nu->pntsu;
4982  bezt = nu->bezt;
4983  bp = nu->bp;
4984  while (a--) {
4985  if ((type == CU_POLY && bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) ||
4986  (use_handles == false)) {
4987  /* vector handle becomes 1 poly vertice */
4988  copy_v3_v3(bp->vec, bezt->vec[1]);
4989  bp->vec[3] = 1.0;
4990  bp->f1 = bezt->f2;
4991  if (use_handles) {
4992  nr -= 2;
4993  }
4994  bp->radius = bezt->radius;
4995  bp->weight = bezt->weight;
4996  bp++;
4997  }
4998  else {
4999  const uint8_t *f = &bezt->f1;
5000  for (c = 0; c < 3; c++, f++) {
5001  copy_v3_v3(bp->vec, bezt->vec[c]);
5002  bp->vec[3] = 1.0;
5003  bp->f1 = *f;
5004  bp->radius = bezt->radius;
5005  bp->weight = bezt->weight;
5006  bp++;
5007  }
5008  }
5009  bezt++;
5010  }
5011  MEM_freeN(nu->bezt);
5012  nu->bezt = NULL;
5013  nu->pntsu = nr;
5014  nu->pntsv = 1;
5015  nu->orderu = 4;
5016  nu->orderv = 1;
5017  nu->type = type;
5018 
5019  if (type == CU_NURBS) {
5020  nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */
5021  nu->flagu |= CU_NURB_BEZIER;
5023  }
5024  }
5025  }
5026  else if (nu->type == CU_NURBS) {
5027  if (type == CU_POLY) {
5028  nu->type = CU_POLY;
5029  if (nu->knotsu) {
5030  MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */
5031  }
5032  nu->knotsu = NULL;
5033  if (nu->knotsv) {
5034  MEM_freeN(nu->knotsv);
5035  }
5036  nu->knotsv = NULL;
5037  }
5038  else if (type == CU_BEZIER) { /* to Bezier */
5039  nr = nu->pntsu / 3;
5040 
5041  if (nr < 2) {
5042  if (r_err_msg != NULL) {
5043  *r_err_msg = "At least 6 points required for conversion";
5044  }
5045  return false; /* conversion impossible */
5046  }
5047 
5048  bezt = MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2");
5049  nu->bezt = bezt;
5050  a = nr;
5051  bp = nu->bp;
5052  while (a--) {
5053  copy_v3_v3(bezt->vec[0], bp->vec);
5054  bezt->f1 = bp->f1;
5055  bp++;
5056  copy_v3_v3(bezt->vec[1], bp->vec);
5057  bezt->f2 = bp->f1;
5058  bp++;
5059  copy_v3_v3(bezt->vec[2], bp->vec);
5060  bezt->f3 = bp->f1;
5061  bezt->radius = bp->radius;
5062  bezt->weight = bp->weight;
5063  bp++;
5064  bezt++;
5065  }
5066  MEM_freeN(nu->bp);
5067  nu->bp = NULL;
5068  MEM_freeN(nu->knotsu);
5069  nu->knotsu = NULL;
5070  nu->pntsu = nr;
5071  nu->type = CU_BEZIER;
5072  }
5073  }
5074 
5075  return true;
5076 }
5077 
5078 /* Get edit nurbs or normal nurbs list */
5080 {
5081  if (cu->editnurb) {
5082  return BKE_curve_editNurbs_get(cu);
5083  }
5084 
5085  return &cu->nurb;
5086 }
5087 
5089 {
5090  if (nu == NULL) {
5091  cu->actnu = CU_ACT_NONE;
5092  }
5093  else {
5094  BLI_assert(!nu->hide);
5095  ListBase *nurbs = BKE_curve_editNurbs_get(cu);
5096  cu->actnu = BLI_findindex(nurbs, nu);
5097  }
5098 }
5099 
5101 {
5102  ListBase *nurbs = BKE_curve_editNurbs_get(cu);
5103  return BLI_findlink(nurbs, cu->actnu);
5104 }
5105 
5106 /* Get active vert for curve */
5108 {
5109  Nurb *nu = NULL;
5110  void *vert = NULL;
5111 
5112  BKE_curve_nurb_vert_active_get(cu, &nu, &vert);
5113  return vert;
5114 }
5115 
5116 int BKE_curve_nurb_vert_index_get(const Nurb *nu, const void *vert)
5117 {
5118  if (nu->type == CU_BEZIER) {
5119  BLI_assert(ARRAY_HAS_ITEM((BezTriple *)vert, nu->bezt, nu->pntsu));
5120  return (BezTriple *)vert - nu->bezt;
5121  }
5122 
5123  BLI_assert(ARRAY_HAS_ITEM((BPoint *)vert, nu->bp, nu->pntsu * nu->pntsv));
5124  return (BPoint *)vert - nu->bp;
5125 }
5126 
5127 /* Set active nurb and active vert for curve */
5128 void BKE_curve_nurb_vert_active_set(Curve *cu, const Nurb *nu, const void *vert)
5129 {
5130  if (nu) {
5131  BKE_curve_nurb_active_set(cu, nu);
5132 
5133  if (vert) {
5134  cu->actvert = BKE_curve_nurb_vert_index_get(nu, vert);
5135  }
5136  else {
5137  cu->actvert = CU_ACT_NONE;
5138  }
5139  }
5140  else {
5141  cu->actnu = cu->actvert = CU_ACT_NONE;
5142  }
5143 }
5144 
5145 /* Get points to active active nurb and active vert for curve */
5146 bool BKE_curve_nurb_vert_active_get(Curve *cu, Nurb **r_nu, void **r_vert)
5147 {
5148  Nurb *nu = NULL;
5149  void *vert = NULL;
5150 
5151  if (cu->actvert != CU_ACT_NONE) {
5152  ListBase *nurbs = BKE_curve_editNurbs_get(cu);
5153  nu = BLI_findlink(nurbs, cu->actnu);
5154 
5155  if (nu) {
5156  if (nu->type == CU_BEZIER) {
5157  BLI_assert(nu->pntsu > cu->actvert);
5158  vert = &nu->bezt[cu->actvert];
5159  }
5160  else {
5161  BLI_assert((nu->pntsu * nu->pntsv) > cu->actvert);
5162  vert = &nu->bp[cu->actvert];
5163  }
5164  }
5165  }
5166 
5167  *r_nu = nu;
5168  *r_vert = vert;
5169 
5170  return (*r_vert != NULL);
5171 }
5172 
5174 {
5175  Nurb *nu;
5176  void *vert;
5177 
5178  if (BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
5179  if (nu->type == CU_BEZIER) {
5180  BezTriple *bezt = vert;
5181  if (BEZT_ISSEL_ANY(bezt) == 0) {
5182  cu->actvert = CU_ACT_NONE;
5183  }
5184  }
5185  else {
5186  BPoint *bp = vert;
5187  if ((bp->f1 & SELECT) == 0) {
5188  cu->actvert = CU_ACT_NONE;
5189  }
5190  }
5191 
5192  if (nu->hide) {
5193  cu->actnu = CU_ACT_NONE;
5194  }
5195  }
5196 }
5197 
5198 /* basic vertex data functions */
5199 bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
5200 {
5201  ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
5202  ListBase temp_nurb_lb = {NULL, NULL};
5203  const bool is_font = (BLI_listbase_is_empty(nurb_lb)) && (cu->len != 0);
5204  /* For font curves we generate temp list of splines.
5205  *
5206  * This is likely to be fine, this function is not supposed to be called
5207  * often, and it's the only way to get meaningful bounds for fonts.
5208  */
5209  if (is_font) {
5210  nurb_lb = &temp_nurb_lb;
5211  BKE_vfont_to_curve_ex(NULL, cu, FO_EDIT, nurb_lb, NULL, NULL, NULL, NULL);
5212  use_radius = false;
5213  }
5214  /* Do bounding box based on splines. */
5215  LISTBASE_FOREACH (const Nurb *, nu, nurb_lb) {
5216  BKE_nurb_minmax(nu, use_radius, min, max);
5217  }
5218  const bool result = (BLI_listbase_is_empty(nurb_lb) == false);
5219  /* Cleanup if needed. */
5220  BKE_nurbList_free(&temp_nurb_lb);
5221  return result;
5222 }
5223 
5224 bool BKE_curve_center_median(Curve *cu, float cent[3])
5225 {
5226  ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
5227  int total = 0;
5228 
5229  zero_v3(cent);
5230 
5231  LISTBASE_FOREACH (Nurb *, nu, nurb_lb) {
5232  int i;
5233 
5234  if (nu->type == CU_BEZIER) {
5235  BezTriple *bezt;
5236  i = nu->pntsu;
5237  total += i * 3;
5238  for (bezt = nu->bezt; i--; bezt++) {
5239  add_v3_v3(cent, bezt->vec[0]);
5240  add_v3_v3(cent, bezt->vec[1]);
5241  add_v3_v3(cent, bezt->vec[2]);
5242  }
5243  }
5244  else {
5245  BPoint *bp;
5246  i = nu->pntsu * nu->pntsv;
5247  total += i;
5248  for (bp = nu->bp; i--; bp++) {
5249  add_v3_v3(cent, bp->vec);
5250  }
5251  }
5252  }
5253 
5254  if (total) {
5255  mul_v3_fl(cent, 1.0f / (float)total);
5256  }
5257 
5258  return (total != 0);
5259 }
5260 
5261 bool BKE_curve_center_bounds(Curve *cu, float cent[3])
5262 {
5263  float min[3], max[3];
5264  INIT_MINMAX(min, max);
5265  if (BKE_curve_minmax(cu, false, min, max)) {
5266  mid_v3_v3v3(cent, min, max);
5267  return true;
5268  }
5269 
5270  return false;
5271 }
5272 
5274  const float mat[4][4],
5275  const bool do_keys,
5276  const bool do_props,
5277  const float unit_scale)
5278 {
5279  BPoint *bp;
5280  BezTriple *bezt;
5281  int i;
5282 
5283  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
5284  if (nu->type == CU_BEZIER) {
5285  i = nu->pntsu;
5286  for (bezt = nu->bezt; i--; bezt++) {
5287  mul_m4_v3(mat, bezt->vec[0]);
5288  mul_m4_v3(mat, bezt->vec[1]);
5289  mul_m4_v3(mat, bezt->vec[2]);
5290  if (do_props) {
5291  bezt->radius *= unit_scale;
5292  }
5293  }
5295  }
5296  else {
5297  i = nu->pntsu * nu->pntsv;
5298  for (bp = nu->bp; i--; bp++) {
5299  mul_m4_v3(mat, bp->vec);
5300  if (do_props) {
5301  bp->radius *= unit_scale;
5302  }
5303  }
5304  }
5305  }
5306 
5307  if (do_keys && cu->key) {
5308  LISTBASE_FOREACH (KeyBlock *, kb, &cu->key->block) {
5309  float *fp = kb->data;
5310  int n = kb->totelem;
5311 
5312  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
5313  if (nu->type == CU_BEZIER) {
5314  for (i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) {
5315  mul_m4_v3(mat, &fp[0]);
5316  mul_m4_v3(mat, &fp[3]);
5317  mul_m4_v3(mat, &fp[6]);
5318  if (do_props) {
5319  fp[10] *= unit_scale; /* radius */
5320  }
5322  }
5323  }
5324  else {
5325  for (i = nu->pntsu * nu->pntsv; i && (n -= KEYELEM_ELEM_LEN_BPOINT) >= 0; i--) {
5326  mul_m4_v3(mat, fp);
5327  if (do_props) {
5328  fp[4] *= unit_scale; /* radius */
5329  }
5331  }
5332  }
5333  }
5334  }
5335  }
5336 }
5337 
5338 void BKE_curve_transform(Curve *cu, const float mat[4][4], const bool do_keys, const bool do_props)
5339 {
5340  float unit_scale = mat4_to_scale(mat);
5341  BKE_curve_transform_ex(cu, mat, do_keys, do_props, unit_scale);
5342 }
5343 
5344 void BKE_curve_translate(Curve *cu, const float offset[3], const bool do_keys)
5345 {
5346  ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
5347 
5348  LISTBASE_FOREACH (Nurb *, nu, nurb_lb) {
5349  if (nu->type == CU_BEZIER) {
5350  int i = nu->pntsu;
5351  for (BezTriple *bezt = nu->bezt; i--; bezt++) {
5352  add_v3_v3(bezt->vec[0], offset);
5353  add_v3_v3(bezt->vec[1], offset);
5354  add_v3_v3(bezt->vec[2], offset);
5355  }
5356  }
5357  else {
5358  int i = nu->pntsu * nu->pntsv;
5359  for (BPoint *bp = nu->bp; i--; bp++) {
5360  add_v3_v3(bp->vec, offset);
5361  }
5362  }
5363  }
5364 
5365  if (do_keys && cu->key) {
5366  LISTBASE_FOREACH (KeyBlock *, kb, &cu->key->block) {
5367  float *fp = kb->data;
5368  int n = kb->totelem;
5369 
5370  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
5371  if (nu->type == CU_BEZIER) {
5372  for (int i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) {
5373  add_v3_v3(&fp[0], offset);
5374  add_v3_v3(&fp[3], offset);
5375  add_v3_v3(&fp[6], offset);
5377  }
5378  }
5379  else {
5380  for (int i = nu->pntsu * nu->pntsv; i && (n -= KEYELEM_ELEM_LEN_BPOINT) >= 0; i--) {
5381  add_v3_v3(fp, offset);
5383  }
5384  }
5385  }
5386  }
5387  }
5388 }
5389 
5391 {
5392  const int curvetype = BKE_curve_type_get(cu);
5393 
5394  if (curvetype == OB_FONT) {
5395  struct CharInfo *info = cu->strinfo;
5396  for (int i = cu->len_char32 - 1; i >= 0; i--, info++) {
5397  if (info->mat_nr && info->mat_nr >= index) {
5398  info->mat_nr--;
5399  }
5400  }
5401  }
5402  else {
5403  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
5404  if (nu->mat_nr && nu->mat_nr >= index) {
5405  nu->mat_nr--;
5406  }
5407  }
5408  }
5409 }
5410 
5411 bool BKE_curve_material_index_used(const Curve *cu, int index)
5412 {
5413  const int curvetype = BKE_curve_type_get(cu);
5414 
5415  if (curvetype == OB_FONT) {
5416  const struct CharInfo *info = cu->strinfo;
5417  for (int i = cu->len_char32 - 1; i >= 0; i--, info++) {
5418  if (info->mat_nr == index) {
5419  return true;
5420  }
5421  }
5422  }
5423  else {
5424  LISTBASE_FOREACH (const Nurb *, nu, &cu->nurb) {
5425  if (nu->mat_nr == index) {
5426  return true;
5427  }
5428  }
5429  }
5430 
5431  return false;
5432 }
5433 
5435 {
5436  const int curvetype = BKE_curve_type_get(cu);
5437 
5438  if (curvetype == OB_FONT) {
5439  struct CharInfo *info = cu->strinfo;
5440  for (int i = cu->len_char32 - 1; i >= 0; i--, info++) {
5441  info->mat_nr = 0;
5442  }
5443  }
5444  else {
5445  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
5446  nu->mat_nr = 0;
5447  }
5448  }
5449 }
5450 
5452 {
5453  const int curvetype = BKE_curve_type_get(cu);
5454  bool is_valid = true;
5455 
5456  if (curvetype == OB_FONT) {
5457  CharInfo *info = cu->strinfo;
5458  const int max_idx = max_ii(0, cu->totcol); /* OB_FONT use 1 as first mat index, not 0!!! */
5459  int i;
5460  for (i = cu->len_char32 - 1; i >= 0; i--, info++) {
5461  if (info->mat_nr > max_idx) {
5462  info->mat_nr = 0;
5463  is_valid = false;
5464  }
5465  }
5466  }
5467  else {
5468  const int max_idx = max_ii(0, cu->totcol - 1);
5469  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
5470  if (nu->mat_nr > max_idx) {
5471  nu->mat_nr = 0;
5472  is_valid = false;
5473  }
5474  }
5475  }
5476 
5477  if (!is_valid) {
5479  return true;
5480  }
5481  return false;
5482 }
5483 
5484 void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len)
5485 {
5486  const int curvetype = BKE_curve_type_get(cu);
5487  const short remap_len_short = (short)remap_len;
5488 
5489 #define MAT_NR_REMAP(n) \
5490  if (n < remap_len_short) { \
5491  BLI_assert(n >= 0 && remap[n] < remap_len_short); \
5492  n = remap[n]; \
5493  } \
5494  ((void)0)
5495 
5496  if (curvetype == OB_FONT) {
5497  struct CharInfo *strinfo;
5498  int charinfo_len, i;
5499 
5500  if (cu->editfont) {
5501  EditFont *ef = cu->editfont;
5502  strinfo = ef->textbufinfo;
5503  charinfo_len = ef->len;
5504  }
5505  else {
5506  strinfo = cu->strinfo;
5507  charinfo_len = cu->len_char32;
5508  }
5509 
5510  for (i = 0; i <= charinfo_len; i++) {
5511  if (strinfo[i].mat_nr > 0) {
5512  strinfo[i].mat_nr -= 1;
5513  MAT_NR_REMAP(strinfo[i].mat_nr);
5514  strinfo[i].mat_nr += 1;
5515  }
5516  }
5517  }
5518  else {
5519  Nurb *nu;
5520  ListBase *nurbs = BKE_curve_editNurbs_get(cu);
5521 
5522  if (nurbs) {
5523  for (nu = nurbs->first; nu; nu = nu->next) {
5524  MAT_NR_REMAP(nu->mat_nr);
5525  }
5526  }
5527  }
5528 
5529 #undef MAT_NR_REMAP
5530 }
5531 
5532 void BKE_curve_smooth_flag_set(Curve *cu, const bool use_smooth)
5533 {
5534  if (use_smooth) {
5535  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
5536  nu->flag |= CU_SMOOTH;
5537  }
5538  }
5539  else {
5540  LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
5541  nu->flag &= ~CU_SMOOTH;
5542  }
5543  }
5544 }
5545 
5546 void BKE_curve_rect_from_textbox(const struct Curve *cu,
5547  const struct TextBox *tb,
5548  struct rctf *r_rect)
5549 {
5550  r_rect->xmin = cu->xof + tb->x;
5551  r_rect->ymax = cu->yof + tb->y + cu->fsize;
5552 
5553  r_rect->xmax = r_rect->xmin + tb->w;
5554  r_rect->ymin = r_rect->ymax - tb->h;
5555 }
5556 
5557 /* This function is almost the same as BKE_fcurve_correct_bezpart(), but doesn't allow as large a
5558  * tangent. */
5559 void BKE_curve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2])
5560 {
5561  float h1[2], h2[2], len1, len2, len, fac;
5562 
5563  /* Calculate handle deltas. */
5564  h1[0] = v1[0] - v2[0];
5565  h1[1] = v1[1] - v2[1];
5566 
5567  h2[0] = v4[0] - v3[0];
5568  h2[1] = v4[1] - v3[1];
5569 
5570  /* Calculate distances:
5571  * - len = span of time between keyframes
5572  * - len1 = length of handle of start key
5573  * - len2 = length of handle of end key
5574  */
5575  len = v4[0] - v1[0];
5576  len1 = fabsf(h1[0]);
5577  len2 = fabsf(h2[0]);
5578 
5579  /* If the handles have no length, no need to do any corrections. */
5580  if ((len1 + len2) == 0.0f) {
5581  return;
5582  }
5583 
5584  /* the two handles cross over each other, so force them
5585  * apart using the proportion they overlap
5586  */
5587  if ((len1 + len2) > len) {
5588  fac = len / (len1 + len2);
5589 
5590  v2[0] = (v1[0] - fac * h1[0]);
5591  v2[1] = (v1[1] - fac * h1[1]);
5592 
5593  v3[0] = (v4[0] - fac * h2[0]);
5594  v3[1] = (v4[1] - fac * h2[1]);
5595  }
5596 }
5597 
5598 /* **** Depsgraph evaluation **** */
5599 
5601 {
5604  if (DEG_is_active(depsgraph)) {
5605  Curve *curve_orig = (Curve *)DEG_get_original_id(&curve->id);
5607  curve_orig->texflag |= CU_AUTOSPACE_EVALUATED;
5608  copy_v3_v3(curve_orig->loc, curve->loc);
5609  copy_v3_v3(curve_orig->size, curve->size);
5610  }
5611  }
5612 }
5613 
5614 /* Draw Engine */
5617 
5619 {
5620  if (cu->batch_cache) {
5622  }
5623 }
5625 {
5626  if (cu->batch_cache) {
5628  }
5629 }
typedef float(TangentPoint)[2]
void BKE_animdata_blend_read_data(struct BlendDataReader *reader, struct AnimData *adt)
Definition: anim_data.c:1574
void BKE_animdata_blend_write(struct BlendWriter *writer, struct AnimData *adt)
Definition: anim_data.c:1552
#define KNOTSU(nu)
Definition: BKE_curve.h:68
#define CU_DO_RADIUS(cu, nu)
Definition: BKE_curve.h:77
int eBezTriple_Flag__Alias
Definition: BKE_curve.h:44
#define CU_IS_2D(cu)
Definition: BKE_curve.h:83
#define KNOTSV(nu)
Definition: BKE_curve.h:70
#define SEGMENTSU(nu)
Definition: BKE_curve.h:74
void BKE_curveprofile_blend_read(struct BlendDataReader *reader, struct CurveProfile *profile)
struct CurveProfile * BKE_curveprofile_copy(const struct CurveProfile *profile)
void BKE_curveprofile_blend_write(struct BlendWriter *writer, const struct CurveProfile *profile)
void BKE_curveprofile_free(struct CurveProfile *profile)
Definition: curveprofile.c:53
display list (or rather multi purpose list) stuff.
struct VFont * BKE_vfont_builtin_get(void)
Definition: font.c:412
bool BKE_vfont_to_curve_ex(struct Object *ob, struct Curve *cu, int mode, struct ListBase *r_nubase, const char32_t **r_text, int *r_text_len, bool *r_text_free, struct CharTrans **r_chartransdata)
Definition: font.c:1704
void key_curve_position_weights(float t, float data[4], int type)
Definition: key.c:348
@ LIB_ID_COPY_SHAPEKEY
Definition: BKE_lib_id.h:133
void * BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag) ATTR_WARN_UNUSED_RESULT
Definition: lib_id.c:1062
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag)
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
Definition: lib_id.c:2395
#define BKE_LIB_FOREACHID_PROCESS(_data, _id_super, _cb_flag)
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:87
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:47
General operations, lookup, etc. for blender objects.
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3])
Definition: object.c:3778
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_endian_switch_float_array(float *val, const int size) ATTR_NONNULL(1)
Definition: endian_switch.c:65
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:900
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:188
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:395
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float saacos(float fac)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
#define M_PI_2
Definition: BLI_math_base.h:41
MINLINE int mod_i(int i, int n)
#define NAN_FLT
Definition: BLI_math_base.h:82
float dist_squared_to_line_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:507
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
float mat4_to_scale(const float M[4][4])
Definition: math_matrix.c:2196
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[3])
void axis_angle_to_quat(float r[4], const float axis[3], const float angle)
float normalize_qt(float q[4])
#define DEG2RADF(_deg)
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:97
void unit_qt(float q[4])
Definition: math_rotation.c:46
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
Definition: math_rotation.c:65
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], const float t)
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:52
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
bool BLI_tridiagonal_solve_cyclic(const float *a, const float *b, const float *c, const float *d, float *r_x, const int count)
Solve a possibly cyclic tridiagonal system using the Sherman-Morrison formula.
Definition: math_solvers.c:133
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[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 mul_v2_fl(float r[2], float f)
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
MINLINE void swap_v3_v3(float a[3], float b[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist)
Definition: math_vector.c:1068
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:505
MINLINE void add_v3_v3(float r[3], const float a[3])
void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3])
Definition: math_vector.c:791
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define INIT_MINMAX(min, max)
#define SWAP(type, a, b)
#define ARRAY_HAS_ITEM(arr_item, arr_start, arr_len)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define UNLIKELY(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define POINTER_OFFSET(v, ofs)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
Definition: readfile.c:5654
void BLO_write_float_array(BlendWriter *writer, uint num, const float *data_ptr)
Definition: writefile.c:1378
#define BLO_read_id_address(reader, lib, id_ptr_p)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_expand(expander, id)
bool BLO_read_requires_endian_switch(BlendDataReader *reader)
Definition: readfile.c:5620
void BLO_write_raw(BlendWriter *writer, size_t size_in_bytes, const void *data_ptr)
Definition: writefile.c:1286
void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
Definition: readfile.c:5727
bool BLO_write_is_undo(BlendWriter *writer)
Definition: writefile.c:1412
void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr)
Definition: writefile.c:1388
#define BLT_I18NCONTEXT_ID_CURVE
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:204
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:331
void DEG_debug_print_eval(struct Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
void DEG_id_tag_update(struct ID *id, int flag)
struct ID * DEG_get_original_id(struct ID *id)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
#define FILTER_ID_CU
Definition: DNA_ID.h:709
@ INDEX_ID_CU
Definition: DNA_ID.h:828
@ ID_CU
Definition: DNA_ID_enums.h:61
@ FCURVE_SMOOTH_NONE
#define MAXTEXTBOX
@ CU_BEZIER
@ CU_POLY
@ CU_NURBS
@ CU_SMOOTH
#define BEZT_IS_AUTOH(bezt)
struct Curve Curve
#define BEZT_ISSEL_ANY(bezt)
#define CU_ACT_NONE
@ CU_NURB_CYCLIC
@ CU_NURB_ENDPOINT
@ CU_NURB_BEZIER
@ CU_TWIST_MINIMUM
@ CU_TWIST_TANGENT
@ CU_AUTOSPACE
@ CU_AUTOSPACE_EVALUATED
@ HD_AUTO_ANIM
@ HD_VECT
@ HD_FREE
@ HD_AUTO
@ HD_ALIGN_DOUBLESIDE
@ HD_ALIGN
#define KEY_CU_EASE
@ HD_AUTOTYPE_NORMAL
@ HD_AUTOTYPE_LOCKED_FINAL
@ CU_3D
@ CU_FRONT
@ CU_BACK
@ CU_BEVFAC_MAP_SPLINE
@ CU_BEVFAC_MAP_SEGMENT
eBezTriple_Flag
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
#define KEYELEM_ELEM_LEN_BPOINT
#define KEYELEM_FLOAT_LEN_BEZTRIPLE
#define KEYELEM_FLOAT_LEN_BPOINT
#define KEYELEM_ELEM_LEN_BEZTRIPLE
Object is a sort of wrapper for general info.
@ BOUNDBOX_DIRTY
@ OB_SURF
@ OB_FONT
@ OB_CURVE
#define FO_EDIT
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_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 type
_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 right
_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 stride
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_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 order
_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.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
static void smooth_iter(CorrectiveSmoothModifierData *csmd, Mesh *mesh, float(*vertexCos)[3], uint numVerts, const float *smooth_weights, uint iterations)
static void init_data(ModifierData *md)
Group RGB to Bright Vector Camera CLAMP
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
static T sum(const btAlignedObjectArray< T > &items)
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
void BKE_nurb_handles_autocalc(Nurb *nu, uint8_t flag)
Definition: curve.c:4236
static void bevel_list_flip_tangents(BevList *bl)
Definition: curve.c:2212
static void makeknots(Nurb *nu, short uv)
Definition: curve.c:1261
void BKE_nurb_handle_calc_simple_auto(Nurb *nu, BezTriple *bezt)
Definition: curve.c:4133
bool BKE_nurbList_flag_set_from_flag(ListBase *editnurb, uint8_t from_flag, uint8_t flag)
Definition: curve.c:4513
static void basisNurb(float t, short order, int pnts, const float *knots, float *basis, int *start, int *end)
Definition: curve.c:1313
void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_size[3])
Definition: curve.c:561
void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
Definition: curve.c:4124
void BKE_curve_batch_cache_dirty_tag(Curve *cu, int mode)
Definition: curve.c:5618
void BKE_nurb_index_to_uv(Nurb *nu, int index, int *r_u, int *r_v)
Definition: curve.c:981
void BKE_nurb_handles_calc(Nurb *nu)
Definition: curve.c:4092
Nurb * BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
Definition: curve.c:713
static void bezier_eq_noaccel_left(float *a, float *b, float *c, float *d, const float *dy, const float *l, int i)
Definition: curve.c:3735
void BKE_curve_translate(Curve *cu, const float offset[3], const bool do_keys)
Definition: curve.c:5344
static void nurbList_handles_swap_select(Nurb *nu)
Definition: curve.c:4101
BPoint * BKE_nurb_bpoint_get_next(Nurb *nu, BPoint *bp)
Definition: curve.c:1011
void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect)
Definition: curve.c:5546
static void make_bevel_list_segment_2D(BevList *bl)
Definition: curve.c:2539
void BKE_curve_editNurb_free(Curve *cu)
Definition: curve.c:388
static void * allocate_arrays(int count, float ***floats, char ***chars, const char *name)
Definition: curve.c:3478
bool BKE_curve_center_median(Curve *cu, float cent[3])
Definition: curve.c:5224
void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv)
Definition: curve.c:1394
static void curve_editNurb_keyIndex_cv_free_cb(void *val)
Definition: curve.c:366
void BKE_curve_smooth_flag_set(Curve *cu, const bool use_smooth)
Definition: curve.c:5532
void BKE_curve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2])
Definition: curve.c:5559
static bool bevelinside(const BevList *bl1, const BevList *bl2)
Definition: curve.c:1927
void BKE_nurb_project_2d(Nurb *nu)
Definition: curve.c:748
static void bevel_list_calc_bisect(BevList *bl)
Definition: curve.c:2150
void BKE_curve_texspace_ensure(Curve *cu)
Definition: curve.c:554
bool BKE_nurb_order_clamp_u(struct Nurb *nu)
Definition: curve.c:4901
static void curve_init_data(ID *id)
Definition: curve.c:75
static void free_arrays(void *buffer)
Definition: curve.c:3511
static void makecyclicknots(float *knots, int pnts, short order)
Definition: curve.c:1229
void BKE_nurbList_handles_autocalc(ListBase *editnurb, uint8_t flag)
Definition: curve.c:4317
void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len)
Definition: curve.c:5484
static void make_bevel_list_3D_minimum_twist(BevList *bl)
Definition: curve.c:2336
void BKE_nurb_minmax(const Nurb *nu, bool use_radius, float min[3], float max[3])
Definition: curve.c:778
static void curve_blend_read_data(BlendDataReader *reader, ID *id)
Definition: curve.c:207
static void curve_foreach_id(ID *id, LibraryForeachIDData *data)
Definition: curve.c:130
void BKE_curve_transform_ex(Curve *cu, const float mat[4][4], const bool do_keys, const bool do_props, const float unit_scale)
Definition: curve.c:5273
void BKE_nurb_handles_test(Nurb *nu, const bool use_handle, const bool use_around_local)
Definition: curve.c:4217
static void curve_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
Definition: curve.c:84
static void forward_diff_bezier_cotangent(const float p0[3], const float p1[3], const float p2[3], const float p3[3], float p[3], int it, int stride)
Definition: curve.c:1857
static void bevel_list_smooth(BevList *bl, int smooth_iter)
Definition: curve.c:2253
void BKE_nurb_free(Nurb *nu)
Definition: curve.c:633
void BKE_curve_nurbs_vert_coords_apply_with_mat4(ListBase *lb, const float(*vert_coords)[3], const float mat[4][4], const bool constrain_2d)
Definition: curve.c:4703
void BKE_curve_init(Curve *cu, const short curve_type)
Definition: curve.c:398
static void make_bevel_list_segment_3D(BevList *bl)
Definition: curve.c:2515
Nurb * BKE_curve_nurb_active_get(Curve *cu)
Definition: curve.c:5100
static void curve_blend_read_lib(BlendLibReader *reader, ID *id)
Definition: curve.c:270
void BKE_curve_type_test(Object *ob)
Definition: curve.c:484
static void make_bevel_list_3D_tangent(BevList *bl)
Definition: curve.c:2443
void BKE_curve_bevelList_free(ListBase *bev)
Definition: curve.c:2635
void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
Definition: curve.c:2653
void BKE_curve_nurb_active_set(Curve *cu, const Nurb *nu)
Definition: curve.c:5088
static int vergxcobev(const void *a1, const void *a2)
Definition: curve.c:1988
void BKE_curve_texspace_calc(Curve *cu)
Definition: curve.c:517
static void make_bevel_list_2D(BevList *bl)
Definition: curve.c:2555
#define MAT_NR_REMAP(n)
static bool is_free_auto_point(BezTriple *bezt)
Definition: curve.c:4011
void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3])
Definition: curve.c:1151
Curve * BKE_curve_add(Main *bmain, const char *name, int type)
Definition: curve.c:424
bool BKE_nurb_check_valid_uv(const Nurb *nu)
Definition: curve.c:4889
void(* BKE_curve_batch_cache_free_cb)(Curve *cu)
Definition: curve.c:5616
void BKE_curve_batch_cache_free(Curve *cu)
Definition: curve.c:5624
void BKE_nurb_makeCurve(const Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride)
Definition: curve.c:1591
float BKE_nurb_calc_length(const Nurb *nu, int resolution)
Definition: curve.c:830
void BKE_curve_transform(Curve *cu, const float mat[4][4], const bool do_keys, const bool do_props)
Definition: curve.c:5338
ListBase * BKE_curve_editNurbs_get(Curve *cu)
Definition: curve.c:437
bool BKE_nurb_type_convert(Nurb *nu, const short type, const bool use_handles, const char **r_err_msg)
Definition: curve.c:4932
void BKE_curve_editNurb_keyIndex_free(GHash **keyindex)
Definition: curve.c:379
bool BKE_curve_center_bounds(Curve *cu, float cent[3])
Definition: curve.c:5261
static void make_bevel_list_3D_zup(BevList *bl)
Definition: curve.c:2307
void BKE_curve_nurb_vert_active_set(Curve *cu, const Nurb *nu, const void *vert)
Definition: curve.c:5128
static void calchandlesNurb_intern(Nurb *nu, eBezTriple_Flag handle_sel_flag, bool skip_align)
Definition: curve.c:3428
void BKE_nurb_knot_calc_u(Nurb *nu)
Definition: curve.c:1303
void BKE_nurb_handle_smooth_fcurve(BezTriple *bezt, int total, bool cyclic)
Definition: curve.c:4016
static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl)
Definition: curve.c:2618
unsigned int BKE_curve_calc_coords_axis_len(const unsigned int bezt_array_len, const unsigned int resolu, const bool is_cyclic, const bool use_cyclic_duplicate_endpoint)
Definition: curve.c:1730
static float bezier_calc_handle_adj(float hsize[2], float dx)
Definition: curve.c:3820
static void bevel_list_apply_tilt(BevList *bl)
Definition: curve.c:2233
void BKE_curve_nurbs_vert_coords_get(const ListBase *lb, float(*vert_coords)[3], int vert_len)
Definition: curve.c:4667
void BKE_curve_dimension_update(Curve *cu)
Definition: curve.c:467
void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
Definition: curve.c:4333
void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, const float *key)
Definition: curve.c:4810
void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2)
Definition: curve.c:738
bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
Definition: curve.c:5199
static bool tridiagonal_solve_with_limits(float *a, float *b, float *c, float *d, float *h, const float *hmin, const float *hmax, int solve_count)
Definition: curve.c:3555
void BKE_nurb_handle_calc(BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve, const char smoothing)
Definition: curve.c:4069
void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, BPoint *bp, float r_normal[3])
Definition: curve.c:1128
static void calcknots(float *knots, const int pnts, const short order, const short flag)
Definition: curve.c:1181
#define SEL_F1
static void bezier_lock_unknown(float *a, float *b, float *c, float *d, int i, float value)
Definition: curve.c:3532
#define SEL_F2
static void bezier_handle_calc_smooth_fcurve(BezTriple *bezt, int total, int start, int count, bool cycle)
Definition: curve.c:3830
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.c:1804
static void bezier_eq_noaccel_right(float *a, float *b, float *c, float *d, const float *dy, const float *l, int i)
Definition: curve.c:3726
void BKE_nurbList_free(ListBase *lb)
Definition: curve.c:660
static void curve_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition: curve.c:146
static void tilt_bezpart(const BezTriple *prevbezt, const BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride)
Definition: curve.c:2051
void BKE_curve_editfont_free(Curve *cu)
Definition: curve.c:346
IDTypeInfo IDType_ID_CU
Definition: curve.c:307
#define p2_h1
bool BKE_nurb_check_valid_v(const Nurb *nu)
Definition: curve.c:4861
static void calchandleNurb_intern(BezTriple *bezt, const BezTriple *prev, const BezTriple *next, eBezTriple_Flag handle_sel_flag, bool is_fcurve, bool skip_align, char fcurve_smoothing)
Definition: curve.c:3182
int BKE_nurbList_verts_count(const ListBase *nurb)
Definition: curve.c:599
void BKE_curve_nurbs_vert_coords_apply(ListBase *lb, const float(*vert_coords)[3], const bool constrain_2d)
Definition: curve.c:4740
void BKE_curve_material_index_remove(Curve *cu, int index)
Definition: curve.c:5390
int BKE_nurb_index_from_uv(Nurb *nu, int u, int v)
Definition: curve.c:959
void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.c:1833
void BKE_curve_calc_coords_axis(const BezTriple *bezt_array, const unsigned int bezt_array_len, const unsigned int resolu, const bool is_cyclic, const bool use_cyclic_duplicate_endpoint, const unsigned int axis, const unsigned int stride, float *r_points)
Definition: curve.c:1747
static void nurb_handles_calc__align_selected(Nurb *nu)
Definition: curve.c:4115
void BKE_nurb_knot_calc_v(Nurb *nu)
Definition: curve.c:1308
static void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode)
Definition: curve.c:2493
static bool bezier_check_solve_end_handle(BezTriple *bezt, char htype, bool end)
Definition: curve.c:3814
short BKE_curve_type_get(const Curve *cu)
Definition: curve.c:446
Nurb * BKE_nurb_duplicate(const Nurb *nu)
Definition: curve.c:672
void BKE_nurb_bezt_handle_test(BezTriple *bezt, const eBezTriple_Flag__Alias sel_flag, const bool use_handle, const bool use_around_local)
Definition: curve.c:4161
void(* BKE_curve_batch_cache_dirty_tag_cb)(Curve *cu, int mode)
Definition: curve.c:5615
bool BKE_curve_material_index_used(const Curve *cu, int index)
Definition: curve.c:5411
BPoint * BKE_nurb_bpoint_get_prev(Nurb *nu, BPoint *bp)
Definition: curve.c:1054
void BKE_nurb_direction_switch(Nurb *nu)
Definition: curve.c:4544
static void curve_blend_read_expand(BlendExpander *expander, ID *id)
Definition: curve.c:289
void BKE_curve_nurb_vert_active_validate(Curve *cu)
Definition: curve.c:5173
#define SEL_F3
void BKE_curve_material_index_clear(Curve *cu)
Definition: curve.c:5434
BoundBox * BKE_curve_boundbox_get(Object *ob)
Definition: curve.c:496
void BKE_curve_eval_geometry(Depsgraph *depsgraph, Curve *curve)
Definition: curve.c:5600
static CLG_LogRef LOG
Definition: curve.c:73
bool BKE_curve_nurb_vert_active_get(Curve *cu, Nurb **r_nu, void **r_vert)
Definition: curve.c:5146
bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
Definition: curve.c:573
bool BKE_nurb_check_valid_u(const Nurb *nu)
Definition: curve.c:4834
void BKE_nurb_bezierPoints_add(Nurb *nu, int number)
Definition: curve.c:945
static float bezier_relax_direction(const float *a, const float *b, const float *c, const float *d, const float *h, int i, int count)
Definition: curve.c:3517
void BKE_nurbList_flag_set(ListBase *editnurb, uint8_t flag, bool set)
Definition: curve.c:4475
static void bezier_output_handle_inner(BezTriple *bezt, bool right, const float newval[3], bool endpoint)
Definition: curve.c:3770
static void curve_free_data(ID *id)
Definition: curve.c:111
static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], const float v4[3], short cox, short coy, float *lambda, float *mu, float vec[3])
Definition: curve.c:1881
static void bezier_restore_equation(float *a, float *b, float *c, float *d, const float *a0, const float *b0, const float *c0, const float *d0, int i)
Definition: curve.c:3539
void * BKE_curve_vert_active_get(Curve *cu)
Definition: curve.c:5107
#define p2_h2
static void minimum_twist_between_two_points(BevPoint *current_point, BevPoint *previous_point)
Definition: curve.c:2320
void BKE_curve_editNurb_keyIndex_delCV(GHash *keyindex, const void *cv)
Definition: curve.c:373
int BKE_nurbList_verts_count_without_handles(const ListBase *nurb)
Definition: curve.c:615
BezTriple * BKE_nurb_bezt_get_prev(Nurb *nu, BezTriple *bezt)
Definition: curve.c:1032
static void bezier_output_handle(BezTriple *bezt, bool right, float dy, bool endpoint)
Definition: curve.c:3803
float(* BKE_curve_nurbs_key_vert_coords_alloc(const ListBase *lb, float *key, int *r_vert_len))[3]
Definition: curve.c:4776
bool BKE_nurb_order_clamp_v(struct Nurb *nu)
Definition: curve.c:4915
static void switch_endian_knots(Nurb *nu)
Definition: curve.c:197
static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *r_sina, float *r_cosa)
Definition: curve.c:2003
void BKE_nurb_bezt_calc_plane(struct Nurb *nu, BezTriple *bezt, float r_plane[3])
Definition: curve.c:1091
int BKE_curve_nurb_vert_index_get(const Nurb *nu, const void *vert)
Definition: curve.c:5116
static void bezier_eq_continuous(float *a, float *b, float *c, float *d, const float *dy, const float *l, int i)
Definition: curve.c:3717
static void bezier_clamp(float *hmax, float *hmin, int i, float dy, bool no_reverse, bool no_overshoot)
Definition: curve.c:3745
void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), BezTriple *bezt, float r_normal[3])
Definition: curve.c:1076
float(* BKE_curve_nurbs_vert_coords_alloc(const ListBase *lb, int *r_vert_len))[3]
Definition: curve.c:4694
void BKE_nurb_handle_calc_ex(BezTriple *bezt, BezTriple *prev, BezTriple *next, const eBezTriple_Flag__Alias handle_sel_flag, const bool is_fcurve, const char smoothing)
Definition: curve.c:4082
void BKE_nurbList_handles_recalculate(ListBase *editnurb, const bool calc_length, const uint8_t flag)
Definition: curve.c:4418
BezTriple * BKE_nurb_bezt_get_next(Nurb *nu, BezTriple *bezt)
Definition: curve.c:990
bool BKE_curve_material_index_validate(Curve *cu)
Definition: curve.c:5451
void BKE_nurb_points_add(Nurb *nu, int number)
Definition: curve.c:932
ListBase * BKE_curve_nurbs_get(Curve *cu)
Definition: curve.c:5079
#define SELECT
Curve curve
bool is_valid
const Depsgraph * depsgraph
int count
#define sinf(x)
#define cosf(x)
#define atan2f(x, y)
#define floorf(x)
#define fabsf(x)
#define sqrtf(x)
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong * next
static ulong state[N]
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
static RawVector< RawArray< int64_t, 0 > > arrays
const btScalar eps
Definition: poly34.cpp:11
#define min(a, b)
Definition: sort.c:51
unsigned char uint8_t
Definition: stdint.h:81
float weight
uint8_t f1
float vec[4]
float radius
float tilt
struct BevList * next
float * seglen
BevPoint * bevpoints
int * segbevcount
short dupe_tag
float offset
float radius
float dir[3]
float tan[3]
float quat[4]
float weight
float vec[3]
int dir
Definition: curve.c:1985
BevList * bl
Definition: curve.c:1983
float left
Definition: curve.c:1984
char auto_handle_type
float vec[3][3]
void * orig_cv
Definition: BKE_curve.h:63
ListBase bev
Definition: BKE_curve.h:50
struct Object * bevobj
float loc[3]
struct CurveProfile * bevel_profile
struct Material ** mat
struct VFont * vfont
short totcol
float xof
int len_char32
struct TextBox * tb
short resolv
void * batch_cache
struct AnimData * adt
struct EditFont * editfont
char bevfac2_mapping
short resolu
short twist_mode
float wordspace
struct Key * key
struct CharInfo * strinfo
struct VFont * vfontb
float linewidth
struct Object * textoncurve
char * str
EditNurb * editnurb
struct VFont * vfonti
short texflag
ListBase nurb
float fsize
float yof
struct VFont * vfontbi
char bevfac1_mapping
struct Object * taperobj
short resolu_ren
float size[3]
float twist_smooth
short type
EditFontSelBox * selboxes
Definition: BKE_font.h:53
int len
Definition: BKE_font.h:58
char32_t * textbuf
Definition: BKE_font.h:48
struct CharInfo * textbufinfo
Definition: BKE_font.h:49
struct GHash * keyindex
ListBase nurbs
short id_code
Definition: BKE_idtype.h:120
Definition: DNA_ID.h:273
struct Library * lib
Definition: DNA_ID.h:277
int us
Definition: DNA_ID.h:293
char name[66]
Definition: DNA_ID.h:283
ID * from
ID id
Definition: DNA_key_types.h:79
ListBase block
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
short flagu
short orderu
struct Nurb * next
short orderv
float * knotsu
short tilt_interp
short type
float * knotsv
BezTriple * bezt
BPoint * bp
short resolu
short radius_interp
short hide
short flagv
short mat_nr
struct CurveCache * curve_cache
struct BoundBox * bb
Object_Runtime runtime
void * data
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
float max
__forceinline bool all(const avxb &b)
Definition: util_avxb.h:214
__forceinline avxf cross(const avxf &a, const avxf &b)
Definition: util_avxf.h:119
uint len