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