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