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