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