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