ce4e45db4057fac3132205b3c3ca838168391cb6
[blender.git] / source / blender / blenkernel / intern / displist.c
1
2 /*  displist.c
3  * 
4  * 
5  * $Id$
6  *
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * The Original Code is: all of this file.
30  *
31  * Contributor(s): none yet.
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <math.h>
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "MEM_guardedalloc.h"
45
46 #include "IMB_imbuf_types.h"
47
48 #include "DNA_texture_types.h"
49 #include "DNA_meta_types.h"
50 #include "DNA_curve_types.h"
51 #include "DNA_effect_types.h"
52 #include "DNA_listBase.h"
53 #include "DNA_lamp_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_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 #include "DNA_key_types.h"
64
65 #include "BLI_blenlib.h"
66 #include "BLI_arithb.h"
67 #include "BLI_editVert.h"
68
69 #include "BKE_bad_level_calls.h"
70 #include "BKE_utildefines.h"
71 #include "BKE_global.h"
72 #include "BKE_displist.h"
73 #include "BKE_deform.h"
74 #include "BKE_DerivedMesh.h"
75 #include "BKE_object.h"
76 #include "BKE_world.h"
77 #include "BKE_mesh.h"
78 #include "BKE_effect.h"
79 #include "BKE_mball.h"
80 #include "BKE_material.h"
81 #include "BKE_curve.h"
82 #include "BKE_anim.h"
83 #include "BKE_screen.h"
84 #include "BKE_texture.h"
85 #include "BKE_library.h"
86 #include "BKE_font.h"
87 #include "BKE_lattice.h"
88 #include "BKE_scene.h"
89 #include "BKE_subsurf.h"
90
91 #include "nla.h" /* For __NLA: Please do not remove yet */
92 #include "render.h"
93
94
95 /***/
96
97 typedef struct _FastLamp FastLamp;
98 struct _FastLamp {
99         FastLamp *next;
100         
101         short type, mode, lay, rt;
102         float co[3];
103         float vec[3];
104         float dist, distkw, att1, att2, spotsi, spotbl, r, g, b;
105 };
106
107 /***/
108
109 static void boundbox_displist(Object *ob);
110
111 static FastLamp *fastlamplist= NULL;
112 static float fviewmat[4][4];
113
114 void displistmesh_free(DispListMesh *dlm) 
115 {
116         // also check on mvert and mface, can be NULL after decimator (ton)
117         if (!dlm->dontFreeVerts && dlm->mvert) MEM_freeN(dlm->mvert);
118         if (!dlm->dontFreeNors && dlm->nors) MEM_freeN(dlm->nors);
119         if (!dlm->dontFreeOther) {
120                 if (dlm->medge) MEM_freeN(dlm->medge);
121                 if (dlm->mface) MEM_freeN(dlm->mface);
122                 if (dlm->mcol) MEM_freeN(dlm->mcol);
123                 if (dlm->tface) MEM_freeN(dlm->tface);
124         }
125         MEM_freeN(dlm);
126 }
127
128 DispListMesh *displistmesh_copy(DispListMesh *odlm) 
129 {
130         DispListMesh *ndlm= MEM_dupallocN(odlm);
131         ndlm->mvert= MEM_dupallocN(odlm->mvert);
132         if (odlm->medge) ndlm->medge= MEM_dupallocN(odlm->medge);
133         ndlm->mface= MEM_dupallocN(odlm->mface);
134         if (odlm->nors) ndlm->nors = MEM_dupallocN(odlm->nors);
135         if (odlm->mcol) ndlm->mcol= MEM_dupallocN(odlm->mcol);
136         if (odlm->tface) ndlm->tface= MEM_dupallocN(odlm->tface);
137         
138         return ndlm;
139 }
140
141 DispListMesh *displistmesh_copyShared(DispListMesh *odlm) 
142 {
143         DispListMesh *ndlm= MEM_dupallocN(odlm);
144         ndlm->dontFreeNors = ndlm->dontFreeOther = ndlm->dontFreeVerts = 1;
145         
146         return ndlm;
147 }
148
149 void displistmesh_to_mesh(DispListMesh *dlm, Mesh *me) 
150 {
151                 /* We assume, rather courageously, that any
152                  * shared data came from the mesh itself and so
153                  * we can ignore the dlm->dontFreeOther flag.
154                  */
155
156         if (me->mvert && dlm->mvert!=me->mvert) MEM_freeN(me->mvert);
157         if (me->mface && dlm->mface!=me->mface) MEM_freeN(me->mface);
158         if (me->tface && dlm->tface!=me->tface) MEM_freeN(me->tface);
159         if (me->mcol && dlm->mcol!=me->mcol) MEM_freeN(me->mcol);
160         if (me->medge && dlm->medge!=me->medge) MEM_freeN(me->medge);
161
162         me->tface = NULL;
163         me->mcol = NULL;
164         me->medge = NULL;
165
166         if (dlm->totvert!=me->totvert) {
167                 if (me->msticky) MEM_freeN(me->msticky);
168                 me->msticky = NULL;
169
170                 if (me->dvert) free_dverts(me->dvert, me->totvert);
171                 me->dvert = NULL;
172
173                 if(me->key) me->key->id.us--;
174                 me->key = NULL;
175         }
176
177         me->totface= dlm->totface;
178         me->totvert= dlm->totvert;
179         me->totedge= 0;
180
181         me->mvert= dlm->mvert;
182         me->mface= dlm->mface;
183         if (dlm->tface)
184                 me->tface= dlm->tface;
185         if (dlm->mcol)
186                 me->mcol= dlm->mcol;
187
188         if(dlm->medge) {
189                 me->totedge= dlm->totedge;
190                 me->medge= dlm->medge;
191         }
192
193         if (dlm->nors && !dlm->dontFreeNors) MEM_freeN(dlm->nors);
194
195         MEM_freeN(dlm);
196 }
197
198 void free_disp_elem(DispList *dl)
199 {
200         if(dl) {
201                 if(dl->verts) MEM_freeN(dl->verts);
202                 if(dl->nors) MEM_freeN(dl->nors);
203                 if(dl->index) MEM_freeN(dl->index);
204                 if(dl->col1) MEM_freeN(dl->col1);
205                 if(dl->col2) MEM_freeN(dl->col2);
206                 MEM_freeN(dl);
207         }
208 }
209
210 void freedisplist(ListBase *lb)
211 {
212         DispList *dl;
213
214         dl= lb->first;
215         while(dl) {
216                 BLI_remlink(lb, dl);
217                 free_disp_elem(dl);
218                 dl= lb->first;
219         }
220 }
221
222 DispList *find_displist_create(ListBase *lb, int type)
223 {
224         DispList *dl;
225         
226         dl= lb->first;
227         while(dl) {
228                 if(dl->type==type) return dl;
229                 dl= dl->next;
230         }
231
232         dl= MEM_callocN(sizeof(DispList), "find_disp");
233         dl->type= type;
234         BLI_addtail(lb, dl);
235
236         return dl;
237 }
238
239 DispList *find_displist(ListBase *lb, int type)
240 {
241         DispList *dl;
242         
243         dl= lb->first;
244         while(dl) {
245                 if(dl->type==type) return dl;
246                 dl= dl->next;
247         }
248
249         return 0;
250 }
251
252 int displist_has_faces(ListBase *lb)
253 {
254         DispList *dl;
255         
256         dl= lb->first;
257         while(dl) {
258                 if ELEM4(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF, DL_POLY)
259                         return 1;
260                 dl= dl->next;
261         }
262         return 0;
263 }
264
265 void copy_displist(ListBase *lbn, ListBase *lb)
266 {
267         DispList *dln, *dl;
268         
269         lbn->first= lbn->last= 0;
270         
271         dl= lb->first;
272         while(dl) {
273                 
274                 dln= MEM_dupallocN(dl);
275                 BLI_addtail(lbn, dln);
276                 dln->verts= MEM_dupallocN(dl->verts);
277                 dln->nors= MEM_dupallocN(dl->nors);
278                 dln->index= MEM_dupallocN(dl->index);
279                 dln->col1= MEM_dupallocN(dl->col1);
280                 dln->col2= MEM_dupallocN(dl->col2);
281                 
282                 dl= dl->next;
283         }
284 }
285
286 static void initfastshade(void)
287 {
288         Base *base;
289         Object *ob;
290         Lamp *la;
291         FastLamp *fl;
292         float mat[4][4];
293
294         init_render_world();
295         
296         if(fastlamplist) return;
297         if(G.scene->camera==0) G.scene->camera= scene_find_camera(G.scene);
298         if(G.scene->camera==0) return;
299
300         /* copied from 'roteerscene' (does that function still exist? (ton) */
301         where_is_object(G.scene->camera);
302         Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
303         Mat4Ortho(R.viewinv);
304         Mat4Invert(fviewmat, R.viewinv);
305
306         /* initrendertexture(); */
307
308         base= G.scene->base.first;
309         while(base) {
310                 ob= base->object;
311                 if( ob->type==OB_LAMP && (base->lay & G.scene->lay)) {
312                         
313                         Mat4MulMat4(mat, ob->obmat, fviewmat);
314                         
315                         la= ob->data;
316                         fl= MEM_mallocN(sizeof(FastLamp), "initfastshade2");
317
318                         fl->next= fastlamplist;
319                         fastlamplist= fl;
320
321                         fl->type= la->type;
322                         fl->mode= la->mode;
323                         fl->lay= base->lay;
324                         
325                         fl->vec[0]= mat[2][0];
326                         fl->vec[1]= mat[2][1];
327                         fl->vec[2]= mat[2][2];
328                         Normalise(fl->vec);
329                         
330                         fl->co[0]= mat[3][0];
331                         fl->co[1]= mat[3][1];
332                         fl->co[2]= mat[3][2];
333
334                         fl->dist= la->dist;
335                         fl->distkw= fl->dist*fl->dist;
336                         fl->att1= la->att1;
337                         fl->att2= la->att2;
338
339                         fl->spotsi= (float)cos( M_PI*la->spotsize/360.0 );
340                         fl->spotbl= (1.0f-fl->spotsi)*la->spotblend;
341         
342                         fl->r= la->energy*la->r;
343                         fl->g= la->energy*la->g;
344                         fl->b= la->energy*la->b;
345                 }
346                 
347                 if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
348                 else base= base->next;
349         }
350 }
351
352
353 void freefastshade()
354 {
355         while (fastlamplist) {
356                 FastLamp *fl= fastlamplist;
357                 fastlamplist= fl->next;
358                 
359                 MEM_freeN(fl);
360         }
361 }
362
363
364 static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2, char *vertcol)
365 {
366         ShadeInput shi;
367         FastLamp *fl;
368         float i, t, inp, is, soft,  lv[3], lampdist, ld;
369         float diff1[3], diff2[3];
370         float isr1=0, isg1=0, isb1=0, isr=0, isg=0, isb=0;
371         int a, back;
372
373         if(ma==0) return;
374         
375         shi.mat= ma;
376         shi.vlr= NULL;  // have to do this!
377         
378         // copy all relevant material vars, note, keep this synced with render_types.h
379         memcpy(&shi.r, &shi.mat->r, 23*sizeof(float));
380         // set special cases:
381         shi.har= shi.mat->har;
382         
383         shi.osatex= 0;  // also prevents reading vlr
384         
385         VECCOPY(shi.vn, nor);
386         
387         if(ma->mode & MA_VERTEXCOLP) {
388                 if(vertcol) {
389                         shi.r= vertcol[3]/255.0;
390                         shi.g= vertcol[2]/255.0;
391                         shi.b= vertcol[1]/255.0;
392                 }
393         }
394         
395         if(ma->texco) {
396                 VECCOPY(shi.lo, orco);
397                 
398                 if(ma->texco & TEXCO_GLOB) {
399                         VECCOPY(shi.gl, shi.lo);
400                 }
401                 if(ma->texco & TEXCO_WINDOW) {
402                         VECCOPY(shi.winco, shi.lo);
403                 }
404                 if(ma->texco & TEXCO_STICKY) {
405                         VECCOPY(shi.sticky, shi.lo);
406                 }
407                 if(ma->texco & TEXCO_UV) {
408                         VECCOPY(shi.uv, shi.lo);
409                 }
410                 if(ma->texco & TEXCO_OBJECT) {
411                         VECCOPY(shi.co, shi.lo);
412                 }
413                 if(ma->texco & TEXCO_NORM) {
414                         VECCOPY(shi.orn, shi.vn);
415                 }
416                 if(ma->texco & TEXCO_REFL) {
417                         
418                         inp= 2.0*(shi.vn[2]);
419                         shi.ref[0]= (inp*shi.vn[0]);
420                         shi.ref[1]= (inp*shi.vn[1]);
421                         shi.ref[2]= (-1.0+inp*shi.vn[2]);
422                 }
423
424                 do_material_tex(&shi);
425         }
426
427         if(ma->mode & MA_SHLESS) {
428                 if(vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
429                         float fac;
430                         fac= vertcol[3]*shi.r;
431                         col1[3]= fac>=1.0?255:(char)fac;
432                         fac= vertcol[2]*shi.g;
433                         col1[2]= fac>=1.0?255:(char)fac;
434                         fac= vertcol[1]*shi.b;
435                         col1[1]= fac>=1.0?255:(char)fac;
436                 }
437                 else {
438                         int fac;
439                         fac= (int) (255.0*shi.r);
440                         col1[3]= fac>255?255:(char)fac;
441                         fac= (int) (255.0*shi.g);
442                         col1[2]= fac>255?255:(char)fac;
443                         fac= (int) (255.0*shi.b);
444                         col1[1]= fac>255?255:(char)fac;
445                 }
446                 if(col2) {
447                         col2[3]= col1[3];
448                         col2[2]= col1[2];
449                         col2[1]= col1[1];
450                 }
451                 return;
452         }
453
454         if( vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
455                 diff1[0]= diff2[0]= shi.r*(shi.emit+vertcol[3]/255.0);
456                 diff1[1]= diff2[1]= shi.g*(shi.emit+vertcol[2]/255.0);
457                 diff1[2]= diff2[2]= shi.b*(shi.emit+vertcol[1]/255.0);
458         }
459         else {
460                 diff1[0]= diff2[0]= shi.r*shi.emit;
461                 diff1[1]= diff2[1]= shi.g*shi.emit;
462                 diff1[2]= diff2[2]= shi.b*shi.emit;
463         }
464         
465         shi.view[0]= 0.0;
466         shi.view[1]= 0.0;
467         shi.view[2]= 1.0;
468         
469         Normalise(shi.view);
470
471         for (fl= fastlamplist; fl; fl= fl->next) {
472                 /* if(fl->mode & LA_LAYER) if((fl->lay & ma->lay)==0) continue; */
473
474                 if(fl->type==LA_SUN || fl->type==LA_HEMI) {
475                         VECCOPY(lv, fl->vec);
476                         lampdist= 1.0;
477                 }
478                 else {
479                         lv[0]= fl->co[0] - co[0];
480                         lv[1]= fl->co[1] - co[1];
481                         lv[2]= fl->co[2] - co[2];
482                         ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
483                         lv[0]/=ld;
484                         lv[1]/=ld;
485                         lv[2]/=ld;
486
487                         if(fl->mode & LA_QUAD) {
488                                 t= 1.0;
489                                 if(fl->att1>0.0)
490                                         t= fl->dist/(fl->dist+fl->att1*ld);
491                                 if(fl->att2>0.0)
492                                         t*= fl->distkw/(fl->distkw+fl->att2*ld*ld);
493
494                                 lampdist= t;
495                         }
496                         else {
497                                 lampdist= (fl->dist/(fl->dist+ld));
498                         }
499
500                         if(fl->mode & LA_SPHERE) {
501                                 t= fl->dist - ld;
502                                 if(t<0.0) continue;
503                                 
504                                 t/= fl->dist;
505                                 lampdist*= (t);
506                         }
507                 }
508
509                 if(fl->type==LA_SPOT) {
510                         inp= lv[0]*fl->vec[0]+lv[1]*fl->vec[1]+lv[2]*fl->vec[2];
511                         if(inp<fl->spotsi) continue;
512                         else {
513                                 t= inp-fl->spotsi;
514                                 i= 1.0;
515                                 soft= 1.0;
516                                 if(t<fl->spotbl && fl->spotbl!=0.0) {
517                                         /* soft area */
518                                         i= t/fl->spotbl;
519                                         t= i*i;
520                                         soft= (3.0*t-2.0*t*i);
521                                         inp*= soft;
522                                 }
523
524                                 lampdist*=inp;
525                         }
526                 }
527
528                 if(fl->mode & LA_NO_DIFF) is= 0.0;
529                 else {
530                         is= nor[0]*lv[0]+ nor[1]*lv[1]+ nor[2]*lv[2];
531         
532                         if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(nor, lv, shi.view, ma->roughness);
533                         else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(nor, lv, shi.view, ma->param[0], ma->param[1]);
534                         else if(ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(is, nor, shi.view, ma->darkness);
535                 }
536                 
537                 back= 0;
538                 if(is<0.0) {
539                         back= 1;
540                         is= -is;
541                 }
542                 inp= is*lampdist*shi.refl;
543
544                 if(back==0) {
545                         add_to_diffuse(diff1, &shi, is, inp*fl->r, inp*fl->g, inp*fl->b);
546                         //diff1[0]+= inp*fl->r;
547                         //diff1[1]+= inp*fl->g;
548                         //diff1[2]+= inp*fl->b;
549                 } else if(col2) {
550                         add_to_diffuse(diff2, &shi, is, inp*fl->r, inp*fl->g, inp*fl->b);
551                         //diff2[0]+= inp*fl->r;
552                         //diff2[1]+= inp*fl->g;
553                         //diff2[2]+= inp*fl->b;
554                 }
555                 if(shi.spec!=0.0 && (fl->mode & LA_NO_SPEC)==0) {
556                         float specfac;
557                         
558                         if(ma->spec_shader==MA_SPEC_PHONG) 
559                                 specfac= Phong_Spec(nor, lv, shi.view, shi.har);
560                         else if(ma->spec_shader==MA_SPEC_COOKTORR) 
561                                 specfac= CookTorr_Spec(nor, lv, shi.view, shi.har);
562                         else if(ma->spec_shader==MA_SPEC_BLINN) 
563                                 specfac= Blinn_Spec(nor, lv, shi.view, ma->refrac, (float)shi.har);
564                         else if(ma->spec_shader==MA_SPEC_WARDISO)
565                                 specfac= WardIso_Spec(nor, lv, shi.view, ma->rms);
566                         else 
567                                 specfac= Toon_Spec(nor, lv, shi.view, ma->param[2], ma->param[3]);
568                         
569                         if(specfac>0) {
570                                 t= specfac*shi.spec*lampdist;
571                                 if(back==0) {
572                                         if(ma->mode & MA_RAMP_SPEC) {
573                                                 float spec[3];
574                                                 do_specular_ramp(&shi, specfac, t, spec);
575                                                 isr+= t*(fl->r * spec[0]);
576                                                 isg+= t*(fl->g * spec[1]);
577                                                 isb+= t*(fl->b * spec[2]);
578                                         }
579                                         else {
580                                                 isr+= t*(fl->r * shi.specr);
581                                                 isg+= t*(fl->g * shi.specg);
582                                                 isb+= t*(fl->b * shi.specb);
583                                         }
584                                 }
585                                 else if(col2) {
586                                         if(ma->mode & MA_RAMP_SPEC) {
587                                                 float spec[3];
588                                                 do_specular_ramp(&shi, specfac, t, spec);
589                                                 isr1+= t*(fl->r * spec[0]);
590                                                 isg1+= t*(fl->g * spec[1]);
591                                                 isb1+= t*(fl->b * spec[2]);
592                                         }
593                                         else {
594                                                 isr1+= t*(fl->r * shi.specr);
595                                                 isg1+= t*(fl->g * shi.specg);
596                                                 isb1+= t*(fl->b * shi.specb);
597                                         }
598                                 }
599                         }
600                 }
601
602         }
603
604         if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(diff1, &shi);
605         if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(&isr, &isg, &isb, &shi);
606
607         a= 256*(diff1[0] + shi.ambr +isr);
608         if(a>255) col1[3]= 255; 
609         else col1[3]= a;
610         a= 256*(diff1[1] + shi.ambg +isg);
611         if(a>255) col1[2]= 255; 
612         else col1[2]= a;
613         a= 256*(diff1[2] + shi.ambb +isb);
614         if(a>255) col1[1]= 255; 
615         else col1[1]= a;
616
617         if(col2) {
618                 if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(diff2, &shi);
619                 if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(&isr1, &isg1, &isb1, &shi);
620                 
621                 a= 256*(diff2[0] + shi.ambr +isr1);
622                 if(a>255) col2[3]= 255; 
623                 else col2[3]= a;
624                 a= 256*(diff2[1] + shi.ambg +isg1);
625                 if(a>255) col2[2]= 255; 
626                 else col2[2]= a;
627                 a= 256*(diff2[2] + shi.ambb +isb1);
628                 if(a>255) col2[1]= 255; 
629                 else col2[1]= a;
630         }
631
632 }
633
634 void addnormalsDispList(Object *ob, ListBase *lb)
635 {
636         DispList *dl = NULL;
637         float *vdata, *ndata, nor[3];
638         float *v1, *v2, *v3, *v4;
639         float *n1, *n2, *n3, *n4;
640         int a, b, p1, p2, p3, p4;
641
642
643         dl= lb->first;
644         
645         while(dl) {
646                 if(dl->type==DL_INDEX3) {
647                         if(dl->nors==0) {
648                                 dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
649                                 if(dl->verts[2]<0.0) dl->nors[2]= -1.0;
650                                 else dl->nors[2]= 1.0;
651                         }
652                 }
653                 else if(dl->type==DL_SURF) {
654                         if(dl->nors==0) {
655                                 dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
656                                 
657                                 vdata= dl->verts;
658                                 ndata= dl->nors;
659                                 
660                                 for(a=0; a<dl->parts; a++) {
661         
662                                         DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
663         
664                                         v1= vdata+ 3*p1; 
665                                         n1= ndata+ 3*p1;
666                                         v2= vdata+ 3*p2; 
667                                         n2= ndata+ 3*p2;
668                                         v3= vdata+ 3*p3; 
669                                         n3= ndata+ 3*p3;
670                                         v4= vdata+ 3*p4; 
671                                         n4= ndata+ 3*p4;
672                                         
673                                         for(; b<dl->nr; b++) {
674         
675                                                 CalcNormFloat4(v1, v3, v4, v2, nor);
676         
677                                                 VecAddf(n1, n1, nor);
678                                                 VecAddf(n2, n2, nor);
679                                                 VecAddf(n3, n3, nor);
680                                                 VecAddf(n4, n4, nor);
681         
682                                                 v2= v1; v1+= 3;
683                                                 v4= v3; v3+= 3;
684                                                 n2= n1; n1+= 3;
685                                                 n4= n3; n3+= 3;
686                                         }
687                                 }
688                                 a= dl->parts*dl->nr;
689                                 v1= ndata;
690                                 while(a--) {
691                                         Normalise(v1);
692                                         v1+= 3;
693                                 }
694                         }
695                 }
696                 dl= dl->next;
697         }
698 }
699
700 static void init_fastshade_for_ob(Object *ob, int *need_orco_r, float mat[4][4], float imat[3][3])
701 {
702         float tmat[4][4];
703         int a;
704
705         initfastshade();
706
707         Mat4MulMat4(mat, ob->obmat, fviewmat);
708         
709         Mat4Invert(tmat, mat);
710         Mat3CpyMat4(imat, tmat);
711         if(ob->transflag & OB_NEG_SCALE) Mat3MulFloat((float *)imat, -1.0);
712
713         if (need_orco_r) *need_orco_r= 0;
714         for(a=0; a<ob->totcol; a++) {
715                 Material *ma= give_current_material(ob, a+1);
716                 if(ma) {
717                         init_render_material(ma);
718                         if(ma->texco & TEXCO_ORCO) {
719                                 if (need_orco_r) *need_orco_r= 1;
720                         }
721                 }
722         }
723 }
724 static void end_fastshade_for_ob(Object *ob)
725 {
726         int a;
727
728         for(a=0; a<ob->totcol; a++) {
729                 Material *ma= give_current_material(ob, a+1);
730                 if(ma) end_render_material(ma);
731         }
732 }
733
734 void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r, unsigned int **col2_r)
735 {
736         Mesh *me= ob->data;
737         int dmNeedsFree;
738         DerivedMesh *dm;
739         DispListMesh *dlm;
740         unsigned int *col1, *col2;
741         float *orco, *vnors, imat[3][3], mat[4][4], vec[3];
742         int a, i, need_orco;
743
744         init_fastshade_for_ob(ob, &need_orco, mat, imat);
745
746         if (need_orco) {
747                 orco = mesh_create_orco(ob);
748         } else {
749                 orco = NULL;
750         }
751
752         if (onlyForMesh) {
753                 dm = mesh_get_derived_deform(ob, &dmNeedsFree);
754         } else {
755                 dm = mesh_get_derived_final(ob, &dmNeedsFree);
756         }
757         dlm= dm->convertToDispListMesh(dm, 1);
758
759         col1 = MEM_mallocN(sizeof(*col1)*dlm->totface*4, "col1");
760         if (col2_r && (me->flag & ME_TWOSIDED)) {
761                 col2 = MEM_mallocN(sizeof(*col2)*dlm->totface*4, "col1");
762         } else {
763                 col2 = NULL;
764         }
765         
766         *col1_r = col1;
767         if (col2_r) *col2_r = col2;
768
769                 /* vertexnormals */
770         vnors= MEM_mallocN(dlm->totvert*3*sizeof(float), "vnors disp");
771         for (a=0; a<dlm->totvert; a++) {
772                 MVert *mv = &dlm->mvert[a];
773                 float *vn= &vnors[a*3];
774                 float xn= mv->no[0]; 
775                 float yn= mv->no[1]; 
776                 float zn= mv->no[2];
777                 
778                         /* transpose ! */
779                 vn[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
780                 vn[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
781                 vn[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
782                 Normalise(vn);
783         }               
784
785         for (i=0; i<dlm->totface; i++) {
786                 MFace *mf= &dlm->mface[i];
787
788                 if (mf->v3) {
789                         int j, vidx[4], nverts= mf->v4?4:3;
790                         unsigned char *col1base= (unsigned char*) &col1[i*4];
791                         unsigned char *col2base= (unsigned char*) (col2?&col2[i*4]:NULL);
792                         unsigned char *mcolbase;
793                         Material *ma= give_current_material(ob, mf->mat_nr+1);
794                         float nor[3], n1[3];
795                         
796                         if(ma==0) ma= &defmaterial;
797                         
798                         if (dlm->tface) {
799                                 mcolbase = (unsigned char*) dlm->tface[i].col;
800                         } else if (dlm->mcol) {
801                                 mcolbase = (unsigned char*) &dlm->mcol[i*4];
802                         } else {
803                                 mcolbase = NULL;
804                         }
805
806                         vidx[0]= mf->v1;
807                         vidx[1]= mf->v2;
808                         vidx[2]= mf->v3;
809                         vidx[3]= mf->v4;
810
811                         if (dlm->nors) {
812                                 VECCOPY(nor, &dlm->nors[i*3]);
813                         } else {
814                                 if (mf->v4)
815                                         CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, nor);
816                                 else
817                                         CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, nor);
818                         }
819
820                         n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
821                         n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
822                         n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
823                         Normalise(n1);
824
825                         for (j=0; j<nverts; j++) {
826                                 MVert *mv= &dlm->mvert[vidx[j]];
827                                 unsigned char *col1= &col1base[j*4];
828                                 unsigned char *col2= col2base?&col2base[j*4]:NULL;
829                                 unsigned char *mcol= mcolbase?&mcolbase[j*4]:NULL;
830                                 float *vn = (mf->flag & ME_SMOOTH)?&vnors[3*vidx[j]]:n1;
831
832                                 VECCOPY(vec, mv->co);
833                                 Mat4MulVecfl(mat, vec);
834                                 fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, ma, col1, col2, mcol);
835                         }
836                 }
837         }
838         MEM_freeN(vnors);
839         displistmesh_free(dlm);
840
841         if (orco) {
842                 MEM_freeN(orco);
843         }
844
845         if (dmNeedsFree) dm->release(dm);
846
847         end_fastshade_for_ob(ob);
848 }
849
850 void shadeDispList(Object *ob)
851 {
852         DispList *dl, *dlob;
853         Material *ma = NULL;
854         Curve *cu;
855         float imat[3][3], mat[4][4], vec[3];
856         float *fp, *nor, n1[3];
857         unsigned int *col1;
858         int a;
859
860         if(ob->flag & OB_FROMDUPLI) return;
861
862         dl = find_displist(&ob->disp, DL_VERTCOL);
863         if (dl) {
864                 BLI_remlink(&ob->disp, dl);
865                 free_disp_elem(dl);
866         }
867
868         if(ob->type==OB_MESH) {
869                 dl= MEM_callocN(sizeof(DispList), "displistshade");
870                 BLI_addtail(&ob->disp, dl);
871                 dl->type= DL_VERTCOL;
872
873                 mesh_create_shadedColors(ob, 0, &dl->col1, &dl->col2);
874
875                 return;
876         }
877
878         init_fastshade_for_ob(ob, NULL, mat, imat);
879         
880         if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
881         
882                 /* now we need the normals */
883                 cu= ob->data;
884                 dl= cu->disp.first;
885                 
886                 while(dl) {
887                         dlob= MEM_callocN(sizeof(DispList), "displistshade");
888                         BLI_addtail(&ob->disp, dlob);
889                         dlob->type= DL_VERTCOL;
890                         dlob->parts= dl->parts;
891                         dlob->nr= dl->nr;
892                         
893                         if(dl->type==DL_INDEX3) {
894                                 col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
895                         }
896                         else {
897                                 col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1");
898                         }
899                         
900                 
901                         ma= give_current_material(ob, dl->col+1);
902                         if(ma==0) ma= &defmaterial;
903
904                         if(dl->type==DL_INDEX3) {
905                                 if(dl->nors) {
906                                         /* there's just one normal */
907                                         n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2];
908                                         n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2];
909                                         n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2];
910                                         Normalise(n1);
911                                         
912                                         fp= dl->verts;
913                                         
914                                         a= dl->nr;              
915                                         while(a--) {
916                                                 VECCOPY(vec, fp);
917                                                 Mat4MulVecfl(mat, vec);
918                                                 
919                                                 fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
920                                                 
921                                                 fp+= 3; col1++;
922                                         }
923                                 }
924                         }
925                         else if(dl->type==DL_SURF) {
926                                 if(dl->nors) {
927                                         a= dl->nr*dl->parts;
928                                         fp= dl->verts;
929                                         nor= dl->nors;
930                                         
931                                         while(a--) {
932                                                 VECCOPY(vec, fp);
933                                                 Mat4MulVecfl(mat, vec);
934                                                 
935                                                 n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
936                                                 n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
937                                                 n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
938                                                 Normalise(n1);
939                         
940                                                 fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
941                                                 
942                                                 fp+= 3; nor+= 3; col1++;
943                                         }
944                                 }
945                         }
946                         dl= dl->next;
947                 }
948         }
949         else if(ob->type==OB_MBALL) {
950                 /* there are normals already */
951                 dl= ob->disp.first;
952                 
953                 while(dl) {
954                         
955                         if(dl->type==DL_INDEX4) {
956                                 if(dl->nors) {
957                                         
958                                         if(dl->col1) MEM_freeN(dl->col1);
959                                         col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1");
960                         
961                                         ma= give_current_material(ob, dl->col+1);
962                                         if(ma==0) ma= &defmaterial;
963         
964                                         fp= dl->verts;
965                                         nor= dl->nors;
966                                         
967                                         a= dl->nr;              
968                                         while(a--) {
969                                                 VECCOPY(vec, fp);
970                                                 Mat4MulVecfl(mat, vec);
971                                                 
972                                                 /* transpose ! */
973                                                 n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2];
974                                                 n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2];
975                                                 n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
976                                                 Normalise(n1);
977                                         
978                                                 fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
979                                                 
980                                                 fp+= 3; col1++; nor+= 3;
981                                         }
982                                 }
983                         }
984                         dl= dl->next;
985                 }
986         }
987         
988         end_fastshade_for_ob(ob);
989 }
990
991 void reshadeall_displist(void)
992 {
993         Base *base;
994         Object *ob;
995         
996         freefastshade();
997         
998         base= G.scene->base.first;
999         while(base) {
1000                 if(base->lay & G.scene->lay) {
1001                         ob= base->object;
1002                         
1003                         /* Metaballs have standard displist at the Object */
1004                         if(ob->type==OB_MBALL) shadeDispList(ob);
1005                         else freedisplist(&ob->disp);
1006                 }
1007                 base= base->next;
1008         }
1009 }
1010
1011 void count_displist(ListBase *lb, int *totvert, int *totface)
1012 {
1013         DispList *dl;
1014         
1015         dl= lb->first;
1016         while(dl) {
1017                 
1018                 switch(dl->type) {
1019                 case DL_SURF:
1020                         *totvert+= dl->nr*dl->parts;
1021                         *totface+= (dl->nr-1)*(dl->parts-1);
1022                         break;
1023                 case DL_INDEX3:
1024                 case DL_INDEX4:
1025                         *totvert+= dl->nr;
1026                         *totface+= dl->parts;
1027                         break;
1028                 case DL_POLY:
1029                 case DL_SEGM:
1030                         *totvert+= dl->nr*dl->parts;
1031                 }
1032                 
1033                 dl= dl->next;
1034         }
1035 }
1036
1037 static void curve_to_displist(ListBase *nubase, ListBase *dispbase)
1038 {
1039         Nurb *nu;
1040         DispList *dl;
1041         BezTriple *bezt, *prevbezt;
1042         BPoint *bp;
1043         float *data, *v1, *v2;
1044         int a, len;
1045         
1046         nu= nubase->first;
1047         
1048         while(nu) {
1049                 if(nu->hide==0) {
1050                         if((nu->type & 7)==CU_BEZIER) {
1051                                 
1052                                 /* count */
1053                                 len= 0;
1054                                 a= nu->pntsu-1;
1055                                 if(nu->flagu & 1) a++;
1056
1057                                 prevbezt= nu->bezt;
1058                                 bezt= prevbezt+1;
1059                                 while(a--) {
1060                                         if(a==0 && (nu->flagu & 1)) bezt= nu->bezt;
1061                                         
1062                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
1063                                         else len+= nu->resolu;
1064                                         
1065                                         if(a==0 && (nu->flagu & 1)==0) len++;
1066                                         
1067                                         prevbezt= bezt;
1068                                         bezt++;
1069                                 }
1070                                 
1071                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
1072                                 /* len+1 because of 'forward_diff_bezier' function */
1073                                 dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
1074                                 BLI_addtail(dispbase, dl);
1075                                 dl->parts= 1;
1076                                 dl->nr= len;
1077                                 dl->col= nu->mat_nr;
1078                                 dl->charidx= nu->charidx;
1079
1080                                 data= dl->verts;
1081
1082                                 if(nu->flagu & 1) {
1083                                         dl->type= DL_POLY;
1084                                         a= nu->pntsu;
1085                                 }
1086                                 else {
1087                                         dl->type= DL_SEGM;
1088                                         a= nu->pntsu-1;
1089                                 }
1090                                 
1091                                 prevbezt= nu->bezt;
1092                                 bezt= prevbezt+1;
1093                                 
1094                                 while(a--) {
1095                                         if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
1096                                         
1097                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
1098                                                 VECCOPY(data, prevbezt->vec[1]);
1099                                                 data+= 3;
1100                                         }
1101                                         else {
1102                                                 v1= prevbezt->vec[1];
1103                                                 v2= bezt->vec[0];
1104                                                 forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], data, nu->resolu, 3);
1105                                                 forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu, 3);
1106                                                 if((nu->type & 8)==0)
1107                                                         forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu, 3);
1108                                                 data+= 3*nu->resolu;
1109                                         }
1110                                         
1111                                         if(a==0 && dl->type==DL_SEGM) {
1112                                                 VECCOPY(data, bezt->vec[1]);
1113                                         }
1114                                         
1115                                         prevbezt= bezt;
1116                                         bezt++;
1117                                 }
1118                         }
1119                         else if((nu->type & 7)==CU_NURBS) {
1120                                 len= nu->pntsu*nu->resolu;
1121                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1122                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1123                                 BLI_addtail(dispbase, dl);
1124                                 dl->parts= 1;
1125                                 dl->nr= len;
1126                                 dl->col= nu->mat_nr;
1127
1128                                 data= dl->verts;
1129                                 if(nu->flagu & 1) dl->type= DL_POLY;
1130                                 else dl->type= DL_SEGM;
1131                                 makeNurbcurve(nu, data, 3);
1132                         }
1133                         else if((nu->type & 7)==CU_POLY) {
1134                                 len= nu->pntsu;
1135                                 dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
1136                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1137                                 BLI_addtail(dispbase, dl);
1138                                 dl->parts= 1;
1139                                 dl->nr= len;
1140                                 dl->col= nu->mat_nr;
1141
1142                                 data= dl->verts;
1143                                 if(nu->flagu & 1) dl->type= DL_POLY;
1144                                 else dl->type= DL_SEGM;
1145                                 
1146                                 a= len;
1147                                 bp= nu->bp;
1148                                 while(a--) {
1149                                         VECCOPY(data, bp->vec);
1150                                         bp++;
1151                                         data+= 3;
1152                                 }
1153                         }
1154                 }
1155                 nu= nu->next;
1156         }
1157 }
1158
1159
1160 void filldisplist(ListBase *dispbase, ListBase *to)
1161 {
1162         EditVert *eve, *v1, *vlast;
1163         EditFace *efa;
1164         DispList *dlnew=0, *dl;
1165         float *f1;
1166         int colnr=0, charidx=0, cont=1, tot, a, *index;
1167         long totvert;
1168         
1169         if(dispbase==0) return;
1170         if(dispbase->first==0) return;
1171
1172         while(cont) {
1173                 cont= 0;
1174                 totvert=0;
1175                 
1176                 dl= dispbase->first;
1177                 while(dl) {
1178         
1179                         if(dl->type==DL_POLY) {
1180                                 if(charidx<dl->charidx) cont= 1;
1181                                 else if(charidx==dl->charidx) {
1182                         
1183                                         colnr= dl->col;
1184                                         charidx= dl->charidx;
1185                 
1186                                         /* make editverts and edges */
1187                                         f1= dl->verts;
1188                                         a= dl->nr;
1189                                         eve= v1= 0;
1190                                         
1191                                         while(a--) {
1192                                                 vlast= eve;
1193                                                 
1194                                                 eve= BLI_addfillvert(f1);
1195                                                 totvert++;
1196                                                 
1197                                                 if(vlast==0) v1= eve;
1198                                                 else {
1199                                                         BLI_addfilledge(vlast, eve);
1200                                                 }
1201                                                 f1+=3;
1202                                         }
1203                                 
1204                                         if(eve!=0 && v1!=0) {
1205                                                 BLI_addfilledge(eve, v1);
1206                                         }
1207                                 }
1208                         }
1209                         dl= dl->next;
1210                 }
1211                 
1212                 /* to make edgefill work 
1213                 G.obedit can be 0 on file load */
1214                 if (G.obedit) {
1215                         BLI_setScanFillObjectRef(G.obedit);
1216                         BLI_setScanFillColourRef(&G.obedit->actcol);
1217                 }
1218
1219                 if(totvert && BLI_edgefill(0)!=0) {
1220
1221                         /* count faces  */
1222                         tot= 0;
1223                         efa= fillfacebase.first;
1224                         while(efa) {
1225                                 tot++;
1226                                 efa= efa->next;
1227                         }
1228
1229                         if(tot) {
1230                                 dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
1231                                 dlnew->type= DL_INDEX3;
1232                                 dlnew->col= colnr;
1233                                 dlnew->nr= totvert;
1234                                 dlnew->parts= tot;
1235
1236                                 dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
1237                                 dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
1238                                 
1239                                 /* vert data */
1240                                 f1= dlnew->verts;
1241                                 totvert= 0;
1242                                 eve= fillvertbase.first;
1243                                 while(eve) {
1244                                         VECCOPY(f1, eve->co);
1245                                         f1+= 3;
1246         
1247                                         /* index number */
1248                                         eve->vn= (EditVert *)totvert;
1249                                         totvert++;
1250                                         
1251                                         eve= eve->next;
1252                                 }
1253                                 
1254                                 /* index data */
1255                                 efa= fillfacebase.first;
1256                                 index= dlnew->index;
1257                                 while(efa) {
1258                                         index[0]= (long)efa->v1->vn;
1259                                         index[1]= (long)efa->v2->vn;
1260                                         index[2]= (long)efa->v3->vn;
1261                                         
1262                                         index+= 3;
1263                                         efa= efa->next;
1264                                 }
1265                         }
1266
1267                         BLI_addhead(to, dlnew);
1268                         
1269                 }
1270                 BLI_end_edgefill();
1271
1272                 charidx++;
1273         }
1274         
1275         /* do not free polys, needed for wireframe display */
1276         
1277 }
1278
1279 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
1280 {
1281         ListBase front, back;
1282         DispList *dl, *dlnew;
1283         float *fp, *fp1;
1284         int a, dpoly;
1285         
1286         front.first= front.last= back.first= back.last= 0;
1287         if(cu->flag & CU_3D) return;
1288         if( (cu->flag & (CU_FRONT+CU_BACK))==0 ) return;
1289         
1290         dl= dispbase->first;
1291         while(dl) {
1292                 if(dl->type==DL_SURF) {
1293                         if( (dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)==0 ) {
1294                                 if( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE) ) {
1295                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1296                                         BLI_addtail(&front, dlnew);
1297                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1298                                         dlnew->nr= dl->parts;
1299                                         dlnew->parts= 1;
1300                                         dlnew->type= DL_POLY;
1301                                         dlnew->col= dl->col;
1302                                         
1303                                         fp= dl->verts;
1304                                         dpoly= 3*dl->nr;
1305                                         
1306                                         a= dl->parts;
1307                                         while(a--) {
1308                                                 VECCOPY(fp1, fp);
1309                                                 fp1+= 3;
1310                                                 fp+= dpoly;
1311                                         }
1312                                 }
1313                                 if( (cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE) ) {
1314                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
1315                                         BLI_addtail(&back, dlnew);
1316                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
1317                                         dlnew->nr= dl->parts;
1318                                         dlnew->parts= 1;
1319                                         dlnew->type= DL_POLY;
1320                                         dlnew->col= dl->col;
1321                                         
1322                                         fp= dl->verts+3*(dl->nr-1);
1323                                         dpoly= 3*dl->nr;
1324                                         
1325                                         a= dl->parts;
1326                                         while(a--) {
1327                                                 VECCOPY(fp1, fp);
1328                                                 fp1+= 3;
1329                                                 fp+= dpoly;
1330                                         }
1331                                 }
1332                         }
1333                 }
1334                 dl= dl->next;
1335         }
1336
1337         filldisplist(&front, dispbase);
1338         filldisplist(&back, dispbase);
1339         
1340         freedisplist(&front);
1341         freedisplist(&back);
1342
1343         filldisplist(dispbase, dispbase);
1344         
1345 }
1346
1347 void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
1348 {
1349         DispList *dl;
1350         Nurb *nu;
1351                 
1352         dl= dispbase->first;
1353         
1354         if(cu->flag & CU_3D) return;
1355         
1356         nu= nurb->first;
1357         while(nu) {
1358                 if(nu->flagu & CU_CYCLIC) break;
1359                 nu= nu->next;
1360         }
1361         if(nu==0) return;
1362
1363         if(dl->type==DL_SURF) bevels_to_filledpoly(cu, dispbase);
1364         else {
1365                 if(cu->flag & CU_FRONT) filldisplist(dispbase, dispbase);
1366         }
1367 }
1368
1369
1370 /* taper rules:
1371   - only 1 curve
1372   - first point left, last point right
1373   - based on subdivided points in original curve, not on points in taper curve (still)
1374 */
1375 float calc_taper(Object *taperobj, int cur, int tot)
1376 {
1377         Curve *cu;
1378         DispList *dl;
1379         
1380         if(taperobj==NULL) return 1.0;
1381         
1382         cu= taperobj->data;
1383         dl= cu->disp.first;
1384         if(dl==NULL) {
1385                 makeDispListCurveTypes(taperobj);
1386                 dl= cu->disp.first;
1387         }
1388         if(dl) {
1389                 float fac= ((float)cur)/(float)(tot-1);
1390                 float minx, dx, *fp;
1391                 int a;
1392                 
1393                 /* horizontal size */
1394                 minx= dl->verts[0];
1395                 dx= dl->verts[3*(dl->nr-1)] - minx;
1396                 if(dx>0.0) {
1397                 
1398                         fp= dl->verts;
1399                         for(a=0; a<dl->nr; a++, fp+=3) {
1400                                 if( (fp[0]-minx)/dx >= fac) {
1401                                         /* interpolate with prev */
1402                                         if(a>0) {
1403                                                 float fac1= (fp[-3]-minx)/dx;
1404                                                 float fac2= (fp[0]-minx)/dx;
1405                                                 if(fac1!=fac2)
1406                                                         return fp[1]*(fac1-fac)/(fac1-fac2) + fp[-2]*(fac-fac2)/(fac1-fac2);
1407                                         }
1408                                         return fp[1];
1409                                 }
1410                         }
1411                         return fp[-2];  // last y coord
1412                 }
1413         }
1414         
1415         return 1.0;
1416 }
1417
1418 void makeDispListMBall(Object *ob)
1419 {
1420         if(!ob || (ob->flag&OB_FROMDUPLI) || ob->type!=OB_MBALL) return;
1421
1422         freedisplist(&(ob->disp));
1423         
1424         if(ob->type==OB_MBALL) {
1425                 if(ob==find_basis_mball(ob)) {
1426                         metaball_polygonize(ob);
1427                         tex_space_mball(ob);
1428
1429                         object_deform(ob);
1430                 }
1431         }
1432         
1433         boundbox_displist(ob);
1434 }
1435 void makeDispListCurveTypes(Object *ob)
1436 {
1437         Nurb *nu;
1438         Curve *cu;
1439         BPoint *bp;
1440         ListBase dlbev, *dispbase;
1441         DispList *dl, *dlb;
1442         BevList *bl;
1443         BevPoint *bevp;
1444         float *data, *fp1, widfac, vec[3];
1445         int len, a, b, draw=0;
1446
1447         if(!ob || (ob->flag&OB_FROMDUPLI) || !ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
1448         if(ob==NULL) return;
1449         if(ob->flag & OB_FROMDUPLI) return;
1450
1451         freedisplist(&(ob->disp));
1452         
1453         if(ob->type==OB_SURF) {
1454                 draw= ob->dt;
1455                 cu= ob->data;
1456                 dispbase= &(cu->disp);
1457                 freedisplist(dispbase);
1458                 
1459                 if(ob==G.obedit) nu= editNurb.first;
1460                 else {
1461                         curve_modifier(ob, 's');
1462                         nu= cu->nurb.first;
1463                 }
1464                 
1465                 while(nu) {
1466                         if(nu->hide==0) {
1467                                 if(nu->pntsv==1) {
1468                                         if(draw==0) len= nu->pntsu;
1469                                         else len= nu->pntsu*nu->resolu;
1470                                         
1471                                         dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1472                                         dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1473                                         
1474                                         BLI_addtail(dispbase, dl);
1475                                         dl->parts= 1;
1476                                         dl->nr= len;
1477                                         dl->col= nu->mat_nr;
1478                                         dl->rt= nu->flag;
1479                                         
1480                                         data= dl->verts;
1481                                         if(nu->flagu & 1) dl->type= DL_POLY;
1482                                         else dl->type= DL_SEGM;
1483                                         
1484                                         if(draw==0) {
1485                                                 bp= nu->bp;
1486                                                 while(len--) {
1487                                                         VECCOPY(data, bp->vec);
1488                                                         bp++;
1489                                                         data+= 3;
1490                                                 }
1491                                         }
1492                                         else makeNurbcurve(nu, data, 3);
1493                                 }
1494                                 else {
1495                                         if(draw==0 && ob==G.obedit) ;
1496                                         else {
1497                                                 if(draw==0) len= nu->pntsu*nu->pntsv;
1498                                                 else len= nu->resolu*nu->resolv;
1499                                                 
1500                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1501                                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1502                                                 BLI_addtail(dispbase, dl);
1503         
1504                                                 dl->col= nu->mat_nr;
1505                                                 dl->rt= nu->flag;
1506                                                 
1507                                                 data= dl->verts;
1508                                                 dl->type= DL_SURF;
1509
1510                                                 if(draw==0) {
1511                                                         dl->parts= nu->pntsv;
1512                                                         dl->nr= nu->pntsu;
1513                                                         if(nu->flagu & CU_CYCLIC) dl->flag|= DL_CYCL_U;
1514                                                         if(nu->flagv & CU_CYCLIC) dl->flag|= DL_CYCL_V;
1515
1516                                                         bp= nu->bp;
1517                                                         while(len--) {
1518                                                                 VECCOPY(data, bp->vec);
1519                                                                 bp++;
1520                                                                 data+= 3;
1521                                                         }
1522                                                 }
1523                                                 else {
1524                                                         dl->parts= nu->resolu;  /* in reverse, because makeNurbfaces works that way */
1525                                                         dl->nr= nu->resolv;
1526                                                         if(nu->flagv & CU_CYCLIC) dl->flag|= DL_CYCL_U; /* reverse too! */
1527                                                         if(nu->flagu & CU_CYCLIC) dl->flag|= DL_CYCL_V;
1528
1529                                                         makeNurbfaces(nu, data, 0);
1530                                                 }
1531                                         }
1532                                 }
1533                         }
1534                         nu= nu->next;
1535                 }
1536                 
1537                 tex_space_curve(cu);
1538
1539                 if(ob!=G.obedit) curve_modifier(ob, 'e');
1540                 if(ob!=G.obedit) object_deform(ob);
1541         }
1542         else if ELEM(ob->type, OB_CURVE, OB_FONT) {
1543                 int obedit= (G.obedit && G.obedit->data==ob->data);
1544                 
1545                 draw= ob->dt;
1546                 cu= ob->data;
1547                 dispbase= &(cu->disp);
1548                 freedisplist(dispbase);
1549                 
1550                 BLI_freelistN(&(cu->bev));
1551                 
1552                 if(cu->path) free_path(cu->path);
1553                 cu->path= NULL;
1554                 
1555                 if(ob->type==OB_FONT) text_to_curve(ob, 0);
1556                 
1557                 if(!obedit) curve_modifier(ob, 's');
1558                 
1559                 if(obedit) {
1560                         if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase);
1561                         else curve_to_displist(&cu->nurb, dispbase);
1562                         makeBevelList(ob);  // always needed, so calc_curvepath() can work
1563                 }
1564                 else if(cu->ext1==0.0 && cu->ext2==0.0 && cu->bevobj==NULL && cu->width==1.0) {
1565                         curve_to_displist(&cu->nurb, dispbase);
1566                         makeBevelList(ob); // always needed, so calc_curvepath() can work
1567                 }
1568                 else {
1569                         
1570                         makeBevelList(ob);
1571
1572                         dlbev.first= dlbev.last= NULL;
1573                         if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) {
1574                                 if(ob->dt!=0) makebevelcurve(ob, &dlbev);
1575                         }
1576
1577                         /* work with bevellist */
1578                         widfac= cu->width-1.0;
1579                         bl= cu->bev.first;
1580                         nu= cu->nurb.first;
1581                         while(bl) {
1582                                 if(dlbev.first==0) {
1583                                         dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
1584                                         dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
1585                                         BLI_addtail(dispbase, dl);
1586                                         
1587                                         if(bl->poly!= -1) dl->type= DL_POLY;
1588                                         else dl->type= DL_SEGM;
1589                                         
1590                                         if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE);
1591                                         
1592                                         dl->parts= 1;
1593                                         dl->nr= bl->nr;
1594                                         dl->col= nu->mat_nr;
1595
1596                                         a= dl->nr;
1597                                         bevp= (BevPoint *)(bl+1);
1598                                         data= dl->verts;
1599                                         while(a--) {
1600                                                 data[0]= bevp->x+widfac*bevp->sina;
1601                                                 data[1]= bevp->y+widfac*bevp->cosa;
1602                                                 data[2]= bevp->z;
1603                                                 bevp++;
1604                                                 data+=3;
1605                                         }
1606                                 }
1607                                 else {
1608                                         /* for each part of the bevel use a separate displblock */
1609                                         dlb= dlbev.first;
1610                                         while(dlb) {
1611                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
1612                                                 dl->verts= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
1613                                                 BLI_addtail(dispbase, dl);
1614                                                 /* dl->type= dlb->type; */
1615
1616                                                 dl->type= DL_SURF;
1617                                                 
1618                                                 dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE);
1619                                                 if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U;
1620                                                 if(bl->poly>=0) dl->flag |= DL_CYCL_V;
1621                                                 
1622                                                 dl->parts= bl->nr;
1623                                                 dl->nr= dlb->nr;
1624                                                 dl->col= nu->mat_nr;
1625                                                 dl->rt= nu->flag;
1626
1627                                                 data= dl->verts;
1628                                                 bevp= (BevPoint *)(bl+1);
1629                                                 for(a=0; a<bl->nr; a++) {       /* for each point of poly make a bevel piece */
1630                                                         float fac;
1631                                                         
1632                                                         /* returns 1.0 if no taper, of course */
1633                                                         fac= calc_taper(cu->taperobj, a, bl->nr);
1634                                                         
1635                                                         /* rotate bevel piece and write in data */
1636                                                         fp1= dlb->verts;
1637                                                         b= dlb->nr;
1638
1639                                                         while(b--) {
1640                                                                 
1641                                                                 if(cu->flag & CU_3D) {
1642                                                                 
1643                                                                         vec[0]= fp1[1]+widfac;
1644                                                                         vec[1]= fp1[2];
1645                                                                         vec[2]= 0.0;
1646                                                                         
1647                                                                         Mat3MulVecfl(bevp->mat, vec);
1648                                                                         
1649                                                                         data[0]= bevp->x+ fac*vec[0];
1650                                                                         data[1]= bevp->y+ fac*vec[1];
1651                                                                         data[2]= bevp->z+ fac*vec[2];
1652                                                                 }
1653                                                                 else {
1654                                                                         data[0]= bevp->x+ fac*(fp1[1]+widfac)*bevp->sina;
1655                                                                         data[1]= bevp->y+ fac*(fp1[1]+widfac)*bevp->cosa;
1656                                                                         data[2]= bevp->z+ fac*fp1[2];
1657                                                                 }
1658
1659                                                                 data+=3;
1660                                                                 fp1+=3;
1661                                                         }
1662
1663                                                         bevp++;
1664                                                 }
1665
1666                                                 dlb= dlb->next;
1667                                         }
1668                                 }
1669
1670                                 bl= bl->next;
1671                                 nu= nu->next;
1672                         }
1673
1674                         if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) {
1675                                 freedisplist(&dlbev);
1676                         }
1677                 }
1678                 if(cu->flag & CU_PATH) calc_curvepath(ob);
1679
1680                 if(!obedit) {
1681                         curve_modifier(ob, 'e');
1682                         object_deform(ob);
1683                 }
1684                 tex_space_curve(cu);
1685
1686         }
1687         
1688         boundbox_displist(ob);
1689 }
1690
1691 /*******************************/
1692 /*****       OUTLINE       *****/
1693 /*******************************/
1694
1695 typedef struct Sample{
1696         short x, y;
1697 } Sample;
1698
1699 typedef struct Segment{
1700         /* coordinates */
1701         struct Segment * next, * prev;
1702         float co[2];
1703 } Segment;
1704
1705
1706
1707 static int dflt_in_out(struct ImBuf * ibuf, int x, int y)
1708 {
1709         unsigned char * rect;
1710         
1711         if (ibuf == 0) return (0);
1712         if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y || ibuf->rect == 0) return (-1);
1713         
1714         rect = (unsigned char *) (ibuf->rect + (y * ibuf->x) + x);
1715         if (rect[0] > 0x81) return (1);
1716         return(0);
1717 }
1718
1719
1720 static Sample * outline(struct ImBuf * ibuf,
1721                                  int (*in_or_out)(struct ImBuf *, int, int))
1722 {
1723         static int dirs[8][2] = {
1724                 {-1,  0}, {-1,  1},     {0,  1}, {1,  1}, 
1725                 {1,  0}, {1, -1}, {0, -1}, {-1, -1}
1726         };
1727         
1728         int dir, x, y, in, i;
1729         int count, sampcount;
1730         int startx = 0, starty = 0;
1731         Sample * samp, * oldsamp;
1732         
1733         /* input:
1734          * 1 - image 
1735          * 2 - pointer to function that defines which pixel 'in' or 'out' is
1736          */
1737         
1738         if (ibuf == 0) return (0);
1739         if (ibuf->rect == 0) return (0);
1740         
1741         if (in_or_out == 0) in_or_out = dflt_in_out;
1742         in = in_or_out(ibuf, 0, 0);
1743         
1744         /* search for first transition, and continue from there */      
1745         for (y = 0; y < ibuf->y; y++) {
1746                 for (x = 0; x < ibuf->x; x++) {
1747                         if (in_or_out(ibuf, x, y) != in) {
1748                                 /* found first 'other' point !! */
1749                                 
1750                                 if (x != startx) dir = 0;
1751                                 else dir = 6;
1752                                 
1753                                 startx = x; starty = y;
1754                                 count = 1;
1755                                 sampcount = 2000;
1756                                 samp = MEM_mallocN(sampcount * sizeof(Sample), "wire_samples");
1757                                 
1758                                 do{
1759                                         samp[count].x = x; samp[count].y = y;
1760                                         count++;
1761                                         
1762                                         if (count >= sampcount) {
1763                                                 oldsamp = samp;
1764                                                 samp = MEM_mallocN(2 * sampcount * sizeof(Sample), "wire_samples");
1765                                                 memcpy(samp, oldsamp, sampcount * sizeof(Sample));
1766                                                 sampcount *= 2;
1767                                                 MEM_freeN(oldsamp);
1768                                         }
1769                                         
1770                                         i = 0;
1771                                         while(in_or_out(ibuf, x + dirs[dir][0], y + dirs[dir][1]) == in) {
1772                                                 dir = (dir + 1) & 0x7;
1773                                                 if (i++ == 9) break;
1774                                         }
1775                                         
1776                                         if (i >= 8) {
1777                                                 /* this has to be a loose point */
1778                                                 break;
1779                                         }
1780                                         
1781                                         x += dirs[dir][0];
1782                                         y += dirs[dir][1];
1783                                         dir = (dir - 3) & 0x7;
1784                                 } while(x != startx || y != starty);
1785                                 
1786                                 if (i >= 8) {
1787                                         /* patch for loose points */
1788                                         MEM_freeN(samp);
1789                                 } else {
1790                                         count = count - 1;
1791                                         samp[0].x = count >> 16;
1792                                         samp[0].y = count;
1793                                         return(samp);
1794                                 }
1795                         }
1796                 }
1797         }
1798         /* printf("no transition \n"); */
1799         return(0);
1800 }
1801
1802
1803
1804 /*******************************/
1805 /*****      WIREFRAME      *****/
1806 /*******************************/
1807
1808
1809 static float DistToLine2D(short *v1, short *v2, short *v3)   /* using Hesse formula :NO LINE PIECE! */
1810 {
1811         float a[2],deler;
1812
1813         a[0] = v2[1]-v3[1];
1814         a[1] = v3[0]-v2[0];
1815         deler = sqrt(a[0]*a[0]+a[1]*a[1]);
1816         if(deler == 0.0) return 0;
1817
1818         return fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler;
1819
1820 }
1821
1822 static float ComputeMaxShpError(Sample *samp, int first, int last, int *splitPoint)
1823     /* samp:  Array of digitized points */
1824     /* first, last:  Indices defining region    */
1825     /* splitpoint:  Point of maximum error      */
1826 {
1827     int         i;
1828     float       maxDist;                                /*  Maximum error               */
1829     float       dist;                                   /*  Current error               */
1830  
1831     *splitPoint = (last - first + 1) / 2;
1832     maxDist = 0.0;
1833         
1834     for (i = first + 1; i < last; i++) {                                
1835                 dist = DistToLine2D((short *)(samp+i), (short *)(samp+first), (short *)(samp+last));
1836
1837                 if (dist >= maxDist) {
1838                 maxDist = dist;
1839                 *splitPoint = i;
1840                 }
1841     }
1842
1843     return (maxDist);
1844 }
1845
1846
1847 static void FitPoly(Sample *samp, int first, int last, float shperr, ListBase *seglist)
1848     /* Samp: Array of digitized points */
1849     /* first,last: Indices of first and last pts in region */
1850     /* spherr: User-defined error squared          */
1851 {
1852     Segment     * seg;                          /* Control points segment*/
1853     float       maxError;                       /*  Maximum fitting error        */
1854     int         splitPoint;                     /*  Point to split point set at  */
1855     int         nPts;                           /*  Number of points in subset  */
1856         
1857     nPts = last - first + 1;
1858
1859     /*  Use heuristic if region only has two points in it */
1860
1861         seg = MEM_mallocN(sizeof(Segment), "wure_segment");
1862
1863         seg->co[0] = samp[first].x;
1864         seg->co[1] = samp[first].y;
1865         
1866     if (nPts == 2) {
1867                 BLI_addtail(seglist, seg);
1868                 return;
1869     }
1870
1871         maxError = ComputeMaxShpError(samp, first, last, &splitPoint);
1872         if (maxError < shperr) {
1873                 BLI_addtail(seglist, seg);
1874                 return;
1875         }
1876         
1877     /* Fitting failed -- split at max error point and fit recursively */
1878         
1879     FitPoly(samp, first, splitPoint, shperr, seglist);
1880     FitPoly(samp, splitPoint, last, shperr, seglist);
1881         
1882         MEM_freeN(seg);
1883 }
1884
1885
1886 static void ibuf2wire(ListBase * wireframe, struct ImBuf * ibuf)
1887 {
1888         int count;
1889         Sample * samp;
1890         
1891         /* first make a list of samples */
1892         
1893         samp = outline(ibuf, 0);
1894         if (samp == 0) return;
1895         
1896         count = (samp[0].x << 16) + samp[0].y;
1897         if (count) FitPoly(samp, 1, count, 1.0, wireframe); /* was 3.0. Frank */
1898
1899         MEM_freeN(samp);
1900 }
1901
1902
1903
1904 void imagestodisplist(void)
1905 {
1906         Base *base;
1907         Object *ob;
1908         Material *ma;
1909         Tex *tex;
1910         Mesh *me;
1911         ListBase _wireframe, *wireframe;
1912         DispList *dl;
1913         Segment *seg;
1914         float *data, xfac, yfac, xsi, ysi, vec[3], dum;
1915         int tot;
1916         
1917         _wireframe.first= 0;
1918         _wireframe.last= 0;
1919         wireframe = &_wireframe;
1920         
1921         init_render_textures();
1922         
1923         base= G.scene->base.first;
1924         while(base) {
1925                 if(( (base->flag & SELECT) && (base->lay & G.scene->lay) ) ) {
1926                         if( base->object->type==OB_MESH) {
1927                                 ob= base->object;
1928                                 me= ob->data;
1929                                 
1930                                 ma= give_current_material(ob, 1);
1931         
1932                                 if(ma && ma->mtex[0] && ma->mtex[0]->tex) {
1933                                         tex= ma->mtex[0]->tex;
1934                                         
1935                                         /* this takes care of correct loading of new imbufs */
1936                                         externtex(ma->mtex[0], vec, &dum, &dum, &dum, &dum, &dum);
1937                                         
1938                                         if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) {                                
1939                                                 
1940                                                 ob->dtx |= OB_DRAWIMAGE;
1941                                                 
1942                                                 ibuf2wire(wireframe, tex->ima->ibuf);
1943
1944                                                 tot= 0;
1945                                                 seg = wireframe->first;
1946                                                 while (seg) {
1947                                                         tot++;
1948                                                         seg = seg->next;
1949                                                 }
1950         
1951                                                 if(tot) {
1952                                                         float size[3];
1953
1954                                                         freedisplist(&(ob->disp));
1955
1956                                                         dl= MEM_callocN(sizeof(DispList), "makeDispListimage");
1957                                                         dl->verts= MEM_callocN(3*sizeof(float)*tot, "dlverts");
1958                                                         
1959                                                         BLI_addtail(&(ob->disp), dl);
1960                                                         dl->type= DL_POLY;
1961                                                         dl->parts= 1;
1962                                                         dl->nr= tot;
1963                                                         
1964                                                         xsi= 0.5*(tex->ima->ibuf->x);
1965                                                         ysi= 0.5*(tex->ima->ibuf->y);
1966
1967                                                         mesh_get_texspace(me, NULL, NULL, size);
1968                                                         xfac= size[0]/xsi;
1969                                                         yfac= size[1]/ysi;
1970                                                                                                 
1971                                                         data= dl->verts;
1972                                                         seg = wireframe->first;
1973                                                         while (seg) {
1974                                                                 data[0]= xfac*(seg->co[0]-xsi);
1975                                                                 data[1]= yfac*(seg->co[1]-ysi);
1976                                                                 data+= 3;
1977                                                                 seg = seg->next;
1978                                                         }
1979                                                         BLI_freelistN(wireframe);
1980                                                 }
1981                                         }
1982                                 }
1983                         }
1984                 }
1985                 base= base->next;
1986         }
1987         
1988         end_render_textures();
1989         
1990         allqueue(REDRAWVIEW3D, 0);
1991 }
1992
1993 static void boundbox_displist(Object *ob)
1994 {
1995         BoundBox *bb=0;
1996         float min[3], max[3];
1997         DispList *dl;
1998         float *vert;
1999         int a, tot=0;
2000         
2001         INIT_MINMAX(min, max);
2002
2003         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
2004                 Curve *cu= ob->data;
2005
2006                 if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");        
2007                 bb= cu->bb;
2008                 
2009                 dl= cu->disp.first;
2010
2011                 while (dl) {
2012                         if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr;
2013                         else tot= dl->nr*dl->parts;
2014                         
2015                         vert= dl->verts;
2016                         for(a=0; a<tot; a++, vert+=3) {
2017                                 DO_MINMAX(vert, min, max);
2018                         }
2019
2020                         dl= dl->next;
2021                 }
2022         }
2023         
2024         if(bb) {
2025                 boundbox_set_from_min_max(bb, min, max);
2026         }
2027 }
2028