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