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