9aa794aa97e19571b44fab96c4ac92e4e22038e0
[blender-staging.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file blender/blenkernel/intern/displist.c
33  *  \ingroup bke
34  */
35
36
37 #include <math.h>
38 #include <stdio.h>
39 #include <string.h>
40
41 #include "MEM_guardedalloc.h"
42
43 #include "DNA_curve_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_material_types.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_math.h"
51 #include "BLI_editVert.h"
52 #include "BLI_scanfill.h"
53 #include "BLI_utildefines.h"
54
55 #include "BKE_global.h"
56 #include "BKE_displist.h"
57 #include "BKE_cdderivedmesh.h"
58 #include "BKE_object.h"
59 #include "BKE_mball.h"
60 #include "BKE_material.h"
61 #include "BKE_curve.h"
62 #include "BKE_key.h"
63 #include "BKE_anim.h"
64 #include "BKE_font.h"
65 #include "BKE_lattice.h"
66 #include "BKE_modifier.h"
67
68 #include "RE_pipeline.h"
69 #include "RE_shader_ext.h"
70
71 #include "BLO_sys_types.h" // for intptr_t support
72
73 #include "ED_curve.h" /* for BKE_curve_nurbs */
74
75 extern Material defmaterial;    /* material.c */
76
77 static void boundbox_displist(Object *ob);
78
79 void free_disp_elem(DispList *dl)
80 {
81         if(dl) {
82                 if(dl->verts) MEM_freeN(dl->verts);
83                 if(dl->nors) MEM_freeN(dl->nors);
84                 if(dl->index) MEM_freeN(dl->index);
85                 if(dl->col1) MEM_freeN(dl->col1);
86                 if(dl->col2) MEM_freeN(dl->col2);
87                 if(dl->bevelSplitFlag) MEM_freeN(dl->bevelSplitFlag);
88                 MEM_freeN(dl);
89         }
90 }
91
92 void freedisplist(ListBase *lb)
93 {
94         DispList *dl;
95
96         dl= lb->first;
97         while(dl) {
98                 BLI_remlink(lb, dl);
99                 free_disp_elem(dl);
100                 dl= lb->first;
101         }
102 }
103
104 DispList *find_displist_create(ListBase *lb, int type)
105 {
106         DispList *dl;
107         
108         dl= lb->first;
109         while(dl) {
110                 if(dl->type==type) return dl;
111                 dl= dl->next;
112         }
113
114         dl= MEM_callocN(sizeof(DispList), "find_disp");
115         dl->type= type;
116         BLI_addtail(lb, dl);
117
118         return dl;
119 }
120
121 DispList *find_displist(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         return NULL;
132 }
133
134 int displist_has_faces(ListBase *lb)
135 {
136         DispList *dl;
137         for(dl= lb->first; dl; dl= dl->next) {
138                 if ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)
139                         return 1;
140         }
141         return 0;
142 }
143
144 void copy_displist(ListBase *lbn, ListBase *lb)
145 {
146         DispList *dln, *dl;
147         
148         freedisplist(lbn);
149         
150         dl= lb->first;
151         while(dl) {
152                 
153                 dln= MEM_dupallocN(dl);
154                 BLI_addtail(lbn, dln);
155                 dln->verts= MEM_dupallocN(dl->verts);
156                 dln->nors= MEM_dupallocN(dl->nors);
157                 dln->index= MEM_dupallocN(dl->index);
158                 dln->col1= MEM_dupallocN(dl->col1);
159                 dln->col2= MEM_dupallocN(dl->col2);
160
161                 if(dl->bevelSplitFlag)
162                         dln->bevelSplitFlag= MEM_dupallocN(dl->bevelSplitFlag);
163
164                 dl= dl->next;
165         }
166 }
167
168 void addnormalsDispList(ListBase *lb)
169 {
170         DispList *dl = NULL;
171         float *vdata, *ndata, nor[3];
172         float *v1, *v2, *v3, *v4;
173         float *n1, *n2, *n3, *n4;
174         int a, b, p1, p2, p3, p4;
175
176
177         dl= lb->first;
178         
179         while(dl) {
180                 if(dl->type==DL_INDEX3) {
181                         if(dl->nors==NULL) {
182                                 dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
183                                 if(dl->verts[2] < 0.0f) dl->nors[2]= -1.0f;
184                                 else dl->nors[2]= 1.0f;
185                         }
186                 }
187                 else if(dl->type==DL_SURF) {
188                         if(dl->nors==NULL) {
189                                 dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
190                                 
191                                 vdata= dl->verts;
192                                 ndata= dl->nors;
193                                 
194                                 for(a=0; a<dl->parts; a++) {
195                                         
196                                         if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
197                                                 break;
198         
199                                         v1= vdata+ 3*p1; 
200                                         n1= ndata+ 3*p1;
201                                         v2= vdata+ 3*p2; 
202                                         n2= ndata+ 3*p2;
203                                         v3= vdata+ 3*p3; 
204                                         n3= ndata+ 3*p3;
205                                         v4= vdata+ 3*p4; 
206                                         n4= ndata+ 3*p4;
207                                         
208                                         for(; b<dl->nr; b++) {
209         
210                                                 normal_quad_v3( nor,v1, v3, v4, v2);
211         
212                                                 add_v3_v3(n1, nor);
213                                                 add_v3_v3(n2, nor);
214                                                 add_v3_v3(n3, nor);
215                                                 add_v3_v3(n4, nor);
216         
217                                                 v2= v1; v1+= 3;
218                                                 v4= v3; v3+= 3;
219                                                 n2= n1; n1+= 3;
220                                                 n4= n3; n3+= 3;
221                                         }
222                                 }
223                                 a= dl->parts*dl->nr;
224                                 v1= ndata;
225                                 while(a--) {
226                                         normalize_v3(v1);
227                                         v1+= 3;
228                                 }
229                         }
230                 }
231                 dl= dl->next;
232         }
233 }
234
235 void count_displist(ListBase *lb, int *totvert, int *totface)
236 {
237         DispList *dl;
238         
239         dl= lb->first;
240         while(dl) {
241                 
242                 switch(dl->type) {
243                         case DL_SURF:
244                                 *totvert+= dl->nr*dl->parts;
245                                 *totface+= (dl->nr-1)*(dl->parts-1);
246                                 break;
247                         case DL_INDEX3:
248                         case DL_INDEX4:
249                                 *totvert+= dl->nr;
250                                 *totface+= dl->parts;
251                                 break;
252                         case DL_POLY:
253                         case DL_SEGM:
254                                 *totvert+= dl->nr*dl->parts;
255                 }
256                 
257                 dl= dl->next;
258         }
259 }
260
261 int surfindex_displist(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
262 {
263         if((dl->flag & DL_CYCL_V)==0 && a==(dl->parts)-1) {
264                 return 0;
265         }
266         
267         if(dl->flag & DL_CYCL_U) {
268                 (*p1)= dl->nr*a;
269                 (*p2)= (*p1)+ dl->nr-1;
270                 (*p3)= (*p1)+ dl->nr;
271                 (*p4)= (*p2)+ dl->nr;
272                 (*b)= 0;
273         } else {
274                 (*p2)= dl->nr*a;
275                 (*p1)= (*p2)+1;
276                 (*p4)= (*p2)+ dl->nr;
277                 (*p3)= (*p1)+ dl->nr;
278                 (*b)= 1;
279         }
280         
281         if( (dl->flag & DL_CYCL_V) && a==dl->parts-1) {                     \
282                 (*p3)-= dl->nr*dl->parts;                                   \
283                 (*p4)-= dl->nr*dl->parts;                                   \
284         }
285         
286         return 1;
287 }
288
289 /* ***************************** shade displist. note colors now are in rgb(a) order ******************** */
290
291 /* create default shade input... save cpu cycles with ugly global */
292 /* XXXX bad code warning: local ShadeInput initialize... */
293 static ShadeInput shi;
294 static void init_fastshade_shadeinput(Render *re)
295 {
296         memset(&shi, 0, sizeof(ShadeInput));
297         shi.lay= RE_GetScene(re)->lay;
298         shi.view[2]= -1.0f;
299         shi.passflag= SCE_PASS_COMBINED;
300         shi.combinedflag= -1;
301 }
302
303 static Render *fastshade_get_render(Scene *UNUSED(scene))
304 {
305         // XXX 2.5: this crashes combined with previewrender
306         // due to global R so disabled for now
307 #if 0
308         /* XXX ugly global still, but we can't do preview while rendering */
309         if(G.rendering==0) {
310                 
311                 Render *re= RE_GetRender("_Shade View_");
312                 if(re==NULL) {
313                         re= RE_NewRender("_Shade View_");
314                 
315                         RE_Database_Baking(re, scene, 0, 0);    /* 0= no faces */
316                 }
317                 return re;
318         }
319 #endif
320         
321         return NULL;
322 }
323
324 /* called on file reading */
325 void fastshade_free_render(void)
326 {
327         Render *re= RE_GetRender("_Shade View_");
328         
329         if(re) {
330                 RE_Database_Free(re);
331                 RE_FreeRender(re);
332         }
333 }
334
335
336 static void fastshade_customdata(CustomData *fdata, int a, int j, Material *ma)
337 {
338         CustomDataLayer *layer;
339         MTFace *mtface;
340         int index, needuv= ma->texco & TEXCO_UV;
341         char *vertcol;
342
343         shi.totuv= 0;
344         shi.totcol= 0;
345
346         for(index=0; index<fdata->totlayer; index++) {
347                 layer= &fdata->layers[index];
348                 
349                 if(needuv && layer->type == CD_MTFACE && shi.totuv < MAX_MTFACE) {
350                         mtface= &((MTFace*)layer->data)[a];
351
352                         shi.uv[shi.totuv].uv[0]= 2.0f*mtface->uv[j][0]-1.0f;
353                         shi.uv[shi.totuv].uv[1]= 2.0f*mtface->uv[j][1]-1.0f;
354                         shi.uv[shi.totuv].uv[2]= 1.0f;
355
356                         shi.uv[shi.totuv].name= layer->name;
357                         shi.totuv++;
358                 }
359                 else if(layer->type == CD_MCOL && shi.totcol < MAX_MCOL) {
360                         vertcol= (char*)&((MCol*)layer->data)[a*4 + j];
361
362                         shi.col[shi.totcol].col[0]= ((float)vertcol[3])/255.0f;
363                         shi.col[shi.totcol].col[1]= ((float)vertcol[2])/255.0f;
364                         shi.col[shi.totcol].col[2]= ((float)vertcol[1])/255.0f;
365
366                         shi.col[shi.totcol].name= layer->name;
367                         shi.totcol++;
368                 }
369         }
370
371         if(needuv && shi.totuv == 0)
372                 VECCOPY(shi.uv[0].uv, shi.lo);
373
374         if(shi.totcol)
375                 VECCOPY(shi.vcol, shi.col[0].col);
376 }
377
378 static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2)
379 {
380         ShadeResult shr;
381         int a;
382         
383         VECCOPY(shi.co, co);
384         shi.vn[0]= -nor[0];
385         shi.vn[1]= -nor[1];
386         shi.vn[2]= -nor[2];
387         VECCOPY(shi.vno, shi.vn);
388         VECCOPY(shi.facenor, shi.vn);
389         
390         if(ma->texco) {
391                 VECCOPY(shi.lo, orco);
392                 
393                 if(ma->texco & TEXCO_GLOB) {
394                         VECCOPY(shi.gl, shi.lo);
395                 }
396                 if(ma->texco & TEXCO_WINDOW) {
397                         VECCOPY(shi.winco, shi.lo);
398                 }
399                 if(ma->texco & TEXCO_STICKY) {
400                         VECCOPY(shi.sticky, shi.lo);
401                 }
402                 if(ma->texco & TEXCO_OBJECT) {
403                         VECCOPY(shi.co, shi.lo);
404                 }
405                 if(ma->texco & TEXCO_NORM) {
406                         VECCOPY(shi.orn, shi.vn);
407                 }
408                 if(ma->texco & TEXCO_REFL) {
409                         float inp= 2.0f * (shi.vn[2]);
410                         shi.ref[0]= (inp*shi.vn[0]);
411                         shi.ref[1]= (inp*shi.vn[1]);
412                         shi.ref[2]= (-1.0f + inp*shi.vn[2]);
413                 }
414         }
415         
416         shi.mat= ma;    /* set each time... node shaders change it */
417         RE_shade_external(NULL, &shi, &shr);
418         
419         a= 256.0f*(shr.combined[0]);
420         col1[0]= CLAMPIS(a, 0, 255);
421         a= 256.0f*(shr.combined[1]);
422         col1[1]= CLAMPIS(a, 0, 255);
423         a= 256.0f*(shr.combined[2]);
424         col1[2]= CLAMPIS(a, 0, 255);
425         
426         if(col2) {
427                 shi.vn[0]= -shi.vn[0];
428                 shi.vn[1]= -shi.vn[1];
429                 shi.vn[2]= -shi.vn[2];
430                 
431                 shi.mat= ma;    /* set each time... node shaders change it */
432                 RE_shade_external(NULL, &shi, &shr);
433                 
434                 a= 256.0f*(shr.combined[0]);
435                 col2[0]= CLAMPIS(a, 0, 255);
436                 a= 256.0f*(shr.combined[1]);
437                 col2[1]= CLAMPIS(a, 0, 255);
438                 a= 256.0f*(shr.combined[2]);
439                 col2[2]= CLAMPIS(a, 0, 255);
440         }
441 }
442
443 static void init_fastshade_for_ob(Render *re, Object *ob, int *need_orco_r, float mat[4][4], float imat[3][3])
444 {
445         float tmat[4][4];
446         float amb[3]= {0.0f, 0.0f, 0.0f};
447         int a;
448         
449         /* initialize globals in render */
450         RE_shade_external(re, NULL, NULL);
451
452         /* initialize global here */
453         init_fastshade_shadeinput(re);
454         
455         RE_DataBase_GetView(re, tmat);
456         mul_m4_m4m4(mat, ob->obmat, tmat);
457         
458         invert_m4_m4(tmat, mat);
459         copy_m3_m4(imat, tmat);
460         if(ob->transflag & OB_NEG_SCALE) mul_m3_fl(imat, -1.0);
461         
462         if (need_orco_r) *need_orco_r= 0;
463         for(a=0; a<ob->totcol; a++) {
464                 Material *ma= give_current_material(ob, a+1);
465                 if(ma) {
466                         init_render_material(ma, 0, amb);
467
468                         if(ma->texco & TEXCO_ORCO) {
469                                 if (need_orco_r) *need_orco_r= 1;
470                         }
471                 }
472         }
473 }
474
475 static void end_fastshade_for_ob(Object *ob)
476 {
477         int a;
478         
479         for(a=0; a<ob->totcol; a++) {
480                 Material *ma= give_current_material(ob, a+1);
481                 if(ma)
482                         end_render_material(ma);
483         }
484 }
485
486
487 static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, unsigned int **col1_r, unsigned int **col2_r)
488 {
489         Mesh *me= ob->data;
490         DerivedMesh *dm;
491         MVert *mvert;
492         MFace *mface;
493         unsigned int *col1, *col2;
494         float *orco, *vnors, *nors, imat[3][3], mat[4][4], vec[3];
495         int a, i, need_orco, totface, totvert;
496         CustomDataMask dataMask = CD_MASK_BAREMESH | CD_MASK_MCOL
497                                                           | CD_MASK_MTFACE | CD_MASK_NORMAL;
498
499
500         init_fastshade_for_ob(re, ob, &need_orco, mat, imat);
501
502         if(need_orco)
503                 dataMask |= CD_MASK_ORCO;
504
505         if (onlyForMesh)
506                 dm = mesh_get_derived_deform(RE_GetScene(re), ob, dataMask);
507         else
508                 dm = mesh_get_derived_final(RE_GetScene(re), ob, dataMask);
509         
510         mvert = dm->getVertArray(dm);
511         mface = dm->getFaceArray(dm);
512         nors = dm->getFaceDataArray(dm, CD_NORMAL);
513         totvert = dm->getNumVerts(dm);
514         totface = dm->getNumFaces(dm);
515         orco= dm->getVertDataArray(dm, CD_ORCO);
516
517         if (onlyForMesh) {
518                 col1 = *col1_r;
519                 col2 = NULL;
520         } else {
521                 *col1_r = col1 = MEM_mallocN(sizeof(*col1)*totface*4, "col1");
522
523                 if (col2_r && (me->flag & ME_TWOSIDED))
524                         col2 = MEM_mallocN(sizeof(*col2)*totface*4, "col2");
525                 else
526                         col2 = NULL;
527                 
528                 if (col2_r) *col2_r = col2;
529         }
530
531                 /* vertexnormals */
532         vnors= MEM_mallocN(totvert*3*sizeof(float), "vnors disp");
533         for (a=0; a<totvert; a++) {
534                 MVert *mv = &mvert[a];
535                 float *vn= &vnors[a*3];
536                 float xn= mv->no[0]; 
537                 float yn= mv->no[1]; 
538                 float zn= mv->no[2];
539                 
540                         /* transpose ! */
541                 vn[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
542                 vn[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
543                 vn[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
544                 normalize_v3(vn);
545         }               
546
547         for (i=0; i<totface; i++) {
548                 MFace *mf= &mface[i];
549                 Material *ma= give_current_material(ob, mf->mat_nr+1);
550                 int j, vidx[4], nverts= mf->v4?4:3;
551                 unsigned char *col1base= (unsigned char*) &col1[i*4];
552                 unsigned char *col2base= (unsigned char*) (col2?&col2[i*4]:NULL);
553                 float nor[3], n1[3];
554                 
555                 if(ma==NULL) ma= &defmaterial;
556                 
557                 vidx[0]= mf->v1;
558                 vidx[1]= mf->v2;
559                 vidx[2]= mf->v3;
560                 vidx[3]= mf->v4;
561
562                 if (nors) {
563                         VECCOPY(nor, &nors[i*3]);
564                 } else {
565                         if (mf->v4)
566                                 normal_quad_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
567                         else
568                                 normal_tri_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
569                 }
570
571                 n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
572                 n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
573                 n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
574                 normalize_v3(n1);
575
576                 for (j=0; j<nverts; j++) {
577                         MVert *mv= &mvert[vidx[j]];
578                         char *col1= (char*)&col1base[j*4];
579                         char *col2= (char*)(col2base?&col2base[j*4]:NULL);
580                         float *vn = (mf->flag & ME_SMOOTH)?&vnors[3*vidx[j]]:n1;
581
582                         mul_v3_m4v3(vec, mat, mv->co);
583
584                         mul_v3_v3fl(vec, vn, 0.001f);
585
586                         fastshade_customdata(&dm->faceData, i, j, ma);
587                         fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, ma, col1, col2);
588                 }
589         } 
590         MEM_freeN(vnors);
591
592         dm->release(dm);
593
594         end_fastshade_for_ob(ob);
595 }
596
597 void shadeMeshMCol(Scene *scene, Object *ob, Mesh *me)
598 {
599         Render *re= fastshade_get_render(scene);
600         int a;
601         char *cp;
602         unsigned int *mcol= (unsigned int*)me->mcol;
603         
604         if(re) {
605                 mesh_create_shadedColors(re, ob, 1, &mcol, NULL);
606                 me->mcol= (MCol*)mcol;
607
608                 /* swap bytes */
609                 for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) {
610                         SWAP(char, cp[0], cp[3]);
611                         SWAP(char, cp[1], cp[2]);
612                 }
613         }
614 }
615
616 /* has base pointer, to check for layer */
617 /* called from drawobject.c */
618 void shadeDispList(Scene *scene, Base *base)
619 {
620         Object *ob= base->object;
621         DispList *dl, *dlob;
622         Material *ma = NULL;
623         Render *re;
624         float imat[3][3], mat[4][4], vec[3];
625         float *fp, *nor, n1[3];
626         unsigned int *col1;
627         int a, need_orco;
628         
629         re= fastshade_get_render(scene);
630         if(re==NULL)
631                 return;
632         
633         dl = find_displist(&ob->disp, DL_VERTCOL);
634         if (dl) {
635                 BLI_remlink(&ob->disp, dl);
636                 free_disp_elem(dl);
637         }
638
639         if(ob->type==OB_MESH) {
640                 dl= MEM_callocN(sizeof(DispList), "displistshade");
641                 dl->type= DL_VERTCOL;
642
643                 mesh_create_shadedColors(re, ob, 0, &dl->col1, &dl->col2);
644
645                 /* add dl to ob->disp after mesh_create_shadedColors, because it
646                    might indirectly free ob->disp */
647                 BLI_addtail(&ob->disp, dl);
648         }
649         else {
650
651                 init_fastshade_for_ob(re, ob, &need_orco, mat, imat);
652                 
653                 if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
654                 
655                         /* now we need the normals */
656                         dl= ob->disp.first;
657                         
658                         while(dl) {
659                                 dlob= MEM_callocN(sizeof(DispList), "displistshade");
660                                 BLI_addtail(&ob->disp, dlob);
661                                 dlob->type= DL_VERTCOL;
662                                 dlob->parts= dl->parts;
663                                 dlob->nr= dl->nr;
664                                 
665                                 if(dl->type==DL_INDEX3) {
666                                         col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
667                                 }
668                                 else {
669                                         col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1");
670                                 }
671                                 
672                         
673                                 ma= give_current_material(ob, dl->col+1);
674                                 if(ma==NULL) ma= &defmaterial;
675                                 
676                                 if(dl->type==DL_INDEX3) {
677                                         if(dl->nors) {
678                                                 /* there's just one normal */
679                                                 n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2];
680                                                 n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2];
681                                                 n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2];
682                                                 normalize_v3(n1);
683                                                 
684                                                 fp= dl->verts;
685                                                 
686                                                 a= dl->nr;              
687                                                 while(a--) {
688                                                         mul_v3_m4v3(vec, mat, fp);
689                                                         
690                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
691                                                         
692                                                         fp+= 3; col1++;
693                                                 }
694                                         }
695                                 }
696                                 else if(dl->type==DL_SURF) {
697                                         if(dl->nors) {
698                                                 a= dl->nr*dl->parts;
699                                                 fp= dl->verts;
700                                                 nor= dl->nors;
701                                                 
702                                                 while(a--) {
703                                                         mul_v3_m4v3(vec, mat, fp);
704                                                         
705                                                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
706                                                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
707                                                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
708                                                         normalize_v3(n1);
709                                 
710                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
711                                                         
712                                                         fp+= 3; nor+= 3; col1++;
713                                                 }
714                                         }
715                                 }
716                                 dl= dl->next;
717                         }
718                 }
719                 else if(ob->type==OB_MBALL) {
720                         /* there are normals already */
721                         dl= ob->disp.first;
722                         
723                         while(dl) {
724                                 
725                                 if(dl->type==DL_INDEX4) {
726                                         if(dl->nors) {
727                                                 if(dl->col1) MEM_freeN(dl->col1);
728                                                 col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
729                                 
730                                                 ma= give_current_material(ob, dl->col+1);
731                                                 if(ma==NULL) ma= &defmaterial;
732                                                 
733                                                 fp= dl->verts;
734                                                 nor= dl->nors;
735                                                 
736                                                 a= dl->nr;              
737                                                 while(a--) {
738                                                         mul_v3_m4v3(vec, mat, fp);
739                                                         
740                                                         /* transpose ! */
741                                                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
742                                                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
743                                                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
744                                                         normalize_v3(n1);
745                                                 
746                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
747                                                         
748                                                         fp+= 3; col1++; nor+= 3;
749                                                 }
750                                         }
751                                 }
752                                 dl= dl->next;
753                         }
754                 }
755                 
756                 end_fastshade_for_ob(ob);
757         }
758 }
759
760 /* frees render and shade part of displists */
761 /* note: dont do a shade again, until a redraw happens */
762 void reshadeall_displist(Scene *scene)
763 {
764         Base *base;
765         Object *ob;
766         
767         fastshade_free_render();
768         
769         for(base= scene->base.first; base; base= base->next) {
770                 ob= base->object;
771
772                 if(ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL))
773                         freedisplist(&ob->disp);
774
775                 if(base->lay & scene->lay) {
776                         /* Metaballs have standard displist at the Object */
777                         if(ob->type==OB_MBALL) shadeDispList(scene, base);
778                 }
779         }
780 }
781
782 /* ****************** make displists ********************* */
783
784 static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, int forRender)
785 {
786         Nurb *nu;
787         DispList *dl;
788         BezTriple *bezt, *prevbezt;
789         BPoint *bp;
790         float *data;
791         int a, len, resolu;
792         
793         nu= nubase->first;
794         while(nu) {
795                 if(nu->hide==0) {
796                         
797                         if(forRender && cu->resolu_ren!=0)
798                                 resolu= cu->resolu_ren;
799                         else
800                                 resolu= nu->resolu;
801                         
802                         if(!check_valid_nurb_u(nu));
803                         else if(nu->type == CU_BEZIER) {
804                                 
805                                 /* count */
806                                 len= 0;
807                                 a= nu->pntsu-1;
808                                 if(nu->flagu & CU_NURB_CYCLIC) a++;
809
810                                 prevbezt= nu->bezt;
811                                 bezt= prevbezt+1;
812                                 while(a--) {
813                                         if(a==0 && (nu->flagu & CU_NURB_CYCLIC)) bezt= nu->bezt;
814                                         
815                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
816                                         else len+= resolu;
817                                         
818                                         if(a==0 && (nu->flagu & CU_NURB_CYCLIC)==0) len++;
819                                         
820                                         prevbezt= bezt;
821                                         bezt++;
822                                 }
823                                 
824                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
825                                 /* len+1 because of 'forward_diff_bezier' function */
826                                 dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
827                                 BLI_addtail(dispbase, dl);
828                                 dl->parts= 1;
829                                 dl->nr= len;
830                                 dl->col= nu->mat_nr;
831                                 dl->charidx= nu->charidx;
832
833                                 data= dl->verts;
834
835                                 if(nu->flagu & CU_NURB_CYCLIC) {
836                                         dl->type= DL_POLY;
837                                         a= nu->pntsu;
838                                 }
839                                 else {
840                                         dl->type= DL_SEGM;
841                                         a= nu->pntsu-1;
842                                 }
843                                 
844                                 prevbezt= nu->bezt;
845                                 bezt= prevbezt+1;
846                                 
847                                 while(a--) {
848                                         if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
849                                         
850                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
851                                                 VECCOPY(data, prevbezt->vec[1]);
852                                                 data+= 3;
853                                         }
854                                         else {
855                                                 int j;
856                                                 for(j=0; j<3; j++) {
857                                                         forward_diff_bezier(    prevbezt->vec[1][j],
858                                                                                                         prevbezt->vec[2][j],
859                                                                                                         bezt->vec[0][j],
860                                                                                                         bezt->vec[1][j],
861                                                                                                         data+j, resolu, 3*sizeof(float));
862                                                 }
863                                                 
864                                                 data+= 3*resolu;
865                                         }
866                                         
867                                         if(a==0 && dl->type==DL_SEGM) {
868                                                 VECCOPY(data, bezt->vec[1]);
869                                         }
870                                         
871                                         prevbezt= bezt;
872                                         bezt++;
873                                 }
874                         }
875                         else if(nu->type == CU_NURBS) {
876                                 len= (resolu*SEGMENTSU(nu));
877                                 
878                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
879                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
880                                 BLI_addtail(dispbase, dl);
881                                 dl->parts= 1;
882                                 
883                                 dl->nr= len;
884                                 dl->col= nu->mat_nr;
885                                 dl->charidx = nu->charidx;
886
887                                 data= dl->verts;
888                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
889                                 else dl->type= DL_SEGM;
890                                 makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float));
891                         }
892                         else if(nu->type == CU_POLY) {
893                                 len= nu->pntsu;
894                                 dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
895                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
896                                 BLI_addtail(dispbase, dl);
897                                 dl->parts= 1;
898                                 dl->nr= len;
899                                 dl->col= nu->mat_nr;
900                                 dl->charidx = nu->charidx;
901
902                                 data= dl->verts;
903                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
904                                 else dl->type= DL_SEGM;
905                                 
906                                 a= len;
907                                 bp= nu->bp;
908                                 while(a--) {
909                                         VECCOPY(data, bp->vec);
910                                         bp++;
911                                         data+= 3;
912                                 }
913                         }
914                 }
915                 nu= nu->next;
916         }
917 }
918
919
920 void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal)
921 {
922         EditVert *eve, *v1, *vlast;
923         EditFace *efa;
924         DispList *dlnew=NULL, *dl;
925         float *f1;
926         int colnr=0, charidx=0, cont=1, tot, a, *index, nextcol= 0;
927         intptr_t totvert;
928         
929         if(dispbase==NULL) return;
930         if(dispbase->first==NULL) return;
931
932         while(cont) {
933                 cont= 0;
934                 totvert= 0;
935                 nextcol= 0;
936                 
937                 dl= dispbase->first;
938                 while(dl) {
939         
940                         if(dl->type==DL_POLY) {
941                                 if(charidx<dl->charidx) cont= 1;
942                                 else if(charidx==dl->charidx) { /* character with needed index */
943                                         if(colnr==dl->col) {
944                                                 /* make editverts and edges */
945                                                 f1= dl->verts;
946                                                 a= dl->nr;
947                                                 eve= v1= NULL;
948                                                 
949                                                 while(a--) {
950                                                         vlast= eve;
951
952                                                         eve= BLI_addfillvert(f1);
953                                                         totvert++;
954
955                                                         if(vlast==NULL) v1= eve;
956                                                         else {
957                                                                 BLI_addfilledge(vlast, eve);
958                                                         }
959                                                         f1+=3;
960                                                 }
961
962                                                 if(eve!=NULL && v1!=NULL) {
963                                                         BLI_addfilledge(eve, v1);
964                                                 }
965                                         } else if (colnr<dl->col) {
966                                                 /* got poly with next material at current char */
967                                                 cont= 1;
968                                                 nextcol= 1;
969                                         }
970                                 }
971                         }
972                         dl= dl->next;
973                 }
974                 
975                 if(totvert && (tot= BLI_edgefill(0))) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) {
976                         if(tot) {
977                                 dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
978                                 dlnew->type= DL_INDEX3;
979                                 dlnew->col= colnr;
980                                 dlnew->nr= totvert;
981                                 dlnew->parts= tot;
982
983                                 dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
984                                 dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
985                                 
986                                 /* vert data */
987                                 f1= dlnew->verts;
988                                 totvert= 0;
989                                 eve= fillvertbase.first;
990                                 while(eve) {
991                                         VECCOPY(f1, eve->co);
992                                         f1+= 3;
993         
994                                         /* index number */
995                                         eve->tmp.l = totvert;
996                                         totvert++;
997                                         
998                                         eve= eve->next;
999                                 }
1000                                 
1001                                 /* index data */
1002                                 efa= fillfacebase.first;
1003                                 index= dlnew->index;
1004                                 while(efa) {
1005                                         index[0]= (intptr_t)efa->v1->tmp.l;
1006                                         index[1]= (intptr_t)efa->v2->tmp.l;
1007                                         index[2]= (intptr_t)efa->v3->tmp.l;
1008
1009                                         if(flipnormal)
1010                                                 SWAP(int, index[0], index[2]);
1011                                         
1012                                         index+= 3;
1013                                         efa= efa->next;
1014                                 }
1015                         }
1016
1017                         BLI_addhead(to, dlnew);
1018                         
1019                 }
1020                 BLI_end_edgefill();
1021
1022                 if(nextcol) {
1023                         /* stay at current char but fill polys with next material */
1024                         colnr++;
1025                 } else {
1026                         /* switch to next char and start filling from first material */
1027                         charidx++;
1028                         colnr= 0;
1029                 }
1030         }
1031         
1032         /* do not free polys, needed for wireframe display */
1033         
1034 }
1035
1036 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
1037 {
1038         ListBase front, back;
1039         DispList *dl, *dlnew;
1040         float *fp, *fp1;
1041         int a, dpoly;
1042         
1043         front.first= front.last= back.first= back.last= NULL;
1044         
1045         dl= dispbase->first;
1046         while(dl) {
1047                 if(dl->type==DL_SURF) {
1048                         if( (dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)==0 ) {
1049                                 if( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE) ) {
1050                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1051                                         BLI_addtail(&front, dlnew);
1052                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1053                                         dlnew->nr= dl->parts;
1054                                         dlnew->parts= 1;
1055                                         dlnew->type= DL_POLY;
1056                                         dlnew->col= dl->col;
1057                                         dlnew->charidx = dl->charidx;
1058                                         
1059                                         fp= dl->verts;
1060                                         dpoly= 3*dl->nr;
1061                                         
1062                                         a= dl->parts;
1063                                         while(a--) {
1064                                                 VECCOPY(fp1, fp);
1065                                                 fp1+= 3;
1066                                                 fp+= dpoly;
1067                                         }
1068                                 }
1069                                 if( (cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE) ) {
1070                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1071                                         BLI_addtail(&back, dlnew);
1072                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1073                                         dlnew->nr= dl->parts;
1074                                         dlnew->parts= 1;
1075                                         dlnew->type= DL_POLY;
1076                                         dlnew->col= dl->col;
1077                                         dlnew->charidx= dl->charidx;
1078                                         
1079                                         fp= dl->verts+3*(dl->nr-1);
1080                                         dpoly= 3*dl->nr;
1081                                         
1082                                         a= dl->parts;
1083                                         while(a--) {
1084                                                 VECCOPY(fp1, fp);
1085                                                 fp1+= 3;
1086                                                 fp+= dpoly;
1087                                         }
1088                                 }
1089                         }
1090                 }
1091                 dl= dl->next;
1092         }
1093
1094         filldisplist(&front, dispbase, 1);
1095         filldisplist(&back, dispbase, 0);
1096         
1097         freedisplist(&front);
1098         freedisplist(&back);
1099
1100         filldisplist(dispbase, dispbase, 0);
1101         
1102 }
1103
1104 static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
1105 {
1106         if(cu->flag & CU_3D) return;
1107
1108         if(dispbase->first && ((DispList*) dispbase->first)->type==DL_SURF) {
1109                 bevels_to_filledpoly(cu, dispbase);
1110         }
1111         else {
1112                 filldisplist(dispbase, dispbase, 0);
1113         }
1114 }
1115
1116 /* taper rules:
1117   - only 1 curve
1118   - first point left, last point right
1119   - based on subdivided points in original curve, not on points in taper curve (still)
1120 */
1121 float calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
1122 {
1123         DispList *dl;
1124         
1125         if(taperobj==NULL || taperobj->type!=OB_CURVE) return 1.0;
1126         
1127         dl= taperobj->disp.first;
1128         if(dl==NULL) {
1129                 makeDispListCurveTypes(scene, taperobj, 0);
1130                 dl= taperobj->disp.first;
1131         }
1132         if(dl) {
1133                 float fac= ((float)cur)/(float)(tot-1);
1134                 float minx, dx, *fp;
1135                 int a;
1136                 
1137                 /* horizontal size */
1138                 minx= dl->verts[0];
1139                 dx= dl->verts[3*(dl->nr-1)] - minx;
1140                 if(dx > 0.0f) {
1141                 
1142                         fp= dl->verts;
1143                         for(a=0; a<dl->nr; a++, fp+=3) {
1144                                 if( (fp[0]-minx)/dx >= fac) {
1145                                         /* interpolate with prev */
1146                                         if(a>0) {
1147                                                 float fac1= (fp[-3]-minx)/dx;
1148                                                 float fac2= (fp[0]-minx)/dx;
1149                                                 if(fac1!=fac2)
1150                                                         return fp[1]*(fac1-fac)/(fac1-fac2) + fp[-2]*(fac-fac2)/(fac1-fac2);
1151                                         }
1152                                         return fp[1];
1153                                 }
1154                         }
1155                         return fp[-2];  // last y coord
1156                 }
1157         }
1158         
1159         return 1.0;
1160 }
1161
1162 void makeDispListMBall(Scene *scene, Object *ob)
1163 {
1164         if(!ob || ob->type!=OB_MBALL) return;
1165
1166         // XXX: mball stuff uses plenty of global variables
1167         //      while this is unchanged updating during render is unsafe
1168         if(G.rendering) return;
1169
1170         freedisplist(&(ob->disp));
1171
1172         if(ob->type==OB_MBALL) {
1173                 if(ob==find_basis_mball(scene, ob)) {
1174                         metaball_polygonize(scene, ob, &ob->disp);
1175                         tex_space_mball(ob);
1176
1177                         object_deform_mball(ob, &ob->disp);
1178                 }
1179         }
1180         
1181         boundbox_displist(ob);
1182 }
1183
1184 void makeDispListMBall_forRender(Scene *scene, Object *ob, ListBase *dispbase)
1185 {
1186         metaball_polygonize(scene, ob, dispbase);
1187         tex_space_mball(ob);
1188         
1189         object_deform_mball(ob, dispbase);
1190 }
1191
1192 static ModifierData *curve_get_tesselate_point(Scene *scene, Object *ob, int forRender, int editmode)
1193 {
1194         ModifierData *md = modifiers_getVirtualModifierList(ob);
1195         ModifierData *preTesselatePoint;
1196         int required_mode;
1197
1198         if(forRender) required_mode = eModifierMode_Render;
1199         else required_mode = eModifierMode_Realtime;
1200
1201         if(editmode) required_mode |= eModifierMode_Editmode;
1202
1203         preTesselatePoint = NULL;
1204         for (; md; md=md->next) {
1205                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1206
1207                 if (!modifier_isEnabled(scene, md, required_mode)) continue;
1208                 if (mti->type == eModifierTypeType_Constructive) return preTesselatePoint;
1209
1210                 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
1211                         preTesselatePoint = md;
1212
1213                         /* this modifiers are moving point of tesselation automatically
1214                            (some of them even can't be applied on tesselated curve), set flag
1215                            for incformation button in modifier's header */
1216                         md->mode |= eModifierMode_ApplyOnSpline;
1217                 } else if(md->mode&eModifierMode_ApplyOnSpline) {
1218                         preTesselatePoint = md;
1219                 }
1220         }
1221
1222         return preTesselatePoint;
1223 }
1224
1225 static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, float (**originalVerts_r)[3], float (**deformedVerts_r)[3], int *numVerts_r)
1226 {
1227         ModifierData *md = modifiers_getVirtualModifierList(ob);
1228         ModifierData *preTesselatePoint;
1229         Curve *cu= ob->data;
1230         ListBase *nurb= BKE_curve_nurbs(cu);
1231         int numVerts = 0;
1232         int editmode = (!forRender && cu->editnurb);
1233         float (*originalVerts)[3] = NULL;
1234         float (*deformedVerts)[3] = NULL;
1235         float *keyVerts= NULL;
1236         int required_mode;
1237
1238         if(forRender) required_mode = eModifierMode_Render;
1239         else required_mode = eModifierMode_Realtime;
1240
1241         preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode);
1242         
1243         if(editmode) required_mode |= eModifierMode_Editmode;
1244
1245         if(cu->editnurb==NULL) {
1246                 keyVerts= do_ob_key(scene, ob);
1247
1248                 if(keyVerts) {
1249                         /* split coords from key data, the latter also includes
1250                            tilts, which is passed through in the modifier stack.
1251                            this is also the reason curves do not use a virtual
1252                            shape key modifier yet. */
1253                         deformedVerts= curve_getKeyVertexCos(cu, nurb, keyVerts);
1254                         originalVerts= MEM_dupallocN(deformedVerts);
1255                 }
1256         }
1257         
1258         if (preTesselatePoint) {
1259                 for (; md; md=md->next) {
1260                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1261
1262                         md->scene= scene;
1263                         
1264                         if ((md->mode & required_mode) != required_mode) continue;
1265                         if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
1266                         if (mti->type!=eModifierTypeType_OnlyDeform) continue;
1267
1268                         if (!deformedVerts) {
1269                                 deformedVerts = curve_getVertexCos(cu, nurb, &numVerts);
1270                                 originalVerts = MEM_dupallocN(deformedVerts);
1271                         }
1272
1273                         mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, forRender, editmode);
1274
1275                         if (md==preTesselatePoint)
1276                                 break;
1277                 }
1278         }
1279
1280         if (deformedVerts)
1281                 curve_applyVertexCos(cu, nurb, deformedVerts);
1282         if (keyVerts) /* these are not passed through modifier stack */
1283                 curve_applyKeyVertexTilts(cu, nurb, keyVerts);
1284
1285         if(keyVerts)
1286                 MEM_freeN(keyVerts);
1287
1288         *originalVerts_r = originalVerts;
1289         *deformedVerts_r = deformedVerts;
1290         *numVerts_r = numVerts;
1291 }
1292
1293 static float (*displist_get_allverts (ListBase *dispbase, int *totvert))[3]
1294 {
1295         DispList *dl;
1296         float (*allverts)[3], *fp;
1297
1298         *totvert= 0;
1299
1300         for (dl=dispbase->first; dl; dl=dl->next)
1301                 *totvert+= (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr;
1302
1303         allverts= MEM_mallocN((*totvert)*sizeof(float)*3, "displist_get_allverts allverts");
1304         fp= (float*)allverts;
1305         for (dl=dispbase->first; dl; dl=dl->next) {
1306                 int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
1307                 memcpy(fp, dl->verts, sizeof(float) * offs);
1308                 fp+= offs;
1309         }
1310
1311         return allverts;
1312 }
1313
1314 static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
1315 {
1316         DispList *dl;
1317         float *fp;
1318
1319         fp= (float*)allverts;
1320         for (dl=dispbase->first; dl; dl=dl->next) {
1321                 int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
1322                 memcpy(dl->verts, fp, sizeof(float) * offs);
1323                 fp+= offs;
1324         }
1325 }
1326
1327 static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase,
1328         DerivedMesh **derivedFinal, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3])
1329 {
1330         ModifierData *md = modifiers_getVirtualModifierList(ob);
1331         ModifierData *preTesselatePoint;
1332         Curve *cu= ob->data;
1333         ListBase *nurb= BKE_curve_nurbs(cu);
1334         int required_mode = 0, totvert = 0;
1335         int editmode = (!forRender && cu->editnurb);
1336         DerivedMesh *dm= NULL, *ndm;
1337         float (*vertCos)[3] = NULL;
1338
1339         if(forRender) required_mode = eModifierMode_Render;
1340         else required_mode = eModifierMode_Realtime;
1341
1342         preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode);
1343         
1344         if(editmode) required_mode |= eModifierMode_Editmode;
1345
1346         if (preTesselatePoint) {
1347                 md = preTesselatePoint->next;
1348         }
1349
1350         if (derivedFinal && *derivedFinal) {
1351                 (*derivedFinal)->release (*derivedFinal);
1352         }
1353
1354         for (; md; md=md->next) {
1355                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1356
1357                 md->scene= scene;
1358
1359                 if ((md->mode & required_mode) != required_mode) continue;
1360                 if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
1361
1362                 if (mti->type == eModifierTypeType_OnlyDeform ||
1363                                 (mti->type == eModifierTypeType_DeformOrConstruct && !dm)) {
1364                         if (dm) {
1365                                 if (!vertCos) {
1366                                         totvert = dm->getNumVerts(dm);
1367                                         vertCos = MEM_mallocN(sizeof(*vertCos) * totvert, "dfmv");
1368                                         dm->getVertCos(dm, vertCos);
1369                                 }
1370
1371                                 mti->deformVerts(md, ob, dm, vertCos, totvert, forRender, editmode);
1372                         } else {
1373                                 if (!vertCos) {
1374                                         vertCos= displist_get_allverts(dispbase, &totvert);
1375                                 }
1376
1377                                 mti->deformVerts(md, ob, NULL, vertCos, totvert, forRender, editmode);
1378                         }
1379                 } else {
1380                         if (!derivedFinal) {
1381                                 /* makeDisplistCurveTypes could be used for beveling, where derived mesh */
1382                                 /* is totally unnecessary, so we could stop modifiers applying */
1383                                 /* when we found constructive modifier but derived mesh is unwanted result */
1384                                 break;
1385                         }
1386
1387                         if (dm) {
1388                                 if (vertCos) {
1389                                         DerivedMesh *tdm = CDDM_copy(dm);
1390                                         dm->release(dm);
1391                                         dm = tdm;
1392
1393                                         CDDM_apply_vert_coords(dm, vertCos);
1394                                         CDDM_calc_normals(dm);
1395                                 }
1396                         } else {
1397                                 if (vertCos) {
1398                                         displist_apply_allverts(dispbase, vertCos);
1399                                 }
1400
1401                                 if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
1402                                         curve_to_filledpoly(cu, nurb, dispbase);
1403                                 }
1404
1405                                 dm= CDDM_from_curve_customDB(ob, dispbase);
1406
1407                                 CDDM_calc_normals(dm);
1408                         }
1409
1410                         if (vertCos) {
1411                                 /* Vertex coordinates were applied to necessary data, could free it */
1412                                 MEM_freeN(vertCos);
1413                                 vertCos= NULL;
1414                         }
1415
1416                         ndm = mti->applyModifier(md, ob, dm, forRender, editmode);
1417
1418                         if (ndm) {
1419                                 /* Modifier returned a new derived mesh */
1420
1421                                 if (dm && dm != ndm) /* Modifier  */
1422                                         dm->release (dm);
1423                                 dm = ndm;
1424                         }
1425                 }
1426         }
1427
1428         if (vertCos) {
1429                 if (dm) {
1430                         DerivedMesh *tdm = CDDM_copy(dm);
1431                         dm->release(dm);
1432                         dm = tdm;
1433
1434                         CDDM_apply_vert_coords(dm, vertCos);
1435                         CDDM_calc_normals(dm);
1436                         MEM_freeN(vertCos);
1437                 } else {
1438                         displist_apply_allverts(dispbase, vertCos);
1439                         MEM_freeN(vertCos);
1440                         vertCos= NULL;
1441                 }
1442         }
1443
1444         if (derivedFinal) {
1445                 (*derivedFinal) = dm;
1446         }
1447
1448         if (deformedVerts) {
1449                 curve_applyVertexCos(ob->data, nurb, originalVerts);
1450                 MEM_freeN(originalVerts);
1451                 MEM_freeN(deformedVerts);
1452         }
1453 }
1454
1455 static void displist_surf_indices(DispList *dl)
1456 {
1457         int a, b, p1, p2, p3, p4;
1458         int *index;
1459         
1460         dl->totindex= 0;
1461         
1462         index=dl->index= MEM_mallocN( 4*sizeof(int)*(dl->parts+1)*(dl->nr+1), "index array nurbs");
1463         
1464         for(a=0; a<dl->parts; a++) {
1465                 
1466                 if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
1467                         break;
1468                 
1469                 for(; b<dl->nr; b++, index+=4) {        
1470                         index[0]= p1;
1471                         index[1]= p2;
1472                         index[2]= p4;
1473                         index[3]= p3;
1474                         
1475                         dl->totindex++;
1476                         
1477                         p2= p1; p1++;
1478                         p4= p3; p3++;
1479
1480                 }
1481         }
1482         
1483 }
1484
1485 static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
1486 {
1487         DerivedMesh *dm;
1488         ListBase disp= {NULL, NULL};
1489
1490         /* OrcoDM should be created from underformed disp lists */
1491         makeDispListCurveTypes_forOrco(scene, ob, &disp);
1492         dm= CDDM_from_curve_customDB(ob, &disp);
1493
1494         freedisplist(&disp);
1495
1496         return dm;
1497 }
1498
1499 static void add_orco_dm(Scene *scene, Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
1500 {
1501         float (*orco)[3], (*layerorco)[3];
1502         int totvert, a;
1503         Curve *cu= ob->data;
1504
1505         totvert= dm->getNumVerts(dm);
1506
1507         if(orcodm) {
1508                 orco= MEM_callocN(sizeof(float)*3*totvert, "dm orco");
1509
1510                 if(orcodm->getNumVerts(orcodm) == totvert)
1511                         orcodm->getVertCos(orcodm, orco);
1512                 else
1513                         dm->getVertCos(dm, orco);
1514         }
1515         else {
1516                 orco= (float(*)[3])make_orco_curve(scene, ob);
1517         }
1518
1519         for(a=0; a<totvert; a++) {
1520                 float *co = orco[a];
1521                 co[0] = (co[0]-cu->loc[0])/cu->size[0];
1522                 co[1] = (co[1]-cu->loc[1])/cu->size[1];
1523                 co[2] = (co[2]-cu->loc[2])/cu->size[2];
1524         }
1525
1526         if((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
1527                 memcpy(layerorco, orco, sizeof(float)*totvert);
1528                 MEM_freeN(orco);
1529         }
1530         else
1531                 DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
1532 }
1533
1534 static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender)
1535 {
1536         /* this function represents logic of mesh's orcodm calculation */
1537         /* for displist-based objects */
1538
1539         ModifierData *md = modifiers_getVirtualModifierList(ob);
1540         ModifierData *preTesselatePoint;
1541         Curve *cu= ob->data;
1542         int required_mode;
1543         int editmode = (!forRender && cu->editnurb);
1544         DerivedMesh *ndm, *orcodm= NULL;
1545
1546         if(forRender) required_mode = eModifierMode_Render;
1547         else required_mode = eModifierMode_Realtime;
1548
1549         preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode);
1550
1551         if(editmode) required_mode |= eModifierMode_Editmode;
1552
1553         if (preTesselatePoint) {
1554                 md = preTesselatePoint->next;
1555         }
1556
1557         for (; md; md=md->next) {
1558                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1559
1560                 md->scene= scene;
1561
1562                 if ((md->mode & required_mode) != required_mode) continue;
1563                 if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
1564                 if (mti->type!=eModifierTypeType_Constructive) continue;
1565
1566                 if(!orcodm)
1567                         orcodm= create_orco_dm(scene, ob);
1568
1569                 ndm = mti->applyModifier(md, ob, orcodm, forRender, 0);
1570
1571                 if(ndm) {
1572                         /* if the modifier returned a new dm, release the old one */
1573                         if(orcodm && orcodm != ndm) {
1574                                 orcodm->release(orcodm);
1575                         }
1576                         orcodm = ndm;
1577                 }
1578         }
1579
1580         /* add an orco layer if needed */
1581         add_orco_dm(scene, ob, derivedFinal, orcodm);
1582
1583         if(orcodm)
1584                 orcodm->release(orcodm);
1585 }
1586
1587 void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
1588         DerivedMesh **derivedFinal, int forRender, int forOrco)
1589 {
1590         ListBase *nubase;
1591         Nurb *nu;
1592         Curve *cu = ob->data;
1593         DispList *dl;
1594         float *data;
1595         int len;
1596         int numVerts;
1597         float (*originalVerts)[3];
1598         float (*deformedVerts)[3];
1599
1600         if(!forRender && cu->editnurb)
1601                 nubase= ED_curve_editnurbs(cu);
1602         else
1603                 nubase= &cu->nurb;
1604
1605         if(!forOrco)
1606                 curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);
1607
1608         for (nu=nubase->first; nu; nu=nu->next) {
1609                 if(forRender || nu->hide==0) {
1610                         int resolu= nu->resolu, resolv= nu->resolv;
1611
1612                         if(forRender){
1613                                 if(cu->resolu_ren) resolu= cu->resolu_ren;
1614                                 if(cu->resolv_ren) resolv= cu->resolv_ren;
1615                         }
1616
1617                         if(nu->pntsv==1) {
1618                                 len= SEGMENTSU(nu)*resolu;
1619
1620                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1621                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1622
1623                                 BLI_addtail(dispbase, dl);
1624                                 dl->parts= 1;
1625                                 dl->nr= len;
1626                                 dl->col= nu->mat_nr;
1627                                 dl->charidx= nu->charidx;
1628
1629                                 /* dl->rt will be used as flag for render face and */
1630                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1631                                 dl->rt= nu->flag & ~CU_2D;
1632
1633                                 data= dl->verts;
1634                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
1635                                 else dl->type= DL_SEGM;
1636
1637                                 makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float));
1638                         }
1639                         else {
1640                                 len= (nu->pntsu*resolu) * (nu->pntsv*resolv);
1641                                 
1642                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1643                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1644                                 BLI_addtail(dispbase, dl);
1645
1646                                 dl->col= nu->mat_nr;
1647                                 dl->charidx= nu->charidx;
1648
1649                                 /* dl->rt will be used as flag for render face and */
1650                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1651                                 dl->rt= nu->flag & ~CU_2D;
1652
1653                                 data= dl->verts;
1654                                 dl->type= DL_SURF;
1655
1656                                 dl->parts= (nu->pntsu*resolu);  /* in reverse, because makeNurbfaces works that way */
1657                                 dl->nr= (nu->pntsv*resolv);
1658                                 if(nu->flagv & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_U;    /* reverse too! */
1659                                 if(nu->flagu & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_V;
1660
1661                                 makeNurbfaces(nu, data, 0, resolu, resolv);
1662                                 
1663                                 /* gl array drawing: using indices */
1664                                 displist_surf_indices(dl);
1665                         }
1666                 }
1667         }
1668
1669         /* make copy of 'undeformed" displist for texture space calculation
1670            actually, it's not totally undeformed -- pre-tesselation modifiers are
1671            already applied, thats how it worked for years, so keep for compatibility (sergey) */
1672         copy_displist(&cu->disp, dispbase);
1673
1674         if (!forRender) {
1675                 tex_space_curve(cu);
1676         }
1677
1678         if(!forOrco)
1679                 curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal,
1680                         forRender, originalVerts, deformedVerts);
1681 }
1682
1683 static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
1684         DerivedMesh **derivedFinal, int forRender, int forOrco)
1685 {
1686         Curve *cu = ob->data;
1687
1688         /* we do allow duplis... this is only displist on curve level */
1689         if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
1690
1691         if(ob->type==OB_SURF) {
1692                 makeDispListSurf(scene, ob, dispbase, derivedFinal, forRender, forOrco);
1693         }
1694         else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
1695                 ListBase dlbev;
1696                 ListBase *nubase;
1697                 float (*originalVerts)[3];
1698                 float (*deformedVerts)[3];
1699                 int numVerts;
1700
1701                 nubase= BKE_curve_nurbs(cu);
1702
1703                 BLI_freelistN(&(cu->bev));
1704
1705                 if(cu->path) free_path(cu->path);
1706                 cu->path= NULL;
1707
1708                 if(ob->type==OB_FONT) BKE_text_to_curve(scene, ob, 0);
1709
1710                 if(!forOrco) curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);
1711
1712                 makeBevelList(ob);
1713
1714                 /* If curve has no bevel will return nothing */
1715                 makebevelcurve(scene, ob, &dlbev, forRender);
1716
1717                 /* no bevel or extrude, and no width correction? */
1718                 if (!dlbev.first && cu->width==1.0f) {
1719                         curve_to_displist(cu, nubase, dispbase, forRender);
1720                 } else {
1721                         float widfac= cu->width - 1.0f;
1722                         BevList *bl= cu->bev.first;
1723                         Nurb *nu= nubase->first;
1724
1725                         for (; bl && nu; bl=bl->next,nu=nu->next) {
1726                                 DispList *dl;
1727                                 float *fp1, *data;
1728                                 BevPoint *bevp;
1729                                 int a,b;
1730
1731                                 if (bl->nr) { /* blank bevel lists can happen */
1732
1733                                         /* exception handling; curve without bevel or extrude, with width correction */
1734                                         if(dlbev.first==NULL) {
1735                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
1736                                                 dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
1737                                                 BLI_addtail(dispbase, dl);
1738
1739                                                 if(bl->poly!= -1) dl->type= DL_POLY;
1740                                                 else dl->type= DL_SEGM;
1741
1742                                                 if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE);
1743
1744                                                 dl->parts= 1;
1745                                                 dl->nr= bl->nr;
1746                                                 dl->col= nu->mat_nr;
1747                                                 dl->charidx= nu->charidx;
1748
1749                                                 /* dl->rt will be used as flag for render face and */
1750                                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1751                                                 dl->rt= nu->flag & ~CU_2D;
1752
1753                                                 a= dl->nr;
1754                                                 bevp= (BevPoint *)(bl+1);
1755                                                 data= dl->verts;
1756                                                 while(a--) {
1757                                                         data[0]= bevp->vec[0]+widfac*bevp->sina;
1758                                                         data[1]= bevp->vec[1]+widfac*bevp->cosa;
1759                                                         data[2]= bevp->vec[2];
1760                                                         bevp++;
1761                                                         data+=3;
1762                                                 }
1763                                         }
1764                                         else {
1765                                                 DispList *dlb;
1766
1767                                                 for (dlb=dlbev.first; dlb; dlb=dlb->next) {
1768         
1769                                                         /* for each part of the bevel use a separate displblock */
1770                                                         dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
1771                                                         dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
1772                                                         BLI_addtail(dispbase, dl);
1773         
1774                                                         dl->type= DL_SURF;
1775                                                         
1776                                                         dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE);
1777                                                         if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U;
1778                                                         if(bl->poly>=0) dl->flag |= DL_CYCL_V;
1779                                                         
1780                                                         dl->parts= bl->nr;
1781                                                         dl->nr= dlb->nr;
1782                                                         dl->col= nu->mat_nr;
1783                                                         dl->charidx= nu->charidx;
1784
1785                                                         /* dl->rt will be used as flag for render face and */
1786                                                         /* CU_2D conflicts with R_NOPUNOFLIP */
1787                                                         dl->rt= nu->flag & ~CU_2D;
1788
1789                                                         dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "bevelSplitFlag");
1790         
1791                                                         /* for each point of poly make a bevel piece */
1792                                                         bevp= (BevPoint *)(bl+1);
1793                                                         for(a=0; a<bl->nr; a++,bevp++) {
1794                                                                 float fac=1.0;
1795                                                                 if (cu->taperobj==NULL) {
1796                                                                         if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) )
1797                                                                                 fac = bevp->radius;
1798                                                                 } else {
1799                                                                         fac = calc_taper(scene, cu->taperobj, a, bl->nr);
1800                                                                 }
1801
1802                                                                 if (bevp->split_tag) {
1803                                                                         dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F);
1804                                                                 }
1805         
1806                                                                         /* rotate bevel piece and write in data */
1807                                                                 fp1= dlb->verts;
1808                                                                 for (b=0; b<dlb->nr; b++,fp1+=3,data+=3) {
1809                                                                         if(cu->flag & CU_3D) {
1810                                                                                 float vec[3];
1811         
1812                                                                                 vec[0]= fp1[1]+widfac;
1813                                                                                 vec[1]= fp1[2];
1814                                                                                 vec[2]= 0.0;
1815
1816                                                                                 mul_qt_v3(bevp->quat, vec);
1817
1818                                                                                 data[0]= bevp->vec[0] + fac*vec[0];
1819                                                                                 data[1]= bevp->vec[1] + fac*vec[1];
1820                                                                                 data[2]= bevp->vec[2] + fac*vec[2];
1821                                                                         }
1822                                                                         else {
1823                                                                                 data[0]= bevp->vec[0] + fac*(widfac+fp1[1])*bevp->sina;
1824                                                                                 data[1]= bevp->vec[1] + fac*(widfac+fp1[1])*bevp->cosa;
1825                                                                                 data[2]= bevp->vec[2] + fac*fp1[2];
1826                                                                         }
1827                                                                 }
1828                                                         }
1829                                                         
1830                                                         /* gl array drawing: using indices */
1831                                                         displist_surf_indices(dl);
1832                                                 }
1833                                         }
1834                                 }
1835
1836                         }
1837                         freedisplist(&dlbev);
1838                 }
1839
1840                 if (!(cu->flag & CU_DEFORM_FILL)) {
1841                         curve_to_filledpoly(cu, nubase, dispbase);
1842                 }
1843
1844                 if(cu->flag & CU_PATH) calc_curvepath(ob);
1845
1846                 /* make copy of 'undeformed" displist for texture space calculation
1847                    actually, it's not totally undeformed -- pre-tesselation modifiers are
1848                    already applied, thats how it worked for years, so keep for compatibility (sergey) */
1849                 copy_displist(&cu->disp, dispbase);
1850
1851                 if (!forRender) {
1852                         tex_space_curve(cu);
1853                 }
1854
1855                 if(!forOrco) curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, originalVerts, deformedVerts);
1856
1857                 if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
1858                         curve_to_filledpoly(cu, nubase, dispbase);
1859                 }
1860         }
1861 }
1862
1863 void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco)
1864 {
1865         Curve *cu= ob->data;
1866         ListBase *dispbase;
1867
1868         freedisplist(&(ob->disp));
1869         dispbase= &(ob->disp);
1870         freedisplist(dispbase);
1871
1872         /* free displist used for textspace */
1873         freedisplist(&cu->disp);
1874
1875         do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco);
1876
1877         if (ob->derivedFinal) {
1878                 DM_set_object_boundbox (ob, ob->derivedFinal);
1879         } else {
1880                 boundbox_displist (ob);
1881
1882                 /* if there is no derivedMesh, object's boundbox is unneeded */
1883                 if (ob->bb) {
1884                         MEM_freeN(ob->bb);
1885                         ob->bb= NULL;
1886                 }
1887         }
1888 }
1889
1890 void makeDispListCurveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
1891         DerivedMesh **derivedFinal, int forOrco)
1892 {
1893         do_makeDispListCurveTypes(scene, ob, dispbase, derivedFinal, 1, forOrco);
1894 }
1895
1896 void makeDispListCurveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
1897 {
1898         do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1);
1899 }
1900
1901 /* add Orco layer to the displist object which has got derived mesh and return orco */
1902 float *makeOrcoDispList(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender) {
1903         float *orco;
1904
1905         if (derivedFinal == NULL)
1906                 derivedFinal= ob->derivedFinal;
1907
1908         if (!derivedFinal->getVertDataArray(derivedFinal, CD_ORCO)) {
1909                 curve_calc_orcodm(scene, ob, derivedFinal, forRender);
1910         }
1911
1912         orco= derivedFinal->getVertDataArray(derivedFinal, CD_ORCO);
1913
1914         if(orco) {
1915                 orco= MEM_dupallocN(orco);
1916         }
1917
1918         return orco;
1919 }
1920
1921 /* this is confusing, there's also min_max_object, appplying the obmat... */
1922 static void boundbox_displist(Object *ob)
1923 {
1924         BoundBox *bb=NULL;
1925         float min[3], max[3];
1926         DispList *dl;
1927         float *vert;
1928         int a, tot=0;
1929         
1930         INIT_MINMAX(min, max);
1931
1932         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1933                 Curve *cu= ob->data;
1934                 int doit= 0;
1935
1936                 if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
1937                 bb= cu->bb;
1938                 
1939                 dl= ob->disp.first;
1940
1941                 while (dl) {
1942                         if(dl->type==DL_INDEX3) tot= dl->nr;
1943                         else tot= dl->nr*dl->parts;
1944                         
1945                         vert= dl->verts;
1946                         for(a=0; a<tot; a++, vert+=3) {
1947                                 doit= 1;
1948                                 DO_MINMAX(vert, min, max);
1949                         }
1950
1951                         dl= dl->next;
1952                 }
1953                 
1954                 if(!doit) {
1955                         /* there's no geometry in displist, use zero-sized boundbox */
1956                         zero_v3(min);
1957                         zero_v3(max);
1958                 }
1959                 
1960         }
1961         
1962         if(bb) {
1963                 boundbox_set_from_min_max(bb, min, max);
1964         }
1965 }
1966