8 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version. The Blender
14 * Foundation also sells licenses for use in proprietary software under
15 * the Blender License. See http://www.blender.org/BL/ for information
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
28 * All rights reserved.
30 * The Original Code is: all of this file.
32 * Contributor(s): none yet.
34 * ***** END GPL/BL DUAL LICENSE BLOCK *****
39 #include <math.h> // floor
44 #include "BLI_winstuff.h"
46 #include "MEM_guardedalloc.h"
47 #include "BLI_blenlib.h"
48 #include "BLI_arithb.h"
50 #include "DNA_object_types.h"
51 #include "DNA_curve_types.h"
52 #include "DNA_material_types.h"
53 #include "DNA_mesh_types.h"
55 /* for dereferencing pointers */
57 #include "DNA_vfont_types.h"
58 #include "DNA_key_types.h"
59 #include "DNA_ipo_types.h"
61 #include "BKE_global.h"
63 #include "BKE_utildefines.h" // VECCOPY
64 #include "BKE_object.h"
66 #include "BKE_curve.h"
67 #include "BKE_displist.h"
70 #include "BKE_library.h"
76 extern ListBase editNurb; /* editcurve.c */
79 int cu_isectLL(float *v1, float *v2, float *v3, float *v4,
81 float *labda, float *mu, float *vec);
85 /* hotfix; copies x*y array into extended (x+dx)*(y+dy) array
86 old[] and new[] can be the same ! */
87 int copyintoExtendedArray(float *old, int oldx, int oldy, float *new, int newx, int newy)
91 if (newx < oldx || newy < oldy) return 0;
94 for (y = newy - 1; y >= oldy; y--) {
95 for (x = newx - 1; x >= 0; x--) {
96 newp = new + 3 * (y * newx + x);
97 newp[0] = 0.0; newp[1] = 0.0; newp[2] = 0.0;
101 for (; y >= 0; y--) {
103 for (x = newx - 1; x >= oldx; x--) {
104 newp = new + 3 * (y * newx + x);
105 newp[0] = 0.0; newp[1] = 0.0; newp[2] = 0.0;
107 for (; x >= 0; x--) {
108 oldp = old + 3 * (y * oldx + x);
109 newp = new + 3 * (y * newx + x);
117 void unlink_curve(Curve *cu)
121 for(a=0; a<cu->totcol; a++) {
122 if(cu->mat[a]) cu->mat[a]->id.us--;
125 if(cu->vfont) cu->vfont->id.us--;
127 if(cu->key) cu->key->id.us--;
129 if(cu->ipo) cu->ipo->id.us--;
134 /* niet curve zelf vrijgeven */
135 void free_curve(Curve *cu)
138 freeNurblist(&cu->nurb);
139 BLI_freelistN(&cu->bev);
140 freedisplist(&cu->disp);
144 if(cu->mat) MEM_freeN(cu->mat);
145 if(cu->str) MEM_freeN(cu->str);
146 if(cu->bb) MEM_freeN(cu->bb);
147 if(cu->path) free_path(cu->path);
150 Curve *add_curve(int type)
155 if(type==OB_CURVE) str= "Curve";
156 else if(type==OB_SURF) str= "Surf";
159 cu= alloc_libblock(&G.main->curve, ID_CU, str);
161 cu->size[0]= cu->size[1]= cu->size[2]= 1.0;
162 cu->flag= CU_FRONT+CU_BACK;
164 cu->resolu= cu->resolv= 6;
166 cu->spacing= cu->linedist= 1.0;
168 cu->texflag= AUTOSPACE;
170 cu->bb= unit_boundbox();
175 Curve *copy_curve(Curve *cu)
180 cun= copy_libblock(cu);
181 cun->nurb.first= cun->nurb.last= 0;
182 duplicateNurblist( &(cun->nurb), &(cu->nurb));
184 cun->mat= MEM_dupallocN(cu->mat);
185 for(a=0; a<cun->totcol; a++) {
186 id_us_plus((ID *)cun->mat[a]);
189 cun->str= MEM_dupallocN(cu->str);
190 cun->bb= MEM_dupallocN(cu->bb);
192 cun->key= copy_key(cu->key);
193 if(cun->key) cun->key->from= (ID *)cun;
195 cun->disp.first= cun->disp.last= 0;
196 cun->bev.first= cun->bev.last= 0;
199 /* ook single user ipo */
200 if(cun->ipo) cun->ipo= copy_ipo(cun->ipo);
202 id_us_plus((ID *)cun->vfont);
207 void make_local_curve(Curve *cu)
213 /* - zijn er alleen lib users: niet doen
214 * - zijn er alleen locale users: flag zetten
218 if(cu->id.lib==0) return;
220 if(cu->vfont) cu->vfont->id.lib= 0;
224 cu->id.flag= LIB_LOCAL;
225 new_id(0, (ID *)cu, 0);
229 ob= G.main->object.first;
232 if(ob->id.lib) lib= 1;
238 if(local && lib==0) {
240 cu->id.flag= LIB_LOCAL;
241 new_id(0, (ID *)cu, 0);
243 else if(local && lib) {
247 ob= G.main->object.first;
263 void test_curve_type(Object *ob)
286 void tex_space_curve(Curve *cu)
290 float *data, min[3], max[3], loc[3], size[3];
293 if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
296 INIT_MINMAX(min, max);
301 if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr;
302 else tot= dl->nr*dl->parts;
307 DO_MINMAX(data, min, max);
314 loc[0]= (min[0]+max[0])/2.0f;
315 loc[1]= (min[1]+max[1])/2.0f;
316 loc[2]= (min[2]+max[2])/2.0f;
318 size[0]= (max[0]-min[0])/2.0f;
319 size[1]= (max[1]-min[1])/2.0f;
320 size[2]= (max[2]-min[2])/2.0f;
323 loc[0]= loc[1]= loc[2]= 0.0f;
324 size[0]= size[1]= size[2]= 1.0f;
327 bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0];
328 bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0];
330 bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1];
331 bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1];
333 bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2];
334 bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2];
336 if(cu->texflag & AUTOSPACE) {
337 VECCOPY(cu->loc, loc);
338 VECCOPY(cu->size, size);
339 cu->rot[0]= cu->rot[1]= cu->rot[2]= 0.0;
341 if(cu->size[0]==0.0) cu->size[0]= 1.0;
342 else if(cu->size[0]>0.0 && cu->size[0]<0.00001) cu->size[0]= 0.00001;
343 else if(cu->size[0]<0.0 && cu->size[0]> -0.00001) cu->size[0]= -0.00001;
345 if(cu->size[1]==0.0) cu->size[1]= 1.0;
346 else if(cu->size[1]>0.0 && cu->size[1]<0.00001) cu->size[1]= 0.00001;
347 else if(cu->size[1]<0.0 && cu->size[1]> -0.00001) cu->size[1]= -0.00001;
349 if(cu->size[2]==0.0) cu->size[2]= 1.0;
350 else if(cu->size[2]>0.0 && cu->size[2]<0.00001) cu->size[2]= 0.00001;
351 else if(cu->size[2]<0.0 && cu->size[2]> -0.00001) cu->size[2]= -0.00001;
357 int count_curveverts(ListBase *nurb)
364 if(nu->bezt) tot+= 3*nu->pntsu;
365 else if(nu->bp) tot+= nu->pntsu*nu->pntsv;
374 /* **************** NURBS ROUTINES ******************** */
376 void freeNurb(Nurb *nu)
381 if(nu->bezt) MEM_freeN(nu->bezt);
383 if(nu->bp) MEM_freeN(nu->bp);
385 if(nu->knotsu) MEM_freeN(nu->knotsu);
387 if(nu->knotsv) MEM_freeN(nu->knotsv);
389 /* if(nu->trim.first) freeNurblist(&(nu->trim)); */
396 void freeNurblist(ListBase *lb)
408 lb->first= lb->last= 0;
411 Nurb *duplicateNurb(Nurb *nu)
416 newnu= (Nurb*)MEM_mallocN(sizeof(Nurb),"duplicateNurb");
417 if(newnu==0) return 0;
418 memcpy(newnu, nu, sizeof(Nurb));
422 (BezTriple*)MEM_mallocN((nu->pntsu)* sizeof(BezTriple),"duplicateNurb2");
423 memcpy(newnu->bezt, nu->bezt, nu->pntsu*sizeof(BezTriple));
426 len= nu->pntsu*nu->pntsv;
428 (BPoint*)MEM_mallocN((len)* sizeof(BPoint),"duplicateNurb3");
429 memcpy(newnu->bp, nu->bp, len*sizeof(BPoint));
431 newnu->knotsu=newnu->knotsv= 0;
436 newnu->knotsu= MEM_mallocN(len*sizeof(float), "duplicateNurb4");
437 memcpy(newnu->knotsu, nu->knotsu, sizeof(float)*len);
440 if(nu->pntsv>1 && nu->knotsv) {
443 newnu->knotsv= MEM_mallocN(len*sizeof(float), "duplicateNurb5");
444 memcpy(newnu->knotsv, nu->knotsv, sizeof(float)*len);
451 void duplicateNurblist(ListBase *lb1, ListBase *lb2)
459 nun= duplicateNurb(nu);
460 BLI_addtail(lb1, nun);
466 void test2DNurb(Nurb *nu)
472 if( nu->type== CU_BEZIER+CU_2D ) {
476 bezt->vec[0][2]= 0.0;
477 bezt->vec[1][2]= 0.0;
478 bezt->vec[2][2]= 0.0;
482 else if(nu->type & CU_2D) {
483 a= nu->pntsu*nu->pntsv;
492 void minmaxNurb(Nurb *nu, float *min, float *max)
498 if( (nu->type & 7)==CU_BEZIER ) {
502 DO_MINMAX(bezt->vec[0], min, max);
503 DO_MINMAX(bezt->vec[1], min, max);
504 DO_MINMAX(bezt->vec[2], min, max);
509 a= nu->pntsu*nu->pntsv;
512 DO_MINMAX(bp->vec, min, max);
519 /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline berekeningen ~~~~~~~~~~~ */
522 /* voor de goede orde: eigenlijk horen hier doubles gebruikt te worden */
524 void extend_spline(float * pnts, int in, int out)
531 add = (double*)MEM_mallocN((in)* sizeof(double), "extend_spline");
533 for (k = 3; k > 0; k--){
536 /* punten kopieren naar add */
537 for (i = 0; i < in; i++){
542 /* inverse forward differencen */
543 for (i = 0; i < in - 1; i++){
544 for (j = in - 1; j > i; j--){
545 add[j] -= add[j - 1];
550 for (i = out; i > 0; i--){
551 *pnts = (float)(add[0]);
553 for (j = 0; j < in - 1; j++){
565 void calcknots(float *knots, short aantal, short order, short type)
566 /* knots: aantal pnts NIET gecorrigeerd voor cyclic */
567 /* aantal, order, type; 0: uniform, 1: endpoints, 2: bezier */
573 for(a=0;a<aantal+order;a++) {
579 for(a=1;a<=aantal+order;a++) {
581 if(a>=order && a<=aantal) k+= 1.0;
587 for(a=0;a<aantal+order;a++) {
588 knots[a]= (float)floor(k);
594 for(a=0;a<aantal+order;a++) {
595 if(a>=order && a<=aantal) k+= (0.5);
596 knots[a]= (float)floor(k);
602 void makecyclicknots(float *knots, short pnts, short order)
603 /* pnts, order: aantal pnts NIET gecorrigeerd voor cyclic */
609 /* eerst lange rijen (order -1) dezelfde knots aan uiteinde verwijderen */
612 for(a=1; a<order-1; a++) {
613 if(knots[b]!= knots[b-a]) break;
615 if(a==order-1) knots[pnts+order-2]+= 1.0;
619 for(a=pnts+order-1; a<pnts+order+order-1; a++) {
620 knots[a]= knots[a-1]+ (knots[b]-knots[b-1]);
626 void makeknots(Nurb *nu, short uv, short type) /* 0: uniform, 1: endpoints, 2: bezier */
628 if( (nu->type & 7)==CU_NURBS ) {
630 if(nu->knotsu) MEM_freeN(nu->knotsu);
632 nu->knotsu= MEM_callocN(4+sizeof(float)*KNOTSU(nu), "makeknots");
633 calcknots(nu->knotsu, nu->pntsu, nu->orderu, type);
634 if(nu->flagu & 1) makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
639 if(nu->knotsv) MEM_freeN(nu->knotsv);
641 nu->knotsv= MEM_callocN(4+sizeof(float)*KNOTSV(nu), "makeknots");
642 calcknots(nu->knotsv, nu->pntsv, nu->orderv, type);
643 if(nu->flagv & 1) makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
650 void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end)
653 int i, i1 = 0, i2 = 0 ,j, orderpluspnts;
655 orderpluspnts= order+pnts;
657 /* this is for float inaccuracy */
658 if(t < knots[0]) t= knots[0];
659 else if(t > knots[orderpluspnts-1]) t= knots[orderpluspnts-1];
661 /* dit stuk is order '1' */
662 for(i=0;i<orderpluspnts-1;i++) {
663 if(knots[i]!=knots[i+1] && t>= knots[i] && t<=knots[i+1]) {
669 while(i<orderpluspnts-1) {
679 /* printf("u %f\n", t); for(k=0;k<orderpluspnts;k++) printf(" %2.2f",basis[k]); printf("\n"); */
681 /* dit is order 2,3,... */
682 for(j=2; j<=order; j++) {
684 if(i2+j>= orderpluspnts) i2= orderpluspnts-j-1;
686 for(i= i1; i<=i2; i++) {
688 d= ((t-knots[i])*basis[i]) / (knots[i+j-1]-knots[i]);
693 e= ((knots[i+j]-t)*basis[i+1]) / (knots[i+j]-knots[i+1]);
704 for(i=i1; i<=i2; i++) {
707 if(*start==1000) *start= i;
713 void makeNurbfaces(Nurb *nu, float *data)
714 /* data moet 3*4*resolu*resolv lang zijn en op nul staan */
717 float *basisu, *basis, *basisv, *sum, *fp, *in;
718 float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv;
719 int i, j, iofs, jofs, cycl, len, resolu, resolv;
720 int istart, iend, jsta, jen, *jstart, *jend, ratcomp;
722 if(nu->knotsu==0 || nu->knotsv==0) return;
723 if(nu->orderu>nu->pntsu) return;
724 if(nu->orderv>nu->pntsv) return;
727 /* alloceren en vars goedzetten */
728 len= nu->pntsu*nu->pntsv;
730 sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbfaces1");
741 i= nu->pntsu*nu->pntsv;
744 if(bp->vec[3]!=1.0) {
752 ustart= fp[nu->orderu-1];
753 if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1];
754 else uend= fp[nu->pntsu];
755 ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1));
756 basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbfaces3");
759 vstart= fp[nu->orderv-1];
761 if(nu->flagv & 1) vend= fp[nu->pntsv+nu->orderv-1];
762 else vend= fp[nu->pntsv];
763 vstep= (vend-vstart)/(resolv-1+(nu->flagv & 1));
765 basisv= (float *)MEM_mallocN(sizeof(float)*len*resolv, "makeNurbfaces3");
766 jstart= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces4");
767 jend= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces5");
769 /* voorberekenen basisv en jstart,jend */
770 if(nu->flagv & 1) cycl= nu->orderv-1;
775 basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+resolv, jend+resolv);
780 if(nu->flagu & 1) cycl= nu->orderu-1;
786 basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
792 jsta= jstart[resolv];
799 for(j= jsta; j<=jen; j++) {
801 if(j>=nu->pntsv) jofs= (j - nu->pntsv);
803 bp= nu->bp+ nu->pntsu*jofs+istart-1;
805 for(i= istart; i<=iend; i++, fp++) {
809 bp= nu->bp+ nu->pntsu*jofs+iofs;
814 *fp= basisu[i]*basis[j]*bp->vec[3];
817 else *fp= basisu[i]*basis[j];
823 for(j= jsta; j<=jen; j++) {
824 for(i= istart; i<=iend; i++, fp++) {
830 /* een! (1.0) echt punt nu */
832 for(j= jsta; j<=jen; j++) {
834 if(j>=nu->pntsv) jofs= (j - nu->pntsv);
836 bp= nu->bp+ nu->pntsu*jofs+istart-1;
838 for(i= istart; i<=iend; i++, fp++) {
842 bp= nu->bp+ nu->pntsu*jofs+iofs;
847 in[0]+= (*fp) * bp->vec[0];
848 in[1]+= (*fp) * bp->vec[1];
849 in[2]+= (*fp) * bp->vec[2];
869 void makeNurbcurve_forw(Nurb *nu, float *data)
870 /* *data: moet 3*4*pntsu*resolu lang zijn en op nul staan */
873 float *basisu, *sum, *fp, *in;
874 float u, ustart, uend, ustep, sumdiv;
875 int i, j, k, len, resolu, istart, iend;
878 if(nu->knotsu==0) return;
881 /* alloceren en vars goedzetten */
884 sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1");
886 resolu= nu->resolu*nu->pntsu;
893 ustart= fp[nu->orderu-1];
895 ustep= (uend-ustart)/(resolu-1);
896 basisu= (float *)MEM_mallocN(sizeof(float)*(nu->orderu+nu->pntsu), "makeNurbcurve3");
900 for (k = nu->orderu - 1; k < nu->pntsu; k++){
902 wanted = (int)((nu->knotsu[k+1] - nu->knotsu[k]) / ustep);
903 org = 4; /* gelijk aan order */
904 if (org > wanted) org = wanted;
906 for (j = org; j > 0; j--){
908 basisNurb(u, nu->orderu, nu->pntsu, nu->knotsu, basisu, &istart, &iend);
912 for(i= istart; i<=iend; i++, fp++) {
913 /* hier nog rationele component doen */
917 if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) {
918 /* is dit normaliseren ook nodig? */
920 for(i= istart; i<=iend; i++, fp++) {
925 /* een! (1.0) echt punt nu */
928 for(i= istart; i<=iend; i++, bp++, fp++) {
931 in[0]+= (*fp) * bp->vec[0];
932 in[1]+= (*fp) * bp->vec[1];
933 in[2]+= (*fp) * bp->vec[2];
943 extend_spline(in - 3 * org, org, wanted);
944 in += 3 * (wanted - org);
945 u += ustep * (wanted - org);
955 void makeNurbcurve(Nurb *nu, float *data, int dim)
956 /* data moet dim*4*pntsu*resolu lang zijn en op nul staan */
959 float u, ustart, uend, ustep, sumdiv;
960 float *basisu, *sum, *fp, *in;
961 int i, len, resolu, istart, iend, cycl;
963 if(nu->knotsu==0) return;
964 if(nu->orderu>nu->pntsu) return;
967 /* alloceren en vars goedzetten */
970 sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1");
972 resolu= nu->resolu*nu->pntsu;
979 ustart= fp[nu->orderu-1];
980 if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1];
981 else uend= fp[nu->pntsu];
982 ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1));
983 basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbcurve3");
985 if(nu->flagu & 1) cycl= nu->orderu-1;
992 basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
996 bp= nu->bp+ istart-1;
997 for(i= istart; i<=iend; i++, fp++) {
999 if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu);
1002 *fp= basisu[i]*bp->vec[3];
1005 if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) {
1006 /* is dit normaliseren ook nodig? */
1008 for(i= istart; i<=iend; i++, fp++) {
1013 /* een! (1.0) echt punt nu */
1015 bp= nu->bp+ istart-1;
1016 for(i= istart; i<=iend; i++, fp++) {
1018 if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu);
1023 in[0]+= (*fp) * bp->vec[0];
1024 in[1]+= (*fp) * bp->vec[1];
1026 in[2]+= (*fp) * bp->vec[2];
1027 if(dim==4) in[3]+= (*fp) * bp->alfa;
1042 void maakbez(float q0, float q1, float q2, float q3, float *p, int it)
1044 float rt0,rt1,rt2,rt3,f;
1049 rt1= 3.0f*(q1-q0)/f;
1051 rt2= 3.0f*(q0-2.0f*q1+q2)/f;
1053 rt3= (q3-q0+3.0f*(q1-q2))/f;
1060 for(a=0; a<=it; a++) {
1069 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1071 void make_orco_surf(Curve *cu)
1075 int sizeu, sizev;// ###
1079 /* eerst voorspellen hoelang datablok moet worden */
1083 /* this is a bad hack: as we want to avoid the seam in a cyclic nurbs
1084 texture wrapping, reserve extra orco data space to save these extra needed
1085 vertex based UV coordinates for the meridian vertices.
1086 Vertices on the 0/2pi boundary are not duplicated inside the displist but later in
1087 the renderface/vert construction.
1089 See also blenderWorldManipulation.c: init_render_surf()
1093 sizeu = nu->resolu; sizev = nu->resolv;
1094 if (nu->flagu & CU_CYCLIC) sizeu++;
1095 if (nu->flagv & CU_CYCLIC) sizev++;
1096 if(nu->pntsv>1) tot+= sizeu * sizev;
1098 if(nu->pntsv>1) tot+= nu->resolu*nu->resolv;
1102 /* makeNurbfaces wil nullen */
1103 data= cu->orco= MEM_callocN(3*sizeof(float)*tot, "make_orco");
1111 if (nu->flagu & CU_CYCLIC) sizeu++;
1112 if (nu->flagv & CU_CYCLIC) sizev++;
1115 if(cu->flag & CU_UV_ORCO) {
1116 for(b=0; b< sizeu; b++) {
1117 for(a=0; a< sizev; a++) {
1119 if(sizev <2) data[0]= 0.0f;
1120 else data[0]= -1.0f + 2.0f*((float)a)/(sizev - 1);
1122 if(sizeu <2) data[1]= 0.0f;
1123 else data[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1);
1132 makeNurbfaces(nu, data);
1134 for(b=0; b< nu->resolu; b++) {
1135 for(a=0; a< nu->resolv; a++) {
1136 data = cu->orco + 3 * (b * nu->resolv + a);
1137 data[0]= (data[0]-cu->loc[0])/cu->size[0];
1138 data[1]= (data[1]-cu->loc[1])/cu->size[1];
1139 data[2]= (data[2]-cu->loc[2])/cu->size[2];
1142 copyintoExtendedArray(cu->orco, nu->resolv, nu->resolu, cu->orco, sizev, sizeu);
1143 /* copy U/V-cyclic orco's */
1144 if (nu->flagv & CU_CYCLIC) {
1146 for(a=0; a< sizev; a++) {
1147 data = cu->orco + 3 * (b * sizev + a);
1148 VECCOPY(data, cu->orco + 3*a);
1151 if (nu->flagu & CU_CYCLIC) {
1153 for(b=0; b< sizeu; b++) {
1154 data = cu->orco + 3 * (b * sizev + a);
1155 VECCOPY(data, cu->orco + 3 * b*sizev);
1162 data[0]= (data[0]-cu->loc[0])/cu->size[0];
1163 data[1]= (data[1]-cu->loc[1])/cu->size[1];
1164 data[2]= (data[2]-cu->loc[2])/cu->size[2];
1173 /* loadkeypostype(22, base, base); */
1179 /* ***************** BEVEL ****************** */
1181 void makebevelcurve(Object *ob, ListBase *disp)
1183 DispList *dl, *dlnew;
1185 float *fp, facx, facy, hoek, dhoek;
1190 if(cu->bevobj && cu->bevobj!=ob) {
1191 if(cu->bevobj->type==OB_CURVE) {
1192 bevcu= cu->bevobj->data;
1193 if(bevcu->ext1==0.0 && bevcu->ext2==0.0) {
1194 facx= cu->bevobj->size[0];
1195 facy= cu->bevobj->size[1];
1197 dl= bevcu->disp.first;
1199 makeDispList(cu->bevobj);
1200 dl= bevcu->disp.first;
1203 if ELEM(dl->type, DL_POLY, DL_SEGM) {
1204 dlnew= MEM_mallocN(sizeof(DispList), "makebevelcurve1");
1206 dlnew->verts= MEM_mallocN(3*sizeof(float)*dl->parts*dl->nr, "makebevelcurve1");
1207 memcpy(dlnew->verts, dl->verts, 3*sizeof(float)*dl->parts*dl->nr);
1209 BLI_addtail(disp, dlnew);
1211 nr= dlnew->parts*dlnew->nr;
1224 else if(cu->ext2==0.0) {
1225 dl= MEM_callocN(sizeof(DispList), "makebevelcurve2");
1226 dl->verts= MEM_mallocN(2*3*sizeof(float), "makebevelcurve2");
1227 BLI_addtail(disp, dl);
1238 nr= 4+2*cu->bevresol;
1240 dl= MEM_callocN(sizeof(DispList), "makebevelcurve3");
1241 dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve3");
1242 BLI_addtail(disp, dl);
1247 /* eerst cirkel maken */
1250 dhoek= (float)(M_PI/(nr-2));
1251 for(a=0; a<nr; a++) {
1253 fp[1]= (float)(cos(hoek)*(cu->ext2));
1254 fp[2]= (float)(sin(hoek)*(cu->ext2));
1257 if(cu->ext1!=0.0 && a==((nr/2)-1) ) {
1263 if(cu->ext1==0.0) dl->nr--;
1266 for(a=0; a<nr; a++) {
1267 if(a<=(nr/2-1)) fp[2]-= (cu->ext1);
1268 else fp[2]+= (cu->ext1);
1276 int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec)
1280 0: no intersection of segments
1281 1: exact intersection of segments
1282 2: cross-intersection of segments
1286 deler= (v1[cox]-v2[cox])*(v3[coy]-v4[coy])-(v3[cox]-v4[cox])*(v1[coy]-v2[coy]);
1287 if(deler==0.0) return -1;
1289 *labda= (v1[coy]-v3[coy])*(v3[cox]-v4[cox])-(v1[cox]-v3[cox])*(v3[coy]-v4[coy]);
1290 *labda= -(*labda/deler);
1292 deler= v3[coy]-v4[coy];
1294 deler=v3[cox]-v4[cox];
1295 *mu= -(*labda*(v2[cox]-v1[cox])+v1[cox]-v3[cox])/deler;
1297 *mu= -(*labda*(v2[coy]-v1[coy])+v1[coy]-v3[coy])/deler;
1299 vec[cox]= *labda*(v2[cox]-v1[cox])+v1[cox];
1300 vec[coy]= *labda*(v2[coy]-v1[coy])+v1[coy];
1302 if(*labda>=0.0 && *labda<=1.0 && *mu>=0.0 && *mu<=1.0) {
1303 if(*labda==0.0 || *labda==1.0 || *mu==0.0 || *mu==1.0) return 1;
1310 short bevelinside(BevList *bl1,BevList *bl2)
1312 /* is bl2 INSIDE bl1 ? met links-rechts methode en "labda's" */
1313 /* geeft als correct gat 1 terug */
1314 BevPoint *bevp, *prevbevp;
1315 float min,max,vec[3],hvec1[3],hvec2[3],lab,mu;
1316 int nr, links=0,rechts=0,mode;
1318 /* neem eerste vertex van het mogelijke gat */
1320 bevp= (BevPoint *)(bl2+1);
1324 VECCOPY(hvec2,hvec1);
1327 /* test deze met alle edges van mogelijk omringende poly */
1328 /* tel aantal overgangen links en rechts */
1330 bevp= (BevPoint *)(bl1+1);
1332 prevbevp= bevp+(nr-1);
1342 if(min<=hvec1[1] && max>=hvec1[1]) {
1343 /* er is een overgang, snijpunt berekenen */
1344 mode= cu_isectLL(&(prevbevp->x),&(bevp->x),hvec1,hvec2,0,1,&lab,&mu,vec);
1345 /* als lab==0.0 of lab==1.0 dan snijdt de edge exact de overgang
1346 * alleen toestaan voor lab= 1.0 (of andersom, maakt niet uit)
1348 if(mode>=0 && lab!=0.0) {
1349 if(vec[0]<hvec1[0]) links++;
1358 if( (links & 1) && (rechts & 1) ) return 1;
1369 int vergxcobev(const void *a1, const void *a2)
1371 const struct bevelsort *x1=a1,*x2=a2;
1373 if( x1->left > x2->left ) return 1;
1374 else if( x1->left < x2->left) return -1;
1378 /* deze kan niet zomaar door atan2 vervangen worden, maar waarom? */
1380 void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *sina, float *cosa)
1382 float t01, t02, x3, y3;
1384 t01= (float)sqrt(x1*x1+y1*y1);
1385 t02= (float)sqrt(x2*x2+y2*y2);
1386 if(t01==0.0) t01= 1.0;
1387 if(t02==0.0) t02= 1.0;
1395 if(fabs(t02)>=1.0) t02= .5*M_PI;
1396 else t02= (saacos(t02))/2.0f;
1398 t02= (float)sin(t02);
1399 if(t02==0.0) t02= 1.0;
1403 if(x3==0 && y3==0) {
1404 /* printf("x3 en y3 nul \n"); */
1408 t01= (float)sqrt(x3*x3+y3*y3);
1418 void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *data_a)
1420 BezTriple *pprev, *next, *last;
1421 float fac, dfac, t[4];
1424 last= nu->bezt+(nu->pntsu-1);
1426 /* een punt terug */
1427 if(prevbezt==nu->bezt) {
1428 if(nu->flagu & 1) pprev= last;
1429 else pprev= prevbezt;
1431 else pprev= prevbezt-1;
1433 /* een punt verder */
1435 if(nu->flagu & 1) next= nu->bezt;
1441 dfac= 1.0f/(float)nu->resolu;
1443 for(a=0; a<nu->resolu; a++, fac+= dfac) {
1445 set_four_ipo(fac, t, KEY_BSPLINE);
1447 data_a[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa;
1451 void makeBevelList(Object *ob)
1453 /* - alle curves omzetten in poly's, met aangegeven resol en vlaggen voor dubbele punten
1454 - eventueel intelligent punten verwijderen (geval Nurb)
1455 - scheiden in verschillende blokken met Boundbox
1456 - Autogat detectie */
1459 BezTriple *bezt, *prevbezt;
1461 BevList *bl, *blnew, *blnext;
1462 BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
1463 float *data, *data_a, *v1, *v2, min, inp, x1, x2, y1, y2, vec[3];
1464 struct bevelsort *sortdata, *sd, *sd1;
1465 int a, b, len, nr, poly;
1467 /* deze fie moet object hebben in verband met tflag en upflag */
1470 /* STAP 1: POLY'S MAKEN */
1472 BLI_freelistN(&(cu->bev));
1473 if(ob==G.obedit) nu= editNurb.first;
1474 else nu= cu->nurb.first;
1479 if((nu->type & 7)==CU_POLY) {
1482 bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
1483 BLI_addtail(&(cu->bev), bl);
1485 if(nu->flagu & 1) bl->poly= 0;
1489 bevp= (BevPoint *)(bl+1);
1493 bevp->x= bp->vec[0];
1494 bevp->y= bp->vec[1];
1495 bevp->z= bp->vec[2];
1496 bevp->alfa= bp->alfa;
1502 else if((nu->type & 7)==CU_BEZIER) {
1504 len= nu->resolu*(nu->pntsu+ (nu->flagu & 1) -1)+1; /* voor laatste punt niet cyclic */
1505 bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
1506 BLI_addtail(&(cu->bev), bl);
1508 if(nu->flagu & 1) bl->poly= 0;
1510 bevp= (BevPoint *)(bl+1);
1516 prevbezt= nu->bezt+(nu->pntsu-1);
1523 data= MEM_mallocN(3*sizeof(float)*(nu->resolu+1), "makeBevelList2");
1524 data_a= MEM_callocN(sizeof(float)*(nu->resolu+1), "data_a");
1527 if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
1529 bevp->x= prevbezt->vec[1][0];
1530 bevp->y= prevbezt->vec[1][1];
1531 bevp->z= prevbezt->vec[1][2];
1532 bevp->alfa= prevbezt->alfa;
1540 v1= prevbezt->vec[1];
1543 /* altijd alle drie doen: anders blijft data hangen */
1544 maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu);
1545 maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu);
1546 maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu);
1548 if((nu->type & CU_2D)==0) {
1549 if(cu->flag & CU_3D) {
1550 alfa_bezpart(prevbezt, bezt, nu, data_a);
1555 /* met handlecodes dubbele punten aangeven */
1556 if(prevbezt->h1==prevbezt->h2) {
1557 if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1;
1560 if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1;
1561 else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= 1;
1577 bl->nr+= nu->resolu;
1587 if((nu->flagu & 1)==0) { /* niet cyclic: endpoint */
1588 bevp->x= prevbezt->vec[1][0];
1589 bevp->y= prevbezt->vec[1][1];
1590 bevp->z= prevbezt->vec[1][2];
1595 else if((nu->type & 7)==CU_NURBS) {
1597 len= nu->resolu*nu->pntsu;
1598 bl= MEM_mallocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3");
1599 BLI_addtail(&(cu->bev), bl);
1602 if(nu->flagu & 1) bl->poly= 0;
1604 bevp= (BevPoint *)(bl+1);
1606 data= MEM_callocN(4*sizeof(float)*len, "makeBevelList4"); /* moet op nul staan */
1607 makeNurbcurve(nu, data, 4);
1616 bevp->f1= bevp->f2= 0;
1627 /* STAP 2: DUBBELE PUNTEN EN AUTOMATISCHE RESOLUTIE, DATABLOKKEN VERKLEINEN */
1631 bevp1= (BevPoint *)(bl+1);
1632 bevp0= bevp1+(nr-1);
1635 if( fabs(bevp0->x-bevp1->x)<0.00001 ) {
1636 if( fabs(bevp0->y-bevp1->y)<0.00001 ) {
1637 if( fabs(bevp0->z-bevp1->z)<0.00001 ) {
1652 nr= bl->nr- bl->flag+1; /* +1 want vectorbezier zet ook flag */
1653 blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList");
1654 memcpy(blnew, bl, sizeof(BevList));
1656 BLI_remlink(&(cu->bev), bl);
1657 BLI_insertlinkbefore(&(cu->bev),blnext,blnew); /* zodat bevlijst met nurblijst gelijk loopt */
1658 bevp0= (BevPoint *)(bl+1);
1659 bevp1= (BevPoint *)(blnew+1);
1663 memcpy(bevp1, bevp0, sizeof(BevPoint));
1675 /* STAP 3: POLY'S TELLEN EN AUTOGAT */
1688 /* meest linkse punten vinden, tevens richting testen */
1690 sd= sortdata= MEM_mallocN(sizeof(struct bevelsort)*poly, "makeBevelList5");
1696 bevp= (BevPoint *)(bl+1);
1708 bevp= (BevPoint *)(bl+1);
1709 if(bevp1== bevp) bevp0= bevp+ (bl->nr-1);
1710 else bevp0= bevp1-1;
1711 bevp= bevp+ (bl->nr-1);
1712 if(bevp1== bevp) bevp2= (BevPoint *)(bl+1);
1713 else bevp2= bevp1+1;
1715 inp= (bevp1->x- bevp0->x)*(bevp0->y- bevp2->y)
1716 +(bevp0->y- bevp1->y)*(bevp0->x- bevp2->x);
1718 if(inp>0.0) sd->dir= 1;
1726 qsort(sortdata,poly,sizeof(struct bevelsort), vergxcobev);
1729 for(a=1; a<poly; a++, sd++) {
1730 bl= sd->bl; /* is bl een gat? */
1731 sd1= sortdata+ (a-1);
1732 for(b=a-1; b>=0; b--, sd1--) { /* alle polys links ervan */
1733 if(bevelinside(sd1->bl, bl)) {
1734 bl->gat= 1- sd1->bl->gat;
1741 if((cu->flag & CU_3D)==0) {
1743 for(a=0; a<poly; a++, sd++) {
1744 if(sd->bl->gat==sd->dir) {
1746 bevp1= (BevPoint *)(bl+1);
1747 bevp2= bevp1+ (bl->nr-1);
1750 SWAP(BevPoint, *bevp1, *bevp2);
1757 MEM_freeN(sortdata);
1760 /* STAP 4: COSINUSSEN */
1764 if(bl->nr==2) { /* 2 pnt, apart afhandelen: KAN DAT NIET AFGESCHAFT? */
1765 bevp2= (BevPoint *)(bl+1);
1768 x1= bevp1->x- bevp2->x;
1769 y1= bevp1->y- bevp2->y;
1771 calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
1772 bevp2->sina= bevp1->sina;
1773 bevp2->cosa= bevp1->cosa;
1775 if(cu->flag & CU_3D) { /* 3D */
1778 vec[0]= bevp1->x - bevp2->x;
1779 vec[1]= bevp1->y - bevp2->y;
1780 vec[2]= bevp1->z - bevp2->z;
1782 quat= vectoquat(vec, 5, 1);
1785 q[0]= (float)cos(0.5*bevp1->alfa);
1786 x1= (float)sin(0.5*bevp1->alfa);
1790 QuatMul(quat, q, quat);
1792 QuatToMat3(quat, bevp1->mat);
1793 Mat3CpyMat3(bevp2->mat, bevp1->mat);
1798 bevp2= (BevPoint *)(bl+1);
1799 bevp1= bevp2+(bl->nr-1);
1807 if(cu->flag & CU_3D) { /* 3D */
1810 vec[0]= bevp2->x - bevp0->x;
1811 vec[1]= bevp2->y - bevp0->y;
1812 vec[2]= bevp2->z - bevp0->z;
1816 quat= vectoquat(vec, 5, 1);
1818 q[0]= (float)cos(0.5*bevp1->alfa);
1819 x1= (float)sin(0.5*bevp1->alfa);
1823 QuatMul(quat, q, quat);
1825 QuatToMat3(quat, bevp1->mat);
1828 x1= bevp1->x- bevp0->x;
1829 x2= bevp1->x- bevp2->x;
1830 y1= bevp1->y- bevp0->y;
1831 y2= bevp1->y- bevp2->y;
1833 calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
1840 /* niet cyclic gevallen corrigeren */
1843 bevp= (BevPoint *)(bl+1);
1845 bevp->sina= bevp1->sina;
1846 bevp->cosa= bevp1->cosa;
1847 Mat3CpyMat3(bevp->mat, bevp1->mat);
1848 bevp= (BevPoint *)(bl+1);
1851 bevp->sina= bevp1->sina;
1852 bevp->cosa= bevp1->cosa;
1853 Mat3CpyMat3(bevp->mat, bevp1->mat);
1861 /* ****************** HANDLES ************** */
1865 * 1: niets, 1:auto, 2:vector, 3:aligned
1869 void calchandleNurb(BezTriple *bezt,BezTriple *prev, BezTriple *next, int mode)
1871 float *p1,*p2,*p3,pt[3];
1872 float dx1,dy1,dz1,dx,dy,dz,vx,vy,vz,len,len1,len2;
1874 if(bezt->h1==0 && bezt->h2==0) return;
1880 pt[0]= 2*p2[0]- p3[0];
1881 pt[1]= 2*p2[1]- p3[1];
1882 pt[2]= 2*p2[2]- p3[2];
1885 else p1= prev->vec[1];
1888 pt[0]= 2*p2[0]- p1[0];
1889 pt[1]= 2*p2[1]- p1[1];
1890 pt[2]= 2*p2[2]- p1[2];
1893 else p3= next->vec[1];
1895 if(mode && bezt->h1==HD_AUTO && prev) {
1896 dx= p2[0] - (p1[0]+p1[3])/2.0f;
1897 dy= p2[1] - (p1[1]+p1[4])/2.0f;
1898 dz= p2[2] - (p1[2]+p1[5])/2.0f;
1905 len1= (float)sqrt(dx*dx+dy*dy+dz*dz);
1907 if(mode && bezt->h2==HD_AUTO && next) {
1908 dx1= (p3[0]+p3[-3])/2.0f - p2[0];
1909 dy1= (p3[1]+p3[-2])/2.0f - p2[1];
1910 dz1= (p3[2]+p3[-1])/2.0f - p2[2];
1917 len2= (float)sqrt(dx1*dx1+dy1*dy1+dz1*dz1);
1919 if(len1==0.0f) len1=1.0f;
1920 if(len2==0.0f) len2=1.0f;
1923 if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */
1924 vx= dx1/len2 + dx/len1;
1925 vy= dy1/len2 + dy/len1;
1926 vz= dz1/len2 + dz/len1;
1927 len= 2.71f*(float)sqrt(vx*vx + vy*vy + vz*vz);
1930 if(len1>5.0f*len2) len1= 5.0f*len2;
1931 if(len2>5.0f*len1) len2= 5.0f*len1;
1933 if(bezt->h1==HD_AUTO) {
1935 *(p2-3)= *p2-vx*len1;
1936 *(p2-2)= *(p2+1)-vy*len1;
1937 *(p2-1)= *(p2+2)-vz*len1;
1939 if(bezt->h2==HD_AUTO) {
1941 *(p2+3)= *p2+vx*len2;
1942 *(p2+4)= *(p2+1)+vy*len2;
1943 *(p2+5)= *(p2+2)+vz*len2;
1948 if(bezt->h1==HD_VECT) { /* vector */
1953 *(p2-2)= *(p2+1)-dy;
1954 *(p2-1)= *(p2+2)-dz;
1956 if(bezt->h2==HD_VECT) {
1961 *(p2+4)= *(p2+1)+dy1;
1962 *(p2+5)= *(p2+2)+dz1;
1965 len2= VecLenf(p2, p2+3);
1966 len1= VecLenf(p2, p2-3);
1967 if(len1==0.0) len1=1.0;
1968 if(len2==0.0) len2=1.0;
1969 if(bezt->f1 & 1) { /* volgorde van berekenen */
1970 if(bezt->h2==HD_ALIGN) { /* aligned */
1972 p2[3]= p2[0]+len*(p2[0]-p2[-3]);
1973 p2[4]= p2[1]+len*(p2[1]-p2[-2]);
1974 p2[5]= p2[2]+len*(p2[2]-p2[-1]);
1976 if(bezt->h1==HD_ALIGN) {
1978 p2[-3]= p2[0]+len*(p2[0]-p2[3]);
1979 p2[-2]= p2[1]+len*(p2[1]-p2[4]);
1980 p2[-1]= p2[2]+len*(p2[2]-p2[5]);
1984 if(bezt->h1==HD_ALIGN) {
1986 p2[-3]= p2[0]+len*(p2[0]-p2[3]);
1987 p2[-2]= p2[1]+len*(p2[1]-p2[4]);
1988 p2[-1]= p2[2]+len*(p2[2]-p2[5]);
1990 if(bezt->h2==HD_ALIGN) { /* aligned */
1992 p2[3]= p2[0]+len*(p2[0]-p2[-3]);
1993 p2[4]= p2[1]+len*(p2[1]-p2[-2]);
1994 p2[5]= p2[2]+len*(p2[2]-p2[-1]);
1999 void calchandlesNurb(Nurb *nu) /* wel eerst (zonodig) de handlevlaggen zetten */
2001 BezTriple *bezt, *prev, *next;
2004 if((nu->type & 7)!=1) return;
2005 if(nu->pntsu<2) return;
2009 if(nu->flagu & 1) prev= bezt+(a-1);
2014 calchandleNurb(bezt, prev, next, 0);
2017 if(nu->flagu & 1) next= nu->bezt;
2027 void testhandlesNurb(Nurb *nu)
2029 /* Te gebruiken als er iets an de handles is veranderd.
2030 * Loopt alle BezTriples af met de volgende regels:
2031 * FASE 1: types veranderen?
2032 * Autocalchandles: worden ligned als NOT(000 || 111)
2033 * Vectorhandles worden 'niets' als (selected en andere niet)
2034 * FASE 2: handles herbereken
2039 if((nu->type & 7)!=CU_BEZIER) return;
2045 if(bezt->f1 & 1) flag++;
2046 if(bezt->f2 & 1) flag += 2;
2047 if(bezt->f3 & 1) flag += 4;
2049 if( !(flag==0 || flag==7) ) {
2050 if(bezt->h1==HD_AUTO) { /* auto */
2053 if(bezt->h2==HD_AUTO) { /* auto */
2057 if(bezt->h1==HD_VECT) { /* vector */
2058 if(flag < 4) bezt->h1= 0;
2060 if(bezt->h2==HD_VECT) { /* vector */
2061 if( flag > 3) bezt->h2= 0;
2067 calchandlesNurb(nu);
2070 void autocalchandlesNurb(Nurb *nu, int flag)
2072 /* Kijkt naar de coordinaten van de handles en berekent de soort */
2074 BezTriple *bezt2, *bezt1, *bezt0;
2075 int i, align, leftsmall, rightsmall;
2077 if(nu==0 || nu->bezt==0) return;
2080 bezt1 = bezt2 + (nu->pntsu-1);
2086 align= leftsmall= rightsmall= 0;
2088 /* linker handle: */
2089 if(flag==0 || (bezt1->f1 & flag) ) {
2091 /* afstand te klein: vectorhandle */
2092 if( VecLenf( bezt1->vec[1], bezt0->vec[1] ) < 0.0001) {
2097 /* aligned handle? */
2098 if(DistVL2Dfl(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001) {
2100 bezt1->h1= HD_ALIGN;
2102 /* of toch vector handle? */
2103 if(DistVL2Dfl(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001)
2108 /* rechter handle: */
2109 if(flag==0 || (bezt1->f3 & flag) ) {
2111 /* afstand te klein: vectorhandle */
2112 if( VecLenf( bezt1->vec[1], bezt2->vec[1] ) < 0.0001) {
2117 /* aligned handle? */
2118 if(align) bezt1->h2= HD_ALIGN;
2120 /* of toch vector handle? */
2121 if(DistVL2Dfl(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001)
2126 if(leftsmall && bezt1->h2==HD_ALIGN) bezt1->h2= 0;
2127 if(rightsmall && bezt1->h1==HD_ALIGN) bezt1->h1= 0;
2129 /* onzalige combinatie: */
2130 if(bezt1->h1==HD_ALIGN && bezt1->h2==HD_VECT) bezt1->h1= 0;
2131 if(bezt1->h2==HD_ALIGN && bezt1->h1==HD_VECT) bezt1->h2= 0;
2138 calchandlesNurb(nu);
2141 void autocalchandlesNurb_all(int flag)
2147 autocalchandlesNurb(nu, flag);
2152 void sethandlesNurb(short code)
2154 /* code==1: set autohandle */
2155 /* code==2: set vectorhandle */
2156 /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
2161 if(code==1 || code==2) {
2164 if( (nu->type & 7)==1) {
2168 if(bezt->f1 || bezt->f3) {
2169 if(bezt->f1) bezt->h1= code;
2170 if(bezt->f3) bezt->h2= code;
2171 if(bezt->h1!=bezt->h2) {
2172 if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
2173 if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
2178 calchandlesNurb(nu);
2184 /* is er 1 handle NIET vrij: alles vrijmaken, else ALIGNED maken */
2188 if( (nu->type & 7)==1) {
2192 if(bezt->f1 && bezt->h1) ok= 1;
2193 if(bezt->f3 && bezt->h2) ok= 1;
2205 if( (nu->type & 7)==1) {
2209 if(bezt->f1) bezt->h1= ok;
2210 if(bezt->f3 ) bezt->h2= ok;
2214 calchandlesNurb(nu);
2221 void swapdata(void *adr1, void *adr2, int len)
2229 memcpy(adr, adr1, len);
2230 memcpy(adr1, adr2, len);
2231 memcpy(adr2, adr, len);
2236 adr= (char *)malloc(len);
2237 memcpy(adr, adr1, len);
2238 memcpy(adr1, adr2, len);
2239 memcpy(adr2, adr, len);
2244 void switchdirectionNurb(Nurb *nu)
2246 BezTriple *bezt1, *bezt2;
2248 float *fp1, *fp2, *tempf;
2251 if(nu->pntsu==1 && nu->pntsv==1) return;
2253 if((nu->type & 7)==CU_BEZIER) {
2257 if(a & 1) a+= 1; /* bij oneven ook van middelste inhoud swappen */
2260 if(bezt1!=bezt2) SWAP(BezTriple, *bezt1, *bezt2);
2262 swapdata(bezt1->vec[0], bezt1->vec[2], 12);
2263 if(bezt1!=bezt2) swapdata(bezt2->vec[0], bezt2->vec[2], 12);
2265 SWAP(char, bezt1->h1, bezt1->h2);
2266 SWAP(short, bezt1->f1, bezt1->f3);
2269 SWAP(char, bezt2->h1, bezt2->h2);
2270 SWAP(short, bezt2->f1, bezt2->f3);
2271 bezt1->alfa= -bezt1->alfa;
2272 bezt2->alfa= -bezt2->alfa;
2279 else if(nu->pntsv==1) {
2284 while(bp1!=bp2 && a>0) {
2285 SWAP(BPoint, *bp1, *bp2);
2287 bp1->alfa= -bp1->alfa;
2288 bp2->alfa= -bp2->alfa;
2292 if((nu->type & 7)==CU_NURBS) {
2293 /* de knots omkeren */
2298 while(fp1!=fp2 && a>0) {
2299 SWAP(float, *fp1, *fp2);
2304 /* en weer in stijgende lijn maken */
2307 fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
2309 fp2[0]= fabs(fp1[1]-fp1[0]);
2320 fp1[0]= fp1[-1]+fp2[0];
2329 for(b=0; b<nu->pntsv; b++) {
2331 bp1= nu->bp+b*nu->pntsu;
2336 while(bp1!=bp2 && a>0) {
2337 SWAP(BPoint, *bp1, *bp2);