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