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