-= Cloth cleanup =-
[blender.git] / source / blender / src / drawobject.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <string.h>
34 #include <math.h>
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BMF_Api.h"
43
44 #include "IMB_imbuf.h"
45
46
47 #include "MTC_matrixops.h"
48
49 #include "DNA_armature_types.h"
50 #include "DNA_camera_types.h"
51 #include "DNA_curve_types.h"
52 #include "DNA_constraint_types.h" // for drawing constraint
53 #include "DNA_effect_types.h"
54 #include "DNA_ipo_types.h"
55 #include "DNA_lamp_types.h"
56 #include "DNA_lattice_types.h"
57 #include "DNA_material_types.h"
58 #include "DNA_mesh_types.h"
59 #include "DNA_meshdata_types.h"
60 #include "DNA_meta_types.h"
61 #include "DNA_modifier_types.h"
62 #include "DNA_object_types.h"
63 #include "DNA_object_force.h"
64 #include "DNA_particle_types.h"
65 #include "DNA_space_types.h"
66 #include "DNA_scene_types.h"
67 #include "DNA_screen_types.h"
68 #include "DNA_userdef_types.h"
69 #include "DNA_view3d_types.h"
70 #include "DNA_world_types.h"
71 // FSPARTICLE
72 #include "DNA_object_fluidsim.h"
73
74 #include "BLI_blenlib.h"
75 #include "BLI_arithb.h"
76 #include "BLI_editVert.h"
77 #include "BLI_edgehash.h"
78 #include "BLI_rand.h"
79
80 #include "BKE_utildefines.h"
81 #include "BKE_cloth.h"
82 #include "BKE_curve.h"
83 #include "BKE_constraint.h" // for the get_constraint_target function
84 #include "BKE_DerivedMesh.h"
85 #include "BKE_displist.h"
86 #include "BKE_effect.h"
87 #include "BKE_font.h"
88 #include "BKE_global.h"
89 #include "BKE_image.h"
90 #include "BKE_ipo.h"
91 #include "BKE_key.h"
92 #include "BKE_lattice.h"
93 #include "BKE_mesh.h"
94 #include "BKE_material.h"
95 #include "BKE_mball.h"
96 #include "BKE_modifier.h"
97 #include "BKE_object.h"
98 #include "BKE_anim.h"                   //for the where_on_path function
99 #include "BKE_particle.h"
100 #include "BKE_utildefines.h"
101 #ifdef WITH_VERSE
102 #include "BKE_verse.h"
103 #endif
104
105 #include "BIF_editarmature.h"
106 #include "BIF_editdeform.h"
107 #include "BIF_editmesh.h"
108 #include "BIF_editparticle.h"
109 #include "BIF_glutil.h"
110 #include "BIF_gl.h"
111 #include "BIF_glutil.h"
112 #include "BIF_mywindow.h"
113 #include "BIF_resources.h"
114 #include "BIF_retopo.h"
115 #include "BIF_screen.h"
116 #include "BIF_space.h"
117 #include "BIF_toolbox.h"
118
119 #include "BDR_drawmesh.h"
120 #include "BDR_drawobject.h"
121 #include "BDR_editobject.h"
122 #include "BDR_sculptmode.h"
123 #include "BDR_vpaint.h"
124
125 #include "BSE_drawview.h"
126 #include "BSE_node.h"
127 #include "BSE_trans_types.h"
128 #include "BSE_view.h"
129
130 #include "blendef.h"
131 #include "mydevice.h"
132 #include "nla.h"
133
134 #include "BKE_deform.h"
135
136 /* pretty stupid */
137 /*  extern Lattice *editLatt; already in BKE_lattice.h  */
138 /* editcurve.c */
139 extern ListBase editNurb;
140 /* editmball.c */
141 extern ListBase editelems;
142
143 static void draw_bounding_volume(Object *ob);
144
145 static void drawcube_size(float size);
146 static void drawcircle_size(float size);
147 static void draw_empty_sphere(float size);
148 static void draw_empty_cone(float size);
149
150 /* ************* Setting OpenGL Material ************ */
151
152 // Materials start counting at # one....
153 #define MAXMATBUF (MAXMAT + 1)
154 static float matbuf[MAXMATBUF][2][4];
155 static int totmat_gl= 0;
156
157 int set_gl_material(int nr)
158 {
159         static int last_gl_matnr= -1;
160         static int last_ret_val= 1;
161         
162         /* prevent index to use un-initialized array items */
163         if(nr>totmat_gl) nr= totmat_gl;
164         
165         if(nr<0) {
166                 last_gl_matnr= -1;
167                 last_ret_val= 1;
168         }
169         else if(nr<MAXMATBUF && nr!=last_gl_matnr) {
170                 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matbuf[nr][0]);
171                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matbuf[nr][1]);
172                 last_gl_matnr = nr;
173                 last_ret_val= matbuf[nr][0][3]!=0.0;
174                 
175                 /* matbuf alpha: 0.0 = skip draw, 1.0 = no blending, else blend */
176                 if(matbuf[nr][0][3]!= 0.0 && matbuf[nr][0][3]!= 1.0) {
177                         glEnable(GL_BLEND);
178                 }
179                 else
180                         glDisable(GL_BLEND);
181                         
182         }
183         
184         return last_ret_val;
185 }
186
187 /* returns 1: when there's alpha needed to be drawn in a 2nd pass */
188 int init_gl_materials(Object *ob, int check_alpha)
189 {
190         extern Material defmaterial;    // render module abuse...
191         Material *ma;
192         int a, has_alpha= 0;
193         
194         if(ob->totcol==0) {
195                 matbuf[0][0][0]= defmaterial.r;
196                 matbuf[0][0][1]= defmaterial.g;
197                 matbuf[0][0][2]= defmaterial.b;
198                 matbuf[0][0][3]= 1.0;
199
200                 matbuf[0][1][0]= defmaterial.specr;
201                 matbuf[0][1][1]= defmaterial.specg;
202                 matbuf[0][1][2]= defmaterial.specb;
203                 matbuf[0][1][3]= 1.0;
204                 
205                 /* do material 1 too, for displists! */
206                 QUATCOPY(matbuf[1][0], matbuf[0][0]);
207                 QUATCOPY(matbuf[1][1], matbuf[0][1]);
208         }
209         
210         for(a=1; a<=ob->totcol; a++) {
211                 ma= give_current_material(ob, a);
212                 ma= editnode_get_active_material(ma);
213                 if(ma==NULL) ma= &defmaterial;
214
215                 if(a<MAXMATBUF) {
216                         if (ma->mode & MA_SHLESS) {
217                                 matbuf[a][0][0]= 2*ma->r;
218                                 matbuf[a][0][1]= 2*ma->g;
219                                 matbuf[a][0][2]= 2*ma->b;
220                         } else {
221                                 matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r;
222                                 matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g;
223                                 matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b;
224                         }
225
226                         /* draw transparent, not in pick-select, nor editmode */
227                         if(check_alpha && !(G.f & G_PICKSEL) && (ob->dtx & OB_DRAWTRANSP) && !(G.obedit && G.obedit->data==ob->data)) {
228                                 if(G.vd->transp) {      // drawing the transparent pass
229                                         if(ma->alpha==1.0) matbuf[a][0][3]= 0.0;        // means skip solid
230                                         else matbuf[a][0][3]= ma->alpha;
231                                 }
232                                 else {  // normal pass
233                                         if(ma->alpha==1.0) matbuf[a][0][3]= 1.0;
234                                         else {
235                                                 matbuf[a][0][3]= 0.0;   // means skip transparent
236                                                 has_alpha= 1;                   // return value, to indicate adding to after-draw queue
237                                         }
238                                 }
239                         }
240                         else
241                                 matbuf[a][0][3]= 1.0;
242                         
243                         if (!(ma->mode & MA_SHLESS)) {
244                                 matbuf[a][1][0]= ma->spec*ma->specr;
245                                 matbuf[a][1][1]= ma->spec*ma->specg;
246                                 matbuf[a][1][2]= ma->spec*ma->specb;
247                                 matbuf[a][1][3]= 1.0;
248                         }
249                 }
250         }
251
252         totmat_gl= ob->totcol;
253         set_gl_material(-1);            // signal for static variable
254         return has_alpha;
255 }
256
257
258         /***/
259 static unsigned int colortab[24]=
260         {0x0,           0xFF88FF, 0xFFBBFF, 
261          0x403000,      0xFFFF88, 0xFFFFBB, 
262          0x104040,      0x66CCCC, 0x77CCCC, 
263          0x104010,      0x55BB55, 0x66FF66, 
264          0xFFFFFF
265 };
266
267
268 static float cube[8][3] = {
269         {-1.0, -1.0, -1.0},
270         {-1.0, -1.0,  1.0},
271         {-1.0,  1.0,  1.0},
272         {-1.0,  1.0, -1.0},
273         { 1.0, -1.0, -1.0},
274         { 1.0, -1.0,  1.0},
275         { 1.0,  1.0,  1.0},
276         { 1.0,  1.0, -1.0},
277 };
278
279 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
280 /* 32 values of sin function (still same result!) */
281 static float sinval[32] = {
282         0.00000000,
283         0.20129852,
284         0.39435585,
285         0.57126821,
286         0.72479278,
287         0.84864425,
288         0.93775213,
289         0.98846832,
290         0.99871650,
291         0.96807711,
292         0.89780453,
293         0.79077573,
294         0.65137248,
295         0.48530196,
296         0.29936312,
297         0.10116832,
298         -0.10116832,
299         -0.29936312,
300         -0.48530196,
301         -0.65137248,
302         -0.79077573,
303         -0.89780453,
304         -0.96807711,
305         -0.99871650,
306         -0.98846832,
307         -0.93775213,
308         -0.84864425,
309         -0.72479278,
310         -0.57126821,
311         -0.39435585,
312         -0.20129852,
313         0.00000000
314 };
315
316 /* 32 values of cos function (still same result!) */
317 static float cosval[32] ={
318         1.00000000,
319         0.97952994,
320         0.91895781,
321         0.82076344,
322         0.68896691,
323         0.52896401,
324         0.34730525,
325         0.15142777,
326         -0.05064916,
327         -0.25065253,
328         -0.44039415,
329         -0.61210598,
330         -0.75875812,
331         -0.87434661,
332         -0.95413925,
333         -0.99486932,
334         -0.99486932,
335         -0.95413925,
336         -0.87434661,
337         -0.75875812,
338         -0.61210598,
339         -0.44039415,
340         -0.25065253,
341         -0.05064916,
342         0.15142777,
343         0.34730525,
344         0.52896401,
345         0.68896691,
346         0.82076344,
347         0.91895781,
348         0.97952994,
349         1.00000000
350 };
351
352 /* flag is same as for draw_object */
353 void drawaxes(float size, int flag, char drawtype)
354 {
355         int axis;
356         float v1[3]= {0.0, 0.0, 0.0};
357         float v2[3]= {0.0, 0.0, 0.0};
358         float v3[3]= {0.0, 0.0, 0.0};
359         
360         switch(drawtype) {
361         
362         case OB_PLAINAXES:
363                 for (axis=0; axis<3; axis++) {
364                         float v1[3]= {0.0, 0.0, 0.0};
365                         float v2[3]= {0.0, 0.0, 0.0};
366                         
367                         glBegin(GL_LINES);
368
369                         v1[axis]= size;
370                         v2[axis]= -size;
371                         glVertex3fv(v1);
372                         glVertex3fv(v2);
373                         
374                         glEnd();
375                 }
376                 break;
377         case OB_SINGLE_ARROW:
378         
379                 glBegin(GL_LINES);
380                 /* in positive z direction only */
381                 v1[2]= size;
382                 glVertex3fv(v1);
383                 glVertex3fv(v2);
384                 glEnd();
385                 
386                 /* square pyramid */
387                 glBegin(GL_TRIANGLES);
388                 
389                 v2[0]= size*0.035; v2[1] = size*0.035;
390                 v3[0]= size*-0.035; v3[1] = size*0.035;
391                 v2[2]= v3[2]= size*0.75;
392                 
393                 for (axis=0; axis<4; axis++) {
394                         if (axis % 2 == 1) {
395                                 v2[0] *= -1;
396                                 v3[1] *= -1;
397                         } else {
398                                 v2[1] *= -1;
399                                 v3[0] *= -1;
400                         }
401                         
402                         glVertex3fv(v1);
403                         glVertex3fv(v2);
404                         glVertex3fv(v3);
405                         
406                 }
407                 glEnd();
408                 
409                 break;
410         case OB_CUBE:
411                 drawcube_size(size);
412                 break;
413                 
414         case OB_CIRCLE:
415                 drawcircle_size(size);
416                 break;
417         
418         case OB_EMPTY_SPHERE:
419                  draw_empty_sphere(size);
420              break;
421
422         case OB_EMPTY_CONE:
423                  draw_empty_cone(size);
424              break;
425
426         case OB_ARROWS:
427         default:
428                 for (axis=0; axis<3; axis++) {
429                         float v1[3]= {0.0, 0.0, 0.0};
430                         float v2[3]= {0.0, 0.0, 0.0};
431                         int arrow_axis= (axis==0)?1:0;
432                         
433                         glBegin(GL_LINES);
434
435                         v2[axis]= size;
436                         glVertex3fv(v1);
437                         glVertex3fv(v2);
438                                 
439                         v1[axis]= size*0.8;
440                         v1[arrow_axis]= -size*0.125;
441                         glVertex3fv(v1);
442                         glVertex3fv(v2);
443                                 
444                         v1[arrow_axis]= size*0.125;
445                         glVertex3fv(v1);
446                         glVertex3fv(v2);
447
448                         glEnd();
449                                 
450                         v2[axis]+= size*0.125;
451                         glRasterPos3fv(v2);
452                         
453                         // patch for 3d cards crashing on glSelect for text drawing (IBM)
454                         if((flag & DRAW_PICKING) == 0) {
455                                 if (axis==0)
456                                         BMF_DrawString(G.font, "x");
457                                 else if (axis==1)
458                                         BMF_DrawString(G.font, "y");
459                                 else
460                                         BMF_DrawString(G.font, "z");
461                         }
462                 }
463                 break;
464         }
465 }
466
467 /* circle for object centers, special_color is for library or ob users */
468 static void drawcentercircle(float *vec, int selstate, int special_color)
469 {
470         View3D *v3d= G.vd;
471         float size;
472         
473         size= v3d->persmat[0][3]*vec[0]+ v3d->persmat[1][3]*vec[1]+ v3d->persmat[2][3]*vec[2]+ v3d->persmat[3][3];
474         size*= v3d->pixsize*((float)U.obcenter_dia*0.5f);
475
476         /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
477         if(v3d->zbuf)  glDepthFunc(GL_ALWAYS);
478         glEnable(GL_BLEND);
479         
480         if(special_color) {
481 #ifdef WITH_VERSE
482                 if (selstate==VERSE) glColor4ub(0x00, 0xFF, 0x00, 155);
483                 else if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
484 #else
485                 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
486 #endif
487
488                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
489         }
490         else {
491                 if (selstate == ACTIVE) BIF_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
492                 else if (selstate == SELECT) BIF_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
493                 else if (selstate == DESELECT) BIF_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
494         }
495         drawcircball(GL_POLYGON, vec, size, v3d->viewinv);
496         
497         BIF_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
498         drawcircball(GL_LINE_LOOP, vec, size, v3d->viewinv);
499         
500         glDisable(GL_BLEND);
501         if(v3d->zbuf)  glDepthFunc(GL_LEQUAL);
502 }
503
504
505 void drawsolidcube(float size)
506 {
507         float n[3];
508
509         glPushMatrix();
510         glScalef(size, size, size);
511         
512         n[0]=0; n[1]=0; n[2]=0;
513         glBegin(GL_QUADS);
514                 n[0]= -1.0;
515                 glNormal3fv(n); 
516                 glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
517                 n[0]=0;
518         glEnd();
519
520         glBegin(GL_QUADS);
521                 n[1]= -1.0;
522                 glNormal3fv(n); 
523                 glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
524                 n[1]=0;
525         glEnd();
526
527         glBegin(GL_QUADS);
528                 n[0]= 1.0;
529                 glNormal3fv(n); 
530                 glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
531                 n[0]=0;
532         glEnd();
533
534         glBegin(GL_QUADS);
535                 n[1]= 1.0;
536                 glNormal3fv(n); 
537                 glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
538                 n[1]=0;
539         glEnd();
540
541         glBegin(GL_QUADS);
542                 n[2]= 1.0;
543                 glNormal3fv(n); 
544                 glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
545                 n[2]=0;
546         glEnd();
547
548         glBegin(GL_QUADS);
549                 n[2]= -1.0;
550                 glNormal3fv(n); 
551                 glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
552         glEnd();
553         
554         glPopMatrix();
555 }
556
557 static void drawcube(void)
558 {
559
560         glBegin(GL_LINE_STRIP);
561                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
562                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
563                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
564         glEnd();
565
566         glBegin(GL_LINE_STRIP);
567                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
568         glEnd();
569
570         glBegin(GL_LINE_STRIP);
571                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
572         glEnd();
573
574         glBegin(GL_LINE_STRIP);
575                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
576         glEnd();
577 }
578
579 /* draws a cube on given the scaling of the cube, assuming that 
580  * all required matrices have been set (used for drawing empties)
581  */
582 static void drawcube_size(float size)
583 {
584         glBegin(GL_LINE_STRIP);
585                 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
586                 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
587                 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
588         glEnd();
589
590         glBegin(GL_LINE_STRIP);
591                 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
592         glEnd();
593
594         glBegin(GL_LINE_STRIP);
595                 glVertex3f(-size,size,size); glVertex3f(size,size,size);
596         glEnd();
597
598         glBegin(GL_LINE_STRIP);
599                 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
600         glEnd();
601 }
602
603 /* this is an unused (old) cube-drawing function based on a given size */
604 #if 0
605 static void drawcube_size(float *size)
606 {
607
608         glPushMatrix();
609         glScalef(size[0],  size[1],  size[2]);
610         
611
612         glBegin(GL_LINE_STRIP);
613                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
614                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
615                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
616         glEnd();
617
618         glBegin(GL_LINE_STRIP);
619                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
620         glEnd();
621
622         glBegin(GL_LINE_STRIP);
623                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
624         glEnd();
625
626         glBegin(GL_LINE_STRIP);
627                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
628         glEnd();
629         
630         glPopMatrix();
631 }
632 #endif
633
634 static void drawshadbuflimits(Lamp *la, float mat[][4])
635 {
636         float sta[3], end[3], lavec[3];
637
638         lavec[0]= -mat[2][0];
639         lavec[1]= -mat[2][1];
640         lavec[2]= -mat[2][2];
641         Normalize(lavec);
642
643         sta[0]= mat[3][0]+ la->clipsta*lavec[0];
644         sta[1]= mat[3][1]+ la->clipsta*lavec[1];
645         sta[2]= mat[3][2]+ la->clipsta*lavec[2];
646
647         end[0]= mat[3][0]+ la->clipend*lavec[0];
648         end[1]= mat[3][1]+ la->clipend*lavec[1];
649         end[2]= mat[3][2]+ la->clipend*lavec[2];
650
651
652         glBegin(GL_LINE_STRIP);
653                 glVertex3fv(sta);
654                 glVertex3fv(end);
655         glEnd();
656
657         glPointSize(3.0);
658         bglBegin(GL_POINTS);
659         bglVertex3fv(sta);
660         bglVertex3fv(end);
661         bglEnd();
662         glPointSize(1.0);
663 }
664
665
666
667 static void spotvolume(float *lvec, float *vvec, float inp)
668 {
669         /* camera is at 0,0,0 */
670         float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
671
672         Normalize(lvec);
673         Normalize(vvec);                                /* is this the correct vector ? */
674
675         Crossf(temp,vvec,lvec);         /* equation for a plane through vvec en lvec */
676         Crossf(plane,lvec,temp);                /* a plane perpendicular to this, parrallel with lvec */
677
678         Normalize(plane);
679
680         /* now we've got two equations: one of a cone and one of a plane, but we have
681         three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
682
683         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
684         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
685
686         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
687         
688         q[1] = plane[1] ; 
689         q[2] = -plane[0] ; 
690         q[3] = 0 ;
691         Normalize(&q[1]);
692
693         angle = saacos(plane[2])/2.0;
694         co = cos(angle);
695         si = sqrt(1-co*co);
696
697         q[0] =  co;
698         q[1] *= si;
699         q[2] *= si;
700         q[3] =  0;
701
702         QuatToMat3(q,mat1);
703
704         /* rotate lamp vector now over acos(inp) degrees */
705
706         vvec[0] = lvec[0] ; 
707         vvec[1] = lvec[1] ; 
708         vvec[2] = lvec[2] ;
709
710         Mat3One(mat2);
711         co = inp;
712         si = sqrt(1-inp*inp);
713
714         mat2[0][0] =  co;
715         mat2[1][0] = -si;
716         mat2[0][1] =  si;
717         mat2[1][1] =  co;
718         Mat3MulMat3(mat3,mat2,mat1);
719
720         mat2[1][0] =  si;
721         mat2[0][1] = -si;
722         Mat3MulMat3(mat4,mat2,mat1);
723         Mat3Transp(mat1);
724
725         Mat3MulMat3(mat2,mat1,mat3);
726         Mat3MulVecfl(mat2,lvec);
727         Mat3MulMat3(mat2,mat1,mat4);
728         Mat3MulVecfl(mat2,vvec);
729
730         return;
731 }
732
733 static void drawlamp(Object *ob)
734 {
735         Lamp *la;
736         View3D *v3d= G.vd;
737         float vec[3], lvec[3], vvec[3], circrad, x,y,z;
738         float pixsize, lampsize;
739         float imat[4][4], curcol[4];
740         char col[4];
741         
742         la= ob->data;
743         
744         /* we first draw only the screen aligned & fixed scale stuff */
745         glPushMatrix();
746         myloadmatrix(G.vd->viewmat);
747
748         /* lets calculate the scale: */
749         pixsize= v3d->persmat[0][3]*ob->obmat[3][0]+ v3d->persmat[1][3]*ob->obmat[3][1]+ v3d->persmat[2][3]*ob->obmat[3][2]+ v3d->persmat[3][3];
750         pixsize*= v3d->pixsize;
751         lampsize= pixsize*((float)U.obcenter_dia*0.5f);
752
753         /* and view aligned matrix: */
754         Mat4CpyMat4(imat, G.vd->viewinv);
755         Normalize(imat[0]);
756         Normalize(imat[1]);
757         
758         /* for AA effects */
759         glGetFloatv(GL_CURRENT_COLOR, curcol);
760         curcol[3]= 0.6;
761         glColor4fv(curcol);
762         
763         if(ob->id.us>1) {
764                 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
765                 else glColor4ub(0x77, 0xCC, 0xCC, 155);
766         }
767         
768         /* Inner Circle */
769         VECCOPY(vec, ob->obmat[3]);
770         glEnable(GL_BLEND);
771         drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
772         glDisable(GL_BLEND);
773         drawcircball(GL_POLYGON, vec, lampsize, imat);
774         
775         /* restore */
776         if(ob->id.us>1)
777                 glColor4fv(curcol);
778                 
779         /* Outer circle */
780         circrad = 3.0f*lampsize;
781         drawcircball(GL_LINE_LOOP, vec, circrad, imat);
782         
783         setlinestyle(3);
784
785         /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
786         if (la->type!=LA_HEMI) {
787                 if ((la->mode & LA_SHAD_RAY) ||
788                         ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
789                 {
790                         drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
791                 }
792         }
793         
794         /* draw the pretty sun rays */
795         if(la->type==LA_SUN) {
796                 float v1[3], v2[3], mat[3][3];
797                 short axis;
798                 
799                 /* setup a 45 degree rotation matrix */
800                 VecRotToMat3(imat[2], M_PI/4.0f, mat);
801                 
802                 /* vectors */
803                 VECCOPY(v1, imat[0]);
804                 VecMulf(v1, circrad*1.2f);
805                 VECCOPY(v2, imat[0]);
806                 VecMulf(v2, circrad*2.5f);
807                 
808                 /* center */
809                 glTranslatef(vec[0], vec[1], vec[2]);
810                 
811                 setlinestyle(3);
812                 
813                 glBegin(GL_LINES);
814                 for (axis=0; axis<8; axis++) {
815                         glVertex3fv(v1);
816                         glVertex3fv(v2);
817                         Mat3MulVecfl(mat, v1);
818                         Mat3MulVecfl(mat, v2);
819                 }
820                 glEnd();
821                 
822                 glTranslatef(-vec[0], -vec[1], -vec[2]);
823
824         }               
825         
826         if (la->type==LA_LOCAL) {
827                 if(la->mode & LA_SPHERE) {
828                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
829                 }
830                 /* yafray: for photonlight also draw lightcone as for spot */
831         }
832         
833         glPopMatrix();  /* back in object space */
834         vec[0]= vec[1]= vec[2]= 0.0f;
835         
836         if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {  
837                 lvec[0]=lvec[1]= 0.0; 
838                 lvec[2] = 1.0;
839                 x = G.vd->persmat[0][2];
840                 y = G.vd->persmat[1][2];
841                 z = G.vd->persmat[2][2];
842                 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
843                 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
844                 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
845
846                 y = cos( M_PI*la->spotsize/360.0 );
847                 spotvolume(lvec, vvec, y);
848                 x = -la->dist;
849                 lvec[0] *=  x ; 
850                 lvec[1] *=  x ; 
851                 lvec[2] *=  x;
852                 vvec[0] *= x ; 
853                 vvec[1] *= x ; 
854                 vvec[2] *= x;
855
856                 /* draw the angled sides of the cone */
857                 glBegin(GL_LINE_STRIP);
858                         glVertex3fv(vvec);
859                         glVertex3fv(vec);
860                         glVertex3fv(lvec);
861                 glEnd();
862                 
863                 z = x*sqrt(1.0 - y*y);
864                 x *= y;
865
866                 /* draw the circle/square at the end of the cone */
867                 glTranslatef(0.0, 0.0 ,  x);
868                 if(la->mode & LA_SQUARE) {
869                         vvec[0]= fabs(z);
870                         vvec[1]= fabs(z);
871                         vvec[2]= 0.0;
872                         glBegin(GL_LINE_LOOP);
873                                 glVertex3fv(vvec);
874                                 vvec[1]= -fabs(z);
875                                 glVertex3fv(vvec);
876                                 vvec[0]= -fabs(z);
877                                 glVertex3fv(vvec);
878                                 vvec[1]= fabs(z);
879                                 glVertex3fv(vvec);
880                         glEnd();
881                 }
882                 else circ(0.0, 0.0, fabs(z));
883                 
884                 /* draw the circle/square representing spotbl */
885                 if(la->type==LA_SPOT) {
886                         float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
887                         /* make sure the line is always visible - prevent it from reaching the outer border (or 0) 
888                          * values are kinda arbitrary - just what seemed to work well */
889                         if (spotblcirc == 0) spotblcirc = 0.15;
890                         else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
891                         circ(0.0, 0.0, spotblcirc);
892                 }
893                 
894         }
895         else if ELEM(la->type, LA_HEMI, LA_SUN) {
896                 
897                 /* draw the line from the circle along the dist */
898                 glBegin(GL_LINE_STRIP);
899                         vec[2] = -circrad;
900                         glVertex3fv(vec); 
901                         vec[2]= -la->dist; 
902                         glVertex3fv(vec);
903                 glEnd();
904                 
905                 if(la->type==LA_HEMI) {
906                         /* draw the hemisphere curves */
907                         short axis, steps, dir;
908                         float outdist, zdist, mul;
909                         vec[0]=vec[1]=vec[2]= 0.0;
910                         outdist = 0.14; mul = 1.4; dir = 1;
911                         
912                         setlinestyle(4);
913                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
914                         for (axis=0; axis<4; axis++) {
915                                 float v[3]= {0.0, 0.0, 0.0};
916                                 zdist = 0.02;
917                                 
918                                 glBegin(GL_LINE_STRIP);
919                                 
920                                 for (steps=0; steps<6; steps++) {
921                                         if (axis == 0 || axis == 1) {           /* x axis up, x axis down */    
922                                                 /* make the arcs start at the edge of the energy circle */
923                                                 if (steps == 0) v[0] = dir*circrad;
924                                                 else v[0] = v[0] + dir*(steps*outdist);
925                                         } else if (axis == 2 || axis == 3) {            /* y axis up, y axis down */
926                                                 /* make the arcs start at the edge of the energy circle */
927                                                 if (steps == 0) v[1] = dir*circrad;
928                                                 else v[1] = v[1] + dir*(steps*outdist); 
929                                         }
930                 
931                                         v[2] = v[2] - steps*zdist;
932                                         
933                                         glVertex3fv(v);
934                                         
935                                         zdist = zdist * mul;
936                                 }
937                                 
938                                 glEnd();
939                                 /* flip the direction */
940                                 dir = -dir;
941                         }
942                 }
943         } else if(la->type==LA_AREA) {
944                 setlinestyle(3);
945                 if(la->area_shape==LA_AREA_SQUARE) 
946                         fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
947                 else if(la->area_shape==LA_AREA_RECT) 
948                         fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
949
950                 glBegin(GL_LINE_STRIP); 
951                 glVertex3f(0.0,0.0,-circrad);
952                 glVertex3f(0.0,0.0,-la->dist);
953                 glEnd();
954         }
955         
956         /* and back to viewspace */
957         myloadmatrix(G.vd->viewmat);
958         VECCOPY(vec, ob->obmat[3]);
959
960         setlinestyle(0);
961         
962         if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
963                 drawshadbuflimits(la, ob->obmat);
964         }
965         
966         BIF_GetThemeColor4ubv(TH_LAMP, col);
967         glColor4ub(col[0], col[1], col[2], col[3]);
968          
969         glEnable(GL_BLEND);
970         
971         if (vec[2]>0) vec[2] -= circrad;
972         else vec[2] += circrad;
973         
974         glBegin(GL_LINE_STRIP);
975                 glVertex3fv(vec); 
976                 vec[2]= 0; 
977                 glVertex3fv(vec);
978         glEnd();
979         
980         glPointSize(2.0);
981         glBegin(GL_POINTS);
982                 glVertex3fv(vec);
983         glEnd();
984         glPointSize(1.0);
985         
986         glDisable(GL_BLEND);
987         
988         /* restore for drawing extra stuff */
989         glColor3fv(curcol);
990
991 }
992
993 static void draw_limit_line(float sta, float end, unsigned int col)
994 {
995         glBegin(GL_LINES);
996         glVertex3f(0.0, 0.0, -sta);
997         glVertex3f(0.0, 0.0, -end);
998         glEnd();
999
1000         glPointSize(3.0);
1001         glBegin(GL_POINTS);
1002         cpack(col);
1003         glVertex3f(0.0, 0.0, -sta);
1004         glVertex3f(0.0, 0.0, -end);
1005         glEnd();
1006         glPointSize(1.0);
1007 }               
1008
1009
1010 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1011 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1012 static void draw_focus_cross(float dist, float size)
1013 {
1014         glBegin(GL_LINES);
1015         glVertex3f(-size, 0.f, -dist);
1016         glVertex3f(size, 0.f, -dist);
1017         glVertex3f(0.f, -size, -dist);
1018         glVertex3f(0.f, size, -dist);
1019         glEnd();
1020 }
1021
1022 /* flag similar to draw_object() */
1023 static void drawcamera(Object *ob, int flag)
1024 {
1025         /* a standing up pyramid with (0,0,0) as top */
1026         Camera *cam;
1027         World *wrld;
1028         float vec[8][4], tmat[4][4], fac, facx, facy, depth;
1029         int i;
1030
1031         cam= ob->data;
1032         
1033         glDisable(GL_LIGHTING);
1034         glDisable(GL_CULL_FACE);
1035         
1036         if(G.vd->persp>=2 && cam->type==CAM_ORTHO && ob==G.vd->camera) {
1037                 facx= 0.5*cam->ortho_scale*1.28;
1038                 facy= 0.5*cam->ortho_scale*1.024;
1039                 depth= -cam->clipsta-0.1;
1040         }
1041         else {
1042                 fac= cam->drawsize;
1043                 if(G.vd->persp>=2 && ob==G.vd->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1044                 
1045                 depth= - fac*cam->lens/16.0;
1046                 facx= fac*1.28;
1047                 facy= fac*1.024;
1048         }
1049         
1050         vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001;       /* GLBUG: for picking at iris Entry (well thats old!) */
1051         vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
1052         vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
1053         vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
1054         vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
1055
1056         glBegin(GL_LINE_LOOP);
1057                 glVertex3fv(vec[1]); 
1058                 glVertex3fv(vec[2]); 
1059                 glVertex3fv(vec[3]); 
1060                 glVertex3fv(vec[4]);
1061         glEnd();
1062         
1063
1064         if(G.vd->persp>=2 && ob==G.vd->camera) return;
1065         
1066         glBegin(GL_LINE_STRIP);
1067                 glVertex3fv(vec[2]); 
1068                 glVertex3fv(vec[0]);
1069                 glVertex3fv(vec[1]);
1070                 glVertex3fv(vec[4]);
1071                 glVertex3fv(vec[0]);
1072                 glVertex3fv(vec[3]); 
1073         glEnd();
1074
1075
1076         /* arrow on top */
1077         vec[0][2]= depth;
1078
1079         
1080         /* draw an outline arrow for inactive cameras and filled
1081          * for active cameras. We actually draw both outline+filled
1082          * for active cameras so the wire can be seen side-on */        
1083         for (i=0;i<2;i++) {
1084                 if (i==0) glBegin(GL_LINE_LOOP);
1085                 else if (i==1 && (ob == G.vd->camera)) glBegin(GL_TRIANGLES);
1086                 else break;
1087                 
1088                 vec[0][0]= -0.7*cam->drawsize;
1089                 vec[0][1]= 1.1*cam->drawsize;
1090                 glVertex3fv(vec[0]);
1091                 
1092                 vec[0][0]= 0.0; 
1093                 vec[0][1]= 1.8*cam->drawsize;
1094                 glVertex3fv(vec[0]);
1095                 
1096                 vec[0][0]= 0.7*cam->drawsize; 
1097                 vec[0][1]= 1.1*cam->drawsize;
1098                 glVertex3fv(vec[0]);
1099         
1100                 glEnd();
1101         }
1102
1103         if(flag==0) {
1104                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1105                         myloadmatrix(G.vd->viewmat);
1106                         Mat4CpyMat4(vec, ob->obmat);
1107                         Mat4Ortho(vec);
1108                         mymultmatrix(vec);
1109
1110                         MTC_Mat4SwapMat4(G.vd->persmat, tmat);
1111                         mygetsingmatrix(G.vd->persmat);
1112
1113                         if(cam->flag & CAM_SHOWLIMITS) {
1114                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1115                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1116                                 draw_focus_cross(dof_camera(ob), cam->drawsize);
1117                         }
1118
1119                         wrld= G.scene->world;
1120                         if(cam->flag & CAM_SHOWMIST) 
1121                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1122                                 
1123                         MTC_Mat4SwapMat4(G.vd->persmat, tmat);
1124                 }
1125         }
1126 }
1127
1128 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1129 {
1130         BPoint *bp = lt->def;
1131         float *co = dl?dl->verts:NULL;
1132         int u, v, w;
1133
1134         BIF_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1135         glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
1136         bglBegin(GL_POINTS);
1137
1138         for(w=0; w<lt->pntsw; w++) {
1139                 int wxt = (w==0 || w==lt->pntsw-1);
1140                 for(v=0; v<lt->pntsv; v++) {
1141                         int vxt = (v==0 || v==lt->pntsv-1);
1142                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1143                                 int uxt = (u==0 || u==lt->pntsu-1);
1144                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1145                                         if(bp->hide==0) {
1146                                                 if((bp->f1 & SELECT)==sel) {
1147                                                         bglVertex3fv(dl?co:bp->vec);
1148                                                 }
1149                                         }
1150                                 }
1151                         }
1152                 }
1153         }
1154         
1155         glPointSize(1.0);
1156         bglEnd();       
1157 }
1158
1159 void lattice_foreachScreenVert(void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1160 {
1161         int i, N = editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1162         DispList *dl = find_displist(&G.obedit->disp, DL_VERTS);
1163         float *co = dl?dl->verts:NULL;
1164         BPoint *bp = editLatt->def;
1165         float pmat[4][4], vmat[4][4];
1166         short s[2];
1167
1168         view3d_get_object_project_mat(curarea, G.obedit, pmat, vmat);
1169
1170         for (i=0; i<N; i++, bp++, co+=3) {
1171                 if (bp->hide==0) {
1172                         view3d_project_short_clip(curarea, dl?co:bp->vec, s, pmat, vmat);
1173                         func(userData, bp, s[0], s[1]);
1174                 }
1175         }
1176 }
1177
1178 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1179 {
1180         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1181
1182         if(use_wcol) {
1183                 float col[3];
1184                 MDeformWeight *mdw= get_defweight (lt->dvert+index, use_wcol-1);
1185                 
1186                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1187                 glColor3fv(col);
1188         }
1189         
1190         if (dl) {
1191                 glVertex3fv(&dl->verts[index*3]);
1192         } else {
1193                 glVertex3fv(lt->def[index].vec);
1194         }
1195 }
1196
1197 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1198 static void drawlattice(Object *ob)
1199 {
1200         Lattice *lt;
1201         DispList *dl;
1202         int u, v, w;
1203         int use_wcol= 0;
1204
1205         lt= (ob==G.obedit)?editLatt:ob->data;
1206         dl= find_displist(&ob->disp, DL_VERTS);
1207         if(ob==G.obedit) {
1208                 cpack(0x004000);
1209                 
1210                 if(ob->defbase.first && lt->dvert) {
1211                         use_wcol= ob->actdef;
1212                         glShadeModel(GL_SMOOTH);
1213                 }
1214         }
1215         
1216         glBegin(GL_LINES);
1217         for(w=0; w<lt->pntsw; w++) {
1218                 int wxt = (w==0 || w==lt->pntsw-1);
1219                 for(v=0; v<lt->pntsv; v++) {
1220                         int vxt = (v==0 || v==lt->pntsv-1);
1221                         for(u=0; u<lt->pntsu; u++) {
1222                                 int uxt = (u==0 || u==lt->pntsu-1);
1223
1224                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1225                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1226                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1227                                 }
1228                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1229                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1230                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1231                                 }
1232                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1233                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1234                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1235                                 }
1236                         }
1237                 }
1238         }               
1239         glEnd();
1240         
1241         /* restoration for weight colors */
1242         if(use_wcol)
1243                 glShadeModel(GL_FLAT);
1244
1245         if(ob==G.obedit) {
1246                 if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
1247                 
1248                 lattice_draw_verts(lt, dl, 0);
1249                 lattice_draw_verts(lt, dl, 1);
1250                 
1251                 if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); 
1252         }
1253 }
1254
1255 /* ***************** ******************** */
1256
1257 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1258 {
1259         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1260         EditVert *eve = EM_get_vert_for_index(index);
1261         short s[2];
1262
1263         if (eve->h==0) {
1264                 if (data->clipVerts) {
1265                         view3d_project_short_clip(curarea, co, s, data->pmat, data->vmat);
1266                 } else {
1267                         view3d_project_short_noclip(curarea, co, s, data->pmat);
1268                 }
1269
1270                 data->func(data->userData, eve, s[0], s[1], index);
1271         }
1272 }
1273 void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1274 {
1275         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
1276         DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1277
1278         data.func = func;
1279         data.userData = userData;
1280         data.clipVerts = clipVerts;
1281
1282         view3d_get_object_project_mat(curarea, G.obedit, data.pmat, data.vmat);
1283
1284         EM_init_index_arrays(1, 0, 0);
1285         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1286         EM_free_index_arrays();
1287
1288         dm->release(dm);
1289 }
1290
1291 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1292 {
1293         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1294         EditEdge *eed = EM_get_edge_for_index(index);
1295         short s[2][2];
1296
1297         if (eed->h==0) {
1298                 if (data->clipVerts==1) {
1299                         view3d_project_short_clip(curarea, v0co, s[0], data->pmat, data->vmat);
1300                         view3d_project_short_clip(curarea, v1co, s[1], data->pmat, data->vmat);
1301                 } else {
1302                         view3d_project_short_noclip(curarea, v0co, s[0], data->pmat);
1303                         view3d_project_short_noclip(curarea, v1co, s[1], data->pmat);
1304
1305                         if (data->clipVerts==2) {
1306                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<curarea->winx && s[0][1]<curarea->winy)) 
1307                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<curarea->winx && s[1][1]<curarea->winy)) 
1308                                                 return;
1309                         }
1310                 }
1311
1312                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1313         }
1314 }
1315 void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
1316 {
1317         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
1318         DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1319
1320         data.func = func;
1321         data.userData = userData;
1322         data.clipVerts = clipVerts;
1323
1324         view3d_get_object_project_mat(curarea, G.obedit, data.pmat, data.vmat);
1325
1326         EM_init_index_arrays(0, 1, 0);
1327         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1328         EM_free_index_arrays();
1329
1330         dm->release(dm);
1331 }
1332
1333 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1334 {
1335         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } *data = userData;
1336         EditFace *efa = EM_get_face_for_index(index);
1337         short s[2];
1338
1339         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1340                 view3d_project_short_clip(curarea, cent, s, data->pmat, data->vmat);
1341
1342                 data->func(data->userData, efa, s[0], s[1], index);
1343         }
1344 }
1345 void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1346 {
1347         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } data;
1348         DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1349
1350         data.func = func;
1351         data.userData = userData;
1352
1353         view3d_get_object_project_mat(curarea, G.obedit, data.pmat, data.vmat);
1354
1355         EM_init_index_arrays(0, 0, 1);
1356         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1357         EM_free_index_arrays();
1358
1359         dm->release(dm);
1360 }
1361
1362 void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1363 {
1364         float pmat[4][4], vmat[4][4];
1365         short s[2];
1366         Nurb *nu;
1367         int i;
1368
1369         view3d_get_object_project_mat(curarea, G.obedit, pmat, vmat);
1370
1371         for (nu= editNurb.first; nu; nu=nu->next) {
1372                 if((nu->type & 7)==CU_BEZIER) {
1373                         for (i=0; i<nu->pntsu; i++) {
1374                                 BezTriple *bezt = &nu->bezt[i];
1375
1376                                 if(bezt->hide==0) {
1377                                         if (G.f & G_HIDDENHANDLES) {
1378                                                 view3d_project_short_clip(curarea, bezt->vec[1], s, pmat, vmat);
1379                                                 if (s[0] != IS_CLIPPED)
1380                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1381                                         } else {
1382                                                 view3d_project_short_clip(curarea, bezt->vec[0], s, pmat, vmat);
1383                                                 if (s[0] != IS_CLIPPED)
1384                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1385                                                 view3d_project_short_clip(curarea, bezt->vec[1], s, pmat, vmat);
1386                                                 if (s[0] != IS_CLIPPED)
1387                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1388                                                 view3d_project_short_clip(curarea, bezt->vec[2], s, pmat, vmat);
1389                                                 if (s[0] != IS_CLIPPED)
1390                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1391                                         }
1392                                 }
1393                         }
1394                 }
1395                 else {
1396                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1397                                 BPoint *bp = &nu->bp[i];
1398
1399                                 if(bp->hide==0) {
1400                                         view3d_project_short_clip(curarea, bp->vec, s, pmat, vmat);
1401                                         func(userData, nu, bp, NULL, -1, s[0], s[1]);
1402                                 }
1403                         }
1404                 }
1405         }
1406 }
1407
1408 /* ************** DRAW MESH ****************** */
1409
1410 /* First section is all the "simple" draw routines, 
1411  * ones that just pass some sort of primitive to GL,
1412  * with perhaps various options to control lighting,
1413  * color, etc.
1414  *
1415  * These routines should not have user interface related
1416  * logic!!!
1417  */
1418
1419 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1420 {
1421         EditFace *efa = EM_get_face_for_index(index);
1422
1423         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1424                 glVertex3fv(cent);
1425                 glVertex3f(     cent[0] + no[0]*G.scene->editbutsize,
1426                                         cent[1] + no[1]*G.scene->editbutsize,
1427                                         cent[2] + no[2]*G.scene->editbutsize);
1428         }
1429 }
1430 static void draw_dm_face_normals(DerivedMesh *dm) {
1431         glBegin(GL_LINES);
1432         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, 0);
1433         glEnd();
1434 }
1435
1436 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1437 {
1438         EditFace *efa = EM_get_face_for_index(index);
1439         int sel = *((int*) userData);
1440
1441         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1442                 bglVertex3fv(cent);
1443         }
1444 }
1445 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1446 {
1447         bglBegin(GL_POINTS);
1448         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1449         bglEnd();
1450 }
1451
1452 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1453 {
1454         EditVert *eve = EM_get_vert_for_index(index);
1455
1456         if (eve->h==0) {
1457                 glVertex3fv(co);
1458
1459                 if (no_f) {
1460                         glVertex3f(     co[0] + no_f[0]*G.scene->editbutsize,
1461                                                 co[1] + no_f[1]*G.scene->editbutsize,
1462                                                 co[2] + no_f[2]*G.scene->editbutsize);
1463                 } else {
1464                         glVertex3f(     co[0] + no_s[0]*G.scene->editbutsize/32767.0f,
1465                                                 co[1] + no_s[1]*G.scene->editbutsize/32767.0f,
1466                                                 co[2] + no_s[2]*G.scene->editbutsize/32767.0f);
1467                 }
1468         }
1469 }
1470 static void draw_dm_vert_normals(DerivedMesh *dm) {
1471         glBegin(GL_LINES);
1472         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, NULL);
1473         glEnd();
1474 }
1475
1476         /* Draw verts with color set based on selection */
1477 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1478 {
1479         struct { int sel; EditVert *eve_act; } * data = userData;
1480         EditVert *eve = EM_get_vert_for_index(index);
1481
1482         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1483                 /* draw active larger - need to stop/start point drawing for this :/ */
1484                 if (eve==data->eve_act) {
1485                         float size = BIF_GetThemeValuef(TH_VERTEX_SIZE);
1486                         BIF_ThemeColor4(TH_EDITMESH_ACTIVE);
1487                         
1488                         bglEnd();
1489                         
1490                         glPointSize(size);
1491                         bglBegin(GL_POINTS);
1492                         bglVertex3fv(co);
1493                         bglEnd();
1494                         
1495                         BIF_ThemeColor4(TH_VERTEX_SELECT);
1496                         glPointSize(size);
1497                         bglBegin(GL_POINTS);
1498                 } else {
1499                         bglVertex3fv(co);
1500                 }
1501         }
1502 }
1503 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1504 {
1505         struct { int sel; EditVert *eve_act; } data;
1506         data.sel = sel;
1507         data.eve_act = eve_act;
1508         
1509         bglBegin(GL_POINTS);
1510         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1511         bglEnd();
1512 }
1513
1514         /* Draw edges with color set based on selection */
1515 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1516 {
1517         EditEdge *eed = EM_get_edge_for_index(index);
1518         //unsigned char **cols = userData, *col;
1519         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1520         unsigned char *col;
1521
1522         if (eed->h==0) {
1523                 if (eed==data->eed_act) {
1524                         glColor4ubv(data->actCol);
1525                 } else {
1526                         if (eed->f&SELECT) {
1527                                 col = data->selCol;
1528                         } else {
1529                                 col = data->baseCol;
1530                         }
1531                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1532                         if (col[3]==0) return 0;
1533                         
1534                         glColor4ubv(col);
1535                 }
1536                 return 1;
1537         } else {
1538                 return 0;
1539         }
1540 }
1541 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1542 {
1543         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1544         
1545         data.baseCol = baseCol;
1546         data.selCol = selCol;
1547         data.actCol = actCol;
1548         data.eed_act = eed_act;
1549         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1550 }
1551
1552         /* Draw edges */
1553 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1554 {
1555         return EM_get_edge_for_index(index)->h==0;
1556 }
1557 static void draw_dm_edges(DerivedMesh *dm) 
1558 {
1559         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1560 }
1561
1562         /* Draw edges with color interpolated based on selection */
1563 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1564 {
1565         return EM_get_edge_for_index(index)->h==0;
1566 }
1567 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1568 {
1569         EditEdge *eed = EM_get_edge_for_index(index);
1570         unsigned char **cols = userData;
1571         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1572         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1573
1574         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1575                                 col0[1] + (col1[1]-col0[1])*t,
1576                                 col0[2] + (col1[2]-col0[2])*t,
1577                                 col0[3] + (col1[3]-col0[3])*t);
1578 }
1579 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1580 {
1581         unsigned char *cols[2];
1582         cols[0] = baseCol;
1583         cols[1] = selCol;
1584         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1585 }
1586
1587         /* Draw only seam edges */
1588 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1589 {
1590         EditEdge *eed = EM_get_edge_for_index(index);
1591
1592         return (eed->h==0 && eed->seam);
1593 }
1594 static void draw_dm_edges_seams(DerivedMesh *dm)
1595 {
1596         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1597 }
1598
1599         /* Draw only sharp edges */
1600 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1601 {
1602         EditEdge *eed = EM_get_edge_for_index(index);
1603
1604         return (eed->h==0 && eed->sharp);
1605 }
1606 static void draw_dm_edges_sharp(DerivedMesh *dm)
1607 {
1608         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1609 }
1610
1611
1612         /* Draw faces with color set based on selection
1613          * return 2 for the active face so it renders with stipple enabled */
1614 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1615 {
1616         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1617         EditFace *efa = EM_get_face_for_index(index);
1618         unsigned char *col;
1619         
1620         if (efa->h==0) {
1621                 if (efa == data->efa_act) {
1622                         glColor4ubv(data->cols[2]);
1623                         return 2; /* stipple */
1624                 } else {
1625                         col = data->cols[(efa->f&SELECT)?1:0];
1626                         if (col[3]==0) return 0;
1627                         glColor4ubv(col);
1628                         return 1;
1629                 }
1630         }
1631         return 0;
1632 }
1633
1634 /* also draws the active face */
1635 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
1636 {
1637         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1638         data.cols[0] = baseCol;
1639         data.cols[1] = selCol;
1640         data.cols[2] = actCol;
1641         data.efa_act = efa_act;
1642         
1643         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
1644 }
1645
1646 static int draw_dm_creases__setDrawOptions(void *userData, int index)
1647 {
1648         EditEdge *eed = EM_get_edge_for_index(index);
1649
1650         if (eed->h==0 && eed->crease!=0.0) {
1651                 BIF_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
1652                 return 1;
1653         } else {
1654                 return 0;
1655         }
1656 }
1657 static void draw_dm_creases(DerivedMesh *dm)
1658 {
1659         glLineWidth(3.0);
1660         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1661         glLineWidth(1.0);
1662 }
1663
1664 /* Second section of routines: Combine first sets to form fancy
1665  * drawing routines (for example rendering twice to get overlays).
1666  *
1667  * Also includes routines that are basic drawing but are too
1668  * specialized to be split out (like drawing creases or measurements).
1669  */
1670
1671 /* EditMesh drawing routines*/
1672
1673 static void draw_em_fancy_verts(EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
1674 {
1675         int sel;
1676
1677         if(G.vd->zbuf) glDepthMask(0);          // disable write in zbuffer, zbuf select
1678
1679         for (sel=0; sel<2; sel++) {
1680                 char col[4], fcol[4];
1681                 int pass;
1682
1683                 BIF_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1684                 BIF_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1685
1686                 for (pass=0; pass<2; pass++) {
1687                         float size = BIF_GetThemeValuef(TH_VERTEX_SIZE);
1688                         float fsize = BIF_GetThemeValuef(TH_FACEDOT_SIZE);
1689
1690                         if (pass==0) {
1691                                 if(G.vd->zbuf && !(G.vd->flag&V3D_ZBUF_SELECT)) {
1692                                         glDisable(GL_DEPTH_TEST);
1693                                                 
1694                                         glEnable(GL_BLEND);
1695                                 } else {
1696                                         continue;
1697                                 }
1698
1699                                 size = (size>2.1?size/2.0:size);
1700                                 fsize = (fsize>2.1?fsize/2.0:fsize);
1701                                 col[3] = fcol[3] = 100;
1702                         } else {
1703                                 col[3] = fcol[3] = 255;
1704                         }
1705                                 
1706                         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1707                                 glPointSize(size);
1708                                 glColor4ubv((GLubyte *)col);
1709                                 draw_dm_verts(cageDM, sel, eve_act);
1710                         }
1711                         
1712                         if( CHECK_OB_DRAWFACEDOT(G.scene, G.vd, G.obedit->dt) ) {
1713                                 glPointSize(fsize);
1714                                 glColor4ubv((GLubyte *)fcol);
1715                                 draw_dm_face_centers(cageDM, sel);
1716                         }
1717                         
1718                         if (pass==0) {
1719                                 glDisable(GL_BLEND);
1720                                 glEnable(GL_DEPTH_TEST);
1721                         }
1722                 }
1723         }
1724
1725         if(G.vd->zbuf) glDepthMask(1);
1726         glPointSize(1.0);
1727 }
1728
1729 static void draw_em_fancy_edges(DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1730 {
1731         int pass;
1732         unsigned char wireCol[4], selCol[4], actCol[4];
1733
1734         /* since this function does transparant... */
1735         BIF_GetThemeColor3ubv(TH_EDGE_SELECT, (char *)selCol);
1736         BIF_GetThemeColor3ubv(TH_WIRE, (char *)wireCol);
1737         BIF_GetThemeColor3ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
1738         
1739         /* when sel only is used, dont render wire, only selected, this is used for
1740          * textured draw mode when the 'edges' option is disabled */
1741         if (sel_only)
1742                 wireCol[3] = 0;
1743
1744         for (pass=0; pass<2; pass++) {
1745                         /* show wires in transparant when no zbuf clipping for select */
1746                 if (pass==0) {
1747                         if (G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0) {
1748                                 glEnable(GL_BLEND);
1749                                 glDisable(GL_DEPTH_TEST);
1750                                 selCol[3] = 85;
1751                                 if (!sel_only) wireCol[3] = 85;
1752                         } else {
1753                                 continue;
1754                         }
1755                 } else {
1756                         selCol[3] = 255;
1757                         if (!sel_only) wireCol[3] = 255;
1758                 }
1759
1760                 if(G.scene->selectmode == SCE_SELECT_FACE) {
1761                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1762                 }       
1763                 else if( (G.f & G_DRAWEDGES) || (G.scene->selectmode & SCE_SELECT_EDGE) ) {     
1764                         if(cageDM->drawMappedEdgesInterp && (G.scene->selectmode & SCE_SELECT_VERTEX)) {
1765                                 glShadeModel(GL_SMOOTH);
1766                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
1767                                 glShadeModel(GL_FLAT);
1768                         } else {
1769                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1770                         }
1771                 }
1772                 else {
1773                         if (!sel_only) {
1774                                 glColor4ubv(wireCol);
1775                                 draw_dm_edges(cageDM);
1776                         }
1777                 }
1778
1779                 if (pass==0) {
1780                         glDisable(GL_BLEND);
1781                         glEnable(GL_DEPTH_TEST);
1782                 }
1783         }
1784 }       
1785
1786 #ifdef WITH_VERSE
1787 /*
1788  * draw some debug info about verse mesh (vertex indexes,
1789  * face indexes, status of )
1790  */
1791 static void draw_verse_debug(Object *ob, EditMesh *em)
1792 {
1793         struct EditVert *eve=NULL;
1794         struct EditFace *efa=NULL;
1795         float v1[3], v2[3], v3[3], v4[3], fvec[3], col[3];
1796         char val[32];
1797         
1798         if(G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0)
1799                 glDisable(GL_DEPTH_TEST);
1800
1801         if(G.vd->zbuf) bglPolygonOffset(5.0);
1802
1803         BIF_GetThemeColor3fv(TH_TEXT, col);
1804         /* make color a bit more red */
1805         if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1806         else col[0]= col[0]*0.7 + 0.3;
1807         glColor3fv(col);
1808
1809         /* draw IDs of verse vertexes */
1810         for(eve = em->verts.first; eve; eve = eve->next) {
1811                 if(eve->vvert) {
1812                         VecLerpf(fvec, ob->loc, eve->co, 1.1);
1813                         glRasterPos3f(fvec[0], fvec[1], fvec[2]);
1814
1815                         sprintf(val, "%d", ((VerseVert*)eve->vvert)->id);
1816                         BMF_DrawString(G.fonts, val);
1817                 }
1818         }
1819
1820         /* draw IDs of verse faces */
1821         for(efa = em->faces.first; efa; efa = efa->next) {
1822                 if(efa->vface) {
1823                         VECCOPY(v1, efa->v1->co);
1824                         VECCOPY(v2, efa->v2->co);
1825                         VECCOPY(v3, efa->v3->co);
1826                         if(efa->v4) {
1827                                 VECCOPY(v4, efa->v4->co);
1828                                 glRasterPos3f(0.25*(v1[0]+v2[0]+v3[0]+v4[0]),
1829                                                 0.25*(v1[1]+v2[1]+v3[1]+v4[1]),
1830                                                 0.25*(v1[2]+v2[2]+v3[2]+v4[2]));
1831                         }
1832                         else {
1833                                 glRasterPos3f((v1[0]+v2[0]+v3[0])/3,
1834                                                 (v1[1]+v2[1]+v3[1])/3,
1835                                                 (v1[2]+v2[2]+v3[2])/3);
1836                         }
1837                         
1838                         sprintf(val, "%d", ((VerseFace*)efa->vface)->id);
1839                         BMF_DrawString(G.fonts, val);
1840                         
1841                 }
1842         }
1843         
1844         if(G.vd->zbuf) {
1845                 glEnable(GL_DEPTH_TEST);
1846                 bglPolygonOffset(0.0);
1847         }
1848 }
1849 #endif
1850
1851 static void draw_em_measure_stats(Object *ob, EditMesh *em)
1852 {
1853         EditEdge *eed;
1854         EditFace *efa;
1855         float v1[3], v2[3], v3[3], v4[3];
1856         float fvec[3];
1857         char val[32]; /* Stores the measurement display text here */
1858         char conv_float[5]; /* Use a float conversion matching the grid size */
1859         float area, col[3]; /* area of the face,  color of the text to draw */
1860         
1861         /* make the precission of the pronted value proportionate to the gridsize */
1862         if ((G.vd->grid) < 0.01)
1863                 strcpy(conv_float, "%.6f");
1864         else if ((G.vd->grid) < 0.1)
1865                 strcpy(conv_float, "%.5f");
1866         else if ((G.vd->grid) < 1.0)
1867                 strcpy(conv_float, "%.4f");
1868         else if ((G.vd->grid) < 10.0)
1869                 strcpy(conv_float, "%.3f");
1870         else
1871                 strcpy(conv_float, "%.2f");
1872         
1873         
1874         if(G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0)
1875                 glDisable(GL_DEPTH_TEST);
1876
1877         if(G.vd->zbuf) bglPolygonOffset(5.0);
1878         
1879         if(G.f & G_DRAW_EDGELEN) {
1880                 BIF_GetThemeColor3fv(TH_TEXT, col);
1881                 /* make color a bit more red */
1882                 if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1883                 else col[0]= col[0]*0.7 + 0.3;
1884                 glColor3fv(col);
1885                 
1886                 for(eed= em->edges.first; eed; eed= eed->next) {
1887                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1888                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1889                                 VECCOPY(v1, eed->v1->co);
1890                                 VECCOPY(v2, eed->v2->co);
1891                                 
1892                                 glRasterPos3f( 0.5*(v1[0]+v2[0]),  0.5*(v1[1]+v2[1]),  0.5*(v1[2]+v2[2]));
1893                                 
1894                                 if(G.vd->flag & V3D_GLOBAL_STATS) {
1895                                         Mat4MulVecfl(ob->obmat, v1);
1896                                         Mat4MulVecfl(ob->obmat, v2);
1897                                 }
1898                                 
1899                                 sprintf(val, conv_float, VecLenf(v1, v2));
1900                                 BMF_DrawString( G.fonts, val);
1901                         }
1902                 }
1903         }
1904
1905         if(G.f & G_DRAW_FACEAREA) {
1906                 extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
1907                 
1908                 BIF_GetThemeColor3fv(TH_TEXT, col);
1909                 /* make color a bit more green */
1910                 if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
1911                 else col[1]= col[1]*0.7 + 0.3;
1912                 glColor3fv(col);
1913                 
1914                 for(efa= em->faces.first; efa; efa= efa->next) {
1915                         if((efa->f & SELECT) || (G.moving && faceselectedOR(efa, SELECT)) ) {
1916                                 VECCOPY(v1, efa->v1->co);
1917                                 VECCOPY(v2, efa->v2->co);
1918                                 VECCOPY(v3, efa->v3->co);
1919                                 if (efa->v4) {
1920                                         VECCOPY(v4, efa->v4->co);
1921                                 }
1922                                 if(G.vd->flag & V3D_GLOBAL_STATS) {
1923                                         Mat4MulVecfl(ob->obmat, v1);
1924                                         Mat4MulVecfl(ob->obmat, v2);
1925                                         Mat4MulVecfl(ob->obmat, v3);
1926                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1927                                 }
1928                                 
1929                                 if (efa->v4)
1930                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
1931                                 else
1932                                         area = AreaT3Dfl(v1, v2, v3);
1933
1934                                 sprintf(val, conv_float, area);
1935                                 glRasterPos3fv(efa->cent);
1936                                 BMF_DrawString( G.fonts, val);
1937                         }
1938                 }
1939         }
1940
1941         if(G.f & G_DRAW_EDGEANG) {
1942                 EditEdge *e1, *e2, *e3, *e4;
1943                 
1944                 BIF_GetThemeColor3fv(TH_TEXT, col);
1945                 /* make color a bit more blue */
1946                 if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
1947                 else col[2]= col[2]*0.7 + 0.3;
1948                 glColor3fv(col);
1949                 
1950                 for(efa= em->faces.first; efa; efa= efa->next) {
1951                         VECCOPY(v1, efa->v1->co);
1952                         VECCOPY(v2, efa->v2->co);
1953                         VECCOPY(v3, efa->v3->co);
1954                         if(efa->v4) {
1955                                 VECCOPY(v4, efa->v4->co); 
1956                         }
1957                         else {
1958                                 VECCOPY(v4, v3);
1959                         }
1960                         if(G.vd->flag & V3D_GLOBAL_STATS) {
1961                                 Mat4MulVecfl(ob->obmat, v1);
1962                                 Mat4MulVecfl(ob->obmat, v2);
1963                                 Mat4MulVecfl(ob->obmat, v3);
1964                                 if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1965                         }
1966                         
1967                         e1= efa->e1;
1968                         e2= efa->e2;
1969                         e3= efa->e3;
1970                         if(efa->e4) e4= efa->e4; else e4= e3;
1971                         
1972                         /* Calculate the angles */
1973                                 
1974                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
1975                                 /* Vec 1 */
1976                                 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
1977                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
1978                                 glRasterPos3fv(fvec);
1979                                 BMF_DrawString( G.fonts, val);
1980                         }
1981                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
1982                                 /* Vec 2 */
1983                                 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
1984                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
1985                                 glRasterPos3fv(fvec);
1986                                 BMF_DrawString( G.fonts, val);
1987                         }
1988                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
1989                                 /* Vec 3 */
1990                                 if(efa->v4) 
1991                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
1992                                 else
1993                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
1994                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
1995                                 glRasterPos3fv(fvec);
1996                                 BMF_DrawString( G.fonts, val);
1997                         }
1998                                 /* Vec 4 */
1999                         if(efa->v4) {
2000                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2001                                         sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
2002                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
2003                                         glRasterPos3fv(fvec);
2004                                         BMF_DrawString( G.fonts, val);
2005                                 }
2006                         }
2007                 }
2008         }    
2009         
2010         if(G.vd->zbuf) {
2011                 glEnable(GL_DEPTH_TEST);
2012                 bglPolygonOffset(0.0);
2013         }
2014 }
2015
2016 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2017 {
2018         EditFace *efa = EM_get_face_for_index(index);
2019
2020         if (efa->h==0) {
2021                 set_gl_material(efa->mat_nr+1);
2022                 return 1;
2023         } else {
2024                 return 0;
2025         }
2026 }
2027 static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2028 {
2029         Mesh *me = ob->data;
2030         EditFace *efa_act = NULL;
2031         EditEdge *eed_act = NULL;
2032         EditVert *eve_act = NULL;
2033         
2034         if (G.editMesh->selected.last) {
2035                 EditSelection *ese = G.editMesh->selected.last;
2036                 if ( ese->type == EDITFACE ) {
2037                         efa_act = (EditFace *)ese->data;
2038                 } else if ( ese->type == EDITEDGE ) {
2039                         eed_act = (EditEdge *)ese->data;
2040                 } else if ( ese->type == EDITVERT ) {
2041                         eve_act = (EditVert *)ese->data;
2042                 }
2043         }
2044         
2045         EM_init_index_arrays(1, 1, 1);
2046
2047         if(dt>OB_WIRE) {
2048                 if( CHECK_OB_DRAWTEXTURE(G.vd, dt) ) {
2049                         draw_mesh_textured(ob, finalDM, 0);
2050                 } else {
2051                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2052
2053                         glEnable(GL_LIGHTING);
2054                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2055
2056                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2057
2058                         glFrontFace(GL_CCW);
2059                         glDisable(GL_LIGHTING);
2060                 }
2061                         
2062                 // Setup for drawing wire over, disable zbuffer
2063                 // write to show selected edge wires better
2064                 BIF_ThemeColor(TH_WIRE);
2065
2066                 bglPolygonOffset(1.0);
2067                 glDepthMask(0);
2068         } 
2069         else {
2070                 if (cageDM!=finalDM) {
2071                         BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2072                         finalDM->drawEdges(finalDM, 1);
2073                 }
2074         }
2075         
2076         if((G.f & (G_DRAWFACES)) || FACESEL_PAINT_TEST) {       /* transp faces */
2077                 unsigned char col1[4], col2[4], col3[4];
2078                         
2079                 BIF_GetThemeColor4ubv(TH_FACE, (char *)col1);
2080                 BIF_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2081                 BIF_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2082                 
2083                 glEnable(GL_BLEND);
2084                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2085                 
2086                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2087                 if CHECK_OB_DRAWTEXTURE(G.vd, dt)
2088                         col1[3] = 0;
2089                 
2090                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2091
2092                 glDisable(GL_BLEND);
2093                 glDepthMask(1);         // restore write in zbuffer
2094         } else if (efa_act) {
2095                 /* even if draw faces is off it would be nice to draw the stipple face
2096                  * Make all other faces zero alpha except for the active
2097                  * */
2098                 unsigned char col1[4], col2[4], col3[4];
2099                 col1[3] = col2[3] = 0; /* dont draw */
2100                 BIF_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2101                 
2102                 glEnable(GL_BLEND);
2103                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2104                 
2105                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2106
2107                 glDisable(GL_BLEND);
2108                 glDepthMask(1);         // restore write in zbuffer
2109                 
2110         }
2111
2112         /* here starts all fancy draw-extra over */
2113         if((G.f & G_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(G.vd, dt)) {
2114                 /* we are drawing textures and 'G_DRAWEDGES' is disabled, dont draw any edges */
2115                 
2116                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2117                 draw_em_fancy_edges(cageDM, 1, eed_act);
2118                 
2119         } else {
2120                 if(G.f & G_DRAWSEAMS) {
2121                         BIF_ThemeColor(TH_EDGE_SEAM);
2122                         glLineWidth(2);
2123         
2124                         draw_dm_edges_seams(cageDM);
2125         
2126                         glColor3ub(0,0,0);
2127                         glLineWidth(1);
2128                 }
2129                 
2130                 if(G.f & G_DRAWSHARP) {
2131                         BIF_ThemeColor(TH_EDGE_SHARP);
2132                         glLineWidth(2);
2133         
2134                         draw_dm_edges_sharp(cageDM);
2135         
2136                         glColor3ub(0,0,0);
2137                         glLineWidth(1);
2138                 }
2139         
2140                 if(G.f & G_DRAWCREASES) {
2141                         draw_dm_creases(cageDM);
2142                 }
2143         
2144                 draw_em_fancy_edges(cageDM, 0, eed_act);
2145         }
2146         if(ob==G.obedit) {
2147                 retopo_matrix_update(G.vd);
2148
2149                 draw_em_fancy_verts(em, cageDM, eve_act);
2150
2151                 if(G.f & G_DRAWNORMALS) {
2152                         BIF_ThemeColor(TH_NORMAL);
2153                         draw_dm_face_normals(cageDM);
2154                 }
2155                 if(G.f & G_DRAW_VNORMALS) {
2156                         BIF_ThemeColor(TH_NORMAL);
2157                         draw_dm_vert_normals(cageDM);
2158                 }
2159
2160                 if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
2161                         draw_em_measure_stats(ob, em);
2162 #ifdef WITH_VERSE
2163                 if(em->vnode && (G.f & G_DRAW_VERSE_DEBUG))
2164                         draw_verse_debug(ob, em);
2165 #endif
2166         }
2167
2168         if(dt>OB_WIRE) {
2169                 glDepthMask(1);
2170                 bglPolygonOffset(0.0);
2171         }
2172
2173         EM_free_index_arrays();
2174 }
2175
2176 /* Mesh drawing routines */
2177
2178
2179
2180 #define AMBIENT 50
2181 #define DECAY 0.04f
2182 #define ALMOST_EQUAL(a, b) ((fabs(a-b)<0.00001f)?1:0)
2183
2184         // cube vertices
2185 GLfloat cv[][3] = {
2186         {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
2187  {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
2188 };
2189
2190         // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz]
2191 float edges[12][2][3] = {
2192         {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
2193  {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
2194  {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
2195  {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
2196
2197  {{1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
2198  {{-1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
2199  {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}},
2200  {{1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}},
2201
2202  {{-1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
2203  {{-1.0f, -1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
2204  {{-1.0f, -1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}},
2205  {{-1.0f, 1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}}
2206 };
2207
2208 void light_ray(unsigned char* _texture_data, int _ray_templ[4096][3], int x, int y, int z, int n, float decay)
2209 {
2210         int xx = x, yy = y, zz = z, i = 0;
2211         int offset;
2212
2213         int l = 255;
2214         float d;
2215
2216         do {
2217                 offset = ((((zz*n) + yy)*n + xx) << 2);
2218                 if (_texture_data[offset + 2] > 0)
2219                         _texture_data[offset + 2] = (unsigned char) ((_texture_data[offset + 2] + l)*0.5f);
2220                 else
2221                         _texture_data[offset + 2] = (unsigned char) l;
2222                 d = _texture_data[offset+1];
2223                 if (l > AMBIENT) {
2224                         l -= d*decay;
2225                         if (l < AMBIENT)
2226                                 l = AMBIENT;
2227                 }
2228
2229                 i++;
2230                 xx = x + _ray_templ[i][0];
2231                 yy = y + _ray_templ[i][1];
2232                 zz = z + _ray_templ[i][2];
2233                 
2234         } while ((xx>=0)&&(xx<n)&&(yy>=0)&&(yy<n)&&(zz>=0)&&(zz<n));
2235 }
2236
2237 void cast_light(unsigned char* _texture_data, int _ray_templ[4096][3], float *_light_dir, int n /*edgelen*/)
2238 {
2239         int i,j;
2240         int sx = (_light_dir[0]>0) ? 0 : n-1;
2241         int sy = (_light_dir[1]>0) ? 0 : n-1;
2242         int sz = (_light_dir[2]>0) ? 0 : n-1;
2243
2244         float decay = 1.0f/(n*DECAY);
2245
2246         for (i=0; i<n; i++)
2247                 for (j=0; j<n; j++) {
2248                 if (!ALMOST_EQUAL(_light_dir[0], 0))
2249                         light_ray(_texture_data, _ray_templ, sx,i,j,n,decay);
2250                 if (!ALMOST_EQUAL(_light_dir[1], 0))
2251                         light_ray(_texture_data, _ray_templ, i,sy,j,n,decay);
2252                 if (!ALMOST_EQUAL(_light_dir[2], 0))
2253                         light_ray(_texture_data, _ray_templ, i,j,sz,n,decay);
2254                 }
2255 }
2256
2257 void gen_ray_templ(int _ray_templ[4096][3], float *_light_dir, int edgelen)
2258 {
2259         float fx = 0.0f, fy = 0.0f, fz = 0.0f;
2260         int x = 0, y = 0, z = 0;
2261         float lx = _light_dir[0] + 0.000001f, ly = _light_dir[1] + 0.000001f, lz = _light_dir[2] + 0.000001f;
2262         int xinc = (lx > 0) ? 1 : -1;
2263         int yinc = (ly > 0) ? 1 : -1;
2264         int zinc = (lz > 0) ? 1 : -1;
2265         float tx, ty, tz;
2266         int i = 1;
2267         int len = 0;
2268         int maxlen = 3*edgelen*edgelen;
2269         _ray_templ[0][0] = _ray_templ[0][2] = _ray_templ[0][2] = 0;
2270         
2271         while (len <= maxlen)
2272         {
2273                 // fx + t*lx = (x+1)   ->   t = (x+1-fx)/lx
2274                 tx = (x+xinc-fx)/lx;
2275                 ty = (y+yinc-fy)/ly;
2276                 tz = (z+zinc-fz)/lz;
2277
2278                 if ((tx<=ty)&&(tx<=tz)) {
2279                         _ray_templ[i][0] = _ray_templ[i-1][0] + xinc;
2280                         x =+ xinc;
2281                         fx = x;
2282
2283                         if (ALMOST_EQUAL(ty,tx)) {
2284                                 _ray_templ[i][1] = _ray_templ[i-1][1] + yinc;
2285                                 y += yinc;
2286                                 fy = y;
2287                         } else {
2288                                 _ray_templ[i][1] = _ray_templ[i-1][1];
2289                                 fy += tx*ly;
2290                         }
2291
2292                         if (ALMOST_EQUAL(tz,tx)) {
2293                                 _ray_templ[i][2] = _ray_templ[i-1][2] + zinc;
2294                                 z += zinc;
2295                                 fz = z;
2296                         } else {
2297                                 _ray_templ[i][2] = _ray_templ[i-1][2];
2298                                 fz += tx*lz;
2299                         }
2300                 } else if ((ty<tx)&&(ty<=tz)) {
2301                         _ray_templ[i][0] = _ray_templ[i-1][0];
2302                         fx += ty*lx;
2303
2304                         _ray_templ[i][1] = _ray_templ[i-1][1] + yinc;
2305                         y += yinc;
2306                         fy = y;
2307
2308                         if (ALMOST_EQUAL(tz,ty)) {
2309                                 _ray_templ[i][2] = _ray_templ[i-1][2] + zinc;
2310                                 z += zinc;
2311                                 fz = z;
2312                         } else {
2313                                 _ray_templ[i][2] = _ray_templ[i-1][2];
2314                                 fz += ty*lz;
2315                         }
2316                 } else {
2317                         // assert((tz<tx)&&(tz<ty));
2318                         if((tz<tx)&&(tz<ty))
2319                                 break;
2320                         
2321                         _ray_templ[i][0] = _ray_templ[i-1][0];
2322                         fx += tz*lx;
2323                         _ray_templ[i][1] = _ray_templ[i-1][1];
2324                         fy += tz*ly;
2325                         _ray_templ[i][2] = _ray_templ[i-1][2] + zinc;
2326                         z += zinc;
2327                         fz = z;
2328                 }
2329
2330                 len = _ray_templ[i][0]*_ray_templ[i][0]
2331                                 + _ray_templ[i][1]*_ray_templ[i][1]
2332                                 + _ray_templ[i][2]*_ray_templ[i][2];
2333                 i++;
2334         }
2335 }
2336
2337 int intersect_edges(float ret[12][3], float a, float b, float c, float d)
2338 {
2339         int i;
2340         float t;
2341         int num = 0;
2342
2343         for (i=0; i<12; i++) {
2344                 t = -(a*edges[i][0][0] + b*edges[i][0][1] + c*edges[i][0][2] + d)
2345                         / (a*edges[i][1][0] + b*edges[i][1][1] + c*edges[i][1][2]);
2346                 if ((t>0)&&(t<2)) {
2347                         ret[num][0] = edges[i][0][0] + edges[i][1][0]*t;
2348                         ret[num][1] = edges[i][0][1] + edges[i][1][1]*t;
2349                         ret[num][2] = edges[i][0][2] + edges[i][1][2]*t;
2350                         num++;
2351                 }
2352         }
2353
2354         return num;
2355 }
2356
2357 void draw_slices ( float m[][4] )
2358 {
2359         int i;
2360
2361         float viewdir[3];
2362         float d0;
2363         float dd;
2364         int n;
2365         float d;
2366         
2367         viewdir[0] = m[0][2];
2368         viewdir[1] = m[1][2];
2369         viewdir[2] = m[2][2];
2370         Normalize(viewdir);
2371         
2372         // find cube vertex that is closest to the viewer
2373         for ( i=0; i<8; i++ )
2374         {
2375                 float x = cv[i][0] + viewdir[0];
2376                 float y = cv[i][1] + viewdir[1];
2377                 float z = cv[i][2] + viewdir[2];
2378                 if ( ( x>=-1.0f ) && ( x<=1.0f )
2379                         && ( y>=-1.0f ) && ( y<=1.0f )
2380                         && ( z>=-1.0f ) && ( z<=1.0f ) )
2381                 {
2382                         break;
2383                 }
2384         }
2385         if ( i != 8 ) return;
2386
2387         glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
2388         glDisable ( GL_DEPTH_TEST );
2389         // our slices are defined by the plane equation a*x + b*y +c*z + d = 0
2390         // (a,b,c), the plane normal, are given by viewdir
2391         // d is the parameter along the view direction. the first d is given by
2392         // inserting previously found vertex into the plane equation
2393         d0 = - ( viewdir[0]*cv[i][0] + viewdir[1]*cv[i][1] + viewdir[2]*cv[i][2] );
2394         dd = 2*d0/64.0f;
2395         n = 0;
2396         
2397         for ( d = -d0; d < d0; d += dd )
2398         {
2399                 // intersect_edges returns the intersection points of all cube edges with
2400                 // the given plane that lie within the cube
2401                 float pt[12][3];
2402                 int num = intersect_edges ( pt, viewdir[0], viewdir[1], viewdir[2], d );
2403
2404                 if ( num > 2 )
2405                 {
2406                         // sort points to get a convex polygon
2407                         // std::sort(pt.begin()+1, pt.end(), Convexcomp(pt[0], viewdir));
2408                         int shuffled = 1;
2409
2410                         while ( shuffled )
2411                         {
2412                                 int j;
2413                                 shuffled = 0;
2414
2415                                 for ( j = 0; j < num-1; j++ )
2416                                 {
2417                                         // Vec3 va = a-p0, vb = b-p0;
2418                                         // return dot(up, cross(va, vb)) >= 0;
2419                                         float va[3], vb[3], vc[3];
2420
2421                                         VECSUB ( va, pt[j], pt[0] );
2422                                         VECSUB ( vb, pt[j+1], pt[0] );
2423                                         Crossf ( vc, va, vb );
2424
2425                                         if ( INPR ( viewdir, vc ) >= 0 )
2426                                         {
2427                                                 float temp[3];
2428
2429                                                 VECCOPY ( temp, pt[j] );
2430                                                 VECCOPY ( pt[j], pt[j+1] );
2431                                                 VECCOPY ( pt[j+1], temp );
2432
2433                                                 shuffled = 1;
2434                                         }
2435                                 }
2436                         }
2437 /*
2438                         glEnable ( GL_TEXTURE_3D );
2439                         glEnable ( GL_FRAGMENT_PROGRAM_ARB );
2440                         glBindProgramARB ( GL_FRAGMENT_PROGRAM_ARB, _prog[0] );
2441                         glActiveTextureARB ( GL_TEXTURE0_ARB );
2442                         glBindTexture ( GL_TEXTURE_3D, _txt[0] );
2443                         glBegin ( GL_POLYGON );
2444                         for ( i=0; i<num; i++ )
2445                         {
2446                                 glColor3f ( 1.0, 1.0, 1.0 );
2447                                 glTexCoord3d ( ( pt[i][0]+1.0 ) /2.0, ( -pt[i][1]+1 ) /2.0, ( pt[i][2]+1.0 ) /2.0 );
2448                                 glVertex3f ( pt[i][0], pt[i][1], pt[i][2] );
2449                         }
2450                         glEnd();
2451                         */
2452                 }
2453                 n++;
2454         }
2455 }
2456
2457 static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm)
2458 {
2459         
2460         if(G.vd->transp==0) {   // not when we draw the transparent pass
2461                 glLineWidth(2.0);
2462                 glDepthMask(0);
2463                 
2464                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2465                    drawFacesSolid() doesn't draw the transparent faces */
2466                 if(ob->dtx & OB_DRAWTRANSP) {
2467                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2468                         dm->drawFacesSolid(dm, set_gl_material);
2469                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2470                 }
2471                 else {
2472                         dm->drawEdges(dm, 0);
2473                 }
2474                                         
2475                 glLineWidth(1.0);
2476                 glDepthMask(1);
2477         }
2478 }
2479
2480 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2481 {
2482         *drawSmooth_r = 1;
2483         return 1;
2484 }
2485
2486 static void draw_mesh_fancy(Base *base, int dt, int flag)
2487 {
2488         Object *ob= base->object;
2489         Mesh *me = ob->data;
2490         Material *ma= give_current_material(ob, 1);
2491         int hasHaloMat = (ma && (ma->mode&MA_HALO));
2492         int draw_wire = ob->dtx&OB_DRAWWIRE;
2493         int totvert, totedge, totface;
2494         DispList *dl;
2495         DerivedMesh *dm= mesh_get_derived_final(ob, get_viewedit_datamask());
2496
2497         if(!dm)
2498                 return;
2499
2500 #ifdef WITH_VERSE
2501         if(me->vnode) {
2502                 struct VNode *vnode = (VNode*)me->vnode;
2503                 struct VLayer *vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
2504                 struct VLayer *face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
2505
2506                 if(vert_vlayer) totvert = vert_vlayer->dl.da.count;
2507                 else totvert = 0;
2508                 totedge = 0;    /* total count of edge needn't to be zero, but verse doesn't know edges */
2509                 if(face_vlayer) totface = face_vlayer->dl.da.count;
2510                 else totface = 0;
2511         }
2512         else {
2513                 totvert = dm->getNumVerts(dm);
2514                 totedge = dm->getNumEdges(dm);
2515                 totface = dm->getNumFaces(dm);
2516         }
2517 #else
2518         totvert = dm->getNumVerts(dm);
2519         totedge = dm->getNumEdges(dm);
2520         totface = dm->getNumFaces(dm);
2521 #endif
2522         
2523         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2524         if(dt!=OB_SHADED)
2525                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2526
2527                 // Unwanted combination.
2528         if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
2529
2530         if(dt==OB_BOUNDBOX) {
2531                 draw_bounding_volume(ob);
2532         }
2533         else if(hasHaloMat || (totface==0 && totedge==0)) {
2534                 glPointSize(1.5);
2535                 dm->drawVerts(dm);
2536                 glPointSize(1.0);
2537         }
2538         else if(dt==OB_WIRE || totface==0) {
2539                 draw_wire = 1;
2540         }
2541         else if(        (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
2542                                 CHECK_OB_DRAWTEXTURE(G.vd, dt))
2543         {
2544                 int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
2545
2546                 if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
2547                         draw_mesh_object_outline(ob, dm);
2548                 }
2549
2550                 draw_mesh_textured(ob, dm, faceselect);
2551
2552                 if(!faceselect) {
2553                         if(base->flag & SELECT)
2554                                 BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2555                         else
2556                                 BIF_ThemeColor(TH_WIRE);
2557
2558                         dm->drawLooseEdges(dm);
2559                 }
2560         }
2561         else if(dt==OB_SOLID ) {
2562                 
2563                 if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2564                         draw_mesh_object_outline(ob, dm);
2565                 }
2566
2567                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2568
2569                 glEnable(GL_LIGHTING);
2570                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2571
2572                 dm->drawFacesSolid(dm, set_gl_material);
2573
2574                 glFrontFace(GL_CCW);
2575                 glDisable(GL_LIGHTING);
2576
2577                 if(base->flag & SELECT) {
2578                         BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2579                 } else {
2580                         BIF_ThemeColor(TH_WIRE);
2581                 }
2582                 dm->drawLooseEdges(dm);
2583         }
2584         else if(dt==OB_SHADED) {
2585                 int do_draw= 1; /* to resolve all G.f settings below... */
2586                 
2587                 if(ob==OBACT) {
2588                         do_draw= 0;
2589                         if( (G.f & G_WEIGHTPAINT)) {
2590                                 set_gl_material(0);             /* enforce defmaterial settings */
2591                                 
2592                                 /* but set default spec */
2593                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2594                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2595                                 glColor3ub(120, 120, 120);
2596                                 glDisable(GL_COLOR_MATERIAL);
2597                                 /* diffuse */
2598                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2599                                 glEnable(GL_LIGHTING);
2600                                 glEnable(GL_COLOR_MATERIAL);
2601
2602                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2603                                 glDisable(GL_COLOR_MATERIAL);
2604                                 glDisable(GL_LIGHTING);
2605                         }
2606                         else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
2607                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2608                         }
2609                         else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
2610                                 glColor3f(1.0f, 1.0f, 1.0f);
2611                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2612                         }
2613                         else do_draw= 1;
2614                 }
2615                 if(do_draw) {
2616                         dl = ob->disp.first;
2617                         if (!dl || !dl->col1) {
2618                                 /* release and reload derivedmesh because it might be freed in
2619                                    shadeDispList due to a different datamask */
2620                                 dm->release(dm);
2621                                 shadeDispList(base);
2622                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2623                             dm= mesh_get_derived_final(ob, get_viewedit_datamask());
2624                         }
2625
2626                         if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2627                                 draw_mesh_object_outline(ob, dm);
2628                         }
2629
2630                                 /* False for dupliframe objects */
2631                         if (dl) {
2632                                 unsigned int *obCol1 = dl->col1;
2633                                 unsigned int *obCol2 = dl->col2;
2634
2635                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2636                         }
2637
2638                         if(base->flag & SELECT) {
2639                                 BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2640                         } else {
2641                                 BIF_ThemeColor(TH_WIRE);
2642                         }
2643                         dm->drawLooseEdges(dm);
2644                 }
2645         }
2646         
2647         /* set default draw color back for wire or for draw-extra later on */
2648         if (dt!=OB_WIRE) {
2649                 if(base->flag & SELECT) {
2650                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2651                                 BIF_ThemeColor(TH_GROUP_ACTIVE);
2652                         else if(ob->flag & OB_FROMGROUP) 
2653                                 BIF_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2654                         else if(flag!=DRAW_CONSTCOLOR)
2655                                 BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2656                         else
2657                                 glColor3ub(80,80,80);
2658                 } else {
2659                         if (ob->flag & OB_FROMGROUP) 
2660                                 BIF_ThemeColor(TH_GROUP);
2661                         else {
2662                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2663                                         glColor3ub(80,80,80);
2664                                 else
2665                                         BIF_ThemeColor(TH_WIRE);
2666                         }
2667                 }
2668         }
2669         if (draw_wire) {
2670                         /* If drawing wire and drawtype is not OB_WIRE then we are
2671                                 * overlaying the wires.
2672                                 */
2673
2674                 if (dt!=OB_WIRE) {
2675                         bglPolygonOffset(1.0);
2676                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2677                 }
2678
2679                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2680
2681                 if (dt!=OB_WIRE) {
2682                         glDepthMask(1);
2683                         bglPolygonOffset(0.0);
2684                 }
2685         }
2686
2687         dm->release(dm);
2688 }
2689
2690 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2691 static int draw_mesh_object(Base *base, int dt, int flag)
2692 {
2693         Object *ob= base->object;
2694         Mesh *me= ob->data;
2695         int has_alpha= 0, drawlinked= 0, retval= 0;
2696         
2697         if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) {
2698                 if(ob_get_key(ob));
2699                 else drawlinked= 1;
2700         }
2701         
2702         if(ob==G.obedit || drawlinked) {
2703                 DerivedMesh *finalDM, *cageDM;
2704                 
2705                 if (G.obedit!=ob)
2706                         finalDM = cageDM = editmesh_get_derived_base();
2707                 else
2708                         cageDM = editmesh_get_derived_cage_and_final(&finalDM,
2709                                                         get_viewedit_datamask());
2710
2711                 if(dt>OB_WIRE) init_gl_materials(ob, 0);        // no transp in editmode, the fancy draw over goes bad then
2712                 draw_em_fancy(ob, G.editMesh, cageDM, finalDM, dt);
2713
2714                 if (G.obedit!=ob && finalDM)
2715                         finalDM->release(finalDM);
2716         }
2717         else if(!G.obedit && (G.f & G_SCULPTMODE) &&(G.scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2718                 OBACT==ob && !sculpt_modifiers_active(ob)) {
2719                 sculptmode_draw_mesh(0);
2720         }
2721         else {
2722                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2723                 if(me->totface<=4 || boundbox_clip(ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2724                         if(dt==OB_SOLID) has_alpha= init_gl_materials(ob, (base->flag & OB_FROMDUPLI)==0);
2725                         draw_mesh_fancy(base, dt, flag);
2726                         
2727                         if(me->totvert==0) retval= 1;
2728                 }
2729         }
2730         
2731         /* init_gl_materials did the proper checking if this is needed */
2732         if(has_alpha) add_view3d_after(G.vd, base, V3D_TRANSP);
2733         
2734         return retval;
2735 }
2736
2737 /* ************** DRAW DISPLIST ****************** */
2738
2739 static int draw_index_wire= 1;
2740 static int index3_nors_incr= 1;
2741
2742 /* returns 1 when nothing was drawn */
2743 static int drawDispListwire(ListBase *dlbase)
2744 {
2745         DispList *dl;
2746         int parts, nr;
2747         float *data;
2748
2749         if(dlbase==NULL) return 1;
2750         
2751         glDisableClientState(GL_NORMAL_ARRAY);
2752         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2753
2754         for(dl= dlbase->first; dl; dl= dl->next) {
2755                 if(dl->parts==0 || dl->nr==0)
2756                         continue;
2757                 
2758                 data= dl->verts;
2759         
2760                 switch(dl->type) {
2761                 case DL_SEGM:
2762                         
2763                         glVertexPointer(3, GL_FLOAT, 0, data);
2764                         
2765                         for(parts=0; parts<dl->parts; parts++)
2766                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2767                                 
2768                         break;
2769                 case DL_POLY:
2770                         
2771                         glVertexPointer(3, GL_FLOAT, 0, data);
2772                         
2773                         for(parts=0; parts<dl->parts; parts++)
2774                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2775                         
2776                         break;
2777                 case DL_SURF:
2778                         
2779                         glVertexPointer(3, GL_FLOAT, 0, data);
2780                         
2781                         for(parts=0; parts<dl->parts; parts++) {
2782                                 if(dl->flag & DL_CYCL_U) 
2783                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2784                                 else
2785                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2786                         }
2787                         
2788                         for(nr=0; nr<dl->nr; nr++) {
2789                                 int ofs= 3*dl->nr;
2790                                 
2791                                 data= (  dl->verts )+3*nr;
2792                                 parts= dl->parts;
2793
2794                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2795                                 else glBegin(GL_LINE_STRIP);
2796                                 
2797                                 while(parts--) {
2798                                         glVertex3fv(data);
2799                                         data+=ofs;
2800                                 }
2801                                 glEnd();
2802                                 
2803                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2804 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2805 //                              if(dl->flag & DL_CYCL_V) 
2806 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2807 //                              else
2808 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2809                         }
2810                         break;
2811                         
2812                 case DL_INDEX3:
2813                         if(draw_index_wire) {
2814                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2815                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2816                         }
2817                         break;
2818                         
2819                 case DL_INDEX4:
2820                         if(draw_index_wire) {
2821                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2822                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2823                         }
2824                         break;
2825                 }
2826         }
2827         
2828         glEnableClientState(GL_NORMAL_ARRAY);
2829         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2830         
2831         return 0;
2832 }
2833
2834 static void drawDispListsolid(ListBase *lb, Object *ob)
2835 {
2836         DispList *dl;
2837         float *data, curcol[4];
2838         float *ndata;
2839         
2840         if(lb==NULL) return;
2841         
2842         /* for drawing wire */
2843         glGetFloatv(GL_CURRENT_COLOR, curcol);
2844
2845         glEnable(GL_LIGHTING);
2846         
2847         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2848         else glFrontFace(GL_CCW);
2849         
2850         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2851                 glShadeModel(GL_SMOOTH);
2852         }
2853         
2854         dl= lb->first;
2855         while(dl) {
2856                 data= dl->verts;
2857                 ndata= dl->nors;
2858
2859                 switch(dl->type) {
2860                 case DL_SEGM:
2861                         if(ob->type==OB_SURF) {
2862                                 int nr;
2863
2864                                 glDisable(GL_LIGHTING);
2865                                 glColor3fv(curcol);
2866                                 
2867                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2868                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2869
2870                                 glBegin(GL_LINE_STRIP);
2871                                 for(nr= dl->nr; nr; nr--, data+=3)
2872                                         glVertex3fv(data);
2873                                 glEnd();
2874
2875                                 glEnable(GL_LIGHTING);
2876                         }
2877                         break;
2878                 case DL_POLY:
2879                         if(ob->type==OB_SURF) {
2880                                 int nr;
2881                                 
2882                                 BIF_ThemeColor(TH_WIRE);
2883                                 glDisable(GL_LIGHTING);
2884                                 
2885                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2886                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2887                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2888                                 
2889                                 glBegin(GL_LINE_LOOP);
2890                                 for(nr= dl->nr; nr; nr--, data+=3)
2891                                         glVertex3fv(data);
2892                                 glEnd();
2893                                 
2894                                 glEnable(GL_LIGHTING);
2895                                 break;
2896                         }
2897                 case DL_SURF:
2898                         
2899                         if(dl->index) {
2900                                 set_gl_material(dl->col+1);
2901                                 
2902                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2903                                 else glShadeModel(GL_FLAT);
2904                                 
2905                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2906                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2907                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2908                         }                       
2909                         break;
2910
2911                 case DL_INDEX3:
2912                 
2913                         set_gl_material(dl->col+1);
2914                         
2915                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2916                         
2917                         /* voor polys only one normal needed */
2918                         if(index3_nors_incr==0) {
2919                                 glDisableClientState(GL_NORMAL_ARRAY);
2920                                 glNormal3fv(ndata);
2921                         }
2922                         else
2923                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2924                         
2925                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2926                         
2927                         if(index3_nors_incr==0)
2928                                 glEnableClientState(GL_NORMAL_ARRAY);
2929
2930                         break;
2931
2932                 case DL_INDEX4:
2933
2934                         set_gl_material(dl->col+1);
2935                         
2936                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2937                         glNormalPointer(GL_FLOAT, 0, dl->nors);
2938                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2939                         
2940                         break;
2941                 }
2942                 dl= dl->next;
2943         }
2944
2945         glShadeModel(GL_FLAT);
2946         glDisable(GL_LIGHTING);
2947         glFrontFace(GL_CCW);
2948 }
2949
2950 static void drawDispListshaded(ListBase *lb, Object *ob)
2951 {
2952         DispList *dl, *dlob;
2953         unsigned int *cdata;
2954
2955         if(lb==NULL) return;
2956
2957         glShadeModel(GL_SMOOTH);
2958         glDisableClientState(GL_NORMAL_ARRAY);
2959         glEnableClientState(GL_COLOR_ARRAY);
2960         
2961         dl= lb->first;
2962         dlob= ob->disp.first;
2963         while(dl && dlob) {
2964                 
2965                 cdata= dlob->col1;
2966                 if(cdata==NULL) break;
2967                 
2968                 switch(dl->type) {
2969                 case DL_SURF:
2970                         if(dl->index) {
2971                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2972                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2973                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2974                         }                       
2975                         break;
2976
2977                 case DL_INDEX3:
2978                         
2979                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2980                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2981                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2982                         break;
2983
2984                 case DL_INDEX4:
2985                         
2986                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2987                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2988                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2989                         break;
2990                 }
2991                 
2992                 dl= dl->next;
2993                 dlob= dlob->next;
2994         }
2995         
2996         glShadeModel(GL_FLAT);
2997         glEnableClientState(GL_NORMAL_ARRAY);
2998         glDisableClientState(GL_COLOR_ARRAY);
2999 }
3000
3001 /* returns 1 when nothing was drawn */
3002 static int drawDispList(Base *base, int dt)
3003 {
3004         Object *ob= base->object;
3005         ListBase *lb=0;
3006         DispList *dl;
3007         Curve *cu;
3008         int solid, retval= 0;
3009         
3010         solid= (dt > OB_WIRE);
3011
3012         switch(ob->type) {
3013         case OB_FONT:
3014         case OB_CURVE:
3015                 cu= ob->data;
3016                 
3017                 lb= &cu->disp;
3018                 
3019                 if(solid) {
3020                         dl= lb->first;
3021                         if(dl==NULL) return 1;
3022                         
3023                         if(dl->nors==0) addnormalsDispList(ob, lb);
3024                         index3_nors_incr= 0;
3025                         
3026                         if( displist_has_faces(lb)==0) {
3027                                 draw_index_wire= 0;
3028                                 drawDispListwire(lb);
3029                                 draw_index_wire= 1;
3030                         }
3031                         else {
3032                                 if(dt==OB_SHADED) {
3033                                         if(ob->disp.first==0) shadeDispList(base);
3034                                         drawDispListshaded(lb, ob);
3035                                 }
3036                                 else {
3037                                         init_gl_materials(ob, 0);
3038                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
3039                                         drawDispListsolid(lb, ob);
3040                                 }
3041                                 if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL) {
3042                                         cpack(0);
3043                                         draw_index_wire= 0;
3044                                         drawDispListwire(lb);
3045                                         draw_index_wire= 1;
3046                                 }
3047                         }
3048                         index3_nors_incr= 1;
3049                 }
3050                 else {
3051                         draw_index_wire= 0;
3052                         retval= drawDispListwire(lb);
3053                         draw_index_wire= 1;
3054                 }
3055                 break;
3056         case OB_SURF:
3057         
3058                 lb= &((Curve *)ob->data)->disp;
3059                 
3060                 if(solid) {
3061                         dl= lb->first;
3062                         if(dl==NULL) return 1;
3063                         
3064                         if(dl->nors==NULL) addnormalsDispList(ob, lb);
3065                         
3066                         if(dt==OB_SHADED) {
3067                                 if(ob->disp.first==NULL) shadeDispList(base);
3068                                 drawDispListshaded(lb, ob);
3069                         }
3070                         else {
3071                                 init_gl_materials(ob, 0);
3072                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
3073                         
3074                                 drawDispListsolid(lb, ob);
3075                         }
3076                 }
3077                 else {
3078                         retval= drawDispListwire(lb);
3079                 }
3080                 break;
3081         case OB_MBALL:
3082                 
3083                 if( is_basis_mball(ob)) {
3084                         lb= &ob->disp;
3085                         if(lb->first==NULL) makeDispListMBall(ob);
3086                         if(lb->first==NULL) return 1;
3087                         
3088                         if(solid) {
3089                                 
3090                                 if(dt==OB_SHADED) {
3091                                         dl= lb->first;
3092                                         if(dl && dl->col1==0) shadeDispList(base);
3093                                         drawDispListshaded(lb, ob);
3094                                 }
3095                                 else {
3096                                         init_gl_materials(ob, 0);
3097                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
3098                                 
3099                                         drawDispListsolid(lb, ob);      
3100                                 }
3101                         }
3102                         else{
3103                                 /* MetaBalls use DL_INDEX4 type of DispList */
3104                                 retval= drawDispListwire(lb);
3105                         }
3106                 }
3107                 break;
3108         }
3109         
3110         return retval;
3111 }
3112
3113 /* ******************************** */
3114
3115
3116 static void draw_particle_system(Base *base, PartEff *paf)
3117 {
3118         Object *ob= base->object;
3119         Particle *pa;
3120         float ptime, ctime, vec[3], vec1[3], mat[4][4];
3121         int a, totpart;
3122         
3123         pa= paf->keys;
3124         // FSPARTICLE always rebuild fluid particle system upon change...
3125         if( (pa==NULL) 
3126             || ( (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) 
3127                         ) {
3128                 build_particle_system(ob);
3129                 pa= paf->keys;
3130                 if(pa==NULL) return;
3131         }
3132         
3133         myloadmatrix(G.vd->viewmat);
3134         /* flag abuse... but I need working code too now. This feature doesnt work for per frame animated objects */
3135         if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
3136                 Mat4MulMat4(mat, paf->imat, ob->obmat);
3137                 mymultmatrix(mat);
3138         }
3139         
3140         if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= give_timeoffset(ob);
3141         else ptime= 0.0;
3142         ctime= bsystem_time(ob, (float)(G.scene->r.cfra), ptime);
3143
3144         glPointSize(1.0);
3145         
3146         if(paf->stype==PAF_VECT) glBegin(GL_LINES);
3147         else glBegin(GL_POINTS);
3148
3149         totpart= (paf->disp*paf->totpart)/100;
3150         for(a=0; a<totpart; a++, pa+=paf->totkey) {
3151                 
3152                 if(ctime > pa->time) {
3153                         if(ctime < pa->time+pa->lifetime) {
3154                         
3155                                 if(paf->stype==PAF_VECT) {
3156                                         where_is_particle(paf, pa, ctime, vec);
3157                                         where_is_particle(paf, pa, ctime+1.0, vec1);
3158                 
3159                                         glVertex3fv(vec);
3160                                         glVertex3fv(vec1);
3161                                 }
3162                                 else {
3163                                         where_is_particle(paf, pa, ctime, vec);
3164                                         
3165                                         glVertex3fv(vec);
3166                                 }
3167                         }
3168                 }
3169         }
3170         glEnd();
3171         
3172         myloadmatrix(G.vd->viewmat);
3173         mymultmatrix(ob->obmat);        // bring back local matrix for dtx
3174 }
3175
3176 static void draw_static_particle_system(Object *ob, PartEff *paf, int dt)
3177 {
3178         Particle *pa;
3179         float ctime, mtime, vec[3], veco[3];
3180         int a, use_norm=0, totpart;
3181         
3182         pa= paf->keys;
3183         // FSPARTICLE always rebuild upon change...
3184         if( (pa==NULL) 
3185             || ( (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) 
3186                         ) {
3187                 build_particle_system(ob);
3188                 pa= paf->keys;
3189                 if(pa==NULL) return;
3190         }
3191         
3192         if(paf->stype==PAF_VECT) {
3193                 if(dt>OB_WIRE) {
3194                         
3195                         /* shaded/texture mode: we still draw solid, so have to set materials */
3196                         if(dt>OB_SOLID) init_gl_materials(ob, 0);
3197
3198                         glEnable(GL_LIGHTING);
3199                         set_gl_material(paf->omat);
3200                         use_norm= 1;
3201                 }
3202         }
3203         else {
3204                 glPointSize(1.0);
3205                 glBegin(GL_POINTS);
3206         }
3207         
3208         totpart= (paf->disp*paf->totpart)/100;
3209         for(a=0; a<totpart; a++, pa+=paf->totkey) {
3210                 
3211                 if(paf->stype==PAF_VECT) {
3212                         
3213                         glBegin(GL_LINE_STRIP);
3214                         where_is_particle(paf, pa, pa->time, veco);
3215
3216                         mtime= pa->time+pa->lifetime+paf->staticstep;