Curve cleanup
[blender.git] / source / blender / blenkernel / intern / displist.c
1 /*  displist.c
2  * 
3  * 
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 #include <math.h>
33 #include <stdio.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "IMB_imbuf_types.h"
39
40 #include "DNA_texture_types.h"
41 #include "DNA_meta_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_effect_types.h"
44 #include "DNA_listBase.h"
45 #include "DNA_lamp_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_object_force.h"
48 #include "DNA_mesh_types.h"
49 #include "DNA_meshdata_types.h"
50 #include "DNA_modifier_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_image_types.h"
53 #include "DNA_material_types.h"
54 #include "DNA_view3d_types.h"
55 #include "DNA_lattice_types.h"
56 #include "DNA_key_types.h"
57
58 #include "BLI_blenlib.h"
59 #include "BLI_arithb.h"
60 #include "BLI_editVert.h"
61 #include "BLI_edgehash.h"
62
63 #include "BKE_bad_level_calls.h"
64 #include "BKE_utildefines.h"
65 #include "BKE_global.h"
66 #include "BKE_displist.h"
67 #include "BKE_deform.h"
68 #include "BKE_DerivedMesh.h"
69 #include "BKE_object.h"
70 #include "BKE_world.h"
71 #include "BKE_mesh.h"
72 #include "BKE_effect.h"
73 #include "BKE_mball.h"
74 #include "BKE_material.h"
75 #include "BKE_curve.h"
76 #include "BKE_key.h"
77 #include "BKE_anim.h"
78 #include "BKE_screen.h"
79 #include "BKE_texture.h"
80 #include "BKE_library.h"
81 #include "BKE_font.h"
82 #include "BKE_lattice.h"
83 #include "BKE_scene.h"
84 #include "BKE_subsurf.h"
85 #include "BKE_modifier.h"
86 #include "BKE_customdata.h"
87
88 #include "RE_pipeline.h"
89 #include "RE_shader_ext.h"
90
91 #include "BLO_sys_types.h" // for intptr_t support
92
93
94 static void boundbox_displist(Object *ob);
95
96 void free_disp_elem(DispList *dl)
97 {
98         if(dl) {
99                 if(dl->verts) MEM_freeN(dl->verts);
100                 if(dl->nors) MEM_freeN(dl->nors);
101                 if(dl->index) MEM_freeN(dl->index);
102                 if(dl->col1) MEM_freeN(dl->col1);
103                 if(dl->col2) MEM_freeN(dl->col2);
104                 if(dl->bevelSplitFlag) MEM_freeN(dl->bevelSplitFlag);
105                 MEM_freeN(dl);
106         }
107 }
108
109 void freedisplist(ListBase *lb)
110 {
111         DispList *dl;
112
113         dl= lb->first;
114         while(dl) {
115                 BLI_remlink(lb, dl);
116                 free_disp_elem(dl);
117                 dl= lb->first;
118         }
119 }
120
121 DispList *find_displist_create(ListBase *lb, int type)
122 {
123         DispList *dl;
124         
125         dl= lb->first;
126         while(dl) {
127                 if(dl->type==type) return dl;
128                 dl= dl->next;
129         }
130
131         dl= MEM_callocN(sizeof(DispList), "find_disp");
132         dl->type= type;
133         BLI_addtail(lb, dl);
134
135         return dl;
136 }
137
138 DispList *find_displist(ListBase *lb, int type)
139 {
140         DispList *dl;
141         
142         dl= lb->first;
143         while(dl) {
144                 if(dl->type==type) return dl;
145                 dl= dl->next;
146         }
147
148         return 0;
149 }
150
151 int displist_has_faces(ListBase *lb)
152 {
153         DispList *dl;
154         for(dl= lb->first; dl; dl= dl->next) {
155                 if ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)
156                         return 1;
157         }
158         return 0;
159 }
160
161 void copy_displist(ListBase *lbn, ListBase *lb)
162 {
163         DispList *dln, *dl;
164         
165         lbn->first= lbn->last= 0;
166         
167         dl= lb->first;
168         while(dl) {
169                 
170                 dln= MEM_dupallocN(dl);
171                 BLI_addtail(lbn, dln);
172                 dln->verts= MEM_dupallocN(dl->verts);
173                 dln->nors= MEM_dupallocN(dl->nors);
174                 dln->index= MEM_dupallocN(dl->index);
175                 dln->col1= MEM_dupallocN(dl->col1);
176                 dln->col2= MEM_dupallocN(dl->col2);
177                 
178                 dl= dl->next;
179         }
180 }
181
182 void addnormalsDispList(Object *ob, ListBase *lb)
183 {
184         DispList *dl = NULL;
185         float *vdata, *ndata, nor[3];
186         float *v1, *v2, *v3, *v4;
187         float *n1, *n2, *n3, *n4;
188         int a, b, p1, p2, p3, p4;
189
190
191         dl= lb->first;
192         
193         while(dl) {
194                 if(dl->type==DL_INDEX3) {
195                         if(dl->nors==NULL) {
196                                 dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
197                                 if(dl->verts[2]<0.0) dl->nors[2]= -1.0;
198                                 else dl->nors[2]= 1.0;
199                         }
200                 }
201                 else if(dl->type==DL_SURF) {
202                         if(dl->nors==NULL) {
203                                 dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
204                                 
205                                 vdata= dl->verts;
206                                 ndata= dl->nors;
207                                 
208                                 for(a=0; a<dl->parts; a++) {
209                                         
210                                         if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
211                                                 break;
212         
213                                         v1= vdata+ 3*p1; 
214                                         n1= ndata+ 3*p1;
215                                         v2= vdata+ 3*p2; 
216                                         n2= ndata+ 3*p2;
217                                         v3= vdata+ 3*p3; 
218                                         n3= ndata+ 3*p3;
219                                         v4= vdata+ 3*p4; 
220                                         n4= ndata+ 3*p4;
221                                         
222                                         for(; b<dl->nr; b++) {
223         
224                                                 CalcNormFloat4(v1, v3, v4, v2, nor);
225         
226                                                 VecAddf(n1, n1, nor);
227                                                 VecAddf(n2, n2, nor);
228                                                 VecAddf(n3, n3, nor);
229                                                 VecAddf(n4, n4, nor);
230         
231                                                 v2= v1; v1+= 3;
232                                                 v4= v3; v3+= 3;
233                                                 n2= n1; n1+= 3;
234                                                 n4= n3; n3+= 3;
235                                         }
236                                 }
237                                 a= dl->parts*dl->nr;
238                                 v1= ndata;
239                                 while(a--) {
240                                         Normalize(v1);
241                                         v1+= 3;
242                                 }
243                         }
244                 }
245                 dl= dl->next;
246         }
247 }
248
249 void count_displist(ListBase *lb, int *totvert, int *totface)
250 {
251         DispList *dl;
252         
253         dl= lb->first;
254         while(dl) {
255                 
256                 switch(dl->type) {
257                         case DL_SURF:
258                                 *totvert+= dl->nr*dl->parts;
259                                 *totface+= (dl->nr-1)*(dl->parts-1);
260                                 break;
261                         case DL_INDEX3:
262                         case DL_INDEX4:
263                                 *totvert+= dl->nr;
264                                 *totface+= dl->parts;
265                                 break;
266                         case DL_POLY:
267                         case DL_SEGM:
268                                 *totvert+= dl->nr*dl->parts;
269                 }
270                 
271                 dl= dl->next;
272         }
273 }
274
275 int surfindex_displist(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
276 {
277         if((dl->flag & DL_CYCL_V)==0 && a==(dl->parts)-1) {
278                 return 0;
279         }
280         
281         if(dl->flag & DL_CYCL_U) {
282                 (*p1)= dl->nr*a;
283                 (*p2)= (*p1)+ dl->nr-1;
284                 (*p3)= (*p1)+ dl->nr;
285                 (*p4)= (*p2)+ dl->nr;
286                 (*b)= 0;
287         } else {
288                 (*p2)= dl->nr*a;
289                 (*p1)= (*p2)+1;
290                 (*p4)= (*p2)+ dl->nr;
291                 (*p3)= (*p1)+ dl->nr;
292                 (*b)= 1;
293         }
294         
295         if( (dl->flag & DL_CYCL_V) && a==dl->parts-1) {                     \
296                 (*p3)-= dl->nr*dl->parts;                                   \
297                 (*p4)-= dl->nr*dl->parts;                                   \
298         }
299         
300         return 1;
301 }
302
303 /* ***************************** shade displist. note colors now are in rgb(a) order ******************** */
304
305 /* create default shade input... save cpu cycles with ugly global */
306 /* XXXX bad code warning: local ShadeInput initialize... */
307 static ShadeInput shi;
308 static void init_fastshade_shadeinput(void)
309 {
310         memset(&shi, 0, sizeof(ShadeInput));
311         shi.lay= G.scene->lay;
312         shi.view[2]= -1.0f;
313         shi.passflag= SCE_PASS_COMBINED;
314         shi.combinedflag= -1;
315 }
316
317 static Render *fastshade_get_render(void)
318 {
319         Render *re= RE_GetRender("_Shade View_");
320         if(re==NULL) {
321                 re= RE_NewRender("_Shade View_");
322         
323                 RE_Database_Baking(re, G.scene, 0, 0);  /* 0= no faces */
324         }
325         return re;
326 }
327
328 /* called on file reading */
329 void fastshade_free_render(void)
330 {
331         Render *re= RE_GetRender("_Shade View_");
332         
333         if(re) {
334                 RE_Database_Free(re);
335                 RE_FreeRender(re);
336         }
337 }
338
339 static int fastshade_customdata_layer_num(int n, int active)
340 {   
341         /* make the active layer the first */
342         if (n == active) return 0;
343         else if (n < active) return n+1;
344         else return n;
345 }
346
347 static void fastshade_customdata(CustomData *fdata, int a, int j, Material *ma)
348 {
349         CustomDataLayer *layer;
350         MTFace *mtface;
351         int index, n, needuv= ma->texco & TEXCO_UV;
352         char *vertcol;
353
354         shi.totuv= 0;
355         shi.totcol= 0;
356
357         for(index=0; index<fdata->totlayer; index++) {
358                 layer= &fdata->layers[index];
359                 
360                 if(needuv && layer->type == CD_MTFACE && shi.totuv < MAX_MTFACE) {
361                         n= fastshade_customdata_layer_num(shi.totuv, layer->active_rnd);
362                         mtface= &((MTFace*)layer->data)[a];
363
364                         shi.uv[shi.totuv].uv[0]= 2.0f*mtface->uv[j][0]-1.0f;
365                         shi.uv[shi.totuv].uv[1]= 2.0f*mtface->uv[j][1]-1.0f;
366                         shi.uv[shi.totuv].uv[2]= 1.0f;
367
368                         shi.uv[shi.totuv].name= layer->name;
369                         shi.totuv++;
370                 }
371                 else if(layer->type == CD_MCOL && shi.totcol < MAX_MCOL) {
372                         n= fastshade_customdata_layer_num(shi.totcol, layer->active_rnd);
373                         vertcol= (char*)&((MCol*)layer->data)[a*4 + j];
374
375                         shi.col[shi.totcol].col[0]= ((float)vertcol[3])/255.0f;
376                         shi.col[shi.totcol].col[1]= ((float)vertcol[2])/255.0f;
377                         shi.col[shi.totcol].col[2]= ((float)vertcol[1])/255.0f;
378
379                         shi.col[shi.totcol].name= layer->name;
380                         shi.totcol++;
381                 }
382         }
383
384         if(needuv && shi.totuv == 0)
385                 VECCOPY(shi.uv[0].uv, shi.lo);
386
387         if(shi.totcol)
388                 VECCOPY(shi.vcol, shi.col[0].col);
389 }
390
391 static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2)
392 {
393         ShadeResult shr;
394         int a;
395         
396         VECCOPY(shi.co, co);
397         shi.vn[0]= -nor[0];
398         shi.vn[1]= -nor[1];
399         shi.vn[2]= -nor[2];
400         VECCOPY(shi.vno, shi.vn);
401         VECCOPY(shi.facenor, shi.vn);
402         
403         if(ma->texco) {
404                 VECCOPY(shi.lo, orco);
405                 
406                 if(ma->texco & TEXCO_GLOB) {
407                         VECCOPY(shi.gl, shi.lo);
408                 }
409                 if(ma->texco & TEXCO_WINDOW) {
410                         VECCOPY(shi.winco, shi.lo);
411                 }
412                 if(ma->texco & TEXCO_STICKY) {
413                         VECCOPY(shi.sticky, shi.lo);
414                 }
415                 if(ma->texco & TEXCO_OBJECT) {
416                         VECCOPY(shi.co, shi.lo);
417                 }
418                 if(ma->texco & TEXCO_NORM) {
419                         VECCOPY(shi.orn, shi.vn);
420                 }
421                 if(ma->texco & TEXCO_REFL) {
422                         float inp= 2.0*(shi.vn[2]);
423                         shi.ref[0]= (inp*shi.vn[0]);
424                         shi.ref[1]= (inp*shi.vn[1]);
425                         shi.ref[2]= (-1.0+inp*shi.vn[2]);
426                 }
427         }
428         
429         shi.mat= ma;    /* set each time... node shaders change it */
430         RE_shade_external(NULL, &shi, &shr);
431         
432         a= 256.0f*(shr.combined[0]);
433         col1[0]= CLAMPIS(a, 0, 255);
434         a= 256.0f*(shr.combined[1]);
435         col1[1]= CLAMPIS(a, 0, 255);
436         a= 256.0f*(shr.combined[2]);
437         col1[2]= CLAMPIS(a, 0, 255);
438         
439         if(col2) {
440                 shi.vn[0]= -shi.vn[0];
441                 shi.vn[1]= -shi.vn[1];
442                 shi.vn[2]= -shi.vn[2];
443                 
444                 shi.mat= ma;    /* set each time... node shaders change it */
445                 RE_shade_external(NULL, &shi, &shr);
446                 
447                 a= 256.0f*(shr.combined[0]);
448                 col2[0]= CLAMPIS(a, 0, 255);
449                 a= 256.0f*(shr.combined[1]);
450                 col2[1]= CLAMPIS(a, 0, 255);
451                 a= 256.0f*(shr.combined[2]);
452                 col2[2]= CLAMPIS(a, 0, 255);
453         }
454 }
455
456 static void init_fastshade_for_ob(Render *re, Object *ob, int *need_orco_r, float mat[4][4], float imat[3][3])
457 {
458         float tmat[4][4];
459         float amb[3]= {0.0f, 0.0f, 0.0f};
460         int a;
461         
462         /* initialize globals in render */
463         RE_shade_external(re, NULL, NULL);
464
465         /* initialize global here */
466         init_fastshade_shadeinput();
467         
468         RE_DataBase_GetView(re, tmat);
469         Mat4MulMat4(mat, ob->obmat, tmat);
470         
471         Mat4Invert(tmat, mat);
472         Mat3CpyMat4(imat, tmat);
473         if(ob->transflag & OB_NEG_SCALE) Mat3MulFloat((float *)imat, -1.0);
474         
475         if (need_orco_r) *need_orco_r= 0;
476         for(a=0; a<ob->totcol; a++) {
477                 Material *ma= give_current_material(ob, a+1);
478                 if(ma) {
479                         init_render_material(ma, 0, amb);
480
481                         if(ma->texco & TEXCO_ORCO) {
482                                 if (need_orco_r) *need_orco_r= 1;
483                         }
484                 }
485         }
486 }
487
488 static void end_fastshade_for_ob(Object *ob)
489 {
490         int a;
491         
492         for(a=0; a<ob->totcol; a++) {
493                 Material *ma= give_current_material(ob, a+1);
494                 if(ma)
495                         end_render_material(ma);
496         }
497 }
498
499
500 static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, unsigned int **col1_r, unsigned int **col2_r)
501 {
502         Mesh *me= ob->data;
503         DerivedMesh *dm;
504         MVert *mvert;
505         MFace *mface;
506         unsigned int *col1, *col2;
507         float *orco, *vnors, *nors, imat[3][3], mat[4][4], vec[3];
508         int a, i, need_orco, totface, totvert;
509         CustomDataMask dataMask = CD_MASK_BAREMESH | CD_MASK_MCOL
510                                   | CD_MASK_MTFACE | CD_MASK_NORMAL;
511
512
513         init_fastshade_for_ob(re, ob, &need_orco, mat, imat);
514
515         if(need_orco)
516                 dataMask |= CD_MASK_ORCO;
517
518         if (onlyForMesh)
519                 dm = mesh_get_derived_deform(ob, dataMask);
520         else
521                 dm = mesh_get_derived_final(ob, dataMask);
522         
523         mvert = dm->getVertArray(dm);
524         mface = dm->getFaceArray(dm);
525         nors = dm->getFaceDataArray(dm, CD_NORMAL);
526         totvert = dm->getNumVerts(dm);
527         totface = dm->getNumFaces(dm);
528         orco= dm->getVertDataArray(dm, CD_ORCO);
529
530         if (onlyForMesh) {
531                 col1 = *col1_r;
532                 col2 = NULL;
533         } else {
534                 *col1_r = col1 = MEM_mallocN(sizeof(*col1)*totface*4, "col1");
535
536                 if (col2_r && (me->flag & ME_TWOSIDED))
537                         col2 = MEM_mallocN(sizeof(*col2)*totface*4, "col2");
538                 else
539                         col2 = NULL;
540                 
541                 if (col2_r) *col2_r = col2;
542         }
543
544                 /* vertexnormals */
545         vnors= MEM_mallocN(totvert*3*sizeof(float), "vnors disp");
546         for (a=0; a<totvert; a++) {
547                 MVert *mv = &mvert[a];
548                 float *vn= &vnors[a*3];
549                 float xn= mv->no[0]; 
550                 float yn= mv->no[1]; 
551                 float zn= mv->no[2];
552                 
553                         /* transpose ! */
554                 vn[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
555                 vn[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
556                 vn[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
557                 Normalize(vn);
558         }               
559
560         for (i=0; i<totface; i++) {
561                 MFace *mf= &mface[i];
562                 Material *ma= give_current_material(ob, mf->mat_nr+1);
563                 int j, vidx[4], nverts= mf->v4?4:3;
564                 unsigned char *col1base= (unsigned char*) &col1[i*4];
565                 unsigned char *col2base= (unsigned char*) (col2?&col2[i*4]:NULL);
566                 float nor[3], n1[3];
567                 
568                 if(ma==NULL) ma= &defmaterial;
569                 
570                 vidx[0]= mf->v1;
571                 vidx[1]= mf->v2;
572                 vidx[2]= mf->v3;
573                 vidx[3]= mf->v4;
574
575                 if (nors) {
576                         VECCOPY(nor, &nors[i*3]);
577                 } else {
578                         if (mf->v4)
579                                 CalcNormFloat4(mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co, nor);
580                         else
581                                 CalcNormFloat(mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, nor);
582                 }
583
584                 n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
585                 n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
586                 n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
587                 Normalize(n1);
588
589                 for (j=0; j<nverts; j++) {
590                         MVert *mv= &mvert[vidx[j]];
591                         char *col1= (char*)&col1base[j*4];
592                         char *col2= (char*)(col2base?&col2base[j*4]:NULL);
593                         float *vn = (mf->flag & ME_SMOOTH)?&vnors[3*vidx[j]]:n1;
594                         
595                         VECCOPY(vec, mv->co);
596                         Mat4MulVecfl(mat, vec);
597                         vec[0]+= 0.001*vn[0];
598                         vec[1]+= 0.001*vn[1];
599                         vec[2]+= 0.001*vn[2];
600
601                         fastshade_customdata(&dm->faceData, i, j, ma);
602                         fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, ma, col1, col2);
603                 }
604         } 
605         MEM_freeN(vnors);
606
607         dm->release(dm);
608
609         end_fastshade_for_ob(ob);
610 }
611
612 void shadeMeshMCol(Object *ob, Mesh *me)
613 {
614         int a;
615         char *cp;
616         unsigned int *mcol= (unsigned int*)me->mcol;
617         
618         Render *re= fastshade_get_render();
619         mesh_create_shadedColors(re, ob, 1, &mcol, NULL);
620         me->mcol= (MCol*)mcol;
621
622         /* swap bytes */
623         for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) {
624                 SWAP(char, cp[0], cp[3]);
625                 SWAP(char, cp[1], cp[2]);
626         }
627 }
628
629 /* has base pointer, to check for layer */
630 /* called from drawobject.c */
631 void shadeDispList(Base *base)
632 {
633         Object *ob= base->object;
634         DispList *dl, *dlob;
635         Material *ma = NULL;
636         Curve *cu;
637         Render *re;
638         float imat[3][3], mat[4][4], vec[3];
639         float *fp, *nor, n1[3];
640         unsigned int *col1;
641         int a, need_orco;
642         
643         re= fastshade_get_render();
644         
645         dl = find_displist(&ob->disp, DL_VERTCOL);
646         if (dl) {
647                 BLI_remlink(&ob->disp, dl);
648                 free_disp_elem(dl);
649         }
650
651         if(ob->type==OB_MESH) {
652                 dl= MEM_callocN(sizeof(DispList), "displistshade");
653                 dl->type= DL_VERTCOL;
654
655                 mesh_create_shadedColors(re, ob, 0, &dl->col1, &dl->col2);
656
657                 /* add dl to ob->disp after mesh_create_shadedColors, because it
658                    might indirectly free ob->disp */
659                 BLI_addtail(&ob->disp, dl);
660         }
661         else {
662
663                 init_fastshade_for_ob(re, ob, &need_orco, mat, imat);
664                 
665                 if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
666                 
667                         /* now we need the normals */
668                         cu= ob->data;
669                         dl= cu->disp.first;
670                         
671                         while(dl) {
672                                 dlob= MEM_callocN(sizeof(DispList), "displistshade");
673                                 BLI_addtail(&ob->disp, dlob);
674                                 dlob->type= DL_VERTCOL;
675                                 dlob->parts= dl->parts;
676                                 dlob->nr= dl->nr;
677                                 
678                                 if(dl->type==DL_INDEX3) {
679                                         col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
680                                 }
681                                 else {
682                                         col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1");
683                                 }
684                                 
685                         
686                                 ma= give_current_material(ob, dl->col+1);
687                                 if(ma==NULL) ma= &defmaterial;
688                                 
689                                 if(dl->type==DL_INDEX3) {
690                                         if(dl->nors) {
691                                                 /* there's just one normal */
692                                                 n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2];
693                                                 n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2];
694                                                 n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2];
695                                                 Normalize(n1);
696                                                 
697                                                 fp= dl->verts;
698                                                 
699                                                 a= dl->nr;              
700                                                 while(a--) {
701                                                         VECCOPY(vec, fp);
702                                                         Mat4MulVecfl(mat, vec);
703                                                         
704                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
705                                                         
706                                                         fp+= 3; col1++;
707                                                 }
708                                         }
709                                 }
710                                 else if(dl->type==DL_SURF) {
711                                         if(dl->nors) {
712                                                 a= dl->nr*dl->parts;
713                                                 fp= dl->verts;
714                                                 nor= dl->nors;
715                                                 
716                                                 while(a--) {
717                                                         VECCOPY(vec, fp);
718                                                         Mat4MulVecfl(mat, vec);
719                                                         
720                                                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
721                                                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
722                                                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
723                                                         Normalize(n1);
724                                 
725                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
726                                                         
727                                                         fp+= 3; nor+= 3; col1++;
728                                                 }
729                                         }
730                                 }
731                                 dl= dl->next;
732                         }
733                 }
734                 else if(ob->type==OB_MBALL) {
735                         /* there are normals already */
736                         dl= ob->disp.first;
737                         
738                         while(dl) {
739                                 
740                                 if(dl->type==DL_INDEX4) {
741                                         if(dl->nors) {
742                                                 
743                                                 if(dl->col1) MEM_freeN(dl->col1);
744                                                 col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
745                                 
746                                                 ma= give_current_material(ob, dl->col+1);
747                                                 if(ma==NULL) ma= &defmaterial;
748                                                 
749                                                 fp= dl->verts;
750                                                 nor= dl->nors;
751                                                 
752                                                 a= dl->nr;              
753                                                 while(a--) {
754                                                         VECCOPY(vec, fp);
755                                                         Mat4MulVecfl(mat, vec);
756                                                         
757                                                         /* transpose ! */
758                                                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
759                                                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
760                                                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
761                                                         Normalize(n1);
762                                                 
763                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
764                                                         
765                                                         fp+= 3; col1++; nor+= 3;
766                                                 }
767                                         }
768                                 }
769                                 dl= dl->next;
770                         }
771                 }
772                 
773                 end_fastshade_for_ob(ob);
774         }
775 }
776
777 /* frees render and shade part of displists */
778 /* note: dont do a shade again, until a redraw happens */
779 void reshadeall_displist(void)
780 {
781         Base *base;
782         Object *ob;
783         
784         fastshade_free_render();
785         
786         for(base= G.scene->base.first; base; base= base->next) {
787                 ob= base->object;
788
789                 if(ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL))
790                         freedisplist(&ob->disp);
791
792                 if(base->lay & G.scene->lay) {
793                         /* Metaballs have standard displist at the Object */
794                         if(ob->type==OB_MBALL) shadeDispList(base);
795                 }
796         }
797 }
798
799 /* ****************** make displists ********************* */
800
801 static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
802 {
803         Nurb *nu;
804         DispList *dl;
805         BezTriple *bezt, *prevbezt;
806         BPoint *bp;
807         float *data;
808         int a, len, resolu;
809         
810         nu= nubase->first;
811         while(nu) {
812                 if(nu->hide==0) {
813                         
814                         if(G.rendering && cu->resolu_ren!=0) 
815                                 resolu= cu->resolu_ren;
816                         else
817                                 resolu= nu->resolu;
818                         
819                         if(!check_valid_nurb_u(nu));
820                         else if((nu->type & 7)==CU_BEZIER) {
821                                 
822                                 /* count */
823                                 len= 0;
824                                 a= nu->pntsu-1;
825                                 if(nu->flagu & CU_CYCLIC) a++;
826
827                                 prevbezt= nu->bezt;
828                                 bezt= prevbezt+1;
829                                 while(a--) {
830                                         if(a==0 && (nu->flagu & CU_CYCLIC)) bezt= nu->bezt;
831                                         
832                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
833                                         else len+= resolu;
834                                         
835                                         if(a==0 && (nu->flagu & CU_CYCLIC)==0) len++;
836                                         
837                                         prevbezt= bezt;
838                                         bezt++;
839                                 }
840                                 
841                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
842                                 /* len+1 because of 'forward_diff_bezier' function */
843                                 dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
844                                 BLI_addtail(dispbase, dl);
845                                 dl->parts= 1;
846                                 dl->nr= len;
847                                 dl->col= nu->mat_nr;
848                                 dl->charidx= nu->charidx;
849
850                                 data= dl->verts;
851
852                                 if(nu->flagu & CU_CYCLIC) {
853                                         dl->type= DL_POLY;
854                                         a= nu->pntsu;
855                                 }
856                                 else {
857                                         dl->type= DL_SEGM;
858                                         a= nu->pntsu-1;
859                                 }
860                                 
861                                 prevbezt= nu->bezt;
862                                 bezt= prevbezt+1;
863                                 
864                                 while(a--) {
865                                         if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
866                                         
867                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
868                                                 VECCOPY(data, prevbezt->vec[1]);
869                                                 data+= 3;
870                                         }
871                                         else {
872                                                 int j;
873                                                 for(j=0; j<3; j++) {
874                                                         forward_diff_bezier(    prevbezt->vec[1][j],
875                                                                                                         prevbezt->vec[2][j],
876                                                                                                         bezt->vec[0][j],
877                                                                                                         bezt->vec[1][j],
878                                                                                                         data+j, resolu, 3*sizeof(float));
879                                                 }
880                                                 
881                                                 data+= 3*resolu;
882                                         }
883                                         
884                                         if(a==0 && dl->type==DL_SEGM) {
885                                                 VECCOPY(data, bezt->vec[1]);
886                                         }
887                                         
888                                         prevbezt= bezt;
889                                         bezt++;
890                                 }
891                         }
892                         else if((nu->type & 7)==CU_NURBS) {
893                                 len= (resolu*SEGMENTSU(nu));
894                                 
895                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
896                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
897                                 BLI_addtail(dispbase, dl);
898                                 dl->parts= 1;
899                                 
900                                 dl->nr= len;
901                                 dl->col= nu->mat_nr;
902                                 dl->charidx = nu->charidx;
903
904                                 data= dl->verts;
905                                 if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
906                                 else dl->type= DL_SEGM;
907                                 makeNurbcurve(nu, data, NULL, NULL, resolu, 3*sizeof(float));
908                         }
909                         else if((nu->type & 7)==CU_POLY) {
910                                 len= nu->pntsu;
911                                 dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
912                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
913                                 BLI_addtail(dispbase, dl);
914                                 dl->parts= 1;
915                                 dl->nr= len;
916                                 dl->col= nu->mat_nr;
917                                 dl->charidx = nu->charidx;
918
919                                 data= dl->verts;
920                                 if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
921                                 else dl->type= DL_SEGM;
922                                 
923                                 a= len;
924                                 bp= nu->bp;
925                                 while(a--) {
926                                         VECCOPY(data, bp->vec);
927                                         bp++;
928                                         data+= 3;
929                                 }
930                         }
931                 }
932                 nu= nu->next;
933         }
934 }
935
936
937 void filldisplist(ListBase *dispbase, ListBase *to)
938 {
939         EditVert *eve, *v1, *vlast;
940         EditFace *efa;
941         DispList *dlnew=0, *dl;
942         float *f1;
943         int colnr=0, charidx=0, cont=1, tot, a, *index;
944         intptr_t totvert;
945         
946         if(dispbase==0) return;
947         if(dispbase->first==0) return;
948
949         while(cont) {
950                 cont= 0;
951                 totvert=0;
952                 
953                 dl= dispbase->first;
954                 while(dl) {
955         
956                         if(dl->type==DL_POLY) {
957                                 if(charidx<dl->charidx) cont= 1;
958                                 else if(charidx==dl->charidx) {
959                         
960                                         colnr= dl->col;
961                                         charidx= dl->charidx;
962                 
963                                         /* make editverts and edges */
964                                         f1= dl->verts;
965                                         a= dl->nr;
966                                         eve= v1= 0;
967                                         
968                                         while(a--) {
969                                                 vlast= eve;
970                                                 
971                                                 eve= BLI_addfillvert(f1);
972                                                 totvert++;
973                                                 
974                                                 if(vlast==0) v1= eve;
975                                                 else {
976                                                         BLI_addfilledge(vlast, eve);
977                                                 }
978                                                 f1+=3;
979                                         }
980                                 
981                                         if(eve!=0 && v1!=0) {
982                                                 BLI_addfilledge(eve, v1);
983                                         }
984                                 }
985                         }
986                         dl= dl->next;
987                 }
988                 
989                 if(totvert && BLI_edgefill(0, (G.obedit && G.obedit->actcol)?(G.obedit->actcol-1):0)) {
990
991                         /* count faces  */
992                         tot= 0;
993                         efa= fillfacebase.first;
994                         while(efa) {
995                                 tot++;
996                                 efa= efa->next;
997                         }
998
999                         if(tot) {
1000                                 dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
1001                                 dlnew->type= DL_INDEX3;
1002                                 dlnew->col= colnr;
1003                                 dlnew->nr= totvert;
1004                                 dlnew->parts= tot;
1005
1006                                 dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
1007                                 dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
1008                                 
1009                                 /* vert data */
1010                                 f1= dlnew->verts;
1011                                 totvert= 0;
1012                                 eve= fillvertbase.first;
1013                                 while(eve) {
1014                                         VECCOPY(f1, eve->co);
1015                                         f1+= 3;
1016         
1017                                         /* index number */
1018                                         eve->tmp.l = totvert;
1019                                         totvert++;
1020                                         
1021                                         eve= eve->next;
1022                                 }
1023                                 
1024                                 /* index data */
1025                                 efa= fillfacebase.first;
1026                                 index= dlnew->index;
1027                                 while(efa) {
1028                                         index[0]= (intptr_t)efa->v1->tmp.l;
1029                                         index[1]= (intptr_t)efa->v2->tmp.l;
1030                                         index[2]= (intptr_t)efa->v3->tmp.l;
1031                                         
1032                                         index+= 3;
1033                                         efa= efa->next;
1034                                 }
1035                         }
1036
1037                         BLI_addhead(to, dlnew);
1038                         
1039                 }
1040                 BLI_end_edgefill();
1041
1042                 charidx++;
1043         }
1044         
1045         /* do not free polys, needed for wireframe display */
1046         
1047 }
1048
1049 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
1050 {
1051         ListBase front, back;
1052         DispList *dl, *dlnew;
1053         float *fp, *fp1;
1054         int a, dpoly;
1055         
1056         front.first= front.last= back.first= back.last= 0;
1057         
1058         dl= dispbase->first;
1059         while(dl) {
1060                 if(dl->type==DL_SURF) {
1061                         if( (dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)==0 ) {
1062                                 if( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE) ) {
1063                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1064                                         BLI_addtail(&front, dlnew);
1065                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1066                                         dlnew->nr= dl->parts;
1067                                         dlnew->parts= 1;
1068                                         dlnew->type= DL_POLY;
1069                                         dlnew->col= dl->col;
1070                                         dlnew->charidx = dl->charidx;
1071                                         
1072                                         fp= dl->verts;
1073                                         dpoly= 3*dl->nr;
1074                                         
1075                                         a= dl->parts;
1076                                         while(a--) {
1077                                                 VECCOPY(fp1, fp);
1078                                                 fp1+= 3;
1079                                                 fp+= dpoly;
1080                                         }
1081                                 }
1082                                 if( (cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE) ) {
1083                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1084                                         BLI_addtail(&back, dlnew);
1085                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1086                                         dlnew->nr= dl->parts;
1087                                         dlnew->parts= 1;
1088                                         dlnew->type= DL_POLY;
1089                                         dlnew->col= dl->col;
1090                                         dlnew->charidx= dl->charidx;
1091                                         
1092                                         fp= dl->verts+3*(dl->nr-1);
1093                                         dpoly= 3*dl->nr;
1094                                         
1095                                         a= dl->parts;
1096                                         while(a--) {
1097                                                 VECCOPY(fp1, fp);
1098                                                 fp1+= 3;
1099                                                 fp+= dpoly;
1100                                         }
1101                                 }
1102                         }
1103                 }
1104                 dl= dl->next;
1105         }
1106
1107         filldisplist(&front, dispbase);
1108         filldisplist(&back, dispbase);
1109         
1110         freedisplist(&front);
1111         freedisplist(&back);
1112
1113         filldisplist(dispbase, dispbase);
1114         
1115 }
1116
1117 void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
1118 {
1119         if(cu->flag & CU_3D) return;
1120
1121         if(dispbase->first && ((DispList*) dispbase->first)->type==DL_SURF) {
1122                 bevels_to_filledpoly(cu, dispbase);
1123         }
1124         else {
1125                 filldisplist(dispbase, dispbase);
1126         }
1127 }
1128
1129 /* taper rules:
1130   - only 1 curve
1131   - first point left, last point right
1132   - based on subdivided points in original curve, not on points in taper curve (still)
1133 */
1134 float calc_taper(Object *taperobj, int cur, int tot)
1135 {
1136         Curve *cu;
1137         DispList *dl;
1138         
1139         if(taperobj==NULL) return 1.0;
1140         
1141         cu= taperobj->data;
1142         dl= cu->disp.first;
1143         if(dl==NULL) {
1144                 makeDispListCurveTypes(taperobj, 0);
1145                 dl= cu->disp.first;
1146         }
1147         if(dl) {
1148                 float fac= ((float)cur)/(float)(tot-1);
1149                 float minx, dx, *fp;
1150                 int a;
1151                 
1152                 /* horizontal size */
1153                 minx= dl->verts[0];
1154                 dx= dl->verts[3*(dl->nr-1)] - minx;
1155                 if(dx>0.0) {
1156                 
1157                         fp= dl->verts;
1158                         for(a=0; a<dl->nr; a++, fp+=3) {
1159                                 if( (fp[0]-minx)/dx >= fac) {
1160                                         /* interpolate with prev */
1161                                         if(a>0) {
1162                                                 float fac1= (fp[-3]-minx)/dx;
1163                                                 float fac2= (fp[0]-minx)/dx;
1164                                                 if(fac1!=fac2)
1165                                                         return fp[1]*(fac1-fac)/(fac1-fac2) + fp[-2]*(fac-fac2)/(fac1-fac2);
1166                                         }
1167                                         return fp[1];
1168                                 }
1169                         }
1170                         return fp[-2];  // last y coord
1171                 }
1172         }
1173         
1174         return 1.0;
1175 }
1176
1177 void makeDispListMBall(Object *ob)
1178 {
1179         if(!ob || ob->type!=OB_MBALL) return;
1180
1181         freedisplist(&(ob->disp));
1182         
1183         if(ob->type==OB_MBALL) {
1184                 if(ob==find_basis_mball(ob)) {
1185                         metaball_polygonize(ob);
1186                         tex_space_mball(ob);
1187
1188                         object_deform_mball(ob);
1189                 }
1190         }
1191         
1192         boundbox_displist(ob);
1193 }
1194
1195 static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int editmode)
1196 {
1197         ModifierData *md = modifiers_getVirtualModifierList(ob);
1198         ModifierData *preTesselatePoint;
1199         int required_mode;
1200
1201         if(forRender) required_mode = eModifierMode_Render;
1202         else required_mode = eModifierMode_Realtime;
1203
1204         if(editmode) required_mode |= eModifierMode_Editmode;
1205
1206         preTesselatePoint = NULL;
1207         for (; md; md=md->next) {
1208                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1209
1210                 if ((md->mode & required_mode) != required_mode) continue;
1211                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1212
1213                 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
1214                         preTesselatePoint  = md;
1215                 }
1216         }
1217
1218         return preTesselatePoint;
1219 }
1220
1221 void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float (**originalVerts_r)[3], float (**deformedVerts_r)[3], int *numVerts_r)
1222 {
1223         int editmode = (!forRender && ob==G.obedit);
1224         ModifierData *md = modifiers_getVirtualModifierList(ob);
1225         ModifierData *preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode);
1226         int numVerts = 0;
1227         float (*originalVerts)[3] = NULL;
1228         float (*deformedVerts)[3] = NULL;
1229         int required_mode;
1230
1231         if(forRender) required_mode = eModifierMode_Render;
1232         else required_mode = eModifierMode_Realtime;
1233
1234         if(editmode) required_mode |= eModifierMode_Editmode;
1235
1236         if(ob!=G.obedit && do_ob_key(ob)) {
1237                 deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
1238                 originalVerts = MEM_dupallocN(deformedVerts);
1239         }
1240         
1241         if (preTesselatePoint) {
1242                 for (; md; md=md->next) {
1243                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1244
1245                         if ((md->mode & required_mode) != required_mode) continue;
1246                         if (mti->isDisabled && mti->isDisabled(md)) continue;
1247                         if (mti->type!=eModifierTypeType_OnlyDeform) continue;
1248
1249                         if (!deformedVerts) {
1250                                 deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
1251                                 originalVerts = MEM_dupallocN(deformedVerts);
1252                         }
1253                         
1254                         mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
1255
1256                         if (md==preTesselatePoint)
1257                                 break;
1258                 }
1259         }
1260
1261         if (deformedVerts) {
1262                 curve_applyVertexCos(ob->data, nurb, deformedVerts);
1263         }
1264
1265         *originalVerts_r = originalVerts;
1266         *deformedVerts_r = deformedVerts;
1267         *numVerts_r = numVerts;
1268 }
1269
1270 static void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *dispbase, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3])
1271 {
1272         int editmode = (!forRender && ob==G.obedit);
1273         ModifierData *md = modifiers_getVirtualModifierList(ob);
1274         ModifierData *preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode);
1275         DispList *dl;
1276         int required_mode;
1277
1278         if(forRender) required_mode = eModifierMode_Render;
1279         else required_mode = eModifierMode_Realtime;
1280
1281         if(editmode) required_mode |= eModifierMode_Editmode;
1282
1283         if (preTesselatePoint) {
1284                 md = preTesselatePoint->next;
1285         }
1286
1287         for (; md; md=md->next) {
1288                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1289                 
1290                 if ((md->mode & required_mode) != required_mode) continue;
1291                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1292                 if (mti->type!=eModifierTypeType_OnlyDeform && mti->type!=eModifierTypeType_DeformOrConstruct) continue;
1293
1294                 /* need to put all verts in 1 block for curve deform */
1295                 if(md->type==eModifierType_Curve) {
1296                         float *allverts, *fp;
1297                         int totvert= 0;
1298                         
1299                         for (dl=dispbase->first; dl; dl=dl->next)
1300                                 totvert+= (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr;
1301                         
1302                         fp= allverts= MEM_mallocN(totvert*sizeof(float)*3, "temp vert");
1303                         for (dl=dispbase->first; dl; dl=dl->next) {
1304                                 int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
1305                                 memcpy(fp, dl->verts, sizeof(float) * offs);
1306                                 fp+= offs;
1307                         }
1308                         
1309                         mti->deformVerts(md, ob, NULL, (float(*)[3]) allverts, totvert);
1310                         
1311                         fp= allverts;
1312                         for (dl=dispbase->first; dl; dl=dl->next) {
1313                                 int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
1314                                 memcpy(dl->verts, fp, sizeof(float) * offs);
1315                                 fp+= offs;
1316                         }
1317                         MEM_freeN(allverts);
1318                 }
1319                 else {
1320                         for (dl=dispbase->first; dl; dl=dl->next) {
1321                                 mti->deformVerts(md, ob, NULL, (float(*)[3]) dl->verts, (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
1322                         }
1323                 }
1324         }
1325
1326         if (deformedVerts) {
1327                 curve_applyVertexCos(ob->data, nurb, originalVerts);
1328                 MEM_freeN(originalVerts);
1329                 MEM_freeN(deformedVerts);
1330         }
1331 }
1332
1333 static void displist_surf_indices(DispList *dl)
1334 {
1335         int a, b, p1, p2, p3, p4;
1336         int *index;
1337         
1338         dl->totindex= 0;
1339         
1340         index=dl->index= MEM_mallocN( 4*sizeof(int)*(dl->parts+1)*(dl->nr+1), "index array nurbs");
1341         
1342         for(a=0; a<dl->parts; a++) {
1343                 
1344                 if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
1345                         break;
1346                 
1347                 for(; b<dl->nr; b++, index+=4) {        
1348                         index[0]= p1;
1349                         index[1]= p2;
1350                         index[2]= p4;
1351                         index[3]= p3;
1352                         
1353                         dl->totindex++;
1354                         
1355                         p2= p1; p1++;
1356                         p4= p3; p3++;
1357
1358                 }
1359         }
1360         
1361 }
1362
1363 void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender, int forOrco)
1364 {
1365         ListBase *nubase;
1366         Nurb *nu;
1367         Curve *cu = ob->data;
1368         DispList *dl;
1369         float *data;
1370         int len;
1371         int numVerts;
1372         float (*originalVerts)[3];
1373         float (*deformedVerts)[3];
1374                 
1375         if(!forRender && ob==G.obedit) {
1376                 nubase= &editNurb;
1377         }
1378         else {
1379                 nubase= &cu->nurb;
1380         }
1381
1382         if(!forOrco)
1383                 curve_calc_modifiers_pre(ob, nubase, forRender, &originalVerts, &deformedVerts, &numVerts);
1384
1385         for (nu=nubase->first; nu; nu=nu->next) {
1386                 if(forRender || nu->hide==0) {
1387                         if(nu->pntsv==1) {
1388                                 len= SEGMENTSU(nu)*nu->resolu;
1389                                 
1390                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1391                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1392                                 
1393                                 BLI_addtail(dispbase, dl);
1394                                 dl->parts= 1;
1395                                 dl->nr= len;
1396                                 dl->col= nu->mat_nr;
1397                                 dl->charidx= nu->charidx;
1398                                 dl->rt= nu->flag;
1399                                 
1400                                 data= dl->verts;
1401                                 if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
1402                                 else dl->type= DL_SEGM;
1403                                 
1404                                 makeNurbcurve(nu, data, NULL, NULL, nu->resolu, 3*sizeof(float));
1405                         }
1406                         else {
1407                                 len= (nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv);
1408                                 
1409                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1410                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1411                                 BLI_addtail(dispbase, dl);
1412
1413                                 dl->col= nu->mat_nr;
1414                                 dl->charidx= nu->charidx;
1415                                 dl->rt= nu->flag;
1416                                 
1417                                 data= dl->verts;
1418                                 dl->type= DL_SURF;
1419                                 
1420                                 dl->parts= (nu->pntsu*nu->resolu);      /* in reverse, because makeNurbfaces works that way */
1421                                 dl->nr= (nu->pntsv*nu->resolv);
1422                                 if(nu->flagv & CU_CYCLIC) dl->flag|= DL_CYCL_U; /* reverse too! */
1423                                 if(nu->flagu & CU_CYCLIC) dl->flag|= DL_CYCL_V;
1424
1425                                 makeNurbfaces(nu, data, 0);
1426                                 
1427                                 /* gl array drawing: using indices */
1428                                 displist_surf_indices(dl);
1429                         }
1430                 }
1431         }
1432
1433         if (!forRender) {
1434                 tex_space_curve(cu);
1435         }
1436
1437         if(!forOrco)
1438                 curve_calc_modifiers_post(ob, nubase, dispbase, forRender, originalVerts, deformedVerts);
1439 }
1440
1441 void makeDispListCurveTypes(Object *ob, int forOrco)
1442 {
1443         Curve *cu = ob->data;
1444         ListBase *dispbase;
1445         
1446         /* we do allow duplis... this is only displist on curve level */
1447         if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
1448
1449         freedisplist(&(ob->disp));
1450         dispbase= &(cu->disp);
1451         freedisplist(dispbase);
1452         
1453         if(ob->type==OB_SURF) {
1454                 makeDispListSurf(ob, dispbase, 0, forOrco);
1455         }
1456         else if ELEM(ob->type, OB_CURVE, OB_FONT) {
1457                 ListBase dlbev;
1458                 float (*originalVerts)[3];
1459                 float (*deformedVerts)[3];
1460                 int obedit= (G.obedit && G.obedit->data==ob->data && G.obedit->type==OB_CURVE);
1461                 ListBase *nubase = obedit?&editNurb:&cu->nurb;
1462                 int numVerts;
1463
1464                 BLI_freelistN(&(cu->bev));
1465                 
1466                 if(cu->path) free_path(cu->path);
1467                 cu->path= NULL;
1468                 
1469                 if(ob->type==OB_FONT) text_to_curve(ob, 0);
1470                 
1471                 if(!forOrco) curve_calc_modifiers_pre(ob, nubase, 0, &originalVerts, &deformedVerts, &numVerts);
1472
1473                 makeBevelList(ob);
1474
1475                 /* If curve has no bevel will return nothing */
1476                 makebevelcurve(ob, &dlbev);
1477
1478                 /* no bevel or extrude, and no width correction? */
1479                 if (!dlbev.first && cu->width==1.0f) {
1480                         curve_to_displist(cu, nubase, dispbase);
1481                 } else {
1482                         float widfac= cu->width-1.0;
1483                         BevList *bl= cu->bev.first;
1484                         Nurb *nu= nubase->first;
1485
1486                         for (; bl && nu; bl=bl->next,nu=nu->next) {
1487                                 DispList *dl;
1488                                 float *fp1, *data;
1489                                 BevPoint *bevp;
1490                                 int a,b;
1491                                 
1492                                 if (bl->nr) { /* blank bevel lists can happen */
1493                                         
1494                                         /* exception handling; curve without bevel or extrude, with width correction */
1495                                         if(dlbev.first==NULL) {
1496                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
1497                                                 dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
1498                                                 BLI_addtail(dispbase, dl);
1499                                                 
1500                                                 if(bl->poly!= -1) dl->type= DL_POLY;
1501                                                 else dl->type= DL_SEGM;
1502                                                 
1503                                                 if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE);
1504                                                 
1505                                                 dl->parts= 1;
1506                                                 dl->nr= bl->nr;
1507                                                 dl->col= nu->mat_nr;
1508                                                 dl->charidx= nu->charidx;
1509                                                 dl->rt= nu->flag;
1510                                                 
1511                                                 a= dl->nr;
1512                                                 bevp= (BevPoint *)(bl+1);
1513                                                 data= dl->verts;
1514                                                 while(a--) {
1515                                                         data[0]= bevp->vec[0]+widfac*bevp->sina;
1516                                                         data[1]= bevp->vec[1]+widfac*bevp->cosa;
1517                                                         data[2]= bevp->vec[2];
1518                                                         bevp++;
1519                                                         data+=3;
1520                                                 }
1521                                         }
1522                                         else {
1523                                                 DispList *dlb;
1524                                                 
1525                                                 for (dlb=dlbev.first; dlb; dlb=dlb->next) {
1526         
1527                                                                 /* for each part of the bevel use a separate displblock */
1528                                                         dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
1529                                                         dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
1530                                                         BLI_addtail(dispbase, dl);
1531         
1532                                                         dl->type= DL_SURF;
1533                                                         
1534                                                         dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE);
1535                                                         if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U;
1536                                                         if(bl->poly>=0) dl->flag |= DL_CYCL_V;
1537                                                         
1538                                                         dl->parts= bl->nr;
1539                                                         dl->nr= dlb->nr;
1540                                                         dl->col= nu->mat_nr;
1541                                                         dl->charidx= nu->charidx;
1542                                                         dl->rt= nu->flag;
1543                                                         dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "col2");
1544                                                         bevp= (BevPoint *)(bl+1);
1545         
1546                                                                 /* for each point of poly make a bevel piece */
1547                                                         bevp= (BevPoint *)(bl+1);
1548                                                         for(a=0; a<bl->nr; a++,bevp++) {
1549                                                                 float fac=1.0;
1550                                                                 if (cu->taperobj==NULL) {
1551                                                                         if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) )
1552                                                                                 fac = bevp->radius;
1553                                                                 } else {
1554                                                                         fac = calc_taper(cu->taperobj, a, bl->nr);
1555                                                                 }
1556                                                                 
1557                                                                 if (bevp->split_tag) {
1558                                                                         dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F);
1559                                                                 }
1560         
1561                                                                         /* rotate bevel piece and write in data */
1562                                                                 fp1= dlb->verts;
1563                                                                 for (b=0; b<dlb->nr; b++,fp1+=3,data+=3) {
1564                                                                         if(cu->flag & CU_3D) {
1565                                                                                 float vec[3];
1566         
1567                                                                                 vec[0]= fp1[1]+widfac;
1568                                                                                 vec[1]= fp1[2];
1569                                                                                 vec[2]= 0.0;
1570                                                                                 
1571                                                                                 Mat3MulVecfl(bevp->mat, vec);
1572                                                                                 
1573                                                                                 data[0]= bevp->vec[0] + fac*vec[0];
1574                                                                                 data[1]= bevp->vec[1] + fac*vec[1];
1575                                                                                 data[2]= bevp->vec[2] + fac*vec[2];
1576                                                                         }
1577                                                                         else {
1578                                                                                 data[0]= bevp->vec[0] + fac*(widfac+fp1[1])*bevp->sina;
1579                                                                                 data[1]= bevp->vec[1] + fac*(widfac+fp1[1])*bevp->cosa;
1580                                                                                 data[2]= bevp->vec[2] + fac*fp1[2];
1581                                                                         }
1582                                                                 }
1583                                                         }
1584                                                         
1585                                                         /* gl array drawing: using indices */
1586                                                         displist_surf_indices(dl);
1587                                                 }
1588                                         }
1589                                 }
1590
1591                         }
1592                         freedisplist(&dlbev);
1593                 }
1594
1595                 curve_to_filledpoly(cu, nubase, dispbase);
1596
1597                 if(cu->flag & CU_PATH) calc_curvepath(ob);
1598
1599                 if(!forOrco) curve_calc_modifiers_post(ob, nubase, &cu->disp, 0, originalVerts, deformedVerts);
1600                 tex_space_curve(cu);
1601         }
1602         
1603         boundbox_displist(ob);
1604 }
1605
1606 void imagestodisplist(void)
1607 {
1608         /* removed */
1609 }
1610
1611 /* this is confusing, there's also min_max_object, appplying the obmat... */
1612 static void boundbox_displist(Object *ob)
1613 {
1614         BoundBox *bb=0;
1615         float min[3], max[3];
1616         DispList *dl;
1617         float *vert;
1618         int a, tot=0;
1619         
1620         INIT_MINMAX(min, max);
1621
1622         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1623                 Curve *cu= ob->data;
1624                 int doit= 0;
1625
1626                 if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");        
1627                 bb= cu->bb;
1628                 
1629                 dl= cu->disp.first;
1630
1631                 while (dl) {
1632                         if(dl->type==DL_INDEX3) tot= dl->nr;
1633                         else tot= dl->nr*dl->parts;
1634                         
1635                         vert= dl->verts;
1636                         for(a=0; a<tot; a++, vert+=3) {
1637                                 doit= 1;
1638                                 DO_MINMAX(vert, min, max);
1639                         }
1640
1641                         dl= dl->next;
1642                 }
1643                 
1644                 if(!doit) {
1645                         min[0] = min[1] = min[2] = -1.0f;
1646                         max[0] = max[1] = max[2] = 1.0f;
1647                 }
1648                 
1649         }
1650         
1651         if(bb) {
1652                 boundbox_set_from_min_max(bb, min, max);
1653         }
1654 }
1655