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