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