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