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