Merging revisions 14946-15020 of https://svn.blender.org/svnroot/bf-blender/trunk...
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #include "IMB_imbuf_types.h"
39
40 #include "DNA_texture_types.h"
41 #include "DNA_meta_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_effect_types.h"
44 #include "DNA_listBase.h"
45 #include "DNA_lamp_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_object_force.h"
48 #include "DNA_mesh_types.h"
49 #include "DNA_meshdata_types.h"
50 #include "DNA_modifier_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_image_types.h"
53 #include "DNA_material_types.h"
54 #include "DNA_view3d_types.h"
55 #include "DNA_lattice_types.h"
56 #include "DNA_key_types.h"
57
58 #include "BLI_blenlib.h"
59 #include "BLI_arithb.h"
60 #include "BLI_editVert.h"
61 #include "BLI_edgehash.h"
62
63 #include "BKE_bad_level_calls.h"
64 #include "BKE_utildefines.h"
65 #include "BKE_global.h"
66 #include "BKE_displist.h"
67 #include "BKE_deform.h"
68 #include "BKE_DerivedMesh.h"
69 #include "BKE_object.h"
70 #include "BKE_world.h"
71 #include "BKE_mesh.h"
72 #include "BKE_effect.h"
73 #include "BKE_mball.h"
74 #include "BKE_material.h"
75 #include "BKE_curve.h"
76 #include "BKE_key.h"
77 #include "BKE_anim.h"
78 #include "BKE_screen.h"
79 #include "BKE_texture.h"
80 #include "BKE_library.h"
81 #include "BKE_font.h"
82 #include "BKE_lattice.h"
83 #include "BKE_scene.h"
84 #include "BKE_subsurf.h"
85 #include "BKE_modifier.h"
86 #include "BKE_customdata.h"
87
88 #include "RE_pipeline.h"
89 #include "RE_shader_ext.h"
90
91
92 static void boundbox_displist(Object *ob);
93
94 void free_disp_elem(DispList *dl)
95 {
96         if(dl) {
97                 if(dl->verts) MEM_freeN(dl->verts);
98                 if(dl->nors) MEM_freeN(dl->nors);
99                 if(dl->index) MEM_freeN(dl->index);
100                 if(dl->col1) MEM_freeN(dl->col1);
101                 if(dl->col2) MEM_freeN(dl->col2);
102                 if(dl->bevelSplitFlag) MEM_freeN(dl->bevelSplitFlag);
103                 MEM_freeN(dl);
104         }
105 }
106
107 void freedisplist(ListBase *lb)
108 {
109         DispList *dl;
110
111         dl= lb->first;
112         while(dl) {
113                 BLI_remlink(lb, dl);
114                 free_disp_elem(dl);
115                 dl= lb->first;
116         }
117 }
118
119 DispList *find_displist_create(ListBase *lb, int type)
120 {
121         DispList *dl;
122         
123         dl= lb->first;
124         while(dl) {
125                 if(dl->type==type) return dl;
126                 dl= dl->next;
127         }
128
129         dl= MEM_callocN(sizeof(DispList), "find_disp");
130         dl->type= type;
131         BLI_addtail(lb, dl);
132
133         return dl;
134 }
135
136 DispList *find_displist(ListBase *lb, int type)
137 {
138         DispList *dl;
139         
140         dl= lb->first;
141         while(dl) {
142                 if(dl->type==type) return dl;
143                 dl= dl->next;
144         }
145
146         return 0;
147 }
148
149 int displist_has_faces(ListBase *lb)
150 {
151         DispList *dl;
152         for(dl= lb->first; dl; dl= dl->next) {
153                 if ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)
154                         return 1;
155         }
156         return 0;
157 }
158
159 void copy_displist(ListBase *lbn, ListBase *lb)
160 {
161         DispList *dln, *dl;
162         
163         lbn->first= lbn->last= 0;
164         
165         dl= lb->first;
166         while(dl) {
167                 
168                 dln= MEM_dupallocN(dl);
169                 BLI_addtail(lbn, dln);
170                 dln->verts= MEM_dupallocN(dl->verts);
171                 dln->nors= MEM_dupallocN(dl->nors);
172                 dln->index= MEM_dupallocN(dl->index);
173                 dln->col1= MEM_dupallocN(dl->col1);
174                 dln->col2= MEM_dupallocN(dl->col2);
175                 
176                 dl= dl->next;
177         }
178 }
179
180 void addnormalsDispList(Object *ob, ListBase *lb)
181 {
182         DispList *dl = NULL;
183         float *vdata, *ndata, nor[3];
184         float *v1, *v2, *v3, *v4;
185         float *n1, *n2, *n3, *n4;
186         int a, b, p1, p2, p3, p4;
187
188
189         dl= lb->first;
190         
191         while(dl) {
192                 if(dl->type==DL_INDEX3) {
193                         if(dl->nors==NULL) {
194                                 dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
195                                 if(dl->verts[2]<0.0) dl->nors[2]= -1.0;
196                                 else dl->nors[2]= 1.0;
197                         }
198                 }
199                 else if(dl->type==DL_SURF) {
200                         if(dl->nors==NULL) {
201                                 dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
202                                 
203                                 vdata= dl->verts;
204                                 ndata= dl->nors;
205                                 
206                                 for(a=0; a<dl->parts; a++) {
207         
208                                         DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
209         
210                                         v1= vdata+ 3*p1; 
211                                         n1= ndata+ 3*p1;
212                                         v2= vdata+ 3*p2; 
213                                         n2= ndata+ 3*p2;
214                                         v3= vdata+ 3*p3; 
215                                         n3= ndata+ 3*p3;
216                                         v4= vdata+ 3*p4; 
217                                         n4= ndata+ 3*p4;
218                                         
219                                         for(; b<dl->nr; b++) {
220         
221                                                 CalcNormFloat4(v1, v3, v4, v2, nor);
222         
223                                                 VecAddf(n1, n1, nor);
224                                                 VecAddf(n2, n2, nor);
225                                                 VecAddf(n3, n3, nor);
226                                                 VecAddf(n4, n4, nor);
227         
228                                                 v2= v1; v1+= 3;
229                                                 v4= v3; v3+= 3;
230                                                 n2= n1; n1+= 3;
231                                                 n4= n3; n3+= 3;
232                                         }
233                                 }
234                                 a= dl->parts*dl->nr;
235                                 v1= ndata;
236                                 while(a--) {
237                                         Normalize(v1);
238                                         v1+= 3;
239                                 }
240                         }
241                 }
242                 dl= dl->next;
243         }
244 }
245
246 void count_displist(ListBase *lb, int *totvert, int *totface)
247 {
248         DispList *dl;
249         
250         dl= lb->first;
251         while(dl) {
252                 
253                 switch(dl->type) {
254                         case DL_SURF:
255                                 *totvert+= dl->nr*dl->parts;
256                                 *totface+= (dl->nr-1)*(dl->parts-1);
257                                 break;
258                         case DL_INDEX3:
259                         case DL_INDEX4:
260                                 *totvert+= dl->nr;
261                                 *totface+= dl->parts;
262                                 break;
263                         case DL_POLY:
264                         case DL_SEGM:
265                                 *totvert+= dl->nr*dl->parts;
266                 }
267                 
268                 dl= dl->next;
269         }
270 }
271
272
273 /* ***************************** shade displist. note colors now are in rgb(a) order ******************** */
274
275 /* create default shade input... save cpu cycles with ugly global */
276 /* XXXX bad code warning: local ShadeInput initialize... */
277 static ShadeInput shi;
278 static void init_fastshade_shadeinput(void)
279 {
280         memset(&shi, 0, sizeof(ShadeInput));
281         shi.lay= G.scene->lay;
282         shi.view[2]= -1.0f;
283         shi.passflag= SCE_PASS_COMBINED;
284         shi.combinedflag= -1;
285 }
286
287 static Render *fastshade_get_render(void)
288 {
289         Render *re= RE_GetRender("_Shade View_");
290         if(re==NULL) {
291                 re= RE_NewRender("_Shade View_");
292         
293                 RE_Database_Baking(re, G.scene, 0, 0);  /* 0= no faces */
294         }
295         return re;
296 }
297
298 /* called on file reading */
299 void fastshade_free_render(void)
300 {
301         Render *re= RE_GetRender("_Shade View_");
302         
303         if(re) {
304                 RE_Database_Free(re);
305                 RE_FreeRender(re);
306         }
307 }
308
309 static int fastshade_customdata_layer_num(int n, int active)
310 {   
311         /* make the active layer the first */
312         if (n == active) return 0;
313         else if (n < active) return n+1;
314         else return n;
315 }
316
317 static void fastshade_customdata(CustomData *fdata, int a, int j, Material *ma)
318 {
319         CustomDataLayer *layer;
320         MTFace *mtface;
321         int index, n, needuv= ma->texco & TEXCO_UV;
322         char *vertcol;
323
324         shi.totuv= 0;
325         shi.totcol= 0;
326
327         for(index=0; index<fdata->totlayer; index++) {
328                 layer= &fdata->layers[index];
329                 
330                 if(needuv && layer->type == CD_MTFACE && shi.totuv < MAX_MTFACE) {
331                         n= fastshade_customdata_layer_num(shi.totuv, layer->active_rnd);
332                         mtface= &((MTFace*)layer->data)[a];
333
334                         shi.uv[shi.totuv].uv[0]= 2.0f*mtface->uv[j][0]-1.0f;
335                         shi.uv[shi.totuv].uv[1]= 2.0f*mtface->uv[j][1]-1.0f;
336                         shi.uv[shi.totuv].uv[2]= 1.0f;
337
338                         shi.uv[shi.totuv].name= layer->name;
339                         shi.totuv++;
340                 }
341                 else if(layer->type == CD_MCOL && shi.totcol < MAX_MCOL) {
342                         n= fastshade_customdata_layer_num(shi.totcol, layer->active_rnd);
343                         vertcol= (char*)&((MCol*)layer->data)[a*4 + j];
344
345                         shi.col[shi.totcol].col[0]= ((float)vertcol[3])/255.0f;
346                         shi.col[shi.totcol].col[1]= ((float)vertcol[2])/255.0f;
347                         shi.col[shi.totcol].col[2]= ((float)vertcol[1])/255.0f;
348
349                         shi.col[shi.totcol].name= layer->name;
350                         shi.totcol++;
351                 }
352         }
353
354         if(needuv && shi.totuv == 0)
355                 VECCOPY(shi.uv[0].uv, shi.lo);
356
357         if(shi.totcol)
358                 VECCOPY(shi.vcol, shi.col[0].col);
359 }
360
361 static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2)
362 {
363         ShadeResult shr;
364         int a;
365         
366         VECCOPY(shi.co, co);
367         shi.vn[0]= -nor[0];
368         shi.vn[1]= -nor[1];
369         shi.vn[2]= -nor[2];
370         VECCOPY(shi.vno, shi.vn);
371         VECCOPY(shi.facenor, shi.vn);
372         
373         if(ma->texco) {
374                 VECCOPY(shi.lo, orco);
375                 
376                 if(ma->texco & TEXCO_GLOB) {
377                         VECCOPY(shi.gl, shi.lo);
378                 }
379                 if(ma->texco & TEXCO_WINDOW) {
380                         VECCOPY(shi.winco, shi.lo);
381                 }
382                 if(ma->texco & TEXCO_STICKY) {
383                         VECCOPY(shi.sticky, shi.lo);
384                 }
385                 if(ma->texco & TEXCO_OBJECT) {
386                         VECCOPY(shi.co, shi.lo);
387                 }
388                 if(ma->texco & TEXCO_NORM) {
389                         VECCOPY(shi.orn, shi.vn);
390                 }
391                 if(ma->texco & TEXCO_REFL) {
392                         float inp= 2.0*(shi.vn[2]);
393                         shi.ref[0]= (inp*shi.vn[0]);
394                         shi.ref[1]= (inp*shi.vn[1]);
395                         shi.ref[2]= (-1.0+inp*shi.vn[2]);
396                 }
397         }
398         
399         shi.mat= ma;    /* set each time... node shaders change it */
400         RE_shade_external(NULL, &shi, &shr);
401         
402         a= 256.0f*(shr.combined[0]);
403         col1[0]= CLAMPIS(a, 0, 255);
404         a= 256.0f*(shr.combined[1]);
405         col1[1]= CLAMPIS(a, 0, 255);
406         a= 256.0f*(shr.combined[2]);
407         col1[2]= CLAMPIS(a, 0, 255);
408         
409         if(col2) {
410                 shi.vn[0]= -shi.vn[0];
411                 shi.vn[1]= -shi.vn[1];
412                 shi.vn[2]= -shi.vn[2];
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                 col2[0]= CLAMPIS(a, 0, 255);
419                 a= 256.0f*(shr.combined[1]);
420                 col2[1]= CLAMPIS(a, 0, 255);
421                 a= 256.0f*(shr.combined[2]);
422                 col2[2]= CLAMPIS(a, 0, 255);
423         }
424 }
425
426 static void init_fastshade_for_ob(Render *re, Object *ob, int *need_orco_r, float mat[4][4], float imat[3][3])
427 {
428         float tmat[4][4];
429         float amb[3]= {0.0f, 0.0f, 0.0f};
430         int a;
431         
432         /* initialize globals in render */
433         RE_shade_external(re, NULL, NULL);
434
435         /* initialize global here */
436         init_fastshade_shadeinput();
437         
438         RE_DataBase_GetView(re, tmat);
439         Mat4MulMat4(mat, ob->obmat, tmat);
440         
441         Mat4Invert(tmat, mat);
442         Mat3CpyMat4(imat, tmat);
443         if(ob->transflag & OB_NEG_SCALE) Mat3MulFloat((float *)imat, -1.0);
444         
445         if (need_orco_r) *need_orco_r= 0;
446         for(a=0; a<ob->totcol; a++) {
447                 Material *ma= give_current_material(ob, a+1);
448                 if(ma) {
449                         init_render_material(ma, 0, amb);
450
451                         if(ma->texco & TEXCO_ORCO) {
452                                 if (need_orco_r) *need_orco_r= 1;
453                         }
454                 }
455         }
456 }
457
458 static void end_fastshade_for_ob(Object *ob)
459 {
460         int a;
461         
462         for(a=0; a<ob->totcol; a++) {
463                 Material *ma= give_current_material(ob, a+1);
464                 if(ma)
465                         end_render_material(ma);
466         }
467 }
468
469
470 static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, unsigned int **col1_r, unsigned int **col2_r)
471 {
472         Mesh *me= ob->data;
473         DerivedMesh *dm;
474         MVert *mvert;
475         MFace *mface;
476         unsigned int *col1, *col2;
477         float *orco, *vnors, *nors, imat[3][3], mat[4][4], vec[3];
478         int a, i, need_orco, totface, totvert;
479         CustomDataMask dataMask = CD_MASK_BAREMESH | CD_MASK_MCOL
480                                   | CD_MASK_MTFACE | CD_MASK_NORMAL;
481
482
483         init_fastshade_for_ob(re, ob, &need_orco, mat, imat);
484
485         if(need_orco)
486                 dataMask |= CD_MASK_ORCO;
487
488         if (onlyForMesh)
489                 dm = mesh_get_derived_deform(ob, dataMask);
490         else
491                 dm = mesh_get_derived_final(ob, dataMask);
492         
493         mvert = dm->getVertArray(dm);
494         mface = dm->getFaceArray(dm);
495         nors = dm->getFaceDataArray(dm, CD_NORMAL);
496         totvert = dm->getNumVerts(dm);
497         totface = dm->getNumFaces(dm);
498         orco= dm->getVertDataArray(dm, CD_ORCO);
499
500         if (onlyForMesh) {
501                 col1 = *col1_r;
502                 col2 = NULL;
503         } else {
504                 *col1_r = col1 = MEM_mallocN(sizeof(*col1)*totface*4, "col1");
505
506                 if (col2_r && (me->flag & ME_TWOSIDED))
507                         col2 = MEM_mallocN(sizeof(*col2)*totface*4, "col2");
508                 else
509                         col2 = NULL;
510                 
511                 if (col2_r) *col2_r = col2;
512         }
513
514                 /* vertexnormals */
515         vnors= MEM_mallocN(totvert*3*sizeof(float), "vnors disp");
516         for (a=0; a<totvert; a++) {
517                 MVert *mv = &mvert[a];
518                 float *vn= &vnors[a*3];
519                 float xn= mv->no[0]; 
520                 float yn= mv->no[1]; 
521                 float zn= mv->no[2];
522                 
523                         /* transpose ! */
524                 vn[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
525                 vn[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
526                 vn[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
527                 Normalize(vn);
528         }               
529
530         for (i=0; i<totface; i++) {
531                 MFace *mf= &mface[i];
532                 Material *ma= give_current_material(ob, mf->mat_nr+1);
533                 int j, vidx[4], nverts= mf->v4?4:3;
534                 unsigned char *col1base= (unsigned char*) &col1[i*4];
535                 unsigned char *col2base= (unsigned char*) (col2?&col2[i*4]:NULL);
536                 float nor[3], n1[3];
537                 
538                 if(ma==NULL) ma= &defmaterial;
539                 
540                 vidx[0]= mf->v1;
541                 vidx[1]= mf->v2;
542                 vidx[2]= mf->v3;
543                 vidx[3]= mf->v4;
544
545                 if (nors) {
546                         VECCOPY(nor, &nors[i*3]);
547                 } else {
548                         if (mf->v4)
549                                 CalcNormFloat4(mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co, nor);
550                         else
551                                 CalcNormFloat(mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, nor);
552                 }
553
554                 n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
555                 n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
556                 n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
557                 Normalize(n1);
558
559                 for (j=0; j<nverts; j++) {
560                         MVert *mv= &mvert[vidx[j]];
561                         char *col1= (char*)&col1base[j*4];
562                         char *col2= (char*)(col2base?&col2base[j*4]:NULL);
563                         float *vn = (mf->flag & ME_SMOOTH)?&vnors[3*vidx[j]]:n1;
564                         
565                         VECCOPY(vec, mv->co);
566                         Mat4MulVecfl(mat, vec);
567                         vec[0]+= 0.001*vn[0];
568                         vec[1]+= 0.001*vn[1];
569                         vec[2]+= 0.001*vn[2];
570
571                         fastshade_customdata(&dm->faceData, i, j, ma);
572                         fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, ma, col1, col2);
573                 }
574         } 
575         MEM_freeN(vnors);
576
577         dm->release(dm);
578
579         end_fastshade_for_ob(ob);
580 }
581
582 void shadeMeshMCol(Object *ob, Mesh *me)
583 {
584         int a;
585         char *cp;
586         unsigned int *mcol= (unsigned int*)me->mcol;
587         
588         Render *re= fastshade_get_render();
589         mesh_create_shadedColors(re, ob, 1, &mcol, NULL);
590         me->mcol= (MCol*)mcol;
591
592         /* swap bytes */
593         for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) {
594                 SWAP(char, cp[0], cp[3]);
595                 SWAP(char, cp[1], cp[2]);
596         }
597 }
598
599 /* has base pointer, to check for layer */
600 /* called from drawobject.c */
601 void shadeDispList(Base *base)
602 {
603         Object *ob= base->object;
604         DispList *dl, *dlob;
605         Material *ma = NULL;
606         Curve *cu;
607         Render *re;
608         float imat[3][3], mat[4][4], vec[3];
609         float *fp, *nor, n1[3];
610         unsigned int *col1;
611         int a, need_orco;
612         
613         re= fastshade_get_render();
614         
615         dl = find_displist(&ob->disp, DL_VERTCOL);
616         if (dl) {
617                 BLI_remlink(&ob->disp, dl);
618                 free_disp_elem(dl);
619         }
620
621         if(ob->type==OB_MESH) {
622                 dl= MEM_callocN(sizeof(DispList), "displistshade");
623                 dl->type= DL_VERTCOL;
624
625                 mesh_create_shadedColors(re, ob, 0, &dl->col1, &dl->col2);
626
627                 /* add dl to ob->disp after mesh_create_shadedColors, because it
628                    might indirectly free ob->disp */
629                 BLI_addtail(&ob->disp, dl);
630         }
631         else {
632
633                 init_fastshade_for_ob(re, ob, &need_orco, mat, imat);
634                 
635                 if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
636                 
637                         /* now we need the normals */
638                         cu= ob->data;
639                         dl= cu->disp.first;
640                         
641                         while(dl) {
642                                 dlob= MEM_callocN(sizeof(DispList), "displistshade");
643                                 BLI_addtail(&ob->disp, dlob);
644                                 dlob->type= DL_VERTCOL;
645                                 dlob->parts= dl->parts;
646                                 dlob->nr= dl->nr;
647                                 
648                                 if(dl->type==DL_INDEX3) {
649                                         col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
650                                 }
651                                 else {
652                                         col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1");
653                                 }
654                                 
655                         
656                                 ma= give_current_material(ob, dl->col+1);
657                                 if(ma==NULL) ma= &defmaterial;
658                                 
659                                 if(dl->type==DL_INDEX3) {
660                                         if(dl->nors) {
661                                                 /* there's just one normal */
662                                                 n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2];
663                                                 n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2];
664                                                 n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2];
665                                                 Normalize(n1);
666                                                 
667                                                 fp= dl->verts;
668                                                 
669                                                 a= dl->nr;              
670                                                 while(a--) {
671                                                         VECCOPY(vec, fp);
672                                                         Mat4MulVecfl(mat, vec);
673                                                         
674                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
675                                                         
676                                                         fp+= 3; col1++;
677                                                 }
678                                         }
679                                 }
680                                 else if(dl->type==DL_SURF) {
681                                         if(dl->nors) {
682                                                 a= dl->nr*dl->parts;
683                                                 fp= dl->verts;
684                                                 nor= dl->nors;
685                                                 
686                                                 while(a--) {
687                                                         VECCOPY(vec, fp);
688                                                         Mat4MulVecfl(mat, vec);
689                                                         
690                                                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
691                                                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
692                                                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
693                                                         Normalize(n1);
694                                 
695                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
696                                                         
697                                                         fp+= 3; nor+= 3; col1++;
698                                                 }
699                                         }
700                                 }
701                                 dl= dl->next;
702                         }
703                 }
704                 else if(ob->type==OB_MBALL) {
705                         /* there are normals already */
706                         dl= ob->disp.first;
707                         
708                         while(dl) {
709                                 
710                                 if(dl->type==DL_INDEX4) {
711                                         if(dl->nors) {
712                                                 
713                                                 if(dl->col1) MEM_freeN(dl->col1);
714                                                 col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
715                                 
716                                                 ma= give_current_material(ob, dl->col+1);
717                                                 if(ma==NULL) ma= &defmaterial;
718                                                 
719                                                 fp= dl->verts;
720                                                 nor= dl->nors;
721                                                 
722                                                 a= dl->nr;              
723                                                 while(a--) {
724                                                         VECCOPY(vec, fp);
725                                                         Mat4MulVecfl(mat, vec);
726                                                         
727                                                         /* transpose ! */
728                                                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
729                                                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
730                                                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
731                                                         Normalize(n1);
732                                                 
733                                                         fastshade(vec, n1, fp, ma, (char *)col1, NULL);
734                                                         
735                                                         fp+= 3; col1++; nor+= 3;
736                                                 }
737                                         }
738                                 }
739                                 dl= dl->next;
740                         }
741                 }
742                 
743                 end_fastshade_for_ob(ob);
744         }
745 }
746
747 /* frees render and shade part of displists */
748 /* note: dont do a shade again, until a redraw happens */
749 void reshadeall_displist(void)
750 {
751         Base *base;
752         Object *ob;
753         
754         fastshade_free_render();
755         
756         for(base= G.scene->base.first; base; base= base->next) {
757                 ob= base->object;
758                 freedisplist(&ob->disp);
759                 if(base->lay & G.scene->lay) {
760                         /* Metaballs have standard displist at the Object */
761                         if(ob->type==OB_MBALL) shadeDispList(base);
762                 }
763         }
764 }
765
766 /* ****************** make displists ********************* */
767
768 static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
769 {
770         Nurb *nu;
771         DispList *dl;
772         BezTriple *bezt, *prevbezt;
773         BPoint *bp;
774         float *data, *v1, *v2;
775         int a, len, resolu;
776         
777         nu= nubase->first;
778         while(nu) {
779                 if(nu->hide==0) {
780                         
781                         if(G.rendering && cu->resolu_ren!=0) 
782                                 resolu= cu->resolu_ren;
783                         else
784                                 resolu= nu->resolu;
785                         
786                         if(!check_valid_nurb_u(nu));
787                         else if((nu->type & 7)==CU_BEZIER) {
788                                 
789                                 /* count */
790                                 len= 0;
791                                 a= nu->pntsu-1;
792                                 if(nu->flagu & CU_CYCLIC) a++;
793
794                                 prevbezt= nu->bezt;
795                                 bezt= prevbezt+1;
796                                 while(a--) {
797                                         if(a==0 && (nu->flagu & CU_CYCLIC)) bezt= nu->bezt;
798                                         
799                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
800                                         else len+= resolu;
801                                         
802                                         if(a==0 && (nu->flagu & CU_CYCLIC)==0) len++;
803                                         
804                                         prevbezt= bezt;
805                                         bezt++;
806                                 }
807                                 
808                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
809                                 /* len+1 because of 'forward_diff_bezier' function */
810                                 dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
811                                 BLI_addtail(dispbase, dl);
812                                 dl->parts= 1;
813                                 dl->nr= len;
814                                 dl->col= nu->mat_nr;
815                                 dl->charidx= nu->charidx;
816
817                                 data= dl->verts;
818
819                                 if(nu->flagu & CU_CYCLIC) {
820                                         dl->type= DL_POLY;
821                                         a= nu->pntsu;
822                                 }
823                                 else {
824                                         dl->type= DL_SEGM;
825                                         a= nu->pntsu-1;
826                                 }
827                                 
828                                 prevbezt= nu->bezt;
829                                 bezt= prevbezt+1;
830                                 
831                                 while(a--) {
832                                         if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
833                                         
834                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
835                                                 VECCOPY(data, prevbezt->vec[1]);
836                                                 data+= 3;
837                                         }
838                                         else {
839                                                 v1= prevbezt->vec[1];
840                                                 v2= bezt->vec[0];
841                                                 forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], data, resolu, 3);
842                                                 forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], data+1, resolu, 3);
843                                                 forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], data+2, resolu, 3);
844                                                 data+= 3*resolu;
845                                         }
846                                         
847                                         if(a==0 && dl->type==DL_SEGM) {
848                                                 VECCOPY(data, bezt->vec[1]);
849                                         }
850                                         
851                                         prevbezt= bezt;
852                                         bezt++;
853                                 }
854                         }
855                         else if((nu->type & 7)==CU_NURBS) {
856                                 len= nu->pntsu*resolu;
857                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
858                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
859                                 BLI_addtail(dispbase, dl);
860                                 dl->parts= 1;
861                                 dl->nr= len;
862                                 dl->col= nu->mat_nr;
863                                 dl->charidx = nu->charidx;
864
865                                 data= dl->verts;
866                                 if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
867                                 else dl->type= DL_SEGM;
868                                 makeNurbcurve(nu, data, resolu, 3);
869                         }
870                         else if((nu->type & 7)==CU_POLY) {
871                                 len= nu->pntsu;
872                                 dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
873                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
874                                 BLI_addtail(dispbase, dl);
875                                 dl->parts= 1;
876                                 dl->nr= len;
877                                 dl->col= nu->mat_nr;
878                                 dl->charidx = nu->charidx;
879
880                                 data= dl->verts;
881                                 if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
882                                 else dl->type= DL_SEGM;
883                                 
884                                 a= len;
885                                 bp= nu->bp;
886                                 while(a--) {
887                                         VECCOPY(data, bp->vec);
888                                         bp++;
889                                         data+= 3;
890                                 }
891                         }
892                 }
893                 nu= nu->next;
894         }
895 }
896
897
898 void filldisplist(ListBase *dispbase, ListBase *to)
899 {
900         EditVert *eve, *v1, *vlast;
901         EditFace *efa;
902         DispList *dlnew=0, *dl;
903         float *f1;
904         int colnr=0, charidx=0, cont=1, tot, a, *index;
905         long totvert;
906         
907         if(dispbase==0) return;
908         if(dispbase->first==0) return;
909
910         while(cont) {
911                 cont= 0;
912                 totvert=0;
913                 
914                 dl= dispbase->first;
915                 while(dl) {
916         
917                         if(dl->type==DL_POLY) {
918                                 if(charidx<dl->charidx) cont= 1;
919                                 else if(charidx==dl->charidx) {
920                         
921                                         colnr= dl->col;
922                                         charidx= dl->charidx;
923                 
924                                         /* make editverts and edges */
925                                         f1= dl->verts;
926                                         a= dl->nr;
927                                         eve= v1= 0;
928                                         
929                                         while(a--) {
930                                                 vlast= eve;
931                                                 
932                                                 eve= BLI_addfillvert(f1);
933                                                 totvert++;
934                                                 
935                                                 if(vlast==0) v1= eve;
936                                                 else {
937                                                         BLI_addfilledge(vlast, eve);
938                                                 }
939                                                 f1+=3;
940                                         }
941                                 
942                                         if(eve!=0 && v1!=0) {
943                                                 BLI_addfilledge(eve, v1);
944                                         }
945                                 }
946                         }
947                         dl= dl->next;
948                 }
949                 
950                 if(totvert && BLI_edgefill(0, (G.obedit && G.obedit->actcol)?(G.obedit->actcol-1):0)) {
951
952                         /* count faces  */
953                         tot= 0;
954                         efa= fillfacebase.first;
955                         while(efa) {
956                                 tot++;
957                                 efa= efa->next;
958                         }
959
960                         if(tot) {
961                                 dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
962                                 dlnew->type= DL_INDEX3;
963                                 dlnew->col= colnr;
964                                 dlnew->nr= totvert;
965                                 dlnew->parts= tot;
966
967                                 dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
968                                 dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
969                                 
970                                 /* vert data */
971                                 f1= dlnew->verts;
972                                 totvert= 0;
973                                 eve= fillvertbase.first;
974                                 while(eve) {
975                                         VECCOPY(f1, eve->co);
976                                         f1+= 3;
977         
978                                         /* index number */
979                                         eve->tmp.l = totvert;
980                                         totvert++;
981                                         
982                                         eve= eve->next;
983                                 }
984                                 
985                                 /* index data */
986                                 efa= fillfacebase.first;
987                                 index= dlnew->index;
988                                 while(efa) {
989                                         index[0]= (long)efa->v1->tmp.l;
990                                         index[1]= (long)efa->v2->tmp.l;
991                                         index[2]= (long)efa->v3->tmp.l;
992                                         
993                                         index+= 3;
994                                         efa= efa->next;
995                                 }
996                         }
997
998                         BLI_addhead(to, dlnew);
999                         
1000                 }
1001                 BLI_end_edgefill();
1002
1003                 charidx++;
1004         }
1005         
1006         /* do not free polys, needed for wireframe display */
1007         
1008 }
1009
1010 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
1011 {
1012         ListBase front, back;
1013         DispList *dl, *dlnew;
1014         float *fp, *fp1;
1015         int a, dpoly;
1016         
1017         front.first= front.last= back.first= back.last= 0;
1018         
1019         dl= dispbase->first;
1020         while(dl) {
1021                 if(dl->type==DL_SURF) {
1022                         if( (dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)==0 ) {
1023                                 if( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE) ) {
1024                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1025                                         BLI_addtail(&front, dlnew);
1026                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1027                                         dlnew->nr= dl->parts;
1028                                         dlnew->parts= 1;
1029                                         dlnew->type= DL_POLY;
1030                                         dlnew->col= dl->col;
1031                                         dlnew->charidx = dl->charidx;
1032                                         
1033                                         fp= dl->verts;
1034                                         dpoly= 3*dl->nr;
1035                                         
1036                                         a= dl->parts;
1037                                         while(a--) {
1038                                                 VECCOPY(fp1, fp);
1039                                                 fp1+= 3;
1040                                                 fp+= dpoly;
1041                                         }
1042                                 }
1043                                 if( (cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE) ) {
1044                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1045                                         BLI_addtail(&back, dlnew);
1046                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1047                                         dlnew->nr= dl->parts;
1048                                         dlnew->parts= 1;
1049                                         dlnew->type= DL_POLY;
1050                                         dlnew->col= dl->col;
1051                                         dlnew->charidx= dl->charidx;
1052                                         
1053                                         fp= dl->verts+3*(dl->nr-1);
1054                                         dpoly= 3*dl->nr;
1055                                         
1056                                         a= dl->parts;
1057                                         while(a--) {
1058                                                 VECCOPY(fp1, fp);
1059                                                 fp1+= 3;
1060                                                 fp+= dpoly;
1061                                         }
1062                                 }
1063                         }
1064                 }
1065                 dl= dl->next;
1066         }
1067
1068         filldisplist(&front, dispbase);
1069         filldisplist(&back, dispbase);
1070         
1071         freedisplist(&front);
1072         freedisplist(&back);
1073
1074         filldisplist(dispbase, dispbase);
1075         
1076 }
1077
1078 void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
1079 {
1080         if(cu->flag & CU_3D) return;
1081
1082         if(dispbase->first && ((DispList*) dispbase->first)->type==DL_SURF) {
1083                 bevels_to_filledpoly(cu, dispbase);
1084         }
1085         else {
1086                 filldisplist(dispbase, dispbase);
1087         }
1088 }
1089
1090 /* taper rules:
1091   - only 1 curve
1092   - first point left, last point right
1093   - based on subdivided points in original curve, not on points in taper curve (still)
1094 */
1095 float calc_taper(Object *taperobj, int cur, int tot)
1096 {
1097         Curve *cu;
1098         DispList *dl;
1099         
1100         if(taperobj==NULL) return 1.0;
1101         
1102         cu= taperobj->data;
1103         dl= cu->disp.first;
1104         if(dl==NULL) {
1105                 makeDispListCurveTypes(taperobj, 0);
1106                 dl= cu->disp.first;
1107         }
1108         if(dl) {
1109                 float fac= ((float)cur)/(float)(tot-1);
1110                 float minx, dx, *fp;
1111                 int a;
1112                 
1113                 /* horizontal size */
1114                 minx= dl->verts[0];
1115                 dx= dl->verts[3*(dl->nr-1)] - minx;
1116                 if(dx>0.0) {
1117                 
1118                         fp= dl->verts;
1119                         for(a=0; a<dl->nr; a++, fp+=3) {
1120                                 if( (fp[0]-minx)/dx >= fac) {
1121                                         /* interpolate with prev */
1122                                         if(a>0) {
1123                                                 float fac1= (fp[-3]-minx)/dx;
1124                                                 float fac2= (fp[0]-minx)/dx;
1125                                                 if(fac1!=fac2)
1126                                                         return fp[1]*(fac1-fac)/(fac1-fac2) + fp[-2]*(fac-fac2)/(fac1-fac2);
1127                                         }
1128                                         return fp[1];
1129                                 }
1130                         }
1131                         return fp[-2];  // last y coord
1132                 }
1133         }
1134         
1135         return 1.0;
1136 }
1137
1138 void makeDispListMBall(Object *ob)
1139 {
1140         if(!ob || ob->type!=OB_MBALL) return;
1141
1142         freedisplist(&(ob->disp));
1143         
1144         if(ob->type==OB_MBALL) {
1145                 if(ob==find_basis_mball(ob)) {
1146                         metaball_polygonize(ob);
1147                         tex_space_mball(ob);
1148
1149                         object_deform_mball(ob);
1150                 }
1151         }
1152         
1153         boundbox_displist(ob);
1154 }
1155
1156 static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int editmode)
1157 {
1158         ModifierData *md = modifiers_getVirtualModifierList(ob);
1159         ModifierData *preTesselatePoint;
1160         int required_mode;
1161
1162         if(forRender) required_mode = eModifierMode_Render;
1163         else required_mode = eModifierMode_Realtime;
1164
1165         if(editmode) required_mode |= eModifierMode_Editmode;
1166
1167         preTesselatePoint = NULL;
1168         for (; md; md=md->next) {
1169                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1170
1171                 if ((md->mode & required_mode) != required_mode) continue;
1172                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1173
1174                 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
1175                         preTesselatePoint  = md;
1176                 }
1177         }
1178
1179         return preTesselatePoint;
1180 }
1181
1182 void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float (**originalVerts_r)[3], float (**deformedVerts_r)[3], int *numVerts_r)
1183 {
1184         int editmode = (!forRender && ob==G.obedit);
1185         ModifierData *md = modifiers_getVirtualModifierList(ob);
1186         ModifierData *preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode);
1187         int numVerts = 0;
1188         float (*originalVerts)[3] = NULL;
1189         float (*deformedVerts)[3] = NULL;
1190         int required_mode;
1191
1192         if(forRender) required_mode = eModifierMode_Render;
1193         else required_mode = eModifierMode_Realtime;
1194
1195         if(editmode) required_mode |= eModifierMode_Editmode;
1196
1197         if(ob!=G.obedit && do_ob_key(ob)) {
1198                 deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
1199                 originalVerts = MEM_dupallocN(deformedVerts);
1200         }
1201         
1202         if (preTesselatePoint) {
1203                 for (; md; md=md->next) {
1204                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1205
1206                         if ((md->mode & required_mode) != required_mode) continue;
1207                         if (mti->isDisabled && mti->isDisabled(md)) continue;
1208                         if (mti->type!=eModifierTypeType_OnlyDeform) continue;
1209
1210                         if (!deformedVerts) {
1211                                 deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
1212                                 originalVerts = MEM_dupallocN(deformedVerts);
1213                         }
1214                         
1215                         mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
1216
1217                         if (md==preTesselatePoint)
1218                                 break;
1219                 }
1220         }
1221
1222         if (deformedVerts) {
1223                 curve_applyVertexCos(ob->data, nurb, deformedVerts);
1224         }
1225
1226         *originalVerts_r = originalVerts;
1227         *deformedVerts_r = deformedVerts;
1228         *numVerts_r = numVerts;
1229 }
1230
1231 void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *dispbase, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3])
1232 {
1233         int editmode = (!forRender && ob==G.obedit);
1234         ModifierData *md = modifiers_getVirtualModifierList(ob);
1235         ModifierData *preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode);
1236         DispList *dl;
1237         int required_mode;
1238
1239         if(forRender) required_mode = eModifierMode_Render;
1240         else required_mode = eModifierMode_Realtime;
1241
1242         if(editmode) required_mode |= eModifierMode_Editmode;
1243
1244         if (preTesselatePoint) {
1245                 md = preTesselatePoint->next;
1246         }
1247
1248         for (; md; md=md->next) {
1249                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1250
1251                 if ((md->mode & required_mode) != required_mode) continue;
1252                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1253                 if (mti->type!=eModifierTypeType_OnlyDeform && mti->type!=eModifierTypeType_DeformOrConstruct) continue;
1254
1255                 for (dl=dispbase->first; dl; dl=dl->next) {
1256                         mti->deformVerts(md, ob, NULL, (float(*)[3]) dl->verts, (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
1257                 }
1258         }
1259
1260         if (deformedVerts) {
1261                 curve_applyVertexCos(ob->data, nurb, originalVerts);
1262                 MEM_freeN(originalVerts);
1263                 MEM_freeN(deformedVerts);
1264         }
1265 }
1266
1267 static void displist_surf_indices(DispList *dl)
1268 {
1269         int a, b, p1, p2, p3, p4;
1270         int *index;
1271         
1272         dl->totindex= 0;
1273         
1274         index=dl->index= MEM_mallocN( 4*sizeof(int)*(dl->parts+1)*(dl->nr+1), "index array nurbs");
1275         
1276         for(a=0; a<dl->parts; a++) {
1277                 
1278                 DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
1279                 
1280                 for(; b<dl->nr; b++, index+=4) {        
1281                         index[0]= p1;
1282                         index[1]= p2;
1283                         index[2]= p4;
1284                         index[3]= p3;
1285                         
1286                         dl->totindex++;
1287                         
1288                         p2= p1; p1++;
1289                         p4= p3; p3++;
1290
1291                 }
1292         }
1293         
1294 }
1295
1296 void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender)
1297 {
1298         ListBase *nubase;
1299         Nurb *nu;
1300         Curve *cu = ob->data;
1301         DispList *dl;
1302         float *data;
1303         int len;
1304         int numVerts;
1305         float (*originalVerts)[3];
1306         float (*deformedVerts)[3];
1307                 
1308         if(!forRender && ob==G.obedit) {
1309                 nubase= &editNurb;
1310         }
1311         else {
1312                 nubase= &cu->nurb;
1313         }
1314
1315         curve_calc_modifiers_pre(ob, nubase, forRender, &originalVerts, &deformedVerts, &numVerts);
1316
1317         for (nu=nubase->first; nu; nu=nu->next) {
1318                 if(forRender || nu->hide==0) {
1319                         if(nu->pntsv==1) {
1320                                 len= nu->pntsu*nu->resolu;
1321                                 
1322                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1323                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1324                                 
1325                                 BLI_addtail(dispbase, dl);
1326                                 dl->parts= 1;
1327                                 dl->nr= len;
1328                                 dl->col= nu->mat_nr;
1329                                 dl->charidx= nu->charidx;
1330                                 dl->rt= nu->flag;
1331                                 
1332                                 data= dl->verts;
1333                                 if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY;
1334                                 else dl->type= DL_SEGM;
1335                                 
1336                                 makeNurbcurve(nu, data, nu->resolu, 3);
1337                         }
1338                         else {
1339                                 len= nu->resolu*nu->resolv;
1340                                 
1341                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1342                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1343                                 BLI_addtail(dispbase, dl);
1344
1345                                 dl->col= nu->mat_nr;
1346                                 dl->charidx= nu->charidx;
1347                                 dl->rt= nu->flag;
1348                                 
1349                                 data= dl->verts;
1350                                 dl->type= DL_SURF;
1351
1352                                 dl->parts= nu->resolu;  /* in reverse, because makeNurbfaces works that way */
1353                                 dl->nr= nu->resolv;
1354                                 if(nu->flagv & CU_CYCLIC) dl->flag|= DL_CYCL_U; /* reverse too! */
1355                                 if(nu->flagu & CU_CYCLIC) dl->flag|= DL_CYCL_V;
1356
1357                                 makeNurbfaces(nu, data, 0);
1358                                 
1359                                 /* gl array drawing: using indices */
1360                                 displist_surf_indices(dl);
1361                         }
1362                 }
1363         }
1364
1365         if (!forRender) {
1366                 tex_space_curve(cu);
1367         }
1368
1369         curve_calc_modifiers_post(ob, nubase, dispbase, forRender, originalVerts, deformedVerts);
1370 }
1371
1372 void makeDispListCurveTypes(Object *ob, int forOrco)
1373 {
1374         Curve *cu = ob->data;
1375         ListBase *dispbase;
1376         
1377         /* we do allow duplis... this is only displist on curve level */
1378         if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
1379
1380         freedisplist(&(ob->disp));
1381         dispbase= &(cu->disp);
1382         freedisplist(dispbase);
1383         
1384         if(ob->type==OB_SURF) {
1385                 makeDispListSurf(ob, dispbase, 0);
1386         }
1387         else if ELEM(ob->type, OB_CURVE, OB_FONT) {
1388                 ListBase dlbev;
1389                 float (*originalVerts)[3];
1390                 float (*deformedVerts)[3];
1391                 int obedit= (G.obedit && G.obedit->data==ob->data && G.obedit->type==OB_CURVE);
1392                 ListBase *nubase = obedit?&editNurb:&cu->nurb;
1393                 int numVerts;
1394
1395                 BLI_freelistN(&(cu->bev));
1396                 
1397                 if(cu->path) free_path(cu->path);
1398                 cu->path= NULL;
1399                 
1400                 if(ob->type==OB_FONT) text_to_curve(ob, 0);
1401                 
1402                 if(!forOrco) curve_calc_modifiers_pre(ob, nubase, 0, &originalVerts, &deformedVerts, &numVerts);
1403
1404                 makeBevelList(ob);
1405
1406                 /* If curve has no bevel will return nothing */
1407                 makebevelcurve(ob, &dlbev);
1408
1409                 /* no bevel or extrude, and no width correction? */
1410                 if (!dlbev.first && cu->width==1.0f) {
1411                         curve_to_displist(cu, nubase, dispbase);
1412                 } else {
1413                         float widfac= cu->width-1.0;
1414                         BevList *bl= cu->bev.first;
1415                         Nurb *nu= nubase->first;
1416
1417                         for (; bl && nu; bl=bl->next,nu=nu->next) {
1418                                 DispList *dl;
1419                                 float *fp1, *data;
1420                                 BevPoint *bevp;
1421                                 int a,b;
1422                                 
1423                                 if (bl->nr) { /* blank bevel lists can happen */
1424                                         
1425                                         /* exception handling; curve without bevel or extrude, with width correction */
1426                                         if(dlbev.first==NULL) {
1427                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
1428                                                 dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
1429                                                 BLI_addtail(dispbase, dl);
1430                                                 
1431                                                 if(bl->poly!= -1) dl->type= DL_POLY;
1432                                                 else dl->type= DL_SEGM;
1433                                                 
1434                                                 if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE);
1435                                                 
1436                                                 dl->parts= 1;
1437                                                 dl->nr= bl->nr;
1438                                                 dl->col= nu->mat_nr;
1439                                                 dl->charidx= nu->charidx;
1440                                                 dl->rt= nu->flag;
1441                                                 
1442                                                 a= dl->nr;
1443                                                 bevp= (BevPoint *)(bl+1);
1444                                                 data= dl->verts;
1445                                                 while(a--) {
1446                                                         data[0]= bevp->x+widfac*bevp->sina;
1447                                                         data[1]= bevp->y+widfac*bevp->cosa;
1448                                                         data[2]= bevp->z;
1449                                                         bevp++;
1450                                                         data+=3;
1451                                                 }
1452                                         }
1453                                         else {
1454                                                 DispList *dlb;
1455                                                 
1456                                                 for (dlb=dlbev.first; dlb; dlb=dlb->next) {
1457         
1458                                                                 /* for each part of the bevel use a separate displblock */
1459                                                         dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
1460                                                         dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
1461                                                         BLI_addtail(dispbase, dl);
1462         
1463                                                         dl->type= DL_SURF;
1464                                                         
1465                                                         dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE);
1466                                                         if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U;
1467                                                         if(bl->poly>=0) dl->flag |= DL_CYCL_V;
1468                                                         
1469                                                         dl->parts= bl->nr;
1470                                                         dl->nr= dlb->nr;
1471                                                         dl->col= nu->mat_nr;
1472                                                         dl->charidx= nu->charidx;
1473                                                         dl->rt= nu->flag;
1474                                                         dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "col2");
1475                                                         bevp= (BevPoint *)(bl+1);
1476         
1477                                                                 /* for each point of poly make a bevel piece */
1478                                                         bevp= (BevPoint *)(bl+1);
1479                                                         for(a=0; a<bl->nr; a++,bevp++) {
1480                                                                 float fac=1.0;
1481                                                                 if (cu->taperobj==NULL) {
1482                                                                         if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) )
1483                                                                         fac = calc_curve_subdiv_radius(cu, nu, a);
1484                                                                 } else {
1485                                                                         fac = calc_taper(cu->taperobj, a, bl->nr);
1486                                                                 }
1487                                                                 
1488                                                                 if (bevp->f1) {
1489                                                                         dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F);
1490                                                                 }
1491         
1492                                                                         /* rotate bevel piece and write in data */
1493                                                                 fp1= dlb->verts;
1494                                                                 for (b=0; b<dlb->nr; b++,fp1+=3,data+=3) {
1495                                                                         if(cu->flag & CU_3D) {
1496                                                                                 float vec[3];
1497         
1498                                                                                 vec[0]= fp1[1]+widfac;
1499                                                                                 vec[1]= fp1[2];
1500                                                                                 vec[2]= 0.0;
1501                                                                                 
1502                                                                                 Mat3MulVecfl(bevp->mat, vec);
1503                                                                                 
1504                                                                                 data[0]= bevp->x+ fac*vec[0];
1505                                                                                 data[1]= bevp->y+ fac*vec[1];
1506                                                                                 data[2]= bevp->z+ fac*vec[2];
1507                                                                         }
1508                                                                         else {
1509                                                                                 data[0]= bevp->x+ fac*(widfac+fp1[1])*bevp->sina;
1510                                                                                 data[1]= bevp->y+ fac*(widfac+fp1[1])*bevp->cosa;
1511                                                                                 data[2]= bevp->z+ fac*fp1[2];
1512                                                                         }
1513                                                                 }
1514                                                         }
1515                                                         
1516                                                         /* gl array drawing: using indices */
1517                                                         displist_surf_indices(dl);
1518                                                 }
1519                                         }
1520                                 }
1521
1522                         }
1523                         freedisplist(&dlbev);
1524                 }
1525
1526                 curve_to_filledpoly(cu, nubase, dispbase);
1527
1528                 if(cu->flag & CU_PATH) calc_curvepath(ob);
1529
1530                 if(!forOrco) curve_calc_modifiers_post(ob, nubase, &cu->disp, 0, originalVerts, deformedVerts);
1531                 tex_space_curve(cu);
1532         }
1533         
1534         boundbox_displist(ob);
1535 }
1536
1537 void imagestodisplist(void)
1538 {
1539         /* removed */
1540 }
1541
1542 /* this is confusing, there's also min_max_object, appplying the obmat... */
1543 static void boundbox_displist(Object *ob)
1544 {
1545         BoundBox *bb=0;
1546         float min[3], max[3];
1547         DispList *dl;
1548         float *vert;
1549         int a, tot=0;
1550         
1551         INIT_MINMAX(min, max);
1552
1553         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1554                 Curve *cu= ob->data;
1555                 int doit= 0;
1556
1557                 if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");        
1558                 bb= cu->bb;
1559                 
1560                 dl= cu->disp.first;
1561
1562                 while (dl) {
1563                         if(dl->type==DL_INDEX3) tot= dl->nr;
1564                         else tot= dl->nr*dl->parts;
1565                         
1566                         vert= dl->verts;
1567                         for(a=0; a<tot; a++, vert+=3) {
1568                                 doit= 1;
1569                                 DO_MINMAX(vert, min, max);
1570                         }
1571
1572                         dl= dl->next;
1573                 }
1574                 
1575                 if(!doit) {
1576                         min[0] = min[1] = min[2] = -1.0f;
1577                         max[0] = max[1] = max[2] = 1.0f;
1578                 }
1579                 
1580         }
1581         
1582         if(bb) {
1583                 boundbox_set_from_min_max(bb, min, max);
1584         }
1585 }
1586