Initial revision
[blender.git] / source / blender / blenkernel / intern / curve.c
1
2 /*  curve.c      MIXED MODEL
3  * 
4  *  maart 95
5  *  
6  * $Id$
7  *
8  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
9  *
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
16  * about this.
17  *
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.
22  *
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.
26  *
27  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
28  * All rights reserved.
29  *
30  * The Original Code is: all of this file.
31  *
32  * Contributor(s): none yet.
33  *
34  * ***** END GPL/BL DUAL LICENSE BLOCK *****
35  */
36
37 #define STRUBI hack
38
39 #include <math.h>  // floor
40 #include <string.h>
41 #include <stdlib.h>  
42
43 #ifdef WIN32
44 #include "BLI_winstuff.h"
45 #endif
46 #include "MEM_guardedalloc.h"
47 #include "BLI_blenlib.h"  
48 #include "BLI_arithb.h"  
49
50 #include "DNA_object_types.h"  
51 #include "DNA_curve_types.h"  
52 #include "DNA_material_types.h"  
53 #include "DNA_mesh_types.h"
54
55 /* for dereferencing pointers */
56 #include "DNA_ID.h"  
57 #include "DNA_vfont_types.h"  
58 #include "DNA_key_types.h"  
59 #include "DNA_ipo_types.h"  
60
61 #include "BKE_global.h" 
62 #include "BKE_main.h"  
63 #include "BKE_utildefines.h"  // VECCOPY
64 #include "BKE_object.h"  
65 #include "BKE_mesh.h" 
66 #include "BKE_curve.h"  
67 #include "BKE_displist.h"  
68 #include "BKE_ipo.h"  
69 #include "BKE_anim.h"  
70 #include "BKE_library.h"  
71 #include "BKE_key.h"  
72
73
74 /* globals */
75
76 extern ListBase editNurb;  /* editcurve.c */
77
78 /* local */
79 int cu_isectLL(float *v1, float *v2, float *v3, float *v4, 
80                            short cox, short coy, 
81                            float *labda, float *mu, float *vec);
82
83
84 #ifdef STRUBI
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)
88 {
89         int x, y;
90         float *oldp, *newp;
91         if (newx < oldx || newy < oldy) return 0;
92         
93                 
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;
98                 }
99         }       
100
101         for (; y >= 0; y--) {
102                 
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;
106                 }
107                 for (; x  >= 0; x--) {
108                         oldp = old + 3 * (y * oldx + x);
109                         newp = new + 3 * (y * newx + x);
110                         VECCOPY(newp, oldp);
111                 }
112         }
113         return 1;
114 }
115 #endif
116
117 void unlink_curve(Curve *cu)
118 {
119         int a;
120         
121         for(a=0; a<cu->totcol; a++) {
122                 if(cu->mat[a]) cu->mat[a]->id.us--;
123                 cu->mat[a]= 0;
124         }
125         if(cu->vfont) cu->vfont->id.us--; 
126         cu->vfont= 0;
127         if(cu->key) cu->key->id.us--;
128         cu->key= 0;
129         if(cu->ipo) cu->ipo->id.us--;
130         cu->ipo= 0;
131 }
132
133
134 /* niet curve zelf vrijgeven */
135 void free_curve(Curve *cu)
136 {
137
138         freeNurblist(&cu->nurb);
139         BLI_freelistN(&cu->bev);
140         freedisplist(&cu->disp);
141         
142         unlink_curve(cu);
143         
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);
148 }
149
150 Curve *add_curve(int type)
151 {
152         Curve *cu;
153         char *str;
154         
155         if(type==OB_CURVE) str= "Curve";
156         else if(type==OB_SURF) str= "Surf";
157         else str= "Text";
158
159         cu= alloc_libblock(&G.main->curve, ID_CU, str);
160         
161         cu->size[0]= cu->size[1]= cu->size[2]= 1.0;
162         cu->flag= CU_FRONT+CU_BACK;
163         cu->pathlen= 100;
164         cu->resolu= cu->resolv= 6;
165         cu->width= 1.0;
166         cu->spacing= cu->linedist= 1.0;
167         cu->fsize= 1.0;
168         cu->texflag= AUTOSPACE;
169         
170         cu->bb= unit_boundbox();
171         
172         return cu;
173 }
174
175 Curve *copy_curve(Curve *cu)
176 {
177         Curve *cun;
178         int a;
179         
180         cun= copy_libblock(cu);
181         cun->nurb.first= cun->nurb.last= 0;
182         duplicateNurblist( &(cun->nurb), &(cu->nurb));
183
184         cun->mat= MEM_dupallocN(cu->mat);
185         for(a=0; a<cun->totcol; a++) {
186                 id_us_plus((ID *)cun->mat[a]);
187         }
188         
189         cun->str= MEM_dupallocN(cu->str);
190         cun->bb= MEM_dupallocN(cu->bb);
191         
192         cun->key= copy_key(cu->key);
193         if(cun->key) cun->key->from= (ID *)cun;
194         
195         cun->disp.first= cun->disp.last= 0;
196         cun->bev.first= cun->bev.last= 0;
197         cun->path= 0;
198
199         /* ook single user ipo */
200         if(cun->ipo) cun->ipo= copy_ipo(cun->ipo);
201
202         id_us_plus((ID *)cun->vfont);
203         
204         return cun;
205 }
206
207 void make_local_curve(Curve *cu)
208 {
209         Object *ob = 0;
210         Curve *cun;
211         int local=0, lib=0;
212         
213         /* - zijn er alleen lib users: niet doen
214          * - zijn er alleen locale users: flag zetten
215          * - mixed: copy
216          */
217         
218         if(cu->id.lib==0) return;
219         
220         if(cu->vfont) cu->vfont->id.lib= 0;
221         
222         if(cu->id.us==1) {
223                 cu->id.lib= 0;
224                 cu->id.flag= LIB_LOCAL;
225                 new_id(0, (ID *)cu, 0);
226                 return;
227         }
228         
229         ob= G.main->object.first;
230         while(ob) {
231                 if(ob->data==cu) {
232                         if(ob->id.lib) lib= 1;
233                         else local= 1;
234                 }
235                 ob= ob->id.next;
236         }
237         
238         if(local && lib==0) {
239                 cu->id.lib= 0;
240                 cu->id.flag= LIB_LOCAL;
241                 new_id(0, (ID *)cu, 0);
242         }
243         else if(local && lib) {
244                 cun= copy_curve(cu);
245                 cun->id.us= 0;
246                 
247                 ob= G.main->object.first;
248                 while(ob) {
249                         if(ob->data==cu) {
250                                 
251                                 if(ob->id.lib==0) {
252                                         ob->data= cun;
253                                         cun->id.us++;
254                                         cu->id.us--;
255                                 }
256                         }
257                         ob= ob->id.next;
258                 }
259         }
260 }
261
262
263 void test_curve_type(Object *ob)
264 {
265         Nurb *nu;
266         Curve *cu;
267         
268         cu= ob->data;
269         if(cu->vfont) {
270                 ob->type= OB_FONT;
271                 return;
272         }
273         else {
274                 nu= cu->nurb.first;
275                 while(nu) {
276                         if(nu->pntsv>1) {
277                                 ob->type= OB_SURF;
278                                 return;
279                         }
280                         nu= nu->next;
281                 }
282         }
283         ob->type= OB_CURVE;
284 }
285
286 void tex_space_curve(Curve *cu)
287 {
288         DispList *dl;
289         BoundBox *bb;
290         float *data, min[3], max[3], loc[3], size[3];
291         int tot, doit= 0;
292         
293         if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
294         bb= cu->bb;
295         
296         INIT_MINMAX(min, max);
297
298         dl= cu->disp.first;
299         while(dl) {
300                 
301                 if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr;
302                 else tot= dl->nr*dl->parts;
303                 
304                 if(tot) doit= 1;
305                 data= dl->verts;
306                 while(tot--) {
307                         DO_MINMAX(data, min, max);
308                         data+= 3;
309                 }
310                 dl= dl->next;
311         }
312
313         if(doit) {
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;
317                 
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;
321         }
322         else {
323                 loc[0]= loc[1]= loc[2]= 0.0f;
324                 size[0]= size[1]= size[2]= 1.0f;
325         }
326         
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];
329         
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];
332
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];
335
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;
340
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;
344         
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;
348         
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;
352
353         }
354 }
355
356
357 int count_curveverts(ListBase *nurb)
358 {
359         Nurb *nu;
360         int tot=0;
361         
362         nu= nurb->first;
363         while(nu) {
364                 if(nu->bezt) tot+= 3*nu->pntsu;
365                 else if(nu->bp) tot+= nu->pntsu*nu->pntsv;
366                 
367                 nu= nu->next;
368         }
369         return tot;
370 }
371
372
373
374 /* **************** NURBS ROUTINES ******************** */
375
376 void freeNurb(Nurb *nu)
377 {
378
379         if(nu==0) return;
380
381         if(nu->bezt) MEM_freeN(nu->bezt);
382         nu->bezt= 0;
383         if(nu->bp) MEM_freeN(nu->bp);
384         nu->bp= 0;
385         if(nu->knotsu) MEM_freeN(nu->knotsu);
386         nu->knotsu= 0;
387         if(nu->knotsv) MEM_freeN(nu->knotsv);
388         nu->knotsv= 0;
389         /* if(nu->trim.first) freeNurblist(&(nu->trim)); */
390
391         MEM_freeN(nu);
392
393 }
394
395
396 void freeNurblist(ListBase *lb)
397 {
398         Nurb *nu, *next;
399
400         if(lb==0) return;
401
402         nu= lb->first;
403         while(nu) {
404                 next= nu->next;
405                 freeNurb(nu);
406                 nu= next;
407         }
408         lb->first= lb->last= 0;
409 }
410
411 Nurb *duplicateNurb(Nurb *nu)
412 {
413         Nurb *newnu;
414         int len;
415
416         newnu= (Nurb*)MEM_mallocN(sizeof(Nurb),"duplicateNurb");
417         if(newnu==0) return 0;
418         memcpy(newnu, nu, sizeof(Nurb));
419
420         if(nu->bezt) {
421                 newnu->bezt=
422                         (BezTriple*)MEM_mallocN((nu->pntsu)* sizeof(BezTriple),"duplicateNurb2");
423                 memcpy(newnu->bezt, nu->bezt, nu->pntsu*sizeof(BezTriple));
424         }
425         else {
426                 len= nu->pntsu*nu->pntsv;
427                 newnu->bp=
428                         (BPoint*)MEM_mallocN((len)* sizeof(BPoint),"duplicateNurb3");
429                 memcpy(newnu->bp, nu->bp, len*sizeof(BPoint));
430                 
431                 newnu->knotsu=newnu->knotsv= 0;
432                 
433                 if(nu->knotsu) {
434                         len= KNOTSU(nu);
435                         if(len) {
436                                 newnu->knotsu= MEM_mallocN(len*sizeof(float), "duplicateNurb4");
437                                 memcpy(newnu->knotsu, nu->knotsu, sizeof(float)*len);
438                         }
439                 }
440                 if(nu->pntsv>1 && nu->knotsv) {
441                         len= KNOTSV(nu);
442                         if(len) {
443                                 newnu->knotsv= MEM_mallocN(len*sizeof(float), "duplicateNurb5");
444                                 memcpy(newnu->knotsv, nu->knotsv, sizeof(float)*len);
445                         }
446                 }
447         }
448         return newnu;
449 }
450
451 void duplicateNurblist(ListBase *lb1, ListBase *lb2)
452 {
453         Nurb *nu, *nun;
454         
455         freeNurblist(lb1);
456         
457         nu= lb2->first;
458         while(nu) {
459                 nun= duplicateNurb(nu);
460                 BLI_addtail(lb1, nun);
461                 
462                 nu= nu->next;
463         }
464 }
465
466 void test2DNurb(Nurb *nu)
467 {
468         BezTriple *bezt;
469         BPoint *bp;
470         int a;
471
472         if( nu->type== CU_BEZIER+CU_2D ) {
473                 a= nu->pntsu;
474                 bezt= nu->bezt;
475                 while(a--) {
476                         bezt->vec[0][2]= 0.0; 
477                         bezt->vec[1][2]= 0.0; 
478                         bezt->vec[2][2]= 0.0;
479                         bezt++;
480                 }
481         }
482         else if(nu->type & CU_2D) {
483                 a= nu->pntsu*nu->pntsv;
484                 bp= nu->bp;
485                 while(a--) {
486                         bp->vec[2]= 0.0;
487                         bp++;
488                 }
489         }
490 }
491
492 void minmaxNurb(Nurb *nu, float *min, float *max)
493 {
494         BezTriple *bezt;
495         BPoint *bp;
496         int a;
497
498         if( (nu->type & 7)==CU_BEZIER ) {
499                 a= nu->pntsu;
500                 bezt= nu->bezt;
501                 while(a--) {
502                         DO_MINMAX(bezt->vec[0], min, max);
503                         DO_MINMAX(bezt->vec[1], min, max);
504                         DO_MINMAX(bezt->vec[2], min, max);
505                         bezt++;
506                 }
507         }
508         else {
509                 a= nu->pntsu*nu->pntsv;
510                 bp= nu->bp;
511                 while(a--) {
512                         DO_MINMAX(bp->vec, min, max);
513                         bp++;
514                 }
515         }
516
517 }
518
519 /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline berekeningen ~~~~~~~~~~~ */
520
521
522 /* voor de goede orde: eigenlijk horen hier doubles gebruikt te worden */
523
524 void extend_spline(float * pnts, int in, int out)
525 {
526         float *_pnts;
527         double * add;
528         int i, j, k;
529
530         _pnts = pnts;
531         add = (double*)MEM_mallocN((in)* sizeof(double), "extend_spline");
532
533         for (k = 3; k > 0; k--){
534                 pnts = _pnts;
535
536                 /* punten kopieren naar add */
537                 for (i = 0; i < in; i++){
538                         add[i] = *pnts;
539                         pnts += 3;
540                 }
541
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];
546                         }
547                 }
548
549                 pnts = _pnts;
550                 for (i = out; i > 0; i--){
551                         *pnts = (float)(add[0]);
552                         pnts += 3;
553                         for (j = 0; j < in - 1; j++){
554                                 add[j] += add[j+1];
555                         }
556                 }
557
558                 _pnts++;
559         }
560
561         MEM_freeN(add);
562 }
563
564
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 */
568 {
569         float k;
570         int a;
571
572         if(type==0) {
573                 for(a=0;a<aantal+order;a++) {
574                         knots[a]= (float)a;
575                 }
576         }
577         else if(type==1) {
578                 k= 0.0;
579                 for(a=1;a<=aantal+order;a++) {
580                         knots[a-1]= k;
581                         if(a>=order && a<=aantal) k+= 1.0;
582                 }
583         }
584         else if(type==2) {
585                 if(order==4) {
586                         k= 0.34;
587                         for(a=0;a<aantal+order;a++) {
588                                 knots[a]= (float)floor(k);
589                                 k+= (1.0/3.0);
590                         }
591                 }
592                 else if(order==3) {
593                         k= 0.6;
594                         for(a=0;a<aantal+order;a++) {
595                                 if(a>=order && a<=aantal) k+= (0.5);
596                                 knots[a]= (float)floor(k);
597                         }
598                 }
599         }
600 }
601
602 void makecyclicknots(float *knots, short pnts, short order)
603 /* pnts, order: aantal pnts NIET gecorrigeerd voor cyclic */
604 {
605         int a, b;
606
607         if(knots==0) return;
608
609         /* eerst lange rijen (order -1) dezelfde knots aan uiteinde verwijderen */
610         if(order>2) {
611                 b= pnts+order-1;
612                 for(a=1; a<order-1; a++) {
613                         if(knots[b]!= knots[b-a]) break;
614                 }
615                 if(a==order-1) knots[pnts+order-2]+= 1.0;
616         }
617
618         b= order;
619         for(a=pnts+order-1; a<pnts+order+order-1; a++) {
620                 knots[a]= knots[a-1]+ (knots[b]-knots[b-1]);
621                 b--;
622         }
623 }
624
625
626 void makeknots(Nurb *nu, short uv, short type)  /* 0: uniform, 1: endpoints, 2: bezier */
627 {
628         if( (nu->type & 7)==CU_NURBS ) {
629                 if(uv & 1) {
630                         if(nu->knotsu) MEM_freeN(nu->knotsu);
631                         if(nu->pntsu>1) {
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);
635                         }
636                         else nu->knotsu= 0;
637                 }
638                 if(uv & 2) {
639                         if(nu->knotsv) MEM_freeN(nu->knotsv);
640                         if(nu->pntsv>1) {
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);
644                         }
645                         else nu->knotsv= 0;
646                 }
647         }
648 }
649
650 void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end)
651 {
652         float d, e;
653         int i, i1 = 0, i2 = 0 ,j, orderpluspnts;
654
655         orderpluspnts= order+pnts;
656
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];
660
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]) {
664                         basis[i]= 1.0;
665                         i1= i-order+1;
666                         if(i1<0) i1= 0;
667                         i2= i;
668                         i++;
669                         while(i<orderpluspnts-1) {
670                                 basis[i]= 0.0;
671                                 i++;
672                         }
673                         break;
674                 }
675                 else basis[i]= 0.0;
676         }
677         basis[i]= 0.0;
678
679         /* printf("u %f\n", t); for(k=0;k<orderpluspnts;k++) printf(" %2.2f",basis[k]); printf("\n");    */
680         
681         /* dit is order 2,3,... */
682         for(j=2; j<=order; j++) {
683
684                 if(i2+j>= orderpluspnts) i2= orderpluspnts-j-1;
685
686                 for(i= i1; i<=i2; i++) {
687                         if(basis[i]!=0.0)
688                                 d= ((t-knots[i])*basis[i]) / (knots[i+j-1]-knots[i]);
689                         else
690                                 d= 0.0;
691
692                         if(basis[i+1]!=0.0)
693                                 e= ((knots[i+j]-t)*basis[i+1]) / (knots[i+j]-knots[i+1]);
694                         else
695                                 e= 0.0;
696
697                         basis[i]= d+e;
698                 }
699         }
700
701         *start= 1000;
702         *end= 0;
703
704         for(i=i1; i<=i2; i++) {
705                 if(basis[i]>0.0) {
706                         *end= i;
707                         if(*start==1000) *start= i;
708                 }
709         }
710 }
711
712
713 void makeNurbfaces(Nurb *nu, float *data) 
714 /* data  moet 3*4*resolu*resolv lang zijn en op nul staan */
715 {
716         BPoint *bp;
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;
721
722         if(nu->knotsu==0 || nu->knotsv==0) return;
723         if(nu->orderu>nu->pntsu) return;
724         if(nu->orderv>nu->pntsv) return;
725         if(data==0) return;
726
727         /* alloceren en vars goedzetten */
728         len= nu->pntsu*nu->pntsv;
729         if(len==0) return;
730         sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbfaces1");
731
732         resolu= nu->resolu;
733         resolv= nu->resolv;
734         len= resolu*resolv;
735         if(len==0) {
736                 MEM_freeN(sum);
737                 return;
738         }
739
740         bp= nu->bp;
741         i= nu->pntsu*nu->pntsv;
742         ratcomp=0;
743         while(i--) {
744                 if(bp->vec[3]!=1.0) {
745                         ratcomp= 1;
746                         break;
747                 }
748                 bp++;
749         }
750
751         fp= nu->knotsu;
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");
757
758         fp= nu->knotsv;
759         vstart= fp[nu->orderv-1];
760         
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));
764         len= KNOTSV(nu);
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");
768
769         /* voorberekenen basisv en jstart,jend */
770         if(nu->flagv & 1) cycl= nu->orderv-1; 
771         else cycl= 0;
772         v= vstart;
773         basis= basisv;
774         while(resolv--) {
775                 basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+resolv, jend+resolv);
776                 basis+= KNOTSV(nu);
777                 v+= vstep;
778         }
779
780         if(nu->flagu & 1) cycl= nu->orderu-1; 
781         else cycl= 0;
782         in= data;
783         u= ustart;
784         while(resolu--) {
785
786                 basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
787
788                 basis= basisv;
789                 resolv= nu->resolv;
790                 while(resolv--) {
791
792                         jsta= jstart[resolv];
793                         jen= jend[resolv];
794
795                         /* bereken sum */
796                         sumdiv= 0.0;
797                         fp= sum;
798
799                         for(j= jsta; j<=jen; j++) {
800
801                                 if(j>=nu->pntsv) jofs= (j - nu->pntsv);
802                                 else jofs= j;
803                                 bp= nu->bp+ nu->pntsu*jofs+istart-1;
804
805                                 for(i= istart; i<=iend; i++, fp++) {
806
807                                         if(i>= nu->pntsu) {
808                                                 iofs= i- nu->pntsu;
809                                                 bp= nu->bp+ nu->pntsu*jofs+iofs;
810                                         }
811                                         else bp++;
812
813                                         if(ratcomp) {
814                                                 *fp= basisu[i]*basis[j]*bp->vec[3];
815                                                 sumdiv+= *fp;
816                                         }
817                                         else *fp= basisu[i]*basis[j];
818                                 }
819                         }
820                 
821                         if(ratcomp) {
822                                 fp= sum;
823                                 for(j= jsta; j<=jen; j++) {
824                                         for(i= istart; i<=iend; i++, fp++) {
825                                                 *fp/= sumdiv;
826                                         }
827                                 }
828                         }
829
830                         /* een! (1.0) echt punt nu */
831                         fp= sum;
832                         for(j= jsta; j<=jen; j++) {
833
834                                 if(j>=nu->pntsv) jofs= (j - nu->pntsv);
835                                 else jofs= j;
836                                 bp= nu->bp+ nu->pntsu*jofs+istart-1;
837
838                                 for(i= istart; i<=iend; i++, fp++) {
839
840                                         if(i>= nu->pntsu) {
841                                                 iofs= i- nu->pntsu;
842                                                 bp= nu->bp+ nu->pntsu*jofs+iofs;
843                                         }
844                                         else bp++;
845
846                                         if(*fp!=0.0) {
847                                                 in[0]+= (*fp) * bp->vec[0];
848                                                 in[1]+= (*fp) * bp->vec[1];
849                                                 in[2]+= (*fp) * bp->vec[2];
850                                         }
851                                 }
852                         }
853
854                         in+=3;
855                         basis+= KNOTSV(nu);
856                 }
857                 u+= ustep;
858         }
859
860         /* vrijgeven */
861         MEM_freeN(sum);
862         MEM_freeN(basisu);
863         MEM_freeN(basisv);
864         MEM_freeN(jstart);
865         MEM_freeN(jend);
866 }
867
868
869 void makeNurbcurve_forw(Nurb *nu, float *data)
870 /* *data: moet 3*4*pntsu*resolu lang zijn en op nul staan */
871 {
872         BPoint *bp;
873         float *basisu, *sum, *fp,  *in;
874         float u, ustart, uend, ustep, sumdiv;
875         int i, j, k, len, resolu, istart, iend;
876         int wanted, org;
877
878         if(nu->knotsu==0) return;
879         if(data==0) return;
880
881         /* alloceren en vars goedzetten */
882         len= nu->pntsu;
883         if(len==0) return;
884         sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1");
885
886         resolu= nu->resolu*nu->pntsu;
887         if(resolu==0) {
888                 MEM_freeN(sum);
889                 return;
890         }
891
892         fp= nu->knotsu;
893         ustart= fp[nu->orderu-1];
894         uend= fp[nu->pntsu];
895         ustep= (uend-ustart)/(resolu-1);
896         basisu= (float *)MEM_mallocN(sizeof(float)*(nu->orderu+nu->pntsu), "makeNurbcurve3");
897
898         in= data;
899         u= ustart;
900         for (k = nu->orderu - 1; k < nu->pntsu; k++){
901
902                 wanted = (int)((nu->knotsu[k+1] - nu->knotsu[k]) / ustep);
903                 org = 4;        /* gelijk aan order */
904                 if (org > wanted) org = wanted;
905
906                 for (j = org; j > 0; j--){
907
908                         basisNurb(u, nu->orderu, nu->pntsu, nu->knotsu, basisu, &istart, &iend);
909                         /* bereken sum */
910                         sumdiv= 0.0;
911                         fp= sum;
912                         for(i= istart; i<=iend; i++, fp++) {
913                                 /* hier nog rationele component doen */
914                                 *fp= basisu[i];
915                                 sumdiv+= *fp;
916                         }
917                         if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) {
918                                 /* is dit normaliseren ook nodig? */
919                                 fp= sum;
920                                 for(i= istart; i<=iend; i++, fp++) {
921                                         *fp/= sumdiv;
922                                 }
923                         }
924
925                         /* een! (1.0) echt punt nu */
926                         fp= sum;
927                         bp= nu->bp+ istart;
928                         for(i= istart; i<=iend; i++, bp++, fp++) {
929
930                                 if(*fp!=0.0) {
931                                         in[0]+= (*fp) * bp->vec[0];
932                                         in[1]+= (*fp) * bp->vec[1];
933                                         in[2]+= (*fp) * bp->vec[2];
934                                 }
935                         }
936
937                         in+=3;
938
939                         u+= ustep;
940                 }
941
942                 if (wanted > org){
943                         extend_spline(in - 3 * org, org, wanted);
944                         in += 3 * (wanted - org);
945                         u += ustep * (wanted - org);
946                 }
947         }
948
949         /* vrijgeven */
950         MEM_freeN(sum);
951         MEM_freeN(basisu);
952 }
953
954
955 void makeNurbcurve(Nurb *nu, float *data, int dim)
956 /* data moet dim*4*pntsu*resolu lang zijn en op nul staan */
957 {
958         BPoint *bp;
959         float u, ustart, uend, ustep, sumdiv;
960         float *basisu, *sum, *fp,  *in;
961         int i, len, resolu, istart, iend, cycl;
962
963         if(nu->knotsu==0) return;
964         if(nu->orderu>nu->pntsu) return;
965         if(data==0) return;
966
967         /* alloceren en vars goedzetten */
968         len= nu->pntsu;
969         if(len==0) return;
970         sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1");
971
972         resolu= nu->resolu*nu->pntsu;
973         if(resolu==0) {
974                 MEM_freeN(sum);
975                 return;
976         }
977
978         fp= nu->knotsu;
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");
984
985         if(nu->flagu & 1) cycl= nu->orderu-1; 
986         else cycl= 0;
987
988         in= data;
989         u= ustart;
990         while(resolu--) {
991
992                 basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
993                 /* bereken sum */
994                 sumdiv= 0.0;
995                 fp= sum;
996                 bp= nu->bp+ istart-1;
997                 for(i= istart; i<=iend; i++, fp++) {
998
999                         if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu);
1000                         else bp++;
1001
1002                         *fp= basisu[i]*bp->vec[3];
1003                         sumdiv+= *fp;
1004                 }
1005                 if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) {
1006                         /* is dit normaliseren ook nodig? */
1007                         fp= sum;
1008                         for(i= istart; i<=iend; i++, fp++) {
1009                                 *fp/= sumdiv;
1010                         }
1011                 }
1012
1013                 /* een! (1.0) echt punt nu */
1014                 fp= sum;
1015                 bp= nu->bp+ istart-1;
1016                 for(i= istart; i<=iend; i++, fp++) {
1017
1018                         if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu);
1019                         else bp++;
1020
1021                         if(*fp!=0.0) {
1022                                 
1023                                 in[0]+= (*fp) * bp->vec[0];
1024                                 in[1]+= (*fp) * bp->vec[1];
1025                                 if(dim>=3) {
1026                                         in[2]+= (*fp) * bp->vec[2];
1027                                         if(dim==4) in[3]+= (*fp) * bp->alfa;
1028                                 }
1029                         }
1030                 }
1031
1032                 in+= dim;
1033
1034                 u+= ustep;
1035         }
1036
1037         /* vrijgeven */
1038         MEM_freeN(sum);
1039         MEM_freeN(basisu);
1040 }
1041
1042 void maakbez(float q0, float q1, float q2, float q3, float *p, int it)
1043 {
1044         float rt0,rt1,rt2,rt3,f;
1045         int a;
1046
1047         f= (float)it;
1048         rt0= q0;
1049         rt1= 3.0f*(q1-q0)/f;
1050         f*= f;
1051         rt2= 3.0f*(q0-2.0f*q1+q2)/f;
1052         f*= it;
1053         rt3= (q3-q0+3.0f*(q1-q2))/f;
1054         
1055         q0= rt0;
1056         q1= rt1+rt2+rt3;
1057         q2= 2*rt2+6*rt3;
1058         q3= 6*rt3;
1059   
1060         for(a=0; a<=it; a++) {
1061                 *p= q0;
1062                 p+= 3;
1063                 q0+= q1;
1064                 q1+= q2;
1065                 q2+= q3;
1066         }
1067 }       
1068
1069 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1070
1071 void make_orco_surf(Curve *cu)
1072 {
1073         Nurb *nu;
1074         int a, b, tot=0;
1075         int sizeu, sizev;// ###
1076         float *data;
1077
1078
1079         /* eerst voorspellen hoelang datablok moet worden */
1080         nu= cu->nurb.first;
1081         while(nu) {
1082 #ifdef STRUBI
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.
1088
1089 See also blenderWorldManipulation.c: init_render_surf()
1090
1091 */
1092
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;
1097 #else
1098                 if(nu->pntsv>1) tot+= nu->resolu*nu->resolv;
1099 #endif
1100                 nu= nu->next;
1101         }
1102                                 /* makeNurbfaces wil nullen */
1103         data= cu->orco= MEM_callocN(3*sizeof(float)*tot, "make_orco");
1104
1105         nu= cu->nurb.first;
1106         while(nu) {
1107                 if(nu->pntsv>1) {
1108                         sizeu = nu->resolu;
1109                         sizev = nu->resolv;
1110 #ifdef STRUBI
1111                         if (nu->flagu & CU_CYCLIC) sizeu++;
1112                         if (nu->flagv & CU_CYCLIC) sizev++;
1113 #endif
1114                         
1115                         if(cu->flag & CU_UV_ORCO) {
1116                                 for(b=0; b< sizeu; b++) {
1117                                         for(a=0; a< sizev; a++) {
1118                                         
1119                                                 if(sizev <2) data[0]= 0.0f;
1120                                                 else data[0]= -1.0f + 2.0f*((float)a)/(sizev - 1);
1121                                                 
1122                                                 if(sizeu <2) data[1]= 0.0f;
1123                                                 else data[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1);
1124                                                 
1125                                                 data[2]= 0.0;
1126                 
1127                                                 data+= 3;
1128                                         }
1129                                 }
1130                         }
1131                         else {
1132                                 makeNurbfaces(nu, data);
1133 #ifdef STRUBI 
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];
1140                                         }
1141                                 }
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) {
1145                                         b = sizeu - 1;  
1146                                         for(a=0; a< sizev; a++) {
1147                                                 data = cu->orco + 3 * (b * sizev + a);
1148                                                 VECCOPY(data, cu->orco + 3*a);
1149                                         }
1150                                 }       
1151                                 if (nu->flagu & CU_CYCLIC) {
1152                                         a = sizev - 1;  
1153                                         for(b=0; b< sizeu; b++) {
1154                                                 data = cu->orco + 3 * (b * sizev + a);
1155                                                 VECCOPY(data, cu->orco + 3 * b*sizev);
1156                                         }
1157                                 }       
1158
1159 #else
1160                                 tot= sizeu * sizev;
1161                                 while(tot--) {
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];
1165         
1166                                         data+= 3;
1167                                 }
1168 #endif
1169                         }
1170                 }
1171                 nu= nu->next;
1172         }
1173         /* loadkeypostype(22, base, base); */
1174
1175 }
1176
1177
1178
1179 /* ***************** BEVEL ****************** */
1180
1181 void makebevelcurve(Object *ob, ListBase *disp)
1182 {
1183         DispList *dl, *dlnew;
1184         Curve *bevcu, *cu;
1185         float *fp, facx, facy, hoek, dhoek;
1186         int nr, a;
1187
1188         cu= ob->data;
1189
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];
1196
1197                                 dl= bevcu->disp.first;
1198                                 if(dl==0) {
1199                                         makeDispList(cu->bevobj);
1200                                         dl= bevcu->disp.first;
1201                                 }
1202                                 while(dl) {
1203                                         if ELEM(dl->type, DL_POLY, DL_SEGM) {
1204                                                 dlnew= MEM_mallocN(sizeof(DispList), "makebevelcurve1");                                        
1205                                                 *dlnew= *dl;
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);
1208                                                 
1209                                                 BLI_addtail(disp, dlnew);
1210                                                 fp= dlnew->verts;
1211                                                 nr= dlnew->parts*dlnew->nr;
1212                                                 while(nr--) {
1213                                                         fp[2]= fp[1]*facy;
1214                                                         fp[1]= -fp[0]*facx;
1215                                                         fp[0]= 0.0;
1216                                                         fp+= 3;
1217                                                 }
1218                                         }
1219                                         dl= dl->next;
1220                                 }
1221                         }
1222                 }
1223         }
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);
1228                 dl->type= DL_SEGM;
1229                 dl->parts= 1;
1230                 dl->nr= 2;
1231                 fp= dl->verts;
1232                 fp[0]= fp[1]= 0.0;
1233                 fp[2]= -cu->ext1;
1234                 fp[3]= fp[4]= 0.0;
1235                 fp[5]= cu->ext1;
1236         }
1237         else {
1238                 nr= 4+2*cu->bevresol;
1239
1240                 dl= MEM_callocN(sizeof(DispList), "makebevelcurve3");
1241                 dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve3");
1242                 BLI_addtail(disp, dl);
1243                 dl->type= DL_SEGM;
1244                 dl->parts= 1;
1245                 dl->nr= nr;
1246
1247                 /* eerst cirkel maken */
1248                 fp= dl->verts;
1249                 hoek= -0.5*M_PI;
1250                 dhoek= (float)(M_PI/(nr-2));
1251                 for(a=0; a<nr; a++) {
1252                         fp[0]= 0.0;
1253                         fp[1]= (float)(cos(hoek)*(cu->ext2));
1254                         fp[2]= (float)(sin(hoek)*(cu->ext2));
1255                         hoek+= dhoek;
1256                         fp+= 3;
1257                         if(cu->ext1!=0.0 && a==((nr/2)-1) ) {
1258                                 VECCOPY(fp, fp-3);
1259                                 fp+=3;
1260                                 a++;
1261                         }
1262                 }
1263                 if(cu->ext1==0.0) dl->nr--;
1264                 else {
1265                         fp= dl->verts;
1266                         for(a=0; a<nr; a++) {
1267                                 if(a<=(nr/2-1)) fp[2]-= (cu->ext1);
1268                                 else fp[2]+= (cu->ext1);
1269                                 fp+= 3;
1270                         }
1271                 }
1272         }
1273
1274 }
1275
1276 int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec)
1277 {
1278         /* return:
1279                 -1: colliniar
1280                  0: no intersection of segments
1281                  1: exact intersection of segments
1282                  2: cross-intersection of segments
1283         */
1284         float deler;
1285
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;
1288
1289         *labda= (v1[coy]-v3[coy])*(v3[cox]-v4[cox])-(v1[cox]-v3[cox])*(v3[coy]-v4[coy]);
1290         *labda= -(*labda/deler);
1291
1292         deler= v3[coy]-v4[coy];
1293         if(deler==0) {
1294                 deler=v3[cox]-v4[cox];
1295                 *mu= -(*labda*(v2[cox]-v1[cox])+v1[cox]-v3[cox])/deler;
1296         } else {
1297                 *mu= -(*labda*(v2[coy]-v1[coy])+v1[coy]-v3[coy])/deler;
1298         }
1299         vec[cox]= *labda*(v2[cox]-v1[cox])+v1[cox];
1300         vec[coy]= *labda*(v2[coy]-v1[coy])+v1[coy];
1301
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;
1304                 return 2;
1305         }
1306         return 0;
1307 }
1308
1309
1310 short bevelinside(BevList *bl1,BevList *bl2)
1311 {
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;
1317
1318         /* neem eerste vertex van het mogelijke gat */
1319
1320         bevp= (BevPoint *)(bl2+1);
1321         hvec1[0]= bevp->x; 
1322         hvec1[1]= bevp->y; 
1323         hvec1[2]= 0.0;
1324         VECCOPY(hvec2,hvec1);
1325         hvec2[0]+=1000;
1326
1327         /* test deze met alle edges van mogelijk omringende poly */
1328         /* tel aantal overgangen links en rechts */
1329
1330         bevp= (BevPoint *)(bl1+1);
1331         nr= bl1->nr;
1332         prevbevp= bevp+(nr-1);
1333
1334         while(nr--) {
1335                 min= prevbevp->y;
1336                 max= bevp->y;
1337                 if(max<min) {
1338                         min= max;
1339                         max= prevbevp->y;
1340                 }
1341                 if(min!=max) {
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)
1347                                  */
1348                                 if(mode>=0 && lab!=0.0) {
1349                                         if(vec[0]<hvec1[0]) links++;
1350                                         else rechts++;
1351                                 }
1352                         }
1353                 }
1354                 prevbevp= bevp;
1355                 bevp++;
1356         }
1357         
1358         if( (links & 1) && (rechts & 1) ) return 1;
1359         return 0;
1360 }
1361
1362
1363 struct bevelsort {
1364         float left;
1365         BevList *bl;
1366         int dir;
1367 };
1368
1369 int vergxcobev(const void *a1, const void *a2)
1370 {
1371         const struct bevelsort *x1=a1,*x2=a2;
1372
1373         if( x1->left > x2->left ) return 1;
1374         else if( x1->left < x2->left) return -1;
1375         return 0;
1376 }
1377
1378 /* deze kan niet zomaar door atan2 vervangen worden, maar waarom? */
1379
1380 void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *sina, float *cosa)
1381 {
1382         float t01, t02, x3, y3;
1383
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;
1388
1389         x1/=t01; 
1390         y1/=t01;
1391         x2/=t02; 
1392         y2/=t02;
1393
1394         t02= x1*x2+y1*y2;
1395         if(fabs(t02)>=1.0) t02= .5*M_PI;
1396         else t02= (saacos(t02))/2.0f;
1397
1398         t02= (float)sin(t02);
1399         if(t02==0.0) t02= 1.0;
1400
1401         x3= x1-x2;
1402         y3= y1-y2;
1403         if(x3==0 && y3==0) {
1404                 /* printf("x3 en y3  nul \n"); */
1405                 x3= y1;
1406                 y3= -x1;
1407         } else {
1408                 t01= (float)sqrt(x3*x3+y3*y3);
1409                 x3/=t01; 
1410                 y3/=t01;
1411         }
1412
1413         *sina= -y3/t02;
1414         *cosa= x3/t02;
1415
1416 }
1417
1418 void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *data_a)
1419 {
1420         BezTriple *pprev, *next, *last;
1421         float fac, dfac, t[4];
1422         int a;
1423         
1424         last= nu->bezt+(nu->pntsu-1);
1425         
1426         /* een punt terug */
1427         if(prevbezt==nu->bezt) {
1428                 if(nu->flagu & 1) pprev= last;
1429                 else pprev= prevbezt;
1430         }
1431         else pprev= prevbezt-1;
1432         
1433         /* een punt verder */
1434         if(bezt==last) {
1435                 if(nu->flagu & 1) next= nu->bezt;
1436                 else next= bezt;
1437         }
1438         else next= bezt+1;
1439         
1440         fac= 0.0;
1441         dfac= 1.0f/(float)nu->resolu;
1442         
1443         for(a=0; a<nu->resolu; a++, fac+= dfac) {
1444                 
1445                 set_four_ipo(fac, t, KEY_BSPLINE);
1446                 
1447                 data_a[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa;
1448         }
1449 }
1450
1451 void makeBevelList(Object *ob)
1452 {
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 */
1457         Curve *cu;
1458         Nurb *nu;
1459         BezTriple *bezt, *prevbezt;
1460         BPoint *bp;
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;
1466
1467         /* deze fie moet object hebben in verband met tflag en upflag */
1468         cu= ob->data;
1469
1470         /* STAP 1: POLY'S MAKEN */
1471
1472         BLI_freelistN(&(cu->bev));
1473         if(ob==G.obedit) nu= editNurb.first;
1474         else nu= cu->nurb.first;
1475         
1476         while(nu) {
1477                 if(nu->pntsu>1) {
1478                 
1479                         if((nu->type & 7)==CU_POLY) {
1480         
1481                                 len= nu->pntsu;
1482                                 bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList");
1483                                 BLI_addtail(&(cu->bev), bl);
1484         
1485                                 if(nu->flagu & 1) bl->poly= 0;
1486                                 else bl->poly= -1;
1487                                 bl->nr= len;
1488                                 bl->flag= 0;
1489                                 bevp= (BevPoint *)(bl+1);
1490                                 bp= nu->bp;
1491         
1492                                 while(len--) {
1493                                         bevp->x= bp->vec[0];
1494                                         bevp->y= bp->vec[1];
1495                                         bevp->z= bp->vec[2];
1496                                         bevp->alfa= bp->alfa;
1497                                         bevp->f1= 1;
1498                                         bevp++;
1499                                         bp++;
1500                                 }
1501                         }
1502                         else if((nu->type & 7)==CU_BEZIER) {
1503         
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);
1507         
1508                                 if(nu->flagu & 1) bl->poly= 0;
1509                                 else bl->poly= -1;
1510                                 bevp= (BevPoint *)(bl+1);
1511         
1512                                 a= nu->pntsu-1;
1513                                 bezt= nu->bezt;
1514                                 if(nu->flagu & 1) {
1515                                         a++;
1516                                         prevbezt= nu->bezt+(nu->pntsu-1);
1517                                 }
1518                                 else {
1519                                         prevbezt= bezt;
1520                                         bezt++;
1521                                 }
1522                                 
1523                                 data= MEM_mallocN(3*sizeof(float)*(nu->resolu+1), "makeBevelList2");
1524                                 data_a= MEM_callocN(sizeof(float)*(nu->resolu+1), "data_a");
1525                                 
1526                                 while(a--) {
1527                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
1528         
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;
1533                                                 bevp->f1= 1;
1534                                                 bevp->f2= 0;
1535                                                 bevp++;
1536                                                 bl->nr++;
1537                                                 bl->flag= 1;
1538                                         }
1539                                         else {
1540                                                 v1= prevbezt->vec[1];
1541                                                 v2= bezt->vec[0];
1542                                                 
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);
1547                                                 
1548                                                 if((nu->type & CU_2D)==0) {
1549                                                         if(cu->flag & CU_3D) {
1550                                                                 alfa_bezpart(prevbezt, bezt, nu, data_a);
1551                                                         }
1552                                                 }
1553                                                 
1554                                                 
1555                                                 /* met handlecodes dubbele punten aangeven */
1556                                                 if(prevbezt->h1==prevbezt->h2) {
1557                                                         if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1;
1558                                                 }
1559                                                 else {
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;
1562                                                 }
1563                                                 
1564                                                 v1= data;
1565                                                 v2= data_a;
1566                                                 nr= nu->resolu;
1567                                                 
1568                                                 while(nr--) {
1569                                                         bevp->x= v1[0]; 
1570                                                         bevp->y= v1[1];
1571                                                         bevp->z= v1[2];
1572                                                         bevp->alfa= v2[0];
1573                                                         bevp++;
1574                                                         v1+=3;
1575                                                         v2++;
1576                                                 }
1577                                                 bl->nr+= nu->resolu;
1578         
1579                                         }
1580                                         prevbezt= bezt;
1581                                         bezt++;
1582                                 }
1583                                 
1584                                 MEM_freeN(data);
1585                                 MEM_freeN(data_a);
1586                                 
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];
1591                                         bl->nr++;
1592                                 }
1593         
1594                         }
1595                         else if((nu->type & 7)==CU_NURBS) {
1596                                 if(nu->pntsv==1) {
1597                                         len= nu->resolu*nu->pntsu;
1598                                         bl= MEM_mallocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3");
1599                                         BLI_addtail(&(cu->bev), bl);
1600                                         bl->nr= len;
1601                                         bl->flag= 0;
1602                                         if(nu->flagu & 1) bl->poly= 0;
1603                                         else bl->poly= -1;
1604                                         bevp= (BevPoint *)(bl+1);
1605         
1606                                         data= MEM_callocN(4*sizeof(float)*len, "makeBevelList4");    /* moet op nul staan */
1607                                         makeNurbcurve(nu, data, 4);
1608                                         
1609                                         v1= data;
1610                                         while(len--) {
1611                                                 bevp->x= v1[0]; 
1612                                                 bevp->y= v1[1];
1613                                                 bevp->z= v1[2];
1614                                                 bevp->alfa= v1[3];
1615                                                 
1616                                                 bevp->f1= bevp->f2= 0;
1617                                                 bevp++;
1618                                                 v1+=4;
1619                                         }
1620                                         MEM_freeN(data);
1621                                 }
1622                         }
1623                 }
1624                 nu= nu->next;
1625         }
1626
1627         /* STAP 2: DUBBELE PUNTEN EN AUTOMATISCHE RESOLUTIE, DATABLOKKEN VERKLEINEN */
1628         bl= cu->bev.first;
1629         while(bl) {
1630                 nr= bl->nr;
1631                 bevp1= (BevPoint *)(bl+1);
1632                 bevp0= bevp1+(nr-1);
1633                 nr--;
1634                 while(nr--) {
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 ) {
1638                                                 bevp0->f2= 1;
1639                                                 bl->flag++;
1640                                         }
1641                                 }
1642                         }
1643                         bevp0= bevp1;
1644                         bevp1++;
1645                 }
1646                 bl= bl->next;
1647         }
1648         bl= cu->bev.first;
1649         while(bl) {
1650                 blnext= bl->next;
1651                 if(bl->flag) {
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));
1655                         blnew->nr= 0;
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);
1660                         nr= bl->nr;
1661                         while(nr--) {
1662                                 if(bevp0->f2==0) {
1663                                         memcpy(bevp1, bevp0, sizeof(BevPoint));
1664                                         bevp1++;
1665                                         blnew->nr++;
1666                                 }
1667                                 bevp0++;
1668                         }
1669                         MEM_freeN(bl);
1670                         blnew->flag= 0;
1671                 }
1672                 bl= blnext;
1673         }
1674
1675         /* STAP 3: POLY'S TELLEN EN AUTOGAT */
1676         bl= cu->bev.first;
1677         poly= 0;
1678         while(bl) {
1679                 if(bl->poly>=0) {
1680                         poly++;
1681                         bl->poly= poly;
1682                         bl->gat= 0;
1683                 }
1684                 bl= bl->next;
1685         }
1686         
1687
1688         /* meest linkse punten vinden, tevens richting testen */
1689         if(poly>0) {
1690                 sd= sortdata= MEM_mallocN(sizeof(struct bevelsort)*poly, "makeBevelList5");
1691                 bl= cu->bev.first;
1692                 while(bl) {
1693                         if(bl->poly>0) {
1694
1695                                 min= 300000.0;
1696                                 bevp= (BevPoint *)(bl+1);
1697                                 nr= bl->nr;
1698                                 while(nr--) {
1699                                         if(min>bevp->x) {
1700                                                 min= bevp->x;
1701                                                 bevp1= bevp;
1702                                         }
1703                                         bevp++;
1704                                 }
1705                                 sd->bl= bl;
1706                                 sd->left= min;
1707
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;
1714
1715                                 inp= (bevp1->x- bevp0->x)*(bevp0->y- bevp2->y)
1716                                     +(bevp0->y- bevp1->y)*(bevp0->x- bevp2->x);
1717
1718                                 if(inp>0.0) sd->dir= 1;
1719                                 else sd->dir= 0;
1720
1721                                 sd++;
1722                         }
1723
1724                         bl= bl->next;
1725                 }
1726                 qsort(sortdata,poly,sizeof(struct bevelsort), vergxcobev);
1727
1728                 sd= sortdata+1;
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;
1735                                         break;
1736                                 }
1737                         }
1738                 }
1739
1740                 /* draairichting */
1741                 if((cu->flag & CU_3D)==0) {
1742                         sd= sortdata;
1743                         for(a=0; a<poly; a++, sd++) {
1744                                 if(sd->bl->gat==sd->dir) {
1745                                         bl= sd->bl;
1746                                         bevp1= (BevPoint *)(bl+1);
1747                                         bevp2= bevp1+ (bl->nr-1);
1748                                         nr= bl->nr/2;
1749                                         while(nr--) {
1750                                                 SWAP(BevPoint, *bevp1, *bevp2);
1751                                                 bevp1++;
1752                                                 bevp2--;
1753                                         }
1754                                 }
1755                         }
1756                 }
1757                 MEM_freeN(sortdata);
1758         }
1759
1760         /* STAP 4: COSINUSSEN */
1761         bl= cu->bev.first;
1762         while(bl) {
1763         
1764                 if(bl->nr==2) { /* 2 pnt, apart afhandelen: KAN DAT NIET AFGESCHAFT? */
1765                         bevp2= (BevPoint *)(bl+1);
1766                         bevp1= bevp2+1;
1767
1768                         x1= bevp1->x- bevp2->x;
1769                         y1= bevp1->y- bevp2->y;
1770
1771                         calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
1772                         bevp2->sina= bevp1->sina;
1773                         bevp2->cosa= bevp1->cosa;
1774
1775                         if(cu->flag & CU_3D) {  /* 3D */
1776                                 float *quat, q[4];
1777                         
1778                                 vec[0]= bevp1->x - bevp2->x;
1779                                 vec[1]= bevp1->y - bevp2->y;
1780                                 vec[2]= bevp1->z - bevp2->z;
1781                                 
1782                                 quat= vectoquat(vec, 5, 1);
1783                                 
1784                                 Normalise(vec);
1785                                 q[0]= (float)cos(0.5*bevp1->alfa);
1786                                 x1= (float)sin(0.5*bevp1->alfa);
1787                                 q[1]= x1*vec[0];
1788                                 q[2]= x1*vec[1];
1789                                 q[3]= x1*vec[2];
1790                                 QuatMul(quat, q, quat);
1791                                 
1792                                 QuatToMat3(quat, bevp1->mat);
1793                                 Mat3CpyMat3(bevp2->mat, bevp1->mat);
1794                         }
1795
1796                 }
1797                 else if(bl->nr>2) {
1798                         bevp2= (BevPoint *)(bl+1);
1799                         bevp1= bevp2+(bl->nr-1);
1800                         bevp0= bevp1-1;
1801
1802                 
1803                         nr= bl->nr;
1804         
1805                         while(nr--) {
1806         
1807                                 if(cu->flag & CU_3D) {  /* 3D */
1808                                         float *quat, q[4];
1809                                 
1810                                         vec[0]= bevp2->x - bevp0->x;
1811                                         vec[1]= bevp2->y - bevp0->y;
1812                                         vec[2]= bevp2->z - bevp0->z;
1813                                         
1814                                         Normalise(vec);
1815
1816                                         quat= vectoquat(vec, 5, 1);
1817                                         
1818                                         q[0]= (float)cos(0.5*bevp1->alfa);
1819                                         x1= (float)sin(0.5*bevp1->alfa);
1820                                         q[1]= x1*vec[0];
1821                                         q[2]= x1*vec[1];
1822                                         q[3]= x1*vec[2];
1823                                         QuatMul(quat, q, quat);
1824                                         
1825                                         QuatToMat3(quat, bevp1->mat);
1826                                 }
1827                                 
1828                                 x1= bevp1->x- bevp0->x;
1829                                 x2= bevp1->x- bevp2->x;
1830                                 y1= bevp1->y- bevp0->y;
1831                                 y2= bevp1->y- bevp2->y;
1832                         
1833                                 calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
1834                                 
1835                                 
1836                                 bevp0= bevp1;
1837                                 bevp1= bevp2;
1838                                 bevp2++;
1839                         }
1840                         /* niet cyclic gevallen corrigeren */
1841                         if(bl->poly== -1) {
1842                                 if(bl->nr>2) {
1843                                         bevp= (BevPoint *)(bl+1);
1844                                         bevp1= bevp+1;
1845                                         bevp->sina= bevp1->sina;
1846                                         bevp->cosa= bevp1->cosa;
1847                                         Mat3CpyMat3(bevp->mat, bevp1->mat);
1848                                         bevp= (BevPoint *)(bl+1);
1849                                         bevp+= (bl->nr-1);
1850                                         bevp1= bevp-1;
1851                                         bevp->sina= bevp1->sina;
1852                                         bevp->cosa= bevp1->cosa;
1853                                         Mat3CpyMat3(bevp->mat, bevp1->mat);
1854                                 }
1855                         }
1856                 }
1857                 bl= bl->next;
1858         }
1859 }
1860
1861 /* ****************** HANDLES ************** */
1862
1863 /*
1864  *   handlecodes:
1865  *              1: niets,  1:auto,  2:vector,  3:aligned
1866  */
1867
1868
1869 void calchandleNurb(BezTriple *bezt,BezTriple *prev, BezTriple *next, int mode)
1870 {
1871         float *p1,*p2,*p3,pt[3];
1872         float dx1,dy1,dz1,dx,dy,dz,vx,vy,vz,len,len1,len2;
1873
1874         if(bezt->h1==0 && bezt->h2==0) return;
1875
1876         p2= bezt->vec[1];
1877
1878         if(prev==0) {
1879                 p3= next->vec[1];
1880                 pt[0]= 2*p2[0]- p3[0];
1881                 pt[1]= 2*p2[1]- p3[1];
1882                 pt[2]= 2*p2[2]- p3[2];
1883                 p1= pt;
1884         }
1885         else p1= prev->vec[1];
1886
1887         if(next==0) {
1888                 pt[0]= 2*p2[0]- p1[0];
1889                 pt[1]= 2*p2[1]- p1[1];
1890                 pt[2]= 2*p2[2]- p1[2];
1891                 p3= pt;
1892         }
1893         else p3= next->vec[1];
1894
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;
1899         }
1900         else {
1901                 dx= p2[0]- p1[0];
1902                 dy= p2[1]- p1[1];
1903                 dz= p2[2]- p1[2];
1904         }
1905         len1= (float)sqrt(dx*dx+dy*dy+dz*dz);
1906         
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];
1911         }
1912         else {
1913                 dx1= p3[0]- p2[0];
1914                 dy1= p3[1]- p2[1];
1915                 dz1= p3[2]- p2[2];
1916         }
1917         len2= (float)sqrt(dx1*dx1+dy1*dy1+dz1*dz1);
1918
1919         if(len1==0.0f) len1=1.0f;
1920         if(len2==0.0f) len2=1.0f;
1921
1922
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);
1928                 if(len!=0.0f) {
1929                 
1930                         if(len1>5.0f*len2) len1= 5.0f*len2;     
1931                         if(len2>5.0f*len1) len2= 5.0f*len1;
1932                         
1933                         if(bezt->h1==HD_AUTO) {
1934                                 len1/=len;
1935                                 *(p2-3)= *p2-vx*len1;
1936                                 *(p2-2)= *(p2+1)-vy*len1;
1937                                 *(p2-1)= *(p2+2)-vz*len1;
1938                         }
1939                         if(bezt->h2==HD_AUTO) {
1940                                 len2/=len;
1941                                 *(p2+3)= *p2+vx*len2;
1942                                 *(p2+4)= *(p2+1)+vy*len2;
1943                                 *(p2+5)= *(p2+2)+vz*len2;
1944                         }
1945                 }
1946         }
1947
1948         if(bezt->h1==HD_VECT) { /* vector */
1949                 dx/=3.0; 
1950                 dy/=3.0; 
1951                 dz/=3.0;
1952                 *(p2-3)= *p2-dx;
1953                 *(p2-2)= *(p2+1)-dy;
1954                 *(p2-1)= *(p2+2)-dz;
1955         }
1956         if(bezt->h2==HD_VECT) {
1957                 dx1/=3.0; 
1958                 dy1/=3.0; 
1959                 dz1/=3.0;
1960                 *(p2+3)= *p2+dx1;
1961                 *(p2+4)= *(p2+1)+dy1;
1962                 *(p2+5)= *(p2+2)+dz1;
1963         }
1964
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 */
1971                         len= len2/len1;
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]);
1975                 }
1976                 if(bezt->h1==HD_ALIGN) {
1977                         len= len1/len2;
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]);
1981                 }
1982         }
1983         else {
1984                 if(bezt->h1==HD_ALIGN) {
1985                         len= len1/len2;
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]);
1989                 }
1990                 if(bezt->h2==HD_ALIGN) {        /* aligned */
1991                         len= len2/len1;
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]);
1995                 }
1996         }
1997 }
1998
1999 void calchandlesNurb(Nurb *nu) /* wel eerst (zonodig) de handlevlaggen zetten */
2000 {
2001         BezTriple *bezt, *prev, *next;
2002         short a;
2003
2004         if((nu->type & 7)!=1) return;
2005         if(nu->pntsu<2) return;
2006         
2007         a= nu->pntsu;
2008         bezt= nu->bezt;
2009         if(nu->flagu & 1) prev= bezt+(a-1);
2010         else prev= 0;
2011         next= bezt+1;
2012
2013         while(a--) {
2014                 calchandleNurb(bezt, prev, next, 0);
2015                 prev= bezt;
2016                 if(a==1) {
2017                         if(nu->flagu & 1) next= nu->bezt;
2018                         else next= 0;
2019                 }
2020                 else next++;
2021
2022                 bezt++;
2023         }
2024 }
2025
2026
2027 void testhandlesNurb(Nurb *nu)
2028 {
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
2035      */
2036         BezTriple *bezt;
2037         short flag, a;
2038
2039         if((nu->type & 7)!=CU_BEZIER) return;
2040
2041         bezt= nu->bezt;
2042         a= nu->pntsu;
2043         while(a--) {
2044                 flag= 0;
2045                 if(bezt->f1 & 1) flag++;
2046                 if(bezt->f2 & 1) flag += 2;
2047                 if(bezt->f3 & 1) flag += 4;
2048
2049                 if( !(flag==0 || flag==7) ) {
2050                         if(bezt->h1==HD_AUTO) {   /* auto */
2051                                 bezt->h1= HD_ALIGN;
2052                         }
2053                         if(bezt->h2==HD_AUTO) {   /* auto */
2054                                 bezt->h2= HD_ALIGN;
2055                         }
2056
2057                         if(bezt->h1==HD_VECT) {   /* vector */
2058                                 if(flag < 4) bezt->h1= 0;
2059                         }
2060                         if(bezt->h2==HD_VECT) {   /* vector */
2061                                 if( flag > 3) bezt->h2= 0;
2062                         }
2063                 }
2064                 bezt++;
2065         }
2066
2067         calchandlesNurb(nu);
2068 }
2069
2070 void autocalchandlesNurb(Nurb *nu, int flag)
2071 {
2072         /* Kijkt naar de coordinaten van de handles en berekent de soort */
2073         
2074         BezTriple *bezt2, *bezt1, *bezt0;
2075         int i, align, leftsmall, rightsmall;
2076
2077         if(nu==0 || nu->bezt==0) return;
2078         
2079         bezt2 = nu->bezt;
2080         bezt1 = bezt2 + (nu->pntsu-1);
2081         bezt0 = bezt1 - 1;
2082         i = nu->pntsu;
2083
2084         while(i--) {
2085                 
2086                 align= leftsmall= rightsmall= 0;
2087                 
2088                 /* linker handle: */
2089                 if(flag==0 || (bezt1->f1 & flag) ) {
2090                         bezt1->h1= 0;
2091                         /* afstand te klein: vectorhandle */
2092                         if( VecLenf( bezt1->vec[1], bezt0->vec[1] ) < 0.0001) {
2093                                 bezt1->h1= HD_VECT;
2094                                 leftsmall= 1;
2095                         }
2096                         else {
2097                                 /* aligned handle? */
2098                                 if(DistVL2Dfl(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001) {
2099                                         align= 1;
2100                                         bezt1->h1= HD_ALIGN;
2101                                 }
2102                                 /* of toch vector handle? */
2103                                 if(DistVL2Dfl(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001)
2104                                         bezt1->h1= HD_VECT;
2105                                 
2106                         }
2107                 }
2108                 /* rechter handle: */
2109                 if(flag==0 || (bezt1->f3 & flag) ) {
2110                         bezt1->h2= 0;
2111                         /* afstand te klein: vectorhandle */
2112                         if( VecLenf( bezt1->vec[1], bezt2->vec[1] ) < 0.0001) {
2113                                 bezt1->h2= HD_VECT;
2114                                 rightsmall= 1;
2115                         }
2116                         else {
2117                                 /* aligned handle? */
2118                                 if(align) bezt1->h2= HD_ALIGN;
2119
2120                                 /* of toch vector handle? */
2121                                 if(DistVL2Dfl(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001)
2122                                         bezt1->h2= HD_VECT;
2123                                 
2124                         }
2125                 }
2126                 if(leftsmall && bezt1->h2==HD_ALIGN) bezt1->h2= 0;
2127                 if(rightsmall && bezt1->h1==HD_ALIGN) bezt1->h1= 0;
2128                 
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;
2132                 
2133                 bezt0= bezt1;
2134                 bezt1= bezt2;
2135                 bezt2++;
2136         }
2137
2138         calchandlesNurb(nu);
2139 }
2140
2141 void autocalchandlesNurb_all(int flag)
2142 {
2143         Nurb *nu;
2144         
2145         nu= editNurb.first;
2146         while(nu) {
2147                 autocalchandlesNurb(nu, flag);
2148                 nu= nu->next;
2149         }
2150 }
2151
2152 void sethandlesNurb(short code)
2153 {
2154         /* code==1: set autohandle */
2155         /* code==2: set vectorhandle */
2156         /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
2157         Nurb *nu;
2158         BezTriple *bezt;
2159         short a, ok=0;
2160
2161         if(code==1 || code==2) {
2162                 nu= editNurb.first;
2163                 while(nu) {
2164                         if( (nu->type & 7)==1) {
2165                                 bezt= nu->bezt;
2166                                 a= nu->pntsu;
2167                                 while(a--) {
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;
2174                                                 }
2175                                         }
2176                                         bezt++;
2177                                 }
2178                                 calchandlesNurb(nu);
2179                         }
2180                         nu= nu->next;
2181                 }
2182         }
2183         else {
2184                 /* is er 1 handle NIET vrij: alles vrijmaken, else ALIGNED maken */
2185                 
2186                 nu= editNurb.first;
2187                 while(nu) {
2188                         if( (nu->type & 7)==1) {
2189                                 bezt= nu->bezt;
2190                                 a= nu->pntsu;
2191                                 while(a--) {
2192                                         if(bezt->f1 && bezt->h1) ok= 1;
2193                                         if(bezt->f3 && bezt->h2) ok= 1;
2194                                         if(ok) break;
2195                                         bezt++;
2196                                 }
2197                         }
2198                         nu= nu->next;
2199                 }
2200                 if(ok) ok= HD_FREE;
2201                 else ok= HD_ALIGN;
2202                 
2203                 nu= editNurb.first;
2204                 while(nu) {
2205                         if( (nu->type & 7)==1) {
2206                                 bezt= nu->bezt;
2207                                 a= nu->pntsu;
2208                                 while(a--) {
2209                                         if(bezt->f1) bezt->h1= ok;
2210                                         if(bezt->f3 ) bezt->h2= ok;
2211         
2212                                         bezt++;
2213                                 }
2214                                 calchandlesNurb(nu);
2215                         }
2216                         nu= nu->next;
2217                 }
2218         }
2219 }
2220
2221 void swapdata(void *adr1, void *adr2, int len)
2222 {
2223
2224         if(len<=0) return;
2225
2226         if(len<65) {
2227                 char adr[64];
2228
2229                 memcpy(adr, adr1, len);
2230                 memcpy(adr1, adr2, len);
2231                 memcpy(adr2, adr, len);
2232         }
2233         else {
2234                 char *adr;
2235
2236                 adr= (char *)malloc(len);
2237                 memcpy(adr, adr1, len);
2238                 memcpy(adr1, adr2, len);
2239                 memcpy(adr2, adr, len);
2240                 free(adr);
2241         }
2242 }
2243
2244 void switchdirectionNurb(Nurb *nu)
2245 {
2246         BezTriple *bezt1, *bezt2;
2247         BPoint *bp1, *bp2;
2248         float *fp1, *fp2, *tempf;
2249         int a, b;
2250
2251         if(nu->pntsu==1 && nu->pntsv==1) return;
2252
2253         if((nu->type & 7)==CU_BEZIER) {
2254                 a= nu->pntsu;
2255                 bezt1= nu->bezt;
2256                 bezt2= bezt1+(a-1);
2257                 if(a & 1) a+= 1;        /* bij oneven ook van middelste inhoud swappen */
2258                 a/= 2;
2259                 while(a>0) {
2260                         if(bezt1!=bezt2) SWAP(BezTriple, *bezt1, *bezt2);
2261
2262                         swapdata(bezt1->vec[0], bezt1->vec[2], 12);
2263                         if(bezt1!=bezt2) swapdata(bezt2->vec[0], bezt2->vec[2], 12);
2264
2265                         SWAP(char, bezt1->h1, bezt1->h2);
2266                         SWAP(short, bezt1->f1, bezt1->f3);
2267                         
2268                         if(bezt1!=bezt2) {
2269                                 SWAP(char, bezt2->h1, bezt2->h2);
2270                                 SWAP(short, bezt2->f1, bezt2->f3);
2271                                 bezt1->alfa= -bezt1->alfa;
2272                                 bezt2->alfa= -bezt2->alfa;
2273                         }
2274                         a--;
2275                         bezt1++; 
2276                         bezt2--;
2277                 }
2278         }
2279         else if(nu->pntsv==1) {
2280                 a= nu->pntsu;
2281                 bp1= nu->bp;
2282                 bp2= bp1+(a-1);
2283                 a/= 2;
2284                 while(bp1!=bp2 && a>0) {
2285                         SWAP(BPoint, *bp1, *bp2);
2286                         a--;
2287                         bp1->alfa= -bp1->alfa;
2288                         bp2->alfa= -bp2->alfa;
2289                         bp1++; 
2290                         bp2--;
2291                 }
2292                 if((nu->type & 7)==CU_NURBS) {
2293                         /* de knots omkeren */
2294                         a= KNOTSU(nu);
2295                         fp1= nu->knotsu;
2296                         fp2= fp1+(a-1);
2297                         a/= 2;
2298                         while(fp1!=fp2 && a>0) {
2299                                 SWAP(float, *fp1, *fp2);
2300                                 a--;
2301                                 fp1++; 
2302                                 fp2--;
2303                         }
2304                         /* en weer in stijgende lijn maken */
2305                         a= KNOTSU(nu);
2306                         fp1= nu->knotsu;
2307                         fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
2308                         while(a--) {
2309                                 fp2[0]= fabs(fp1[1]-fp1[0]);
2310                                 fp1++;
2311                                 fp2++;
2312                         }
2313         
2314                         a= KNOTSU(nu)-1;
2315                         fp1= nu->knotsu;
2316                         fp2= tempf;
2317                         fp1[0]= 0.0;
2318                         fp1++;
2319                         while(a--) {
2320                                 fp1[0]= fp1[-1]+fp2[0];
2321                                 fp1++;
2322                                 fp2++;
2323                         }
2324                         MEM_freeN(tempf);
2325                 }
2326         }
2327         else {
2328                 
2329                 for(b=0; b<nu->pntsv; b++) {
2330                 
2331                         bp1= nu->bp+b*nu->pntsu;
2332                         a= nu->pntsu;
2333                         bp2= bp1+(a-1);
2334                         a/= 2;
2335                         
2336                         while(bp1!=bp2 && a>0) {
2337                                 SWAP(BPoint, *bp1, *bp2);
2338                                 a--;
2339                                 bp1++; 
2340                                 bp2--;
2341                         }
2342                 }
2343         }
2344 }