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