Biiig commit! Thanks to 2-3 weeks of cvs freeze...
[blender.git] / source / blender / blenkernel / intern / displist.c
1
2 /*  displist.c
3  * 
4  * 
5  * $Id$
6  *
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * The Original Code is: all of this file.
30  *
31  * Contributor(s): none yet.
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <math.h>
41 #include <stdio.h>
42 #include <string.h>
43
44 #ifdef WIN32
45 #include "BLI_winstuff.h"
46 #endif
47 #include "MEM_guardedalloc.h"
48
49 #include "IMB_imbuf_types.h"
50
51 #include "DNA_texture_types.h"
52 #include "DNA_meta_types.h"
53 #include "DNA_curve_types.h"
54 #include "DNA_effect_types.h"
55 #include "DNA_listBase.h"
56 #include "DNA_lamp_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_mesh_types.h"
59 #include "DNA_meshdata_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_image_types.h"
62 #include "DNA_material_types.h"
63 #include "DNA_view3d_types.h"
64 #include "DNA_lattice_types.h"
65
66 #include "BLI_blenlib.h"
67 #include "BLI_arithb.h"
68 #include "BLI_editVert.h"
69
70 #include "BKE_bad_level_calls.h"
71 #include "BKE_utildefines.h"
72 #include "BKE_global.h"
73 #include "BKE_displist.h"
74 #include "BKE_deform.h"
75 #include "BKE_object.h"
76 #include "BKE_world.h"
77 #include "BKE_mesh.h"
78 #include "BKE_effect.h"
79 #include "BKE_mball.h"
80 #include "BKE_material.h"
81 #include "BKE_curve.h"
82 #include "BKE_anim.h"
83 #include "BKE_screen.h"
84 #include "BKE_texture.h"
85 #include "BKE_library.h"
86 #include "BKE_font.h"
87 #include "BKE_lattice.h"
88 #include "BKE_scene.h"
89 #include "BKE_subsurf.h"
90
91 #include "nla.h" /* For __NLA: Please do not remove yet */
92 #include "render.h"
93
94
95 /***/
96
97 typedef struct _FastLamp FastLamp;
98 struct _FastLamp {
99         FastLamp *next;
100         
101         short type, mode, lay, rt;
102         float co[3];
103         float vec[3];
104         float dist, distkw, att1, att2, spotsi, spotbl, r, g, b;
105 };
106
107 /***/
108
109 static FastLamp *fastlamplist= NULL;
110 static float fviewmat[4][4];
111
112 /* only called from subsurf.c when levels is zero */
113 DispListMesh *displistmesh_from_editmesh(EditMesh *em) 
114 {
115         DispListMesh *dlm= MEM_callocN(sizeof(*dlm),"dlm");
116         EditVert *eve, *evePrev;
117         EditEdge *eed;
118         EditFace *evl;
119         MFace *mfNew;
120         int i;
121
122         dlm->flag= 0;
123         dlm->totvert= BLI_countlist(&em->verts);
124         dlm->totface= BLI_countlist(&em->edges)+BLI_countlist(&em->faces);
125         dlm->mvert= MEM_callocN(sizeof(*dlm->mface)*dlm->totvert, "dlm->mvert");
126         dlm->mcol= NULL;
127         dlm->tface= NULL;
128         dlm->mface= MEM_mallocN(sizeof(*dlm->mface)*dlm->totface, "dlm->mface");
129
130         i=0;
131         for (eve= em->verts.first; eve; eve= eve->next, i++) {
132                 MVert *mvNew= &dlm->mvert[i];
133                 VECCOPY(mvNew->co, eve->co);
134                 eve->ssco= eve->co;             /* no subsurf coordinate, but we add a save pointer in it */
135                 eve->prev= (void*) i;   /* hack to fetch indices */
136         }
137
138         mfNew= dlm->mface;
139         for (evl= em->faces.first; evl; evl= evl->next) {
140                 // we skip hidden faces
141                 if(evl->v1->h || evl->v2->h || evl->v3->h || (evl->v4 && evl->v4->h)) dlm->totface--;
142                 else {
143                         mfNew->v1= (int) evl->v1->prev;
144                         mfNew->v2= (int) evl->v2->prev;
145                         mfNew->v3= (int) evl->v3->prev;
146                         mfNew->v4= evl->v4?(int) evl->v4->prev:0;
147                         mfNew->flag= evl->flag;
148                         mfNew->mat_nr= evl->mat_nr;
149                         mfNew->puno= 0;
150                         mfNew->edcode= 0;
151         
152                         if (evl->v4 && !mfNew->v4) {
153                                 mfNew->v1^= mfNew->v3^= mfNew->v1^= mfNew->v3;
154                                 mfNew->v2^= mfNew->v4^= mfNew->v2^= mfNew->v4;
155                         }
156                         mfNew++;
157                 }
158         }
159         for (eed= em->edges.first; eed; eed= eed->next, mfNew++) {
160
161                 mfNew->v1= (int) eed->v1->prev;
162                 mfNew->v2= (int) eed->v2->prev;
163                 mfNew->v3= 0;
164                 mfNew->v4= 0;
165                 mfNew->flag= 0;
166                 mfNew->mat_nr= 0;
167                 mfNew->puno= 0;
168                 mfNew->edcode= 0;
169         }
170
171                 /* restore prev links */
172         for (evePrev=NULL, eve= em->verts.first; eve; evePrev=eve, eve= eve->next)
173                 eve->prev= evePrev;
174
175         displistmesh_calc_vert_normals(dlm);
176
177         return dlm;
178 }
179 DispListMesh *displistmesh_from_mesh(Mesh *me, float *extverts) 
180 {
181         DispListMesh *dlm= MEM_callocN(sizeof(*dlm),"dlm");
182         int i;
183         dlm->flag= 0;
184         dlm->totvert= me->totvert;
185         dlm->totface= me->totface;
186         dlm->mvert= MEM_dupallocN(me->mvert);
187         dlm->mcol= me->mcol?MEM_dupallocN(me->mcol):NULL;
188         dlm->tface= me->tface?MEM_dupallocN(me->tface):NULL;
189         dlm->mface= MEM_mallocN(sizeof(*dlm->mface)*dlm->totface, "dlm->mface");
190
191         if (extverts) {
192                 for (i=0; i<dlm->totvert; i++) {
193                         VECCOPY(dlm->mvert[i].co, &extverts[i*3]);
194                 }
195         }
196         for (i=0; i<dlm->totface; i++) {
197                 MFace *mfOld= &((MFace*) me->mface)[i];
198                 MFace *mfNew= &dlm->mface[i];
199
200                 mfNew->v1= mfOld->v1;
201                 mfNew->v2= mfOld->v2;
202                 mfNew->v3= mfOld->v3;
203                 mfNew->v4= mfOld->v4;
204                 mfNew->flag= mfOld->flag;
205                 mfNew->mat_nr= mfOld->mat_nr;
206                 mfNew->puno= 0;
207                 mfNew->edcode= 0;
208         }
209
210         return dlm;
211 }
212
213 void displistmesh_free(DispListMesh *dlm) 
214 {
215         // also check on mvert and mface, can be NULL after decimator (ton)
216         if (dlm->mvert) MEM_freeN(dlm->mvert);
217         if (dlm->medge) MEM_freeN(dlm->medge);
218         if (dlm->mface) MEM_freeN(dlm->mface);
219         if (dlm->mcol) MEM_freeN(dlm->mcol);
220         if (dlm->tface) MEM_freeN(dlm->tface);
221         if (dlm->editedge) MEM_freeN(dlm->editedge);
222         if (dlm->editface) MEM_freeN(dlm->editface);
223         MEM_freeN(dlm);
224 }
225
226 static DispListMesh *displistmesh_copy(DispListMesh *odlm) 
227 {
228         DispListMesh *ndlm= MEM_dupallocN(odlm);
229         ndlm->mvert= MEM_dupallocN(odlm->mvert);
230         ndlm->medge= MEM_dupallocN(odlm->medge);
231         ndlm->mface= MEM_dupallocN(odlm->mface);
232         if (odlm->mcol) ndlm->mcol= MEM_dupallocN(odlm->mcol);
233         if (odlm->tface) ndlm->tface= MEM_dupallocN(odlm->tface);
234         
235         return ndlm;
236 }
237
238 void displistmesh_calc_vert_normals(DispListMesh *dlm) 
239 {
240         MVert *mverts= dlm->mvert;
241         int nmverts= dlm->totvert;
242         MFace *mfaces= dlm->mface;
243         int nmfaces= dlm->totface;
244         float (*tnorms)[3]= MEM_callocN(nmverts*sizeof(*tnorms), "tnorms");
245         int i;
246         
247         for (i=0; i<nmfaces; i++) {
248                 MFace *mf= &mfaces[i];
249                 float f_no[3];
250
251                 if (!mf->v3)
252                         continue;
253                         
254                 if (mf->v4)
255                         CalcNormFloat4(mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co, f_no);
256                 else
257                         CalcNormFloat(mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, f_no);
258                 
259                 VecAddf(tnorms[mf->v1], tnorms[mf->v1], f_no);
260                 VecAddf(tnorms[mf->v2], tnorms[mf->v2], f_no);
261                 VecAddf(tnorms[mf->v3], tnorms[mf->v3], f_no);
262                 if (mf->v4)
263                         VecAddf(tnorms[mf->v4], tnorms[mf->v4], f_no);
264         }
265         for (i=0; i<nmverts; i++) {
266                 MVert *mv= &mverts[i];
267                 float *no= tnorms[i];
268                 
269                 Normalise(no);
270                 mv->no[0]= (short)(no[0]*32767.0);
271                 mv->no[1]= (short)(no[1]*32767.0);
272                 mv->no[2]= (short)(no[2]*32767.0);
273         }
274         
275         MEM_freeN(tnorms);
276 }
277
278 void displistmesh_to_mesh(DispListMesh *dlm, Mesh *me) 
279 {
280         MFace *mfaces;
281         int i;
282         
283         if (dlm->totvert>MESH_MAX_VERTS) {
284                 error("Too many vertices");
285         } else {
286                 me->totface= dlm->totface;
287                 me->totvert= dlm->totvert;
288
289                 me->mvert= MEM_dupallocN(dlm->mvert);
290                 me->mface= mfaces= MEM_mallocN(sizeof(*mfaces)*me->totface, "me->mface");
291                 me->tface= MEM_dupallocN(dlm->tface);
292                 me->mcol= MEM_dupallocN(dlm->mcol);
293
294                 if(dlm->medge) {
295                         me->totedge= dlm->totedge;
296                         me->medge= MEM_dupallocN(dlm->medge);
297                 }
298
299                 for (i=0; i<me->totface; i++) {
300                         MFace *mf= &mfaces[i];
301                         MFace *oldmf= &dlm->mface[i];
302                 
303                         mf->v1= oldmf->v1;
304                         mf->v2= oldmf->v2;
305                         mf->v3= oldmf->v3;
306                         mf->v4= oldmf->v4;
307                         mf->flag= oldmf->flag;
308                         mf->mat_nr= oldmf->mat_nr;
309                         mf->puno= 0;
310                         mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
311                 }
312         }
313 }
314
315 void free_disp_elem(DispList *dl)
316 {
317         if(dl) {
318                 if(dl->verts) MEM_freeN(dl->verts);
319                 if(dl->nors) MEM_freeN(dl->nors);
320                 if(dl->index) MEM_freeN(dl->index);
321                 if(dl->col1) MEM_freeN(dl->col1);
322                 if(dl->col2) MEM_freeN(dl->col2);
323                 if(dl->mesh) displistmesh_free(dl->mesh);
324                 MEM_freeN(dl);
325         }
326 }
327
328 void freedisplist(ListBase *lb)
329 {
330         DispList *dl;
331
332         dl= lb->first;
333         while(dl) {
334                 BLI_remlink(lb, dl);
335                 free_disp_elem(dl);
336                 dl= lb->first;
337         }
338 }
339
340 static void freedisplist_object(Object *ob)
341 {
342         freedisplist(&ob->disp);
343
344         if(ob->type==OB_MESH) {
345                 Mesh *me= ob->data;
346                 freedisplist(&me->disp);
347         }
348         else if(ob->type==OB_CURVE || ob->type==OB_SURF || ob->type==OB_FONT) {
349                 Curve *cu= ob->data;
350                 freedisplist(&cu->disp);
351         }
352 }
353
354 void free_displist_by_type(ListBase *lb, int type) 
355 {
356         DispList *dl;
357         
358         for (dl= lb->first; dl; ) {
359                 DispList *next= dl->next;
360                 
361                 if (dl->type==type) {
362                         BLI_remlink(lb, dl);
363                         free_disp_elem(dl);
364                 }
365                 
366                 dl= next;
367         }       
368 }
369
370 DispList *find_displist_create(ListBase *lb, int type)
371 {
372         DispList *dl;
373         
374         dl= lb->first;
375         while(dl) {
376                 if(dl->type==type) return dl;
377                 dl= dl->next;
378         }
379
380         dl= MEM_callocN(sizeof(DispList), "find_disp");
381         dl->type= type;
382         BLI_addtail(lb, dl);
383
384         return dl;
385 }
386
387 DispList *find_displist(ListBase *lb, int type)
388 {
389         DispList *dl;
390         
391         dl= lb->first;
392         while(dl) {
393                 if(dl->type==type) return dl;
394                 dl= dl->next;
395         }
396
397         return 0;
398 }
399
400 int displist_has_faces(ListBase *lb)
401 {
402         DispList *dl;
403         
404         dl= lb->first;
405         while(dl) {
406                 if ELEM6(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF, DL_MESH, DL_TRIA, DL_POLY)
407                         return 1;
408                 dl= dl->next;
409         }
410         return 0;
411 }
412
413 void copy_displist(ListBase *lbn, ListBase *lb)
414 {
415         DispList *dln, *dl;
416         
417         lbn->first= lbn->last= 0;
418         
419         dl= lb->first;
420         while(dl) {
421                 
422                 dln= MEM_dupallocN(dl);
423                 BLI_addtail(lbn, dln);
424                 dln->verts= MEM_dupallocN(dl->verts);
425                 dln->nors= MEM_dupallocN(dl->nors);
426                 dln->index= MEM_dupallocN(dl->index);
427                 dln->col1= MEM_dupallocN(dl->col1);
428                 dln->col2= MEM_dupallocN(dl->col2);
429                 if (dl->mesh)
430                         dln->mesh= displistmesh_copy(dl->mesh);
431                 
432                 dl= dl->next;
433         }
434 }
435
436 static void initfastshade(void)
437 {
438         Base *base;
439         Object *ob;
440         Lamp *la;
441         FastLamp *fl;
442         float mat[4][4];
443
444         init_render_world();
445         
446         if(fastlamplist) return;
447         if(G.scene->camera==0) G.scene->camera= scene_find_camera(G.scene);
448         if(G.scene->camera==0) return;
449
450         /* copied from 'roteerscene' (does that function still exist? (ton) */
451         where_is_object(G.scene->camera);
452         Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
453         Mat4Ortho(R.viewinv);
454         Mat4Invert(fviewmat, R.viewinv);
455
456         /* initrendertexture(); */
457
458         base= G.scene->base.first;
459         while(base) {
460                 ob= base->object;
461                 if( ob->type==OB_LAMP && (base->lay & G.scene->lay)) {
462                         
463                         Mat4MulMat4(mat, ob->obmat, fviewmat);
464                         
465                         la= ob->data;
466                         fl= MEM_mallocN(sizeof(FastLamp), "initfastshade2");
467
468                         fl->next= fastlamplist;
469                         fastlamplist= fl;
470
471                         fl->type= la->type;
472                         fl->mode= la->mode;
473                         fl->lay= base->lay;
474                         
475                         fl->vec[0]= mat[2][0];
476                         fl->vec[1]= mat[2][1];
477                         fl->vec[2]= mat[2][2];
478                         Normalise(fl->vec);
479                         
480                         fl->co[0]= mat[3][0];
481                         fl->co[1]= mat[3][1];
482                         fl->co[2]= mat[3][2];
483
484                         fl->dist= la->dist;
485                         fl->distkw= fl->dist*fl->dist;
486                         fl->att1= la->att1;
487                         fl->att2= la->att2;
488
489                         fl->spotsi= (float)cos( M_PI*la->spotsize/360.0 );
490                         fl->spotbl= (1.0f-fl->spotsi)*la->spotblend;
491         
492                         fl->r= la->energy*la->r;
493                         fl->g= la->energy*la->g;
494                         fl->b= la->energy*la->b;
495                 }
496                 
497                 if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
498                 else base= base->next;
499         }
500 }
501
502
503 void freefastshade()
504 {
505         while (fastlamplist) {
506                 FastLamp *fl= fastlamplist;
507                 fastlamplist= fl->next;
508                 
509                 MEM_freeN(fl);
510         }
511 }
512
513
514 static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2, char *vertcol)
515 {
516         ShadeInput shi;
517         FastLamp *fl;
518         float i, t, inp, is, soft,  lv[3], lampdist, ld;
519         float diff1[3], diff2[3];
520         float isr1=0, isg1=0, isb1=0, isr=0, isg=0, isb=0;
521         int a, back;
522
523         if(ma==0) return;
524         
525         shi.mat= ma;
526         shi.vlr= NULL;  // have to do this!
527         
528         // copy all relevant material vars, note, keep this synced with render_types.h
529         memcpy(&shi.r, &shi.mat->r, 23*sizeof(float));
530         // set special cases:
531         shi.har= shi.mat->har;
532         
533         shi.osatex= 0;  // also prevents reading vlr
534         
535         VECCOPY(shi.vn, nor);
536         
537         if(ma->mode & MA_VERTEXCOLP) {
538                 if(vertcol) {
539                         shi.r= vertcol[3]/255.0;
540                         shi.g= vertcol[2]/255.0;
541                         shi.b= vertcol[1]/255.0;
542                 }
543         }
544         
545         if(ma->texco) {
546                 VECCOPY(shi.lo, orco);
547                 
548                 if(ma->texco & TEXCO_GLOB) {
549                         VECCOPY(shi.gl, shi.lo);
550                 }
551                 if(ma->texco & TEXCO_WINDOW) {
552                         VECCOPY(shi.winco, shi.lo);
553                 }
554                 if(ma->texco & TEXCO_STICKY) {
555                         VECCOPY(shi.sticky, shi.lo);
556                 }
557                 if(ma->texco & TEXCO_UV) {
558                         VECCOPY(shi.uv, shi.lo);
559                 }
560                 if(ma->texco & TEXCO_OBJECT) {
561                         VECCOPY(shi.co, shi.lo);
562                 }
563                 if(ma->texco & TEXCO_NORM) {
564                         VECCOPY(shi.orn, shi.vn);
565                 }
566                 if(ma->texco & TEXCO_REFL) {
567                         
568                         inp= 2.0*(shi.vn[2]);
569                         shi.ref[0]= (inp*shi.vn[0]);
570                         shi.ref[1]= (inp*shi.vn[1]);
571                         shi.ref[2]= (-1.0+inp*shi.vn[2]);
572                 }
573
574                 do_material_tex(&shi);
575         }
576
577         if(ma->mode & MA_SHLESS) {
578                 if(vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
579                         col1[3]= vertcol[3]*shi.r;
580                         col1[2]= vertcol[2]*shi.g;
581                         col1[1]= vertcol[1]*shi.b;
582                 }
583                 else {
584                         col1[3]= (255.0*shi.r);
585                         col1[2]= (255.0*shi.g);
586                         col1[1]= (255.0*shi.b);
587                 }
588                 if(col2) {
589                         col2[3]= col1[3];
590                         col2[2]= col1[2];
591                         col2[1]= col1[1];
592                 }
593                 return;
594         }
595
596         if( vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
597                 diff1[0]= diff2[0]= shi.r*(shi.emit+vertcol[3]/255.0);
598                 diff1[1]= diff2[1]= shi.g*(shi.emit+vertcol[2]/255.0);
599                 diff1[2]= diff2[2]= shi.b*(shi.emit+vertcol[1]/255.0);
600         }
601         else {
602                 diff1[0]= diff2[0]= shi.r*shi.emit;
603                 diff1[1]= diff2[1]= shi.g*shi.emit;
604                 diff1[2]= diff2[2]= shi.b*shi.emit;
605         }
606         
607         shi.view[0]= 0.0;
608         shi.view[1]= 0.0;
609         shi.view[2]= 1.0;
610         
611         Normalise(shi.view);
612
613         for (fl= fastlamplist; fl; fl= fl->next) {
614                 /* if(fl->mode & LA_LAYER) if((fl->lay & ma->lay)==0) continue; */
615
616                 if(fl->type==LA_SUN || fl->type==LA_HEMI) {
617                         VECCOPY(lv, fl->vec);
618                         lampdist= 1.0;
619                 }
620                 else {
621                         lv[0]= fl->co[0] - co[0];
622                         lv[1]= fl->co[1] - co[1];
623                         lv[2]= fl->co[2] - co[2];
624                         ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
625                         lv[0]/=ld;
626                         lv[1]/=ld;
627                         lv[2]/=ld;
628
629                         if(fl->mode & LA_QUAD) {
630                                 t= 1.0;
631                                 if(fl->att1>0.0)
632                                         t= fl->dist/(fl->dist+fl->att1*ld);
633                                 if(fl->att2>0.0)
634                                         t*= fl->distkw/(fl->distkw+fl->att2*ld*ld);
635
636                                 lampdist= t;
637                         }
638                         else {
639                                 lampdist= (fl->dist/(fl->dist+ld));
640                         }
641
642                         if(fl->mode & LA_SPHERE) {
643                                 t= fl->dist - ld;
644                                 if(t<0.0) continue;
645                                 
646                                 t/= fl->dist;
647                                 lampdist*= (t);
648                         }
649                 }
650
651                 if(fl->type==LA_SPOT) {
652                         inp= lv[0]*fl->vec[0]+lv[1]*fl->vec[1]+lv[2]*fl->vec[2];
653                         if(inp<fl->spotsi) continue;
654                         else {
655                                 t= inp-fl->spotsi;
656                                 i= 1.0;
657                                 soft= 1.0;
658                                 if(t<fl->spotbl && fl->spotbl!=0.0) {
659                                         /* soft area */
660                                         i= t/fl->spotbl;
661                                         t= i*i;
662                                         soft= (3.0*t-2.0*t*i);
663                                         inp*= soft;
664                                 }
665
666                                 lampdist*=inp;
667                         }
668                 }
669
670                 if(fl->mode & LA_NO_DIFF) is= 0.0;
671                 else {
672                         is= nor[0]*lv[0]+ nor[1]*lv[1]+ nor[2]*lv[2];
673         
674                         if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(nor, lv, shi.view, ma->roughness);
675                         else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(nor, lv, shi.view, ma->param[0], ma->param[1]);
676                 }
677                 
678                 back= 0;
679                 if(is<0.0) {
680                         back= 1;
681                         is= -is;
682                 }
683                 inp= is*lampdist*shi.refl;
684
685                 if(back==0) {
686                         add_to_diffuse(diff1, &shi, is, inp*fl->r, inp*fl->g, inp*fl->b);
687                         //diff1[0]+= inp*fl->r;
688                         //diff1[1]+= inp*fl->g;
689                         //diff1[2]+= inp*fl->b;
690                 } else if(col2) {
691                         add_to_diffuse(diff2, &shi, is, inp*fl->r, inp*fl->g, inp*fl->b);
692                         //diff2[0]+= inp*fl->r;
693                         //diff2[1]+= inp*fl->g;
694                         //diff2[2]+= inp*fl->b;
695                 }
696                 if(shi.spec!=0.0 && (fl->mode & LA_NO_SPEC)==0) {
697                         float specfac;
698                         
699                         if(ma->spec_shader==MA_SPEC_PHONG) 
700                                 specfac= Phong_Spec(nor, lv, shi.view, shi.har);
701                         else if(ma->spec_shader==MA_SPEC_COOKTORR) 
702                                 specfac= CookTorr_Spec(nor, lv, shi.view, shi.har);
703                         else if(ma->spec_shader==MA_SPEC_BLINN) 
704                                 specfac= Blinn_Spec(nor, lv, shi.view, ma->refrac, (float)shi.har);
705                         else 
706                                 specfac= Toon_Spec(nor, lv, shi.view, ma->param[2], ma->param[3]);
707                         
708                         if(specfac>0) {
709                                 t= specfac*shi.spec*lampdist;
710                                 if(back==0) {
711                                         if(ma->mode & MA_RAMP_SPEC) {
712                                                 float spec[3];
713                                                 do_specular_ramp(&shi, specfac, t, spec);
714                                                 isr+= t*(fl->r * spec[0]);
715                                                 isg+= t*(fl->g * spec[1]);
716                                                 isb+= t*(fl->b * spec[2]);
717                                         }
718                                         else {
719                                                 isr+= t*(fl->r * shi.specr);
720                                                 isg+= t*(fl->g * shi.specg);
721                                                 isb+= t*(fl->b * shi.specb);
722                                         }
723                                 }
724                                 else if(col2) {
725                                         if(ma->mode & MA_RAMP_SPEC) {
726                                                 float spec[3];
727                                                 do_specular_ramp(&shi, specfac, t, spec);
728                                                 isr1+= t*(fl->r * spec[0]);
729                                                 isg1+= t*(fl->g * spec[1]);
730                                                 isb1+= t*(fl->b * spec[2]);
731                                         }
732                                         else {
733                                                 isr1+= t*(fl->r * shi.specr);
734                                                 isg1+= t*(fl->g * shi.specg);
735                                                 isb1+= t*(fl->b * shi.specb);
736                                         }
737                                 }
738                         }
739                 }
740
741         }
742
743         if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(diff1, &shi);
744         if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(&isr, &isg, &isb, &shi);
745
746         a= 256*(diff1[0] + shi.ambr +isr);
747         if(a>255) col1[3]= 255; 
748         else col1[3]= a;
749         a= 256*(diff1[1] + shi.ambg +isg);
750         if(a>255) col1[2]= 255; 
751         else col1[2]= a;
752         a= 256*(diff1[2] + shi.ambb +isb);
753         if(a>255) col1[1]= 255; 
754         else col1[1]= a;
755
756         if(col2) {
757                 if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(diff2, &shi);
758                 if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(&isr1, &isg1, &isb1, &shi);
759                 
760                 a= 256*(diff2[0] + shi.ambr +isr1);
761                 if(a>255) col2[3]= 255; 
762                 else col2[3]= a;
763                 a= 256*(diff2[1] + shi.ambg +isg1);
764                 if(a>255) col2[2]= 255; 
765                 else col2[2]= a;
766                 a= 256*(diff2[2] + shi.ambb +isb1);
767                 if(a>255) col2[1]= 255; 
768                 else col2[1]= a;
769         }
770
771 }
772
773 void addnormalsDispList(Object *ob, ListBase *lb)
774 {
775         DispList *dl = NULL;
776         Mesh *me;
777         MVert *ve1, *ve2, *ve3, *ve4;
778         MFace *mface;
779         float *vdata, *ndata, nor[3];
780         float *v1, *v2, *v3, *v4;
781         float *n1, *n2, *n3, *n4;
782         int a, b, p1, p2, p3, p4;
783
784         
785         if(ob->type==OB_MESH) {
786                 
787                 me= get_mesh(ob);
788                 
789                 if (mesh_uses_displist(me)) {
790                         DispList *dl= find_displist(&me->disp, DL_MESH);
791                         
792                         if (dl && !dl->nors) {
793                                 DispListMesh *dlm= dl->mesh;
794                                 int i;
795                                 
796                                 dl->nors= MEM_mallocN(sizeof(*dl->nors)*3*dlm->totface, "meshnormals");
797                                 
798                                 for (i=0; i<dlm->totface; i++) {
799                                         MFace *mf= &dlm->mface[i];
800                                         float *no= &dl->nors[i*3];
801                                         
802                                         if (mf->v3) {
803                                                 if (mf->v4)
804                                                         CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no);
805                                                 else
806                                                         CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no);
807                                         }
808                                 }
809                         }
810                 } else {
811                         if(me->totface==0) return;
812                         
813                         if(me->disp.first==0) {
814                                 dl= MEM_callocN(sizeof(DispList), "meshdisp");
815                                 dl->type= DL_NORS;
816                                 dl->parts= 1;
817                                 dl->nr= me->totface;
818                                 BLI_addtail(&me->disp, dl);
819                         }
820                         else return;
821                         
822                         if(dl->nors==0) {
823                                 dl->nors= MEM_mallocN(sizeof(float)*3*me->totface, "meshnormals");
824                                 n1= dl->nors;
825                                 mface= me->mface;
826                                 a= me->totface;
827                                 while(a--) {
828                                         if(mface->v3) {
829                                                 ve1= me->mvert+mface->v1;
830                                                 ve2= me->mvert+mface->v2;
831                                                 ve3= me->mvert+mface->v3;
832                                                 ve4= me->mvert+mface->v4;
833                                                 
834                                                 if(mface->v4) CalcNormFloat4(ve1->co, ve2->co, ve3->co, ve4->co, n1);
835                                                 else CalcNormFloat(ve1->co, ve2->co, ve3->co, n1);
836                                         }
837                                         n1+= 3;
838                                         mface++;
839                                 }
840                         }
841                 }
842
843                 return;
844         }
845
846         dl= lb->first;
847         
848         while(dl) {
849                 if(dl->type==DL_INDEX3) {
850                         if(dl->nors==0) {
851                                 dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
852                                 if(dl->verts[2]<0.0) dl->nors[2]= -1.0;
853                                 else dl->nors[2]= 1.0;
854                         }
855                 }
856                 else if(dl->type==DL_SURF) {
857                         if(dl->nors==0) {
858                                 dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
859                                 
860                                 vdata= dl->verts;
861                                 ndata= dl->nors;
862                                 
863                                 for(a=0; a<dl->parts; a++) {
864         
865                                         DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
866         
867                                         v1= vdata+ 3*p1; 
868                                         n1= ndata+ 3*p1;
869                                         v2= vdata+ 3*p2; 
870                                         n2= ndata+ 3*p2;
871                                         v3= vdata+ 3*p3; 
872                                         n3= ndata+ 3*p3;
873                                         v4= vdata+ 3*p4; 
874                                         n4= ndata+ 3*p4;
875                                         
876                                         for(; b<dl->nr; b++) {
877         
878                                                 CalcNormFloat4(v1, v3, v4, v2, nor);
879         
880                                                 VecAddf(n1, n1, nor);
881                                                 VecAddf(n2, n2, nor);
882                                                 VecAddf(n3, n3, nor);
883                                                 VecAddf(n4, n4, nor);
884         
885                                                 v2= v1; v1+= 3;
886                                                 v4= v3; v3+= 3;
887                                                 n2= n1; n1+= 3;
888                                                 n4= n3; n3+= 3;
889                                         }
890                                 }
891                                 a= dl->parts*dl->nr;
892                                 v1= ndata;
893                                 while(a--) {
894                                         Normalise(v1);
895                                         v1+= 3;
896                                 }
897                         }
898                 }
899                 dl= dl->next;
900         }
901 }
902
903
904 void shadeDispList(Object *ob)
905 {
906         MFace *mface;
907         MVert *mvert;
908         DispList *dl, *dlob, *dldeform;
909         Material *ma = NULL;
910         Mesh *me;
911         Curve *cu;
912 /*      extern Material defmaterial;     *//* initrender.c, already in bad lev calls*/
913         float *orco=NULL, imat[3][3], tmat[4][4], mat[4][4], vec[3], xn, yn, zn;
914         float *fp, *nor, n1[3];
915         unsigned int *col1, *col2, *vertcol;
916         int a, lastmat= -1, need_orco = 0;
917
918         if(ob->flag & OB_FROMDUPLI) return;
919         initfastshade();
920
921         Mat4MulMat4(mat, ob->obmat, fviewmat);
922         
923         Mat4Invert(tmat, mat);
924         Mat3CpyMat4(imat, tmat);
925         if(ob->transflag & OB_NEG_SCALE) Mat3MulFloat((float *)imat, -1.0);
926         
927         /* we extract dl_verts, deform info */
928         dldeform= find_displist(&ob->disp, DL_VERTS);
929         if(dldeform) BLI_remlink(&ob->disp, dldeform);
930         
931         /* Metaballs have the standard displist in the Object */
932         if(ob->type!=OB_MBALL) freedisplist(&ob->disp);
933
934         need_orco= 0;
935         for(a=0; a<ob->totcol; a++) {
936                 ma= give_current_material(ob, a+1);
937                 if(ma) {
938                         init_render_material(ma);
939                         if(ma->texco & TEXCO_ORCO) need_orco= 1;
940                 }
941         }
942
943         if(ob->type==OB_MESH) {
944                 
945                 me= ob->data;
946                 
947                 if (mesh_uses_displist(me)) {
948                         if (need_orco) {
949                                 make_orco_displist_mesh(ob, me->subdiv);
950                                 orco= me->orco;
951                         }
952
953                         dl= me->disp.first;
954                         while(dl) {
955                                 if(dl->type==DL_MESH && dl->mesh && dl->mesh->totvert) {
956                                         DispListMesh *dlm= dl->mesh;
957                                         float *vnors, *vn;
958                                         int i;
959                                         
960                                         dlob= MEM_callocN(sizeof(DispList), "displistshade");
961                                         BLI_addtail(&ob->disp, dlob);
962                                         dlob->type= DL_VERTCOL;
963                                 
964                                         dlob->col1= MEM_mallocN(sizeof(*dlob->col1)*dlm->totface*4, "col1");
965                                         if (me->flag & ME_TWOSIDED)
966                                                 dlob->col2= MEM_mallocN(sizeof(*dlob->col2)*dlm->totface*4, "col1");
967                                         
968                                         /* vertexnormals */
969                                         vn=vnors= MEM_mallocN(dlm->totvert*3*sizeof(float), "vnors disp");
970                                         mvert= dlm->mvert;
971                                         a= dlm->totvert;
972                                         while(a--) {
973                                                 
974                                                 xn= mvert->no[0]; 
975                                                 yn= mvert->no[1]; 
976                                                 zn= mvert->no[2];
977                                                 
978                                                 /* transpose ! */
979                                                 vn[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
980                                                 vn[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
981                                                 vn[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
982                                                 Normalise(vn);
983                                                 
984                                                 mvert++; vn+=3;
985                                         }               
986                         
987                                         for (i=0; i<dlm->totface; i++) {
988                                                 MFace *mf= &dlm->mface[i];
989
990                                                 if (mf->v3) {
991                                                         int j, vidx[4], nverts= mf->v4?4:3;
992                                                         unsigned int *col1base= &dlob->col1[i*4];
993                                                         unsigned int *col2base= dlob->col2?&dlob->col2[i*4]:NULL;
994                                                         MCol *mcolbase= dlm->mcol?&dlm->mcol[i*4]:NULL;
995                                                         float nor[3];
996                                                         
997                                                         ma= give_current_material(ob, mf->mat_nr+1);
998                                                         if(ma==0) ma= &defmaterial;
999                                                         
1000                                                         vidx[0]= mf->v1;
1001                                                         vidx[1]= mf->v2;
1002                                                         vidx[2]= mf->v3;
1003                                                         vidx[3]= mf->v4;
1004
1005                                                         if (mf->v4)
1006                                                                 CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, nor);
1007                                                         else
1008                                                                 CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, nor);
1009
1010                                                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
1011                                                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
1012                                                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
1013                                                         Normalise(n1);
1014
1015                                                         for (j=0; j<nverts; j++) {
1016                                                                 MVert *mv= &dlm->mvert[vidx[j]];
1017                                                                 unsigned int *col1= &col1base[j];
1018                                                                 unsigned int *col2= col2base?&col2base[j]:NULL;
1019                                                                 MCol *mcol= mcolbase?&mcolbase[j]:NULL;
1020                                                                 
1021                                                                 VECCOPY(vec, mv->co);
1022                                                                 Mat4MulVecfl(mat, vec);
1023                                                                 if(mf->flag & ME_SMOOTH) vn= vnors+3*vidx[j];
1024                                                                 else vn= n1;
1025                                                         
1026                                                                 if (need_orco && orco)
1027                                                                         fastshade(vec, vn, &orco[vidx[j]*3], ma, (char *)col1, (char*)col2, (char*) mcol);
1028                                                                 else
1029                                                                         fastshade(vec, vn, mv->co, ma, (char *)col1, (char*)col2, (char*) mcol);
1030                                                         }
1031                                                 }
1032                                         }
1033                                         MEM_freeN(vnors);
1034                                 }
1035                                 dl= dl->next;
1036                         }
1037                         
1038                         if (need_orco && orco) {
1039                                 MEM_freeN(me->orco);
1040                                 me->orco= NULL;
1041                         }
1042                 }
1043                 else if(me->totvert>0) {
1044                         float *vnors, *vn;
1045                         
1046                         if(me->orco==0 && need_orco) {
1047                                 make_orco_mesh(me);
1048                         }
1049                         orco= me->orco;
1050                         /* ms= me->msticky; */
1051                         
1052                         dl= me->disp.first;
1053                         if(dl==0 || dl->nors==0) addnormalsDispList(ob, &me->disp);
1054                         dl= me->disp.first;
1055                         if(dl==0 || dl->nors==0) return;
1056                         nor= dl->nors;
1057                         
1058                         dl= MEM_callocN(sizeof(DispList), "displistshade");
1059                         BLI_addtail(&ob->disp, dl);
1060                         dl->type= DL_VERTCOL;
1061                         col1= dl->col1= MEM_mallocN(4*sizeof(int)*me->totface, "col1");
1062                         col2= 0;
1063                         if(me->tface) tface_to_mcol(me);
1064                         vertcol= (unsigned int *)me->mcol;
1065                         
1066                         if( me->flag & ME_TWOSIDED) {
1067                                 col2= dl->col2= MEM_mallocN(4*sizeof(int)*me->totface, "col2");
1068                         }
1069                         
1070                         /* vertexnormals */
1071                         vn=vnors= MEM_mallocN(me->totvert*3*sizeof(float), "vnors disp");
1072                         mvert= me->mvert;
1073                         a= me->totvert;
1074                         while(a--) {
1075                                 
1076                                 xn= mvert->no[0]; 
1077                                 yn= mvert->no[1]; 
1078                                 zn= mvert->no[2];
1079                                 
1080                                 /* transpose ! */
1081                                 vn[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
1082                                 vn[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
1083                                 vn[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
1084                                 Normalise(vn);
1085                                 
1086                                 mvert++; vn+=3;
1087                         }               
1088                         
1089                         mface= me->mface;
1090                         a= me->totface;
1091                         while(a--) {
1092                                 
1093                                 if(mface->v3) {
1094                                 
1095                                         /* transpose ! */
1096                                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
1097                                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
1098                                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
1099                                         Normalise(n1);
1100                                         
1101                                         if(lastmat!=mface->mat_nr) {
1102                                                 ma= give_current_material(ob, mface->mat_nr+1);
1103                                                 if(ma==0) ma= &defmaterial;
1104                                                 lastmat= mface->mat_nr;
1105                                         }
1106                                         
1107                                         mvert= me->mvert+mface->v1;
1108                                         VECCOPY(vec, mvert->co);
1109                                         Mat4MulVecfl(mat, vec);
1110                                         if(mface->flag & ME_SMOOTH) vn= vnors+3*mface->v1;
1111                                         else vn= n1;
1112                                         
1113                                         if(orco)  fastshade(vec, vn, orco+3*mface->v1, ma, (char *)col1, (char *)col2, (char *)vertcol);
1114                                         else fastshade(vec, vn, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
1115                                         col1++;
1116                                         if(vertcol) vertcol++; 
1117                                         if(col2) col2++;
1118                                         
1119                                         mvert= me->mvert+mface->v2;
1120                                         VECCOPY(vec, mvert->co);
1121                                         Mat4MulVecfl(mat, vec);
1122                                         if(mface->flag & ME_SMOOTH) vn= vnors+3*mface->v2;
1123                                         else vn= n1;
1124                                         
1125                                         if(orco)  fastshade(vec, vn, orco+3*mface->v2, ma, (char *)col1, (char *)col2, (char *)vertcol);
1126                                         else fastshade(vec, vn, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
1127                                         col1++;
1128                                         if(vertcol) vertcol++; 
1129                                         if(col2) col2++;
1130                                         
1131                                         mvert= me->mvert+mface->v3;
1132                                         VECCOPY(vec, mvert->co);
1133                                         Mat4MulVecfl(mat, vec);
1134                                         if(mface->flag & ME_SMOOTH) vn= vnors+3*mface->v3;
1135                                         else vn= n1;
1136                                         
1137                                         if(orco)  fastshade(vec, vn, orco+3*mface->v3, ma, (char *)col1, (char *)col2, (char *)vertcol);
1138                                         else fastshade(vec, vn, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
1139                                         col1++;
1140                                         if(vertcol) vertcol++; 
1141                                         if(col2) col2++;
1142                                         
1143                                         if(mface->v4) {
1144                                                 mvert= me->mvert+mface->v4;
1145                                                 VECCOPY(vec, mvert->co);
1146                                                 Mat4MulVecfl(mat, vec);
1147                                                 if(mface->flag & ME_SMOOTH) vn= vnors+3*mface->v4;
1148                                                 else vn= n1;
1149                                                 
1150                                                 if(orco)  fastshade(vec, vn, orco+3*mface->v4, ma, (char *)col1, (char *)col2, (char *)vertcol);
1151                                                 else fastshade(vec, vn, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol);
1152                                         }
1153                                         col1++;
1154                                         if(vertcol) vertcol++; 
1155                                         if(col2) col2++;
1156                                                 
1157                                 }
1158                                 else {
1159                                         col1+=4;
1160                                         if(vertcol) vertcol+=4; 
1161                                         if(col2) col2+=4;
1162                                 }
1163         
1164                                 nor+= 3;
1165                                 mface++;
1166                         }
1167                         
1168                         MEM_freeN(vnors);
1169                         
1170                         if(me->orco) {
1171                                 MEM_freeN(me->orco);
1172                                 me->orco= 0;
1173                         }
1174                         if(me->tface) {
1175                                 MEM_freeN(me->mcol);
1176                                 me->mcol= 0;
1177                         }
1178                 }
1179         }
1180         else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
1181         
1182                 /* now we need the normals */
1183                 cu= ob->data;
1184                 dl= cu->disp.first;
1185                 
1186                 while(dl) {
1187                         dlob= MEM_callocN(sizeof(DispList), "displistshade");
1188                         BLI_addtail(&ob->disp, dlob);
1189                         dlob->type= DL_VERTCOL;
1190                         dlob->parts= dl->parts;
1191                         dlob->nr= dl->nr;
1192                         
1193                         if(dl->type==DL_INDEX3) {
1194                                 col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
1195                         }
1196                         else {
1197                                 col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1");
1198                         }
1199                         
1200                 
1201                         ma= give_current_material(ob, dl->col+1);
1202                         if(ma==0) ma= &defmaterial;
1203
1204                         if(dl->type==DL_INDEX3) {
1205                                 if(dl->nors) {
1206                                         /* there's just one normal */
1207                                         n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2];
1208                                         n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2];
1209                                         n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2];
1210                                         Normalise(n1);
1211                                         
1212                                         fp= dl->verts;
1213                                         
1214                                         a= dl->nr;              
1215                                         while(a--) {
1216                                                 VECCOPY(vec, fp);
1217                                                 Mat4MulVecfl(mat, vec);
1218                                                 
1219                                                 fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
1220                                                 
1221                                                 fp+= 3; col1++;
1222                                         }
1223                                 }
1224                         }
1225                         else if(dl->type==DL_SURF) {
1226                                 if(dl->nors) {
1227                                         a= dl->nr*dl->parts;
1228                                         fp= dl->verts;
1229                                         nor= dl->nors;
1230                                         
1231                                         while(a--) {
1232                                                 VECCOPY(vec, fp);
1233                                                 Mat4MulVecfl(mat, vec);
1234                                                 
1235                                                 n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
1236                                                 n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
1237                                                 n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
1238                                                 Normalise(n1);
1239                         
1240                                                 fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
1241                                                 
1242                                                 fp+= 3; nor+= 3; col1++;
1243                                         }
1244                                 }
1245                         }
1246                         dl= dl->next;
1247                 }
1248         }
1249         else if(ob->type==OB_MBALL) {
1250                 /* there are normals already */
1251                 dl= ob->disp.first;
1252                 
1253                 while(dl) {
1254                         
1255                         if(dl->type==DL_INDEX4) {
1256                                 if(dl->nors) {
1257                                         
1258                                         if(dl->col1) MEM_freeN(dl->col1);
1259                                         col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
1260                         
1261                                         ma= give_current_material(ob, dl->col+1);
1262                                         if(ma==0) ma= &defmaterial;
1263         
1264                                         fp= dl->verts;
1265                                         nor= dl->nors;
1266                                         
1267                                         a= dl->nr;              
1268                                         while(a--) {
1269                                                 VECCOPY(vec, fp);
1270                                                 Mat4MulVecfl(mat, vec);
1271                                                 
1272                                                 /* transpose ! */
1273                                                 n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
1274                                                 n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
1275                                                 n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
1276                                                 Normalise(n1);
1277                                         
1278                                                 fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
1279                                                 
1280                                                 fp+= 3; col1++; nor+= 3;
1281                                         }
1282                                 }
1283                         }
1284                         dl= dl->next;
1285                 }
1286         }
1287         
1288         for(a=0; a<ob->totcol; a++) {
1289                 ma= give_current_material(ob, a+1);
1290                 if(ma) end_render_material(ma);
1291         }
1292
1293         /* this one was temporally removed */
1294         if(dldeform) BLI_addtail(&ob->disp, dldeform);
1295 }
1296
1297 void reshadeall_displist(void)
1298 {
1299         DispList *dldeform;
1300         Base *base;
1301         Object *ob;
1302         
1303         freefastshade();
1304         
1305         base= G.scene->base.first;
1306         while(base) {
1307                 if(base->lay & G.scene->lay) {
1308                         
1309                         ob= base->object;
1310                         
1311                         /* we extract dl_verts, deform info */
1312                         dldeform= find_displist(&ob->disp, DL_VERTS);
1313                         if(dldeform) BLI_remlink(&ob->disp, dldeform);
1314                         
1315                         /* Metaballs have standard displist at the Object */
1316                         if(ob->type==OB_MBALL) shadeDispList(ob);
1317                         else freedisplist(&ob->disp);
1318                         
1319                         if(dldeform) BLI_addtail(&ob->disp, dldeform);
1320                 }
1321                 base= base->next;
1322         }
1323 }
1324
1325 void count_displist(ListBase *lb, int *totvert, int *totface)
1326 {
1327         DispList *dl;
1328         
1329         dl= lb->first;
1330         while(dl) {
1331                 
1332                 switch(dl->type) {
1333                 case DL_SURF:
1334                         *totvert+= dl->nr*dl->parts;
1335                         *totface+= (dl->nr-1)*(dl->parts-1);
1336                         break;
1337                 case DL_INDEX3:
1338                 case DL_INDEX4:
1339                         *totvert+= dl->nr;
1340                         *totface+= dl->parts;
1341                         break;
1342                 case DL_POLY:
1343                 case DL_SEGM:
1344                         *totvert+= dl->nr*dl->parts;
1345                 }
1346                 
1347                 dl= dl->next;
1348         }
1349 }
1350
1351 static void curve_to_displist(ListBase *nubase, ListBase *dispbase)
1352 {
1353         Nurb *nu;
1354         DispList *dl;
1355         BezTriple *bezt, *prevbezt;
1356         BPoint *bp;
1357         float *data, *v1, *v2;
1358         int a, len;
1359         
1360         nu= nubase->first;
1361         
1362         while(nu) {
1363                 if(nu->hide==0) {
1364                         if((nu->type & 7)==CU_BEZIER) {
1365                                 
1366                                 /* count */
1367                                 len= 0;
1368                                 a= nu->pntsu-1;
1369                                 if(nu->flagu & 1) a++;
1370
1371                                 prevbezt= nu->bezt;
1372                                 bezt= prevbezt+1;
1373                                 while(a--) {
1374                                         if(a==0 && (nu->flagu & 1)) bezt= nu->bezt;
1375                                         
1376                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
1377                                         else len+= nu->resolu;
1378                                         
1379                                         if(a==0 && (nu->flagu & 1)==0) len++;
1380                                         
1381                                         prevbezt= bezt;
1382                                         bezt++;
1383                                 }
1384                                 
1385                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
1386                                 /* len+1 because of 'maakbez' function */
1387                                 dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
1388                                 BLI_addtail(dispbase, dl);
1389                                 dl->parts= 1;
1390                                 dl->nr= len;
1391                                 dl->col= nu->mat_nr;
1392
1393                                 data= dl->verts;
1394
1395                                 if(nu->flagu & 1) {
1396                                         dl->type= DL_POLY;
1397                                         a= nu->pntsu;
1398                                 }
1399                                 else {
1400                                         dl->type= DL_SEGM;
1401                                         a= nu->pntsu-1;
1402                                 }
1403                                 
1404                                 prevbezt= nu->bezt;
1405                                 bezt= prevbezt+1;
1406                                 
1407                                 while(a--) {
1408                                         if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
1409                                         
1410                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
1411                                                 VECCOPY(data, prevbezt->vec[1]);
1412                                                 data+= 3;
1413                                         }
1414                                         else {
1415                                                 v1= prevbezt->vec[1];
1416                                                 v2= bezt->vec[0];
1417                                                 maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu);
1418                                                 maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu);
1419                                                 if((nu->type & 8)==0)
1420                                                         maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu);
1421                                                 data+= 3*nu->resolu;
1422                                         }
1423                                         
1424                                         if(a==0 && dl->type==DL_SEGM) {
1425                                                 VECCOPY(data, bezt->vec[1]);
1426                                         }
1427                                         
1428                                         prevbezt= bezt;
1429                                         bezt++;
1430                                 }
1431                         }
1432                         else if((nu->type & 7)==CU_NURBS) {
1433                                 len= nu->pntsu*nu->resolu;
1434                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1435                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1436                                 BLI_addtail(dispbase, dl);
1437                                 dl->parts= 1;
1438                                 dl->nr= len;
1439                                 dl->col= nu->mat_nr;
1440
1441                                 data= dl->verts;
1442                                 if(nu->flagu & 1) dl->type= DL_POLY;
1443                                 else dl->type= DL_SEGM;
1444                                 makeNurbcurve(nu, data, 3);
1445                         }
1446                         else if((nu->type & 7)==CU_POLY) {
1447                                 len= nu->pntsu;
1448                                 dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
1449                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1450                                 BLI_addtail(dispbase, dl);
1451                                 dl->parts= 1;
1452                                 dl->nr= len;
1453                                 dl->col= nu->mat_nr;
1454
1455                                 data= dl->verts;
1456                                 if(nu->flagu & 1) dl->type= DL_POLY;
1457                                 else dl->type= DL_SEGM;
1458                                 
1459                                 a= len;
1460                                 bp= nu->bp;
1461                                 while(a--) {
1462                                         VECCOPY(data, bp->vec);
1463                                         bp++;
1464                                         data+= 3;
1465                                 }
1466                         }
1467                 }
1468                 nu= nu->next;
1469         }
1470 }
1471
1472
1473 static void filldisplist(ListBase *dispbase, ListBase *to)
1474 {
1475         EditVert *eve, *v1, *vlast;
1476         EditFace *evl;
1477         DispList *dlnew=0, *dl;
1478         float *f1;
1479         int colnr=0, cont=1, tot, a, *index;
1480         long totvert;
1481         
1482         if(dispbase==0) return;
1483         if(dispbase->first==0) return;
1484
1485         /* tijd= clock(); */
1486         /* bit-wise and comes after == .... so this doesn't work...  */
1487 /*      if(G.f & G_PLAYANIM == 0) waitcursor(1); */
1488         if( !(G.f & G_PLAYANIM) ) waitcursor(1);
1489
1490         while(cont) {
1491                 cont= 0;
1492                 totvert=0;
1493                 
1494                 dl= dispbase->first;
1495                 while(dl) {
1496         
1497                         if(dl->type==DL_POLY) {
1498                                 if(colnr<dl->col) cont= 1;
1499                                 else if(colnr==dl->col) {
1500                         
1501                                         colnr= dl->col;
1502                 
1503                                         /* make editverts and edges */
1504                                         f1= dl->verts;
1505                                         a= dl->nr;
1506                                         eve= v1= 0;
1507                                         
1508                                         while(a--) {
1509                                                 vlast= eve;
1510                                                 
1511                                                 eve= BLI_addfillvert(f1);
1512                                                 totvert++;
1513                                                 
1514                                                 if(vlast==0) v1= eve;
1515                                                 else {
1516                                                         BLI_addfilledge(vlast, eve);
1517                                                 }
1518                                                 f1+=3;
1519                                         }
1520                                 
1521                                         if(eve!=0 && v1!=0) {
1522                                                 BLI_addfilledge(eve, v1);
1523                                         }
1524                                 }
1525                         }
1526                         dl= dl->next;
1527                 }
1528                 
1529                 /* to make edgefill work 
1530                 G.obedit can be 0 on file load */
1531                 if (G.obedit) {
1532                         BLI_setScanFillObjectRef(G.obedit);
1533                         BLI_setScanFillColourRef(&G.obedit->actcol);
1534                 }
1535
1536                 if(totvert && BLI_edgefill(0)!=0) {
1537
1538                         /* count faces  */
1539                         tot= 0;
1540                         evl= fillfacebase.first;
1541                         while(evl) {
1542                                 tot++;
1543                                 evl= evl->next;
1544                         }
1545
1546                         if(tot) {
1547                                 dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
1548                                 dlnew->type= DL_INDEX3;
1549                                 dlnew->col= colnr;
1550                                 dlnew->nr= totvert;
1551                                 dlnew->parts= tot;
1552
1553                                 dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
1554                                 dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
1555                                 
1556                                 /* vert data */
1557                                 f1= dlnew->verts;
1558                                 totvert= 0;
1559                                 eve= fillvertbase.first;
1560                                 while(eve) {
1561                                         VECCOPY(f1, eve->co);
1562                                         f1+= 3;
1563         
1564                                         /* index number */
1565                                         eve->vn= (EditVert *)totvert;
1566                                         totvert++;
1567                                         
1568                                         eve= eve->next;
1569                                 }
1570                                 
1571                                 /* index data */
1572                                 evl= fillfacebase.first;
1573                                 index= dlnew->index;
1574                                 while(evl) {
1575                                         index[0]= (long)evl->v1->vn;
1576                                         index[1]= (long)evl->v2->vn;
1577                                         index[2]= (long)evl->v3->vn;
1578                                         
1579                                         index+= 3;
1580                                         evl= evl->next;
1581                                 }
1582                         }
1583
1584                         BLI_addhead(to, dlnew);
1585                         
1586                 }
1587                 BLI_end_edgefill();
1588
1589                 colnr++;
1590         }
1591         
1592         /* do not free polys, needed for wireframe display */
1593         
1594         /* same as above ... */
1595 /*      if(G.f & G_PLAYANIM == 0) waitcursor(0); */
1596         if( !(G.f & G_PLAYANIM) ) waitcursor(0);
1597         /* printf("time: %d\n",(clock()-tijd)/1000); */
1598
1599 }
1600
1601 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
1602 {
1603         ListBase front, back;
1604         DispList *dl, *dlnew;
1605         float *fp, *fp1;
1606         int a, dpoly;
1607         
1608         front.first= front.last= back.first= back.last= 0;
1609         if(cu->flag & CU_3D) return;
1610         if( (cu->flag & (CU_FRONT+CU_BACK))==0 ) return;
1611         
1612         dl= dispbase->first;
1613         while(dl) {
1614                 if(dl->type==DL_SURF) {
1615                         if( (dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)==0 ) {
1616                                 if( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE) ) {
1617                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1618                                         BLI_addtail(&front, dlnew);
1619                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1620                                         dlnew->nr= dl->parts;
1621                                         dlnew->parts= 1;
1622                                         dlnew->type= DL_POLY;
1623                                         dlnew->col= dl->col;
1624                                         
1625                                         fp= dl->verts;
1626                                         dpoly= 3*dl->nr;
1627                                         
1628                                         a= dl->parts;
1629                                         while(a--) {
1630                                                 VECCOPY(fp1, fp);
1631                                                 fp1+= 3;
1632                                                 fp+= dpoly;
1633                                         }
1634                                 }
1635                                 if( (cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE) ) {
1636                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1637                                         BLI_addtail(&back, dlnew);
1638                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1639                                         dlnew->nr= dl->parts;
1640                                         dlnew->parts= 1;
1641                                         dlnew->type= DL_POLY;
1642                                         dlnew->col= dl->col;
1643                                         
1644                                         fp= dl->verts+3*(dl->nr-1);
1645                                         dpoly= 3*dl->nr;
1646                                         
1647                                         a= dl->parts;
1648                                         while(a--) {
1649                                                 VECCOPY(fp1, fp);
1650                                                 fp1+= 3;
1651                                                 fp+= dpoly;
1652                                         }
1653                                 }
1654                         }
1655                 }
1656                 dl= dl->next;
1657         }
1658
1659         filldisplist(&front, dispbase);
1660         filldisplist(&back, dispbase);
1661         
1662         freedisplist(&front);
1663         freedisplist(&back);
1664
1665         filldisplist(dispbase, dispbase);
1666         
1667 }
1668
1669 void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
1670 {
1671         DispList *dl;
1672         Nurb *nu;
1673                 
1674         dl= dispbase->first;
1675         
1676         if(cu->flag & CU_3D) return;
1677         
1678         nu= nurb->first;
1679         while(nu) {
1680                 if(nu->flagu & CU_CYCLIC) break;
1681                 nu= nu->next;
1682         }
1683         if(nu==0) return;
1684
1685         if(dl->type==DL_SURF) bevels_to_filledpoly(cu, dispbase);
1686         else {
1687                 if(cu->flag & CU_FRONT) filldisplist(dispbase, dispbase);
1688         }
1689 }
1690
1691
1692 static int dl_onlyzero= 0;
1693
1694 void set_displist_onlyzero(int val)
1695 {
1696         dl_onlyzero= val;
1697 }
1698
1699 /* taper rules:
1700   - only 1 curve
1701   - first point left, last point right
1702   - based on subdivided points in original curve, not on points in taper curve (still)
1703 */
1704 float calc_taper(Object *taperobj, int cur, int tot)
1705 {
1706         Curve *cu;
1707         DispList *dl;
1708         
1709         if(taperobj==NULL) return 1.0;
1710         
1711         cu= taperobj->data;
1712         dl= cu->disp.first;
1713         if(dl==NULL) {
1714                 makeDispList(taperobj);
1715                 dl= cu->disp.first;
1716         }
1717         if(dl) {
1718                 float fac= ((float)cur)/(float)(tot-1);
1719                 float minx, dx, *fp;
1720                 int a;
1721                 
1722                 /* horizontal size */
1723                 minx= dl->verts[0];
1724                 dx= dl->verts[3*(dl->nr-1)] - minx;
1725                 if(dx>0.0) {
1726                 
1727                         fp= dl->verts;
1728                         for(a=0; a<dl->nr; a++, fp+=3) {
1729                                 if( (fp[0]-minx)/dx >= fac) {
1730                                         /* interpolate with prev */
1731                                         if(a>0) {
1732                                                 float fac1= (fp[-3]-minx)/dx;
1733                                                 float fac2= (fp[0]-minx)/dx;
1734                                                 if(fac1!=fac2)
1735                                                         return fp[1]*(fac1-fac)/(fac1-fac2) + fp[-2]*(fac-fac2)/(fac1-fac2);
1736                                         }
1737                                         return fp[1];
1738                                 }
1739                         }
1740                         return fp[-2];  // last y coord
1741                 }
1742         }
1743         
1744         return 1.0;
1745 }
1746
1747 void makeDispList(Object *ob)
1748 {
1749         EditMesh *em = G.editMesh;
1750         Mesh *me;
1751         Nurb *nu;
1752         Curve *cu;
1753         BPoint *bp;
1754         ListBase dlbev, *dispbase;
1755         DispList *dl, *dlb;
1756         BevList *bl;
1757         BevPoint *bevp;
1758         float *data, *fp1, widfac, vec[3];
1759         int len, a, b, draw=0;
1760
1761         if(ob==NULL) return;
1762         if(ob->flag & OB_FROMDUPLI) return;
1763
1764         freedisplist(&(ob->disp));
1765         
1766         if(ob->type==OB_MESH) {
1767                 me= ob->data;
1768                 freedisplist(&(me->disp));
1769
1770                 tex_space_mesh(ob->data);
1771                 
1772                 if(ob!=G.obedit) {
1773                         mesh_modifier(ob, 's');
1774                 }
1775                 
1776                 if (mesh_uses_displist(me)) {  /* subsurf */
1777                         DispListMesh *dlm;
1778
1779                         if (ob==G.obedit) {
1780                                 dlm= subsurf_make_dispListMesh_from_editmesh(em, me->subdiv, me->flag, me->subsurftype);
1781                         } else {
1782                                 DispList *dlVerts= find_displist(&ob->disp, DL_VERTS);
1783                                 // dl->verts should not be needed anymore, recode it in modifier (ton)
1784                                 dlm= subsurf_make_dispListMesh_from_mesh(me, dlVerts?dlVerts->verts:NULL, 
1785                                                                                                         me->subdiv, me->flag);
1786                         }
1787
1788                         dl= MEM_callocN(sizeof(*dl), "dl");
1789                         dl->type= DL_MESH;
1790                         dl->mesh= dlm;
1791
1792                         free_displist_by_type(&me->disp, DL_MESH);
1793                         BLI_addtail(&me->disp, dl);
1794                 }
1795                 
1796                 if(ob!=G.obedit) mesh_modifier(ob, 'e');
1797                 
1798         }
1799         else if(ob->type==OB_MBALL) {
1800                 ob= find_basis_mball(ob);
1801
1802                 metaball_polygonize(ob);
1803                 tex_space_mball(ob);
1804
1805                 object_deform(ob);
1806         }
1807         else if(ob->type==OB_SURF) {
1808                 
1809                 draw= ob->dt;
1810                 cu= ob->data;
1811                 dispbase= &(cu->disp);
1812                 if(dl_onlyzero && dispbase->first) return;
1813                 freedisplist(dispbase);
1814                 
1815                 if(ob==G.obedit) nu= editNurb.first;
1816                 else {
1817                         curve_modifier(ob, 's');
1818                         nu= cu->nurb.first;
1819                 }
1820                 
1821                 while(nu) {
1822                         if(nu->hide==0) {
1823                                 if(nu->pntsv==1) {
1824                                         if(draw==0) len= nu->pntsu;
1825                                         else len= nu->pntsu*nu->resolu;
1826                                         
1827                                         dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1828                                         dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1829                                         
1830                                         BLI_addtail(dispbase, dl);
1831                                         dl->parts= 1;
1832                                         dl->nr= len;
1833                                         dl->col= nu->mat_nr;
1834                                         dl->rt= nu->flag;
1835                                         
1836                                         data= dl->verts;
1837                                         if(nu->flagu & 1) dl->type= DL_POLY;
1838                                         else dl->type= DL_SEGM;
1839                                         
1840                                         if(draw==0) {
1841                                                 bp= nu->bp;
1842                                                 while(len--) {
1843                                                         VECCOPY(data, bp->vec);
1844                                                         bp++;
1845                                                         data+= 3;
1846                                                 }
1847                                         }
1848                                         else makeNurbcurve(nu, data, 3);
1849                                 }
1850                                 else {
1851                                         if(draw==0 && ob==G.obedit) ;
1852                                         else {
1853                                                 if(draw==0) len= nu->pntsu*nu->pntsv;
1854                                                 else len= nu->resolu*nu->resolv;
1855                                                 
1856                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1857                                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1858                                                 BLI_addtail(dispbase, dl);
1859         
1860                                                 if(draw==0) {
1861                                                         dl->parts= nu->pntsv;
1862                                                         dl->nr= nu->pntsu;
1863                                                         if(nu->flagu & 1) dl->flag|= DL_CYCL_U;
1864                                                         if(nu->flagv & 1) dl->flag|= DL_CYCL_V;
1865                                                 }
1866                                                 else {
1867                                                         dl->parts= nu->resolu;  /* in reverse, because makeNurbfaces works that way */
1868                                                         dl->nr= nu->resolv;
1869                                                         if(nu->flagv & 1) dl->flag|= DL_CYCL_U; /* reverse too! */
1870                                                         if(nu->flagu & 1) dl->flag|= DL_CYCL_V;
1871                                                 }
1872                                                 dl->col= nu->mat_nr;
1873                                                 dl->rt= nu->flag;
1874                                                 
1875                                                 data= dl->verts;
1876                                                 dl->type= DL_SURF;
1877                                                 
1878                                                 if(draw==0) {
1879                                                         bp= nu->bp;
1880                                                         while(len--) {
1881                                                                 VECCOPY(data, bp->vec);
1882                                                                 bp++;
1883                                                                 data+= 3;
1884                                                         }
1885                                                 }
1886                                                 else makeNurbfaces(nu, data);
1887                                         }
1888                                 }
1889                         }
1890                         nu= nu->next;
1891                 }
1892                 
1893                 tex_space_curve(cu);
1894
1895                 if(ob!=G.obedit) curve_modifier(ob, 'e');
1896                 if(ob!=G.obedit) object_deform(ob);
1897         }
1898         else if ELEM(ob->type, OB_CURVE, OB_FONT) {
1899                 
1900                 draw= ob->dt;
1901                 cu= ob->data;
1902                 dispbase= &(cu->disp);
1903                 if(dl_onlyzero && dispbase->first) return;
1904                 freedisplist(dispbase);
1905                 
1906                 if(cu->path) free_path(cu->path);
1907                 cu->path= 0;
1908                 
1909                 BLI_freelistN(&(cu->bev));
1910                 
1911                 if(ob!=G.obedit) curve_modifier(ob, 's');
1912                 
1913                 if(ob==G.obedit) {
1914                         if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase);
1915                         else curve_to_displist(&cu->nurb, dispbase);
1916                         if(cu->flag & CU_PATH) makeBevelList(ob);
1917                 }
1918                 else if(cu->ext1==0.0 && cu->ext2==0.0 && cu->bevobj==NULL && cu->width==1.0) {
1919                         curve_to_displist(&cu->nurb, dispbase);
1920                         if(cu->flag & CU_PATH) makeBevelList(ob);
1921                 }
1922                 else {
1923                         
1924                         makeBevelList(ob);
1925
1926                         dlbev.first= dlbev.last= NULL;
1927                         if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) {
1928                                 if(ob->dt!=0) makebevelcurve(ob, &dlbev);
1929                         }
1930
1931                         /* work with bevellist */
1932                         widfac= cu->width-1.0;
1933                         bl= cu->bev.first;
1934                         nu= cu->nurb.first;
1935                         while(bl) {
1936                                 if(dlbev.first==0) {
1937                                         dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
1938                                         dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
1939                                         BLI_addtail(dispbase, dl);
1940                                         
1941                                         if(bl->poly!= -1) dl->type= DL_POLY;
1942                                         else dl->type= DL_SEGM;
1943                                         
1944                                         if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE);
1945                                         
1946                                         dl->parts= 1;
1947                                         dl->nr= bl->nr;
1948                                         dl->col= nu->mat_nr;
1949
1950                                         a= dl->nr;
1951                                         bevp= (BevPoint *)(bl+1);
1952                                         data= dl->verts;
1953                                         while(a--) {
1954                                                 data[0]= bevp->x+widfac*bevp->sina;
1955                                                 data[1]= bevp->y+widfac*bevp->cosa;
1956                                                 data[2]= bevp->z;
1957                                                 bevp++;
1958                                                 data+=3;
1959                                         }
1960                                 }
1961                                 else {
1962                                         /* for each part of the bevel use a separate displblock */
1963                                         dlb= dlbev.first;
1964                                         while(dlb) {
1965                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
1966                                                 dl->verts= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
1967                                                 BLI_addtail(dispbase, dl);
1968                                                 /* dl->type= dlb->type; */
1969
1970                                                 dl->type= DL_SURF;
1971                                                 
1972                                                 dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE);
1973                                                 if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U;
1974                                                 if(bl->poly>=0) dl->flag |= DL_CYCL_V;
1975                                                 
1976                                                 dl->parts= bl->nr;
1977                                                 dl->nr= dlb->nr;
1978                                                 dl->col= nu->mat_nr;
1979                                                 dl->rt= nu->flag;
1980
1981                                                 data= dl->verts;
1982                                                 bevp= (BevPoint *)(bl+1);
1983                                                 for(a=0; a<bl->nr; a++) {       /* for each point of poly make a bevel piece */
1984                                                         float fac;
1985                                                         
1986                                                         /* returns 1.0 if no taper, of course */
1987                                                         fac= calc_taper(cu->taperobj, a, bl->nr);
1988                                                         
1989                                                         /* rotate bevel piece and write in data */
1990                                                         fp1= dlb->verts;
1991                                                         b= dlb->nr;
1992
1993                                                         while(b--) {
1994                                                                 
1995                                                                 if(cu->flag & CU_3D) {
1996                                                                 
1997                                                                         vec[0]= fp1[1]+widfac;
1998                                                                         vec[1]= fp1[2];
1999                                                                         vec[2]= 0.0;
2000                                                                         
2001                                                                         Mat3MulVecfl(bevp->mat, vec);
2002                                                                         
2003                                                                         data[0]= bevp->x+ fac*vec[0];
2004                                                                         data[1]= bevp->y+ fac*vec[1];
2005                                                                         data[2]= bevp->z+ fac*vec[2];
2006                                                                 }
2007                                                                 else {
2008                                                                         data[0]= bevp->x+ fac*(fp1[1]+widfac)*bevp->sina;
2009                                                                         data[1]= bevp->y+ fac*(fp1[1]+widfac)*bevp->cosa;
2010                                                                         data[2]= bevp->z+ fac*fp1[2];
2011                                                                 }
2012
2013                                                                 data+=3;
2014                                                                 fp1+=3;
2015                                                         }
2016
2017                                                         bevp++;
2018                                                 }
2019
2020                                                 dlb= dlb->next;
2021                                         }
2022                                 }
2023
2024                                 bl= bl->next;
2025                                 nu= nu->next;
2026                         }
2027
2028                         if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) {
2029                                 freedisplist(&dlbev);
2030                         }
2031                 }
2032
2033                 if(ob!=G.obedit) curve_modifier(ob, 'e');
2034                 if(ob!=G.obedit) object_deform(ob);
2035
2036                 tex_space_curve(cu);
2037
2038         }
2039         
2040         boundbox_displist(ob);
2041 }
2042
2043
2044 /*******************************/
2045 /*****       OUTLINE       *****/
2046 /*******************************/
2047
2048 typedef struct Sample{
2049         short x, y;
2050 } Sample;
2051
2052 typedef struct Segment{
2053         /* coordinates */
2054         struct Segment * next, * prev;
2055         float co[2];
2056 } Segment;
2057
2058
2059
2060 static int dflt_in_out(struct ImBuf * ibuf, int x, int y)
2061 {
2062         unsigned char * rect;
2063         
2064         if (ibuf == 0) return (0);
2065         if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y || ibuf->rect == 0) return (-1);
2066         
2067         rect = (unsigned char *) (ibuf->rect + (y * ibuf->x) + x);
2068         if (rect[0] > 0x81) return (1);
2069         return(0);
2070 }
2071
2072
2073 static Sample * outline(struct ImBuf * ibuf,
2074                                  int (*in_or_out)(struct ImBuf *, int, int))
2075 {
2076         static int dirs[8][2] = {
2077                 {-1,  0}, {-1,  1},     {0,  1}, {1,  1}, 
2078                 {1,  0}, {1, -1}, {0, -1}, {-1, -1}
2079         };
2080         
2081         int dir, x, y, in, i;
2082         int count, sampcount;
2083         int startx = 0, starty = 0;
2084         Sample * samp, * oldsamp;
2085         
2086         /* input:
2087          * 1 - image 
2088          * 2 - pointer to function that defines which pixel 'in' or 'out' is
2089          */
2090         
2091         if (ibuf == 0) return (0);
2092         if (ibuf->rect == 0) return (0);
2093         
2094         if (in_or_out == 0) in_or_out = dflt_in_out;
2095         in = in_or_out(ibuf, 0, 0);
2096         
2097         /* search for first transition, and continue from there */      
2098         for (y = 0; y < ibuf->y; y++) {
2099                 for (x = 0; x < ibuf->x; x++) {
2100                         if (in_or_out(ibuf, x, y) != in) {
2101                                 /* found first 'other' point !! */
2102                                 
2103                                 if (x != startx) dir = 0;
2104                                 else dir = 6;
2105                                 
2106                                 startx = x; starty = y;
2107                                 count = 1;
2108                                 sampcount = 2000;
2109                                 samp = MEM_mallocN(sampcount * sizeof(Sample), "wire_samples");
2110                                 
2111                                 do{
2112                                         samp[count].x = x; samp[count].y = y;
2113                                         count++;
2114                                         
2115                                         if (count >= sampcount) {
2116                                                 oldsamp = samp;
2117                                                 samp = MEM_mallocN(2 * sampcount * sizeof(Sample), "wire_samples");
2118                                                 memcpy(samp, oldsamp, sampcount * sizeof(Sample));
2119                                                 sampcount *= 2;
2120                                                 MEM_freeN(oldsamp);
2121                                         }
2122                                         
2123                                         i = 0;
2124                                         while(in_or_out(ibuf, x + dirs[dir][0], y + dirs[dir][1]) == in) {
2125                                                 dir = (dir + 1) & 0x7;
2126                                                 if (i++ == 9) break;
2127                                         }
2128                                         
2129                                         if (i >= 8) {
2130                                                 /* this has to be a loose point */
2131                                                 break;
2132                                         }
2133                                         
2134                                         x += dirs[dir][0];
2135                                         y += dirs[dir][1];
2136                                         dir = (dir - 3) & 0x7;
2137                                 } while(x != startx || y != starty);
2138                                 
2139                                 if (i >= 8) {
2140                                         /* patch for loose points */
2141                                         MEM_freeN(samp);
2142                                 } else {
2143                                         count = count - 1;
2144                                         samp[0].x = count >> 16;
2145                                         samp[0].y = count;
2146                                         return(samp);
2147                                 }
2148                         }
2149                 }
2150         }
2151         /* printf("no transition \n"); */
2152         return(0);
2153 }
2154
2155
2156
2157 /*******************************/
2158 /*****      WIREFRAME      *****/
2159 /*******************************/
2160
2161
2162 static float DistToLine2D(short *v1, short *v2, short *v3)   /* using Hesse formula :NO LINE PIECE! */
2163 {
2164         float a[2],deler;
2165
2166         a[0] = v2[1]-v3[1];
2167         a[1] = v3[0]-v2[0];
2168         deler = sqrt(a[0]*a[0]+a[1]*a[1]);
2169         if(deler == 0.0) return 0;
2170
2171         return fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler;
2172
2173 }
2174
2175 static float ComputeMaxShpError(Sample *samp, int first, int last, int *splitPoint)
2176     /* samp:  Array of digitized points */
2177     /* first, last:  Indices defining region    */
2178     /* splitpoint:  Point of maximum error      */
2179 {
2180     int         i;
2181     float       maxDist;                                /*  Maximum error               */
2182     float       dist;                                   /*  Current error               */
2183  
2184     *splitPoint = (last - first + 1) / 2;
2185     maxDist = 0.0;
2186         
2187     for (i = first + 1; i < last; i++) {                                
2188                 dist = DistToLine2D((short *)(samp+i), (short *)(samp+first), (short *)(samp+last));
2189
2190                 if (dist >= maxDist) {
2191                 maxDist = dist;
2192                 *splitPoint = i;
2193                 }
2194     }
2195
2196     return (maxDist);
2197 }
2198
2199
2200 static void FitPoly(Sample *samp, int first, int last, float shperr, ListBase *seglist)
2201     /* Samp: Array of digitized points */
2202     /* first,last: Indices of first and last pts in region */
2203     /* spherr: User-defined error squared          */
2204 {
2205     Segment     * seg;                          /* Control points segment*/
2206     float       maxError;                       /*  Maximum fitting error        */
2207     int         splitPoint;                     /*  Point to split point set at  */
2208     int         nPts;                           /*  Number of points in subset  */
2209         
2210     nPts = last - first + 1;
2211
2212     /*  Use heuristic if region only has two points in it */
2213
2214         seg = MEM_mallocN(sizeof(Segment), "wure_segment");
2215
2216         seg->co[0] = samp[first].x;
2217         seg->co[1] = samp[first].y;
2218         
2219     if (nPts == 2) {
2220                 BLI_addtail(seglist, seg);
2221                 return;
2222     }
2223
2224         maxError = ComputeMaxShpError(samp, first, last, &splitPoint);
2225         if (maxError < shperr) {
2226                 BLI_addtail(seglist, seg);
2227                 return;
2228         }
2229         
2230     /* Fitting failed -- split at max error point and fit recursively */
2231         
2232     FitPoly(samp, first, splitPoint, shperr, seglist);
2233     FitPoly(samp, splitPoint, last, shperr, seglist);
2234         
2235         MEM_freeN(seg);
2236 }
2237
2238
2239 static void ibuf2wire(ListBase * wireframe, struct ImBuf * ibuf)
2240 {
2241         int count;
2242         Sample * samp;
2243         
2244         /* first make a list of samples */
2245         
2246         samp = outline(ibuf, 0);
2247         if (samp == 0) return;
2248         
2249         count = (samp[0].x << 16) + samp[0].y;
2250         if (count) FitPoly(samp, 1, count, 1.0, wireframe); /* was 3.0. Frank */
2251
2252         MEM_freeN(samp);
2253 }
2254
2255
2256
2257 void imagestodisplist(void)
2258 {
2259         Base *base;
2260         Object *ob;
2261         Material *ma;
2262         Tex *tex;
2263         Mesh *me;
2264         ListBase _wireframe, *wireframe;
2265         DispList *dl;
2266         Segment *seg;
2267         float *data, xfac, yfac, xsi, ysi, vec[3], dum;
2268         int tot;
2269         
2270         _wireframe.first= 0;
2271         _wireframe.last= 0;
2272         wireframe = &_wireframe;
2273         
2274         init_render_textures();
2275         
2276         base= G.scene->base.first;
2277         while(base) {
2278                 if(( (base->flag & SELECT) && (base->lay & G.scene->lay) ) ) {
2279                         if( base->object->type==OB_MESH) {
2280                                 ob= base->object;
2281                                 me= ob->data;
2282                                 
2283                                 ma= give_current_material(ob, 1);
2284         
2285                                 if(ma && ma->mtex[0] && ma->mtex[0]->tex) {
2286                                         tex= ma->mtex[0]->tex;
2287                                         
2288                                         /* this takes care of correct loading of new imbufs */
2289                                         externtex(ma->mtex[0], vec, &dum, &dum, &dum, &dum, &dum);
2290                                         
2291                                         if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) {                                
2292                                                 
2293                                                 ob->dtx |= OB_DRAWIMAGE;
2294                                                 
2295                                                 ibuf2wire(wireframe, tex->ima->ibuf);
2296
2297                                                 tot= 0;
2298                                                 seg = wireframe->first;
2299                                                 while (seg) {
2300                                                         tot++;
2301                                                         seg = seg->next;
2302                                                 }
2303         
2304                                                 if(tot) {
2305                                                         freedisplist(&(ob->disp));
2306
2307                                                         dl= MEM_callocN(sizeof(DispList), "makeDispListimage");
2308                                                         dl->verts= MEM_callocN(3*sizeof(float)*tot, "dlverts");
2309                                                         
2310                                                         BLI_addtail(&(ob->disp), dl);
2311                                                         dl->type= DL_POLY;
2312                                                         dl->parts= 1;
2313                                                         dl->nr= tot;
2314                                                         
2315                                                         xsi= 0.5*(tex->ima->ibuf->x);
2316                                                         ysi= 0.5*(tex->ima->ibuf->y);
2317                                                         xfac= me->size[0]/xsi;
2318                                                         yfac= me->size[1]/ysi;
2319                                                                                                 
2320                                                         data= dl->verts;
2321                                                         seg = wireframe->first;
2322                                                         while (seg) {
2323                                                                 data[0]= xfac*(seg->co[0]-xsi);
2324                                                                 data[1]= yfac*(seg->co[1]-ysi);
2325                                                                 data+= 3;
2326                                                                 seg = seg->next;
2327                                                         }
2328                                                         BLI_freelistN(wireframe);
2329                                                 }
2330                                         }
2331                                 }
2332                         }
2333                 }
2334                 base= base->next;
2335         }
2336         
2337         end_render_textures();
2338         
2339         allqueue(REDRAWVIEW3D, 0);
2340 }
2341
2342 /* on frame change */
2343 /* new method: only frees displists, and relies on 
2344    drawobject.c & convertscene.c to build it when needed
2345 */
2346 void test_all_displists(void)
2347 {
2348         Base *base;
2349         Object *ob;
2350         unsigned int lay;
2351         int makedisp, freedisp;
2352         
2353         /* background */        
2354         lay= G.scene->lay;
2355         
2356         /* clear flags, we use them because parent->parents are evaluated too */
2357         base= G.scene->base.first;
2358         while(base) {
2359                 if(base->lay & lay) {
2360                         base->object->flag &= ~(BA_DISP_UPDATE|BA_WHERE_UPDATE);
2361                 }
2362                 if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
2363                 else base= base->next;
2364         }
2365         
2366         base= G.scene->base.first;
2367         while(base) {
2368                 if(base->lay & lay) {
2369                         ob= base->object;
2370                         makedisp= freedisp= 0;
2371                         
2372                         if(ob->type==OB_MBALL && (ob->ipo || ob->parent)) {
2373                                 // find metaball object holding the displist
2374                                 // WARNING: if more metaballs have IPO's the displist
2375                                 // is recalculated to often... do we free the displist
2376                                 // and rely on the drawobject.c to build it again when needed
2377
2378                                 if(ob->disp.first == NULL) {
2379                                         ob= find_basis_mball(ob);
2380                                 }
2381                                 makedisp= 1;
2382                         }
2383                         else if(ob->parent) {
2384                                 
2385                                 if (ob->parent->type == OB_LATTICE)
2386                                         freedisp= 1;
2387                                 else if ((ob->parent->type==OB_ARMATURE) && (ob->partype == PARSKEL))
2388                                         makedisp= 1;
2389                                 else if ((ob->parent->type==OB_CURVE) && (ob->partype == PARSKEL))
2390                                         freedisp= 1;
2391                                 else if(ob->partype==PARVERT1 || ob->partype==PARVERT3) {
2392                                         if(ob->parent->parent) 
2393                                                 ob->parent->flag |= BA_DISP_UPDATE;
2394                                         else if(ob->parent->effect.first)       // stupid test for wave
2395                                                 ob->parent->flag |= BA_DISP_UPDATE;
2396                                 }
2397                         }
2398
2399                         if(ob->hooks.first) {
2400                                 ObHook *hook;
2401                                 for(hook= ob->hooks.first; hook; hook= hook->next) {
2402                                         if(hook->parent) 
2403                                                 freedisp= 1;
2404                                         break;
2405                                 }
2406                         }
2407                         
2408                         if(ob->softflag) freedisplist_object(ob);
2409                         /* warn, ob pointer changed in case of OB_MALL */
2410
2411                         if ELEM(ob->type, OB_CURVE, OB_SURF) {
2412                                 if(ob!=G.obedit) {
2413                                         Curve *cu= ob->data;
2414                                         
2415                                         if(cu->key ) makedisp= 1;
2416                                         if(cu->bevobj) {
2417                                                 Curve *cu1= cu->bevobj->data;
2418                                                 if(cu1->key ) freedisp= 1;
2419                                         }
2420                                         if(cu->taperobj) {
2421                                                 Curve *cu1= cu->taperobj->data;
2422                                                 if(cu1->key ) freedisp= 1;
2423                                         }
2424                                 }
2425                         }
2426                         else if(ob->type==OB_FONT) {
2427                                 Curve *cu= ob->data;
2428                                 if(cu->textoncurve) {
2429                                         if( ((Curve *)cu->textoncurve->data)->key ) {
2430                                                 text_to_curve(ob, 0);
2431                                                 freedisp= 1;
2432                                         }
2433                                 }
2434                         }
2435                         else if(ob->type==OB_MESH) {
2436                                 if(ob->effect.first) {
2437                                         Effect *eff= ob->effect.first;
2438                                         while(eff) {
2439                                                 if(eff->type==EFF_WAVE) {
2440                                                         freedisp= 1;
2441                                                         break;
2442                                                 }
2443                                                 eff= eff->next;
2444                                         }
2445                                 }
2446                                 if(ob!=G.obedit) {
2447                                         if(( ((Mesh *)(ob->data))->key )) 
2448                                                 freedisp= 1;
2449                                 }
2450                         }
2451                         if(freedisp) ob->flag |= BA_WHERE_UPDATE;
2452                         if(makedisp) ob->flag |= BA_DISP_UPDATE;
2453                 }
2454                 if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
2455                 else base= base->next;
2456         }
2457         
2458         /* going over the flags to free or make displists */
2459         base= G.scene->base.first;
2460         while(base) {
2461                 if(base->lay & lay) {
2462                         ob= base->object;
2463                         if(ob->flag & BA_DISP_UPDATE) makeDispList(ob);
2464                         else if(ob->flag & BA_WHERE_UPDATE) freedisplist_object(ob);
2465                 }
2466                 if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
2467                 else base= base->next;
2468         }
2469         
2470 }
2471
2472
2473 void boundbox_displist(Object *ob)
2474 {
2475         BoundBox *bb=0;
2476         float min[3], max[3];
2477         DispList *dl;
2478         float *vert;
2479         int a, tot=0;
2480         
2481         INIT_MINMAX(min, max);
2482
2483         if(ob->type==OB_MESH) {
2484                 Mesh *me= ob->data;
2485
2486                 dl= find_displist(&ob->disp, DL_VERTS);
2487                 if(!dl) return;
2488
2489                 if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox");        
2490                 bb= me->bb;
2491
2492                 vert= dl->verts;
2493                 for(a=0; a<dl->nr; a++, vert+=3) {
2494                         DO_MINMAX(vert, min, max);
2495                 }
2496         }
2497         else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
2498                 Curve *cu= ob->data;
2499
2500                 if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");        
2501                 bb= cu->bb;
2502                 
2503                 dl= cu->disp.first;
2504
2505                 while (dl) {
2506                         if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr;
2507                         else tot= dl->nr*dl->parts;
2508                         
2509                         vert= dl->verts;
2510                         for(a=0; a<tot; a++, vert+=3) {
2511                                 DO_MINMAX(vert, min, max);
2512                         }
2513
2514                         dl= dl->next;
2515                 }
2516         }
2517         
2518         if(bb) {
2519                 bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= min[0];
2520                 bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= max[0];
2521                 
2522                 bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= min[1];
2523                 bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= max[1];
2524         
2525                 bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= min[2];
2526                 bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= max[2];
2527         }
2528 }
2529