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