- added make_orco_curf, even does keys!
[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_DerivedMesh.h"
78 #include "BKE_displist.h"
79 #include "BKE_effect.h"
80 #include "BKE_font.h"
81 #include "BKE_global.h"
82 #include "BKE_image.h"
83 #include "BKE_ipo.h"
84 #include "BKE_key.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                 do_latt_key(lt);
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 }
967
968 /* ***************** ******************** */
969
970 static void mesh_foreachScreenVert__mapFunc(void *userData, EditVert *eve, float *co, float *no_f, short *no_s)
971 {
972         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; } *data = userData;
973         short s[2];
974
975         if (eve->h==0) {
976                 if (data->clipVerts) {
977                         project_short(co, s);
978                 } else {
979                         project_short_noclip(co, s);
980                 }
981
982                 data->func(data->userData, eve, s[0], s[1], (int) eve->prev);
983         }
984 }
985 void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
986 {
987         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; } data;
988         int dmNeedsFree;
989         DerivedMesh *dm = editmesh_get_derived_cage(&dmNeedsFree);
990         float mat[4][4];
991         EditVert *eve, *preveve;
992         int index;
993
994         data.func = func;
995         data.userData = userData;
996         data.clipVerts = clipVerts;
997
998         areawinset(curarea->win);
999         persp(PERSP_VIEW);
1000         mymultmatrix(G.obedit->obmat);
1001         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1002         mygetsingmatrix(G.vd->persmat);
1003
1004         for (index=0,eve=G.editMesh->verts.first; eve; index++,eve= eve->next)
1005                 eve->prev = (EditVert*) index;
1006
1007         dm->foreachMappedVertEM(dm, mesh_foreachScreenVert__mapFunc, &data);
1008
1009         for (preveve=NULL, eve=G.editMesh->verts.first; eve; preveve=eve, eve= eve->next)
1010                 eve->prev = preveve;
1011
1012         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1013         myloadmatrix(G.vd->viewmat);
1014
1015         if (dmNeedsFree) {
1016                 dm->release(dm);
1017         }
1018 }
1019
1020 static void mesh_foreachScreenEdge__mapFunc(void *userData, EditEdge *eed, float *v0co, float *v1co)
1021 {
1022         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; } *data = userData;
1023         short s[2][2];
1024
1025         if (eed->h==0) {
1026                 if (data->clipVerts==1) {
1027                         project_short(v0co, s[0]);
1028                         project_short(v1co, s[1]);
1029                 } else {
1030                         project_short_noclip(v0co, s[0]);
1031                         project_short_noclip(v1co, s[1]);
1032
1033                         if (data->clipVerts==2) {
1034                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<curarea->winx && s[0][1]<curarea->winy)) 
1035                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<curarea->winx && s[1][1]<curarea->winy)) 
1036                                                 return;
1037                         }
1038                 }
1039
1040                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], (int) eed->prev);
1041         }
1042 }
1043 void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
1044 {
1045         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; } data;
1046         int dmNeedsFree;
1047         DerivedMesh *dm = editmesh_get_derived_cage(&dmNeedsFree);
1048         float mat[4][4];
1049         EditEdge *eed, *preveed;
1050         int index;
1051
1052         data.func = func;
1053         data.userData = userData;
1054         data.clipVerts = clipVerts;
1055
1056         areawinset(curarea->win);
1057         persp(PERSP_VIEW);
1058         mymultmatrix(G.obedit->obmat);
1059         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1060         mygetsingmatrix(G.vd->persmat);
1061
1062         for (index=0,eed=G.editMesh->edges.first; eed; index++,eed= eed->next)
1063                 eed->prev = (EditEdge*) index;
1064
1065         dm->foreachMappedEdgeEM(dm, mesh_foreachScreenEdge__mapFunc, &data);
1066
1067         for (preveed=NULL, eed=G.editMesh->edges.first; eed; preveed=eed, eed= eed->next)
1068                 eed->prev = preveed;
1069
1070         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1071         myloadmatrix(G.vd->viewmat);
1072
1073         if (dmNeedsFree) {
1074                 dm->release(dm);
1075         }
1076 }
1077
1078 static void mesh_foreachScreenFace__mapFunc(void *userData, EditFace *efa, float *cent, float *no)
1079 {
1080         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; } *data = userData;
1081         short s[2];
1082
1083         if (efa && efa->fgonf!=EM_FGON) {
1084                 project_short(cent, s);
1085
1086                 data->func(data->userData, efa, s[0], s[1], (int) efa->prev);
1087         }
1088 }
1089 void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1090 {
1091         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; } data;
1092         int dmNeedsFree;
1093         DerivedMesh *dm = editmesh_get_derived_cage(&dmNeedsFree);
1094         float mat[4][4];
1095         EditFace *efa, *prevefa;
1096         int index = 0;
1097
1098         data.func = func;
1099         data.userData = userData;
1100
1101         areawinset(curarea->win);
1102         persp(PERSP_VIEW);
1103         mymultmatrix(G.obedit->obmat);
1104         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1105         mygetsingmatrix(G.vd->persmat);
1106
1107         for (index=0,efa=G.editMesh->faces.first; efa; index++,efa= efa->next)
1108                 efa->prev = (EditFace*) index;
1109
1110         dm->foreachMappedFaceCenterEM(dm, mesh_foreachScreenFace__mapFunc, &data);
1111
1112         for (prevefa=NULL, efa=G.editMesh->faces.first; efa; prevefa=efa, efa= efa->next)
1113                 efa->prev = prevefa;
1114
1115         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1116         myloadmatrix(G.vd->viewmat);
1117
1118         if (dmNeedsFree) {
1119                 dm->release(dm);
1120         }
1121 }
1122
1123 void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1124 {
1125         float mat[4][4];
1126         short s[2];
1127         Nurb *nu;
1128         int i;
1129
1130         areawinset(curarea->win);
1131         persp(PERSP_VIEW);
1132         mymultmatrix(G.obedit->obmat);
1133         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1134         mygetsingmatrix(G.vd->persmat);
1135
1136         for (nu= editNurb.first; nu; nu=nu->next) {
1137                 if((nu->type & 7)==CU_BEZIER) {
1138                         for (i=0; i<nu->pntsu; i++) {
1139                                 BezTriple *bezt = &nu->bezt[i];
1140
1141                                 if(bezt->hide==0) {
1142                                         project_short(bezt->vec[0], s);
1143                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1144                                         project_short(bezt->vec[1], s);
1145                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1146                                         project_short(bezt->vec[2], s);
1147                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1148                                 }
1149                         }
1150                 }
1151                 else {
1152                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1153                                 BPoint *bp = &nu->bp[i];
1154
1155                                 if(bp->hide==0) {
1156                                         project_short(bp->vec, s);
1157                                         func(userData, nu, bp, NULL, -1, s[0], s[1]);
1158                                 }
1159                         }
1160                 }
1161         }
1162
1163         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1164         myloadmatrix(G.vd->viewmat);
1165 }
1166
1167 ////
1168
1169 static void calc_weightpaint_vert_color(Object *ob, int vert, unsigned char *col)
1170 {
1171         Mesh *me = ob->data;
1172         float fr, fg, fb, input = 0.0;
1173         int i;
1174
1175         if (me->dvert) {
1176                 for (i=0; i<me->dvert[vert].totweight; i++)
1177                         if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
1178                                 input+=me->dvert[vert].dw[i].weight;            
1179         }
1180
1181         CLAMP(input, 0.0, 1.0);
1182
1183         fr = fg = fb = 85;
1184         if (input<=0.25f){
1185                 fr=0.0f;
1186                 fg=255.0f * (input*4.0f);
1187                 fb=255.0f;
1188         }
1189         else if (input<=0.50f){
1190                 fr=0.0f;
1191                 fg=255.0f;
1192                 fb=255.0f * (1.0f-((input-0.25f)*4.0f)); 
1193         }
1194         else if (input<=0.75){
1195                 fr=255.0f * ((input-0.50f)*4.0f);
1196                 fg=255.0f;
1197                 fb=0.0f;
1198         }
1199         else if (input<=1.0){
1200                 fr=255.0f;
1201                 fg=255.0f * (1.0f-((input-0.75f)*4.0f)); 
1202                 fb=0.0f;
1203         }
1204
1205         col[3] = (unsigned char)(fr * ((input/2.0f)+0.5f));
1206         col[2] = (unsigned char)(fg * ((input/2.0f)+0.5f));
1207         col[1] = (unsigned char)(fb * ((input/2.0f)+0.5f));
1208         col[0] = 255;
1209 }
1210 static unsigned char *calc_weightpaint_colors(Object *ob) 
1211 {
1212         Mesh *me = ob->data;
1213         MFace *mf = me->mface;
1214         unsigned char *wtcol;
1215         int i;
1216         
1217         wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
1218         
1219         memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
1220         for (i=0; i<me->totface; i++, mf++){
1221                 calc_weightpaint_vert_color(ob, mf->v1, &wtcol[(i*4 + 0)*4]); 
1222                 calc_weightpaint_vert_color(ob, mf->v2, &wtcol[(i*4 + 1)*4]); 
1223                 if (mf->v3)
1224                         calc_weightpaint_vert_color(ob, mf->v3, &wtcol[(i*4 + 2)*4]); 
1225                 if (mf->v4)
1226                         calc_weightpaint_vert_color(ob, mf->v4, &wtcol[(i*4 + 3)*4]); 
1227         }
1228         
1229         return wtcol;
1230 }
1231
1232 /* ************** DRAW MESH ****************** */
1233
1234 /* First section is all the "simple" draw routines, 
1235  * ones that just pass some sort of primitive to GL,
1236  * with perhaps various options to control lighting,
1237  * color, etc.
1238  *
1239  * These routines should not have user interface related
1240  * logic!!!
1241  */
1242
1243 static void draw_dm_face_normals__mapFunc(void *userData, EditFace *efa, float *cent, float *no)
1244 {
1245         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1246                 glVertex3fv(cent);
1247                 glVertex3f(     cent[0] + no[0]*G.scene->editbutsize,
1248                                         cent[1] + no[1]*G.scene->editbutsize,
1249                                         cent[2] + no[2]*G.scene->editbutsize);
1250         }
1251 }
1252 static void draw_dm_face_normals(DerivedMesh *dm) {
1253         glBegin(GL_LINES);
1254         dm->foreachMappedFaceCenterEM(dm, draw_dm_face_normals__mapFunc, 0);
1255         glEnd();
1256 }
1257
1258 static void draw_dm_face_centers__mapFunc(void *userData, EditFace *efa, float *cent, float *no)
1259 {
1260         int sel = *((int*) userData);
1261
1262         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1263                 bglVertex3fv(cent);
1264         }
1265 }
1266 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1267 {
1268         bglBegin(GL_POINTS);
1269         dm->foreachMappedFaceCenterEM(dm, draw_dm_face_centers__mapFunc, &sel);
1270         bglEnd();
1271 }
1272
1273 static void draw_dm_vert_normals__mapFunc(void *userData, EditVert *eve, float *co, float *no_f, short *no_s)
1274 {
1275         if (eve->h==0) {
1276                 glVertex3fv(co);
1277
1278                 if (no_f) {
1279                         glVertex3f(     co[0] + no_f[0]*G.scene->editbutsize,
1280                                                 co[1] + no_f[1]*G.scene->editbutsize,
1281                                                 co[2] + no_f[2]*G.scene->editbutsize);
1282                 } else {
1283                         glVertex3f(     co[0] + no_s[0]*G.scene->editbutsize/32767.0f,
1284                                                 co[1] + no_s[1]*G.scene->editbutsize/32767.0f,
1285                                                 co[2] + no_s[2]*G.scene->editbutsize/32767.0f);
1286                 }
1287         }
1288 }
1289 static void draw_dm_vert_normals(DerivedMesh *dm) {
1290         glBegin(GL_LINES);
1291         dm->foreachMappedVertEM(dm, draw_dm_vert_normals__mapFunc, NULL);
1292         glEnd();
1293 }
1294
1295         /* Draw verts with color set based on selection */
1296 static void draw_dm_verts__mapFunc(void *userData, EditVert *eve, float *co, float *no_f, short *no_s)
1297 {
1298         int sel = *((int*) userData);
1299
1300         if (eve->h==0 && (eve->f&SELECT)==sel) {
1301                 bglVertex3fv(co);
1302         }
1303 }
1304 static void draw_dm_verts(DerivedMesh *dm, int sel)
1305 {
1306         bglBegin(GL_POINTS);
1307         dm->foreachMappedVertEM(dm, draw_dm_verts__mapFunc, &sel);
1308         bglEnd();
1309 }
1310
1311         /* Draw edges with color set based on selection */
1312 static int draw_dm_edges_sel__setDrawOptions(void *userData, EditEdge *eed)
1313 {
1314         unsigned char **cols = userData;
1315
1316         if (eed->h==0) {
1317                 glColor4ubv(cols[(eed->f&SELECT)?1:0]);
1318                 return 1;
1319         } else {
1320                 return 0;
1321         }
1322 }
1323 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol) 
1324 {
1325         unsigned char *cols[2];
1326         cols[0] = baseCol;
1327         cols[1] = selCol;
1328         dm->drawMappedEdgesEM(dm, draw_dm_edges_sel__setDrawOptions, cols);
1329 }
1330
1331         /* Draw edges */
1332 static int draw_dm_edges__setDrawOptions(void *userData, EditEdge *eed)
1333 {
1334         return eed->h==0;
1335 }
1336 static void draw_dm_edges(DerivedMesh *dm) 
1337 {
1338         dm->drawMappedEdgesEM(dm, draw_dm_edges__setDrawOptions, NULL);
1339 }
1340
1341         /* Draw edges with color interpolated based on selection */
1342 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, EditEdge *eed)
1343 {
1344         return (eed->h==0);
1345 }
1346 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, EditEdge *eed, float t)
1347 {
1348         unsigned char **cols = userData;
1349         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1350         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1351
1352         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1353                                 col0[1] + (col1[1]-col0[1])*t,
1354                                 col0[2] + (col1[2]-col0[2])*t,
1355                                 col0[3] + (col1[3]-col0[3])*t);
1356 }
1357 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1358 {
1359         unsigned char *cols[2];
1360         cols[0] = baseCol;
1361         cols[1] = selCol;
1362         dm->drawMappedEdgesInterpEM(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1363 }
1364
1365         /* Draw only seam edges */
1366 static int draw_dm_edges_seams__setDrawOptions(void *userData, EditEdge *eed)
1367 {
1368         return (eed->h==0 && eed->seam);
1369 }
1370 static void draw_dm_edges_seams(DerivedMesh *dm)
1371 {
1372         dm->drawMappedEdgesEM(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1373 }
1374
1375         /* Draw faces with color set based on selection */
1376 static int draw_dm_faces_sel__setDrawOptions(void *userData, EditFace *efa)
1377 {
1378         unsigned char **cols = userData;
1379
1380         if (efa->h==0) {
1381                 glColor4ubv(cols[(efa->f&SELECT)?1:0]);
1382                 return 1;
1383         } else {
1384                 return 0;
1385         }
1386 }
1387 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol) 
1388 {
1389         unsigned char *cols[2];
1390         cols[0] = baseCol;
1391         cols[1] = selCol;
1392         dm->drawMappedFacesEM(dm, draw_dm_faces_sel__setDrawOptions, cols);
1393 }
1394
1395 static int draw_dm_creases__setDrawOptions(void *userData, EditEdge *eed)
1396 {
1397         if (eed->h==0 && eed->crease!=0.0) {
1398                 BIF_ThemeColorShade((eed->f&SELECT)?TH_EDGE_SELECT:TH_WIRE, 120*eed->crease);
1399                 return 1;
1400         } else {
1401                 return 0;
1402         }
1403 }
1404
1405 static void draw_dm_creases(DerivedMesh *dm)
1406 {
1407         glLineWidth(3.0);
1408         dm->drawMappedEdgesEM(dm, draw_dm_creases__setDrawOptions, NULL);
1409         glLineWidth(1.0);
1410 }
1411
1412 /* Second section of routines: Combine first sets to form fancy
1413  * drawing routines (for example rendering twice to get overlays).
1414  *
1415  * Also includes routines that are basic drawing but are too
1416  * specialized to be split out (like drawing creases or measurements).
1417  */
1418
1419 /* EditMesh drawing routines*/
1420
1421 static void draw_em_fancy_verts(EditMesh *em, DerivedMesh *cageDM)
1422 {
1423         int sel;
1424
1425         if(G.vd->zbuf) glDepthMask(0);          // disable write in zbuffer, zbuf select
1426
1427         for (sel=0; sel<2; sel++) {
1428                 char col[4], fcol[4];
1429                 int pass;
1430
1431                 BIF_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1432                 BIF_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1433
1434                 for (pass=0; pass<2; pass++) {
1435                         float size = BIF_GetThemeValuef(TH_VERTEX_SIZE);
1436                         float fsize = BIF_GetThemeValuef(TH_FACEDOT_SIZE);
1437
1438                         if (pass==0) {
1439                                 if(G.vd->zbuf && !(G.vd->flag&V3D_ZBUF_SELECT)) {
1440                                         glDisable(GL_DEPTH_TEST);
1441                                                 
1442                                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1443                                         glEnable(GL_BLEND);
1444                                 } else {
1445                                         continue;
1446                                 }
1447
1448                                 size = (size>2.1?size/2.0:size);
1449                                 fsize = (fsize>2.1?fsize/2.0:fsize);
1450                                 col[3] = fcol[3] = 100;
1451                         } else {
1452                                 col[3] = fcol[3] = 255;
1453                         }
1454                                 
1455                         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1456                                 glPointSize(size);
1457                                 glColor4ubv(col);
1458                                 draw_dm_verts(cageDM, sel);
1459                         }
1460                         
1461                         if(G.scene->selectmode & SCE_SELECT_FACE) {
1462                                 glPointSize(fsize);
1463                                 glColor4ubv(fcol);
1464                                 draw_dm_face_centers(cageDM, sel);
1465                         }
1466                         
1467                         if (pass==0) {
1468                                 glDisable(GL_BLEND);
1469                                 glEnable(GL_DEPTH_TEST);
1470                         }
1471                 }
1472         }
1473
1474         if(G.vd->zbuf) glDepthMask(1);
1475         glPointSize(1.0);
1476 }
1477
1478 static void draw_em_fancy_edges(DerivedMesh *cageDM)
1479 {
1480         int pass;
1481         char wire[4], sel[4];
1482
1483         /* since this function does transparant... */
1484         BIF_GetThemeColor3ubv(TH_EDGE_SELECT, sel);
1485         BIF_GetThemeColor3ubv(TH_WIRE, wire);
1486
1487         for (pass=0; pass<2; pass++) {
1488                         /* show wires in transparant when no zbuf clipping for select */
1489                 if (pass==0) {
1490                         if (G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0) {
1491                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1492                                 glEnable(GL_BLEND);
1493                                 glDisable(GL_DEPTH_TEST);
1494
1495                                 wire[3] = sel[3] = 85;
1496                         } else {
1497                                 continue;
1498                         }
1499                 } else {
1500                         wire[3] = sel[3] = 255;
1501                 }
1502
1503                 if(G.scene->selectmode == SCE_SELECT_FACE) {
1504                         draw_dm_edges_sel(cageDM, wire, sel);
1505                 }       
1506                 else if( (G.f & G_DRAWEDGES) || (G.scene->selectmode & SCE_SELECT_EDGE) ) {     
1507                         if(cageDM->drawMappedEdgesInterpEM && (G.scene->selectmode & SCE_SELECT_VERTEX)) {
1508                                 glShadeModel(GL_SMOOTH);
1509                                 draw_dm_edges_sel_interp(cageDM, wire, sel);
1510                                 glShadeModel(GL_FLAT);
1511                         } else {
1512                                 draw_dm_edges_sel(cageDM, wire, sel);
1513                         }
1514                 }
1515                 else {
1516                         glColor4ubv(wire);
1517                         draw_dm_edges(cageDM);
1518                 }
1519
1520                 if (pass==0) {
1521                         glDisable(GL_BLEND);
1522                         glEnable(GL_DEPTH_TEST);
1523                 }
1524         }
1525 }       
1526
1527 static void draw_em_measure_stats(Object *ob, EditMesh *em)
1528 {
1529         EditEdge *eed;
1530         EditFace *efa;
1531         float v1[3], v2[3], v3[3], v4[3];
1532         float fvec[3];
1533         char val[32]; /* Stores the measurement display text here */
1534         float area, col[3]; /* area of the face,  colour of the text to draw */
1535         
1536         if(G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0)
1537                 glDisable(GL_DEPTH_TEST);
1538
1539         if(G.vd->zbuf) bglPolygonOffset(5.0);
1540         
1541         if(G.f & G_DRAW_EDGELEN) {
1542                 BIF_GetThemeColor3fv(TH_TEXT, col);
1543                 /* make color a bit more red */
1544                 if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1545                 else col[0]= col[0]*0.7 + 0.3;
1546                 glColor3fv(col);
1547                 
1548                 for(eed= em->edges.first; eed; eed= eed->next) {
1549                         if((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) )) {
1550                                 VECCOPY(v1, eed->v1->co);
1551                                 VECCOPY(v2, eed->v2->co);
1552                                 
1553                                 glRasterPos3f( 0.5*(v1[0]+v2[0]),  0.5*(v1[1]+v2[1]),  0.5*(v1[2]+v2[2]));
1554                                 
1555                                 if(G.vd->flag & V3D_GLOBAL_STATS) {
1556                                         Mat4MulVecfl(ob->obmat, v1);
1557                                         Mat4MulVecfl(ob->obmat, v2);
1558                                 }
1559                                 
1560                                 sprintf(val,"%.3f", VecLenf(v1, v2));
1561                                 BMF_DrawString( G.fonts, val);
1562                         }
1563                 }
1564         }
1565
1566         if(G.f & G_DRAW_FACEAREA) {
1567                 extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
1568                 
1569                 BIF_GetThemeColor3fv(TH_TEXT, col);
1570                 /* make color a bit more green */
1571                 if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
1572                 else col[1]= col[1]*0.7 + 0.3;
1573                 glColor3fv(col);
1574                 
1575                 for(efa= em->faces.first; efa; efa= efa->next) {
1576                         if((efa->f & SELECT) || (G.moving && faceselectedOR(efa, SELECT)) ) {
1577                                 VECCOPY(v1, efa->v1->co);
1578                                 VECCOPY(v2, efa->v2->co);
1579                                 VECCOPY(v3, efa->v3->co);
1580                                 if (efa->v4) {
1581                                         VECCOPY(v4, efa->v4->co);
1582                                 }
1583                                 if(G.vd->flag & V3D_GLOBAL_STATS) {
1584                                         Mat4MulVecfl(ob->obmat, v1);
1585                                         Mat4MulVecfl(ob->obmat, v2);
1586                                         Mat4MulVecfl(ob->obmat, v3);
1587                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1588                                 }
1589                                 
1590                                 if (efa->v4)
1591                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
1592                                 else
1593                                         area = AreaT3Dfl(v1, v2, v3);
1594
1595                                 sprintf(val,"%.3f", area);
1596                                 glRasterPos3fv(efa->cent);
1597                                 BMF_DrawString( G.fonts, val);
1598                         }
1599                 }
1600         }
1601
1602         if(G.f & G_DRAW_EDGEANG) {
1603                 EditEdge *e1, *e2, *e3, *e4;
1604                 
1605                 BIF_GetThemeColor3fv(TH_TEXT, col);
1606                 /* make color a bit more blue */
1607                 if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
1608                 else col[2]= col[2]*0.7 + 0.3;
1609                 glColor3fv(col);
1610                 
1611                 for(efa= em->faces.first; efa; efa= efa->next) {
1612                         VECCOPY(v1, efa->v1->co);
1613                         VECCOPY(v2, efa->v2->co);
1614                         VECCOPY(v3, efa->v3->co);
1615                         if(efa->v4) {
1616                                 VECCOPY(v4, efa->v4->co); 
1617                         }
1618                         else {
1619                                 VECCOPY(v4, v3);
1620                         }
1621                         if(G.vd->flag & V3D_GLOBAL_STATS) {
1622                                 Mat4MulVecfl(ob->obmat, v1);
1623                                 Mat4MulVecfl(ob->obmat, v2);
1624                                 Mat4MulVecfl(ob->obmat, v3);
1625                                 if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1626                         }
1627                         
1628                         e1= efa->e1;
1629                         e2= efa->e2;
1630                         e3= efa->e3;
1631                         if(efa->e4) e4= efa->e4; else e4= e3;
1632                         
1633                         /* Calculate the angles */
1634                                 
1635                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
1636                                 /* Vec 1 */
1637                                 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
1638                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
1639                                 glRasterPos3fv(fvec);
1640                                 BMF_DrawString( G.fonts, val);
1641                         }
1642                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
1643                                 /* Vec 2 */
1644                                 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
1645                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
1646                                 glRasterPos3fv(fvec);
1647                                 BMF_DrawString( G.fonts, val);
1648                         }
1649                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
1650                                 /* Vec 3 */
1651                                 if(efa->v4) 
1652                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
1653                                 else
1654                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
1655                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
1656                                 glRasterPos3fv(fvec);
1657                                 BMF_DrawString( G.fonts, val);
1658                         }
1659                                 /* Vec 4 */
1660                         if(efa->v4) {
1661                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
1662                                         sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
1663                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
1664                                         glRasterPos3fv(fvec);
1665                                         BMF_DrawString( G.fonts, val);
1666                                 }
1667                         }
1668                 }
1669         }    
1670         
1671         if(G.vd->zbuf) {
1672                 glEnable(GL_DEPTH_TEST);
1673                 bglPolygonOffset(0.0);
1674         }
1675 }
1676
1677 static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
1678 {
1679         Mesh *me = ob->data;
1680
1681         if(dt>OB_WIRE) {
1682                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
1683
1684                 glEnable(GL_LIGHTING);
1685                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
1686
1687                 finalDM->drawFacesSolid(finalDM, set_gl_material);
1688
1689                 glFrontFace(GL_CCW);
1690                 glDisable(GL_LIGHTING);
1691                 
1692                 // Setup for drawing wire over, disable zbuffer
1693                 // write to show selected edge wires better
1694                 BIF_ThemeColor(TH_WIRE);
1695
1696                 bglPolygonOffset(1.0);
1697                 glDepthMask(0);
1698         } 
1699         else {
1700                 if (cageDM!=finalDM) {
1701                         BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
1702                         finalDM->drawEdges(finalDM);
1703                 }
1704         }
1705         
1706         if( (G.f & (G_FACESELECT+G_DRAWFACES))) {       /* transp faces */
1707                 char col1[4], col2[4];
1708                         
1709                 BIF_GetThemeColor4ubv(TH_FACE, col1);
1710                 BIF_GetThemeColor4ubv(TH_FACE_SELECT, col2);
1711                 
1712                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1713                 glEnable(GL_BLEND);
1714                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
1715                 
1716                 draw_dm_faces_sel(cageDM, col1, col2);
1717
1718                 glDisable(GL_BLEND);
1719                 glDepthMask(1);         // restore write in zbuffer
1720         }
1721
1722         /* here starts all fancy draw-extra over */
1723
1724         if(G.f & G_DRAWSEAMS) {
1725                 BIF_ThemeColor(TH_EDGE_SEAM);
1726                 glLineWidth(2);
1727
1728                 draw_dm_edges_seams(cageDM);
1729
1730                 glColor3ub(0,0,0);
1731                 glLineWidth(1);
1732         }
1733
1734         draw_em_fancy_edges(cageDM);
1735
1736         if(G.f & G_DRAWCREASES) {
1737                 draw_dm_creases(cageDM);
1738         }
1739
1740         if(ob==G.obedit) {
1741                 draw_em_fancy_verts(em, cageDM);
1742
1743                 if(G.f & G_DRAWNORMALS) {
1744                         BIF_ThemeColor(TH_NORMAL);
1745                         draw_dm_face_normals(cageDM);
1746                 }
1747                 if(G.f & G_DRAW_VNORMALS) {
1748                         BIF_ThemeColor(TH_NORMAL);
1749                         draw_dm_vert_normals(cageDM);
1750                 }
1751
1752                 if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
1753                         draw_em_measure_stats(ob, em);
1754         }
1755
1756         if(dt>OB_WIRE) {
1757                 glDepthMask(1);
1758                 bglPolygonOffset(0.0);
1759         }
1760 }
1761
1762 /* Mesh drawing routines */
1763
1764 static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm)
1765 {
1766         
1767         if(G.vd->transp==0) {   // not when we draw the transparent pass
1768                 glLineWidth(2.0);
1769                 glDepthMask(0);
1770                 
1771                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
1772                    drawFacesSolid() doesn't draw the transparent faces */
1773                 if(ob->dtx & OB_DRAWTRANSP) {
1774                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
1775                         dm->drawFacesSolid(dm, set_gl_material);
1776                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1777                 }
1778                 else
1779                         dm->drawEdges(dm);
1780                                         
1781                 glLineWidth(1.0);
1782                 glDepthMask(1);
1783         }
1784 }
1785
1786 static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, int dt)
1787 {
1788         Mesh *me = ob->data;
1789         Material *ma= give_current_material(ob, 1);
1790         int hasHaloMat = (ma && (ma->mode&MA_HALO));
1791         int draw_wire = ob->dtx&OB_DRAWWIRE;
1792         DispList *dl;
1793
1794         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
1795
1796                 // Unwanted combination.
1797         if (G.f&G_FACESELECT) draw_wire = 0;
1798
1799         if(dt==OB_BOUNDBOX) {
1800                 draw_bounding_volume(ob);
1801         }
1802         else if(hasHaloMat || (me->totface==0 && (!me->medge || me->totedge==0))) {
1803                 glPointSize(1.5);
1804                 dm->drawVerts(dm);
1805                 glPointSize(1.0);
1806         }
1807         else if(dt==OB_WIRE || me->totface==0) {
1808                 draw_wire = 1;
1809         }
1810         else if( (ob==OBACT && (G.f & G_FACESELECT)) || (G.vd->drawtype==OB_TEXTURE && dt>OB_SOLID)) {
1811                 
1812                 if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !(G.f&(G_FACESELECT|G_PICKSEL)) && !draw_wire) {
1813                         draw_mesh_object_outline(ob, dm);
1814                 }
1815
1816                 draw_tface_mesh(ob, ob->data, dt);
1817         }
1818         else if(dt==OB_SOLID ) {
1819                 
1820                 if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !draw_wire) {
1821                         draw_mesh_object_outline(ob, dm);
1822                 }
1823
1824                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
1825
1826                 glEnable(GL_LIGHTING);
1827                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
1828                 
1829                 dm->drawFacesSolid(dm, set_gl_material);
1830
1831                 glFrontFace(GL_CCW);
1832                 glDisable(GL_LIGHTING);
1833
1834                 BIF_ThemeColor(TH_WIRE);
1835                 dm->drawLooseEdges(dm);
1836         }
1837         else if(dt==OB_SHADED) {
1838                 if( (G.f & G_WEIGHTPAINT)) {
1839                         unsigned char *wtcol = calc_weightpaint_colors(ob);
1840                         baseDM->drawFacesColored(baseDM, me->flag&ME_TWOSIDED, wtcol, 0);
1841                         MEM_freeN (wtcol);
1842                 }
1843                 else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
1844                         baseDM->drawFacesColored(baseDM, me->flag&ME_TWOSIDED, (unsigned char*) me->mcol, 0);
1845                 }
1846                 else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->tface) {
1847                         tface_to_mcol(me);
1848                         baseDM->drawFacesColored(baseDM, me->flag&ME_TWOSIDED, (unsigned char*) me->mcol, 0);
1849                         MEM_freeN(me->mcol); 
1850                         me->mcol= 0;
1851                 }
1852                 else {
1853                         unsigned int *obCol1, *obCol2;
1854
1855                         dl = ob->disp.first;
1856                         if (!dl || !dl->col1) {
1857                                 shadeDispList(ob);
1858                                 dl = find_displist(&ob->disp, DL_VERTCOL);
1859                         }
1860                         obCol1 = dl->col1;
1861                         obCol2 = dl->col2;
1862
1863                         if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !draw_wire) {
1864                                 draw_mesh_object_outline(ob, dm);
1865                         }
1866
1867                         dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
1868                 }
1869         }
1870
1871         if (draw_wire) {
1872                         /* If drawing wire and drawtype is not OB_WIRE then we are
1873                                 * overlaying the wires.
1874                                 */
1875                 if (dt!=OB_WIRE) {
1876                         if(ob->flag & SELECT) {
1877                                 BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
1878                         } else {
1879                                 BIF_ThemeColor(TH_WIRE);
1880                         }
1881
1882                         bglPolygonOffset(1.0);
1883                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
1884                 }
1885
1886                 dm->drawEdges(dm);
1887
1888                 if (dt!=OB_WIRE) {
1889                         glDepthMask(1);
1890                         bglPolygonOffset(0.0);
1891                 }
1892         }
1893 }
1894
1895 static void draw_mesh_object(Base *base, int dt)
1896 {
1897         Object *ob= base->object;
1898         Mesh *me= ob->data;
1899         int has_alpha= 0;
1900         
1901         if(G.obedit && ob->data==G.obedit->data) {
1902                 int cageNeedsFree, finalNeedsFree;
1903                 DerivedMesh *finalDM, *cageDM;
1904                 
1905                 if (G.obedit!=ob) {
1906                         finalDM = cageDM = editmesh_get_derived_base();
1907                         cageNeedsFree = 0;
1908                         finalNeedsFree = 1;
1909                 } else {
1910                         cageDM = editmesh_get_derived_cage_and_final(&finalDM, &cageNeedsFree, &finalNeedsFree);
1911                 }
1912
1913                 if(dt>OB_WIRE) init_gl_materials(ob);   // no transp in editmode, the fancy draw over goes bad then
1914                 draw_em_fancy(ob, G.editMesh, cageDM, finalDM, dt);
1915
1916                 if (cageNeedsFree) cageDM->release(cageDM);
1917                 if (finalNeedsFree) finalDM->release(finalDM);
1918         }
1919         else {
1920                 BoundBox *bb = mesh_get_bb(me);
1921
1922                 if(me->totface<=4 || boundbox_clip(ob->obmat, bb)) {
1923                         int baseDMneedsFree, realDMneedsFree;
1924                         DerivedMesh *baseDM = mesh_get_derived_deform(ob, &baseDMneedsFree);
1925                         DerivedMesh *realDM = mesh_get_derived_final(ob, &realDMneedsFree);
1926
1927                         if(dt==OB_SOLID) has_alpha= init_gl_materials(ob);
1928                         draw_mesh_fancy(ob, baseDM, realDM, dt);
1929
1930                         if (baseDMneedsFree) baseDM->release(baseDM);
1931                         if (realDMneedsFree) realDM->release(realDM);
1932                 }
1933         }
1934         
1935         /* init_gl_materials did the proper checking if this is needed */
1936         if(has_alpha) add_view3d_after(G.vd, base, V3D_TRANSP);
1937 }
1938
1939 /* ************** DRAW DISPLIST ****************** */
1940
1941 static int draw_index_wire= 1;
1942 static int index3_nors_incr= 1;
1943
1944 static void drawDispListwire(ListBase *dlbase)
1945 {
1946         DispList *dl;
1947         int parts, nr, ofs, *index;
1948         float *data;
1949
1950         if(dlbase==0) return;
1951
1952         dl= dlbase->first;
1953         while(dl) {
1954                 data= dl->verts;
1955         
1956                 switch(dl->type) {
1957                 case DL_SEGM:
1958                         parts= dl->parts;
1959                         while(parts--) {
1960                                 nr= dl->nr;
1961                                 glBegin(GL_LINE_STRIP);
1962                                 while(nr--) {
1963                                         glVertex3fv(data);
1964                                         data+=3;
1965                                 }
1966                                 glEnd();
1967                         }
1968                         break;
1969                 case DL_POLY:
1970                         parts= dl->parts;
1971                         while(parts--) {
1972                                 nr= dl->nr;
1973                                 glBegin(GL_LINE_LOOP);
1974                                 while(nr--) {
1975                                         glVertex3fv(data);
1976                                         data+=3;
1977                                 }
1978                                 glEnd();
1979                         }
1980                         break;
1981                 case DL_SURF:
1982                         parts= dl->parts;
1983                         while(parts--) {
1984                                 nr= dl->nr;
1985                                 if(dl->flag & DL_CYCL_U) glBegin(GL_LINE_LOOP);
1986                                 else glBegin(GL_LINE_STRIP);
1987
1988                                 while(nr--) {
1989                                         glVertex3fv(data);
1990                                         data+=3;
1991                                 }
1992                                 glEnd();
1993                         }
1994                         ofs= 3*dl->nr;
1995                         nr= dl->nr;
1996                         while(nr--) {
1997                                 data= (  dl->verts )+3*nr;
1998                                 parts= dl->parts;
1999                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2000                                 else glBegin(GL_LINE_STRIP);
2001                                 
2002                                 while(parts--) {
2003                                         glVertex3fv(data);
2004                                         data+=ofs;
2005                                 }
2006                                 glEnd();
2007                         }
2008                         break;
2009                         
2010                 case DL_INDEX3:
2011                         if(draw_index_wire) {
2012                                 parts= dl->parts;
2013                                 data= dl->verts;
2014                                 index= dl->index;
2015                                 while(parts--) {
2016
2017                                         glBegin(GL_LINE_LOOP);
2018                                                 glVertex3fv(data+3*index[0]);
2019                                                 glVertex3fv(data+3*index[1]);
2020                                                 glVertex3fv(data+3*index[2]);
2021                                         glEnd();
2022                                         index+= 3;
2023                                 }
2024                         }
2025                         break;
2026                         
2027                 case DL_INDEX4:
2028                         if(draw_index_wire) {
2029                                 parts= dl->parts;
2030                                 data= dl->verts;
2031                                 index= dl->index;
2032                                 while(parts--) {
2033
2034                                         glBegin(GL_LINE_LOOP);
2035                                                 glVertex3fv(data+3*index[0]);
2036                                                 glVertex3fv(data+3*index[1]);
2037                                                 glVertex3fv(data+3*index[2]);
2038                                                 if(index[3]) glVertex3fv(data+3*index[3]);
2039                                         glEnd();
2040                                         index+= 4;
2041                                 }
2042                         }
2043                         break;
2044                 }
2045                 dl= dl->next;
2046         }
2047 }
2048
2049 static void drawDispListsolid(ListBase *lb, Object *ob)
2050 {
2051         DispList *dl;
2052         int parts, ofs, p1, p2, p3, p4, a, b, *index;
2053         float *data, *v1, *v2, *v3, *v4;
2054         float *ndata, *n1, *n2, *n3, *n4;
2055         
2056         if(lb==0) return;
2057         
2058         glEnable(GL_LIGHTING);
2059         
2060         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2061         else glFrontFace(GL_CCW);
2062         
2063         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2064                 glShadeModel(GL_SMOOTH);
2065         }
2066         
2067         dl= lb->first;
2068         while(dl) {
2069                 data= dl->verts;
2070                 ndata= dl->nors;
2071
2072                 switch(dl->type) {
2073                 case DL_SURF:
2074
2075                         set_gl_material(dl->col+1);
2076                         
2077                         if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2078                         else glShadeModel(GL_FLAT);
2079
2080                         for(a=0; a<dl->parts; a++) {
2081                                 
2082                                 DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
2083                                 
2084                                 v1= data+ 3*p1; 
2085                                 v2= data+ 3*p2;
2086                                 v3= data+ 3*p3; 
2087                                 v4= data+ 3*p4;
2088                                 n1= ndata+ 3*p1; 
2089                                 n2= ndata+ 3*p2;
2090                                 n3= ndata+ 3*p3; 
2091                                 n4= ndata+ 3*p4;
2092                                 
2093                                 glBegin(GL_QUAD_STRIP);
2094                                 
2095                                 glNormal3fv(n2); glVertex3fv(v2);
2096                                 glNormal3fv(n4); glVertex3fv(v4);
2097
2098                                 for(; b<dl->nr; b++) {
2099                                         
2100                                         glNormal3fv(n1); glVertex3fv(v1);
2101                                         glNormal3fv(n3); glVertex3fv(v3);
2102
2103                                         v2= v1; v1+= 3;
2104                                         v4= v3; v3+= 3;
2105                                         n2= n1; n1+= 3;
2106                                         n4= n3; n3+= 3;
2107                                 }
2108                                 
2109                                 
2110                                 glEnd();
2111                         }
2112                         break;
2113
2114                 case DL_INDEX3:
2115                 
2116                         parts= dl->parts;
2117                         data= dl->verts;
2118                         ndata= dl->nors;
2119                         index= dl->index;
2120
2121                         set_gl_material(dl->col+1);
2122                                                         
2123                         /* voor polys only one normal needed */
2124                         if(index3_nors_incr==0) {
2125                                 while(parts--) {
2126
2127                                         glBegin(GL_TRIANGLES);
2128                                                 glNormal3fv(ndata);
2129                                                 glVertex3fv(data+3*index[0]);
2130                                                 glVertex3fv(data+3*index[1]);
2131                                                 glVertex3fv(data+3*index[2]);
2132                                         glEnd();
2133                                         index+= 3;
2134                                 }
2135                         }
2136                         else {
2137                                 while(parts--) {
2138
2139                                         glBegin(GL_TRIANGLES);
2140                                                 ofs= 3*index[0];
2141                                                 glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2142                                                 ofs= 3*index[1];
2143                                                 glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2144                                                 ofs= 3*index[2];
2145                                                 glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2146                                         glEnd();
2147                                         index+= 3;
2148                                 }
2149                         }
2150                         break;
2151
2152                 case DL_INDEX4:
2153
2154                         parts= dl->parts;
2155                         data= dl->verts;
2156                         ndata= dl->nors;
2157                         index= dl->index;
2158
2159                         set_gl_material(dl->col+1);
2160                 
2161                         while(parts--) {
2162
2163                                 glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
2164                                         ofs= 3*index[0];
2165                                         glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2166                                         ofs= 3*index[1];
2167                                         glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2168                                         ofs= 3*index[2];
2169                                         glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2170                                         if(index[3]) {
2171                                                 ofs= 3*index[3];
2172                                                 glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2173                                         }
2174                                 glEnd();
2175                                 index+= 4;
2176                         }
2177                         break;
2178                 }
2179                 dl= dl->next;
2180         }
2181
2182         glShadeModel(GL_FLAT);
2183         glDisable(GL_LIGHTING);
2184         glFrontFace(GL_CCW);
2185 }
2186
2187 static void drawDispListshaded(ListBase *lb, Object *ob)
2188 {
2189         DispList *dl, *dlob;
2190         int parts, p1, p2, p3, p4, a, b, *index;
2191         float *data, *v1, *v2, *v3, *v4;
2192         unsigned int *cdata, *c1, *c2, *c3, *c4;
2193         char *cp;
2194
2195         if(lb==0) return;
2196
2197         glShadeModel(GL_SMOOTH);
2198
2199         dl= lb->first;
2200         dlob= ob->disp.first;
2201         while(dl && dlob) {
2202                 
2203                 cdata= dlob->col1;
2204                 data= dl->verts;
2205                 if(cdata==0) break;
2206                 
2207                 switch(dl->type) {
2208                 case DL_SURF:
2209
2210                         for(a=0; a<dl->parts; a++) {
2211
2212                                 DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
2213
2214                                 v1= data+ 3*p1; 
2215                                 v2= data+ 3*p2;
2216                                 v3= data+ 3*p3; 
2217                                 v4= data+ 3*p4;
2218                                 c1= cdata+ p1; 
2219                                 c2= cdata+ p2;
2220                                 c3= cdata+ p3; 
2221                                 c4= cdata+ p4;
2222
2223                                 for(; b<dl->nr; b++) {
2224
2225                                         glBegin(GL_QUADS);
2226                                                 cp= (char *)c1;
2227                                                 glColor3ub(cp[3], cp[2], cp[1]);
2228                                                 glVertex3fv(v1);
2229                                                 cp= (char *)c2;
2230                                                 glColor3ub(cp[3], cp[2], cp[1]);
2231                                                 glVertex3fv(v2);
2232                                                 cp= (char *)c4;
2233                                                 glColor3ub(cp[3], cp[2], cp[1]);
2234                                                 glVertex3fv(v4);
2235                                                 cp= (char *)c3;
2236                                                 glColor3ub(cp[3], cp[2], cp[1]);
2237                                                 glVertex3fv(v3);
2238                                         glEnd();
2239
2240                                         v2= v1; v1+= 3;
2241                                         v4= v3; v3+= 3;
2242                                         c2= c1; c1++;
2243                                         c4= c3; c3++;
2244                                 }
2245                         }
2246                         break;
2247
2248                 case DL_INDEX3:
2249                         
2250                         parts= dl->parts;
2251                         index= dl->index;
2252                         
2253                         while(parts--) {
2254
2255                                 glBegin(GL_TRIANGLES);
2256                                         cp= (char *)(cdata+index[0]);
2257                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2258                                         glVertex3fv(data+3*index[0]);
2259
2260                                         cp= (char *)(cdata+index[1]);
2261                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2262                                         glVertex3fv(data+3*index[1]);
2263
2264                                         cp= (char *)(cdata+index[2]);
2265                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2266                                         glVertex3fv(data+3*index[2]);
2267                                 glEnd();
2268                                 index+= 3;
2269                         }
2270                         break;
2271
2272                 case DL_INDEX4:
2273                 
2274                         parts= dl->parts;
2275                         index= dl->index;
2276                         while(parts--) {
2277
2278                                 glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
2279                                         cp= (char *)(cdata+index[0]);
2280                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2281                                         glVertex3fv(data+3*index[0]);
2282
2283                                         cp= (char *)(cdata+index[1]);
2284                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2285                                         glVertex3fv(data+3*index[1]);
2286
2287                                         cp= (char *)(cdata+index[2]);
2288                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2289                                         glVertex3fv(data+3*index[2]);
2290                                         
2291                                         if(index[3]) {
2292                                         
2293                                                 cp= (char *)(cdata+index[3]);
2294                                                 glColor3ub(cp[3], cp[2], cp[1]);        
2295                                                 glVertex3fv(data+3*index[3]);
2296                                         }
2297                                 glEnd();
2298                                 index+= 4;
2299                         }
2300                         break;
2301                         
2302                 }
2303                 dl= dl->next;
2304                 dlob= dlob->next;
2305         }
2306         
2307         glShadeModel(GL_FLAT);
2308 }
2309
2310 static void drawDispList(Object *ob, int dt)
2311 {
2312         ListBase *lb=0;
2313         DispList *dl;
2314         Curve *cu;
2315         int solid;
2316
2317         
2318         solid= (dt > OB_WIRE);
2319
2320         switch(ob->type) {
2321         case OB_FONT:
2322         case OB_CURVE:
2323                 cu= ob->data;
2324                 
2325                 lb= &cu->disp;
2326                 
2327                 if(solid) {
2328                         dl= lb->first;
2329                         if(dl==0) return;
2330                         
2331                         if(dl->nors==0) addnormalsDispList(ob, lb);
2332                         index3_nors_incr= 0;
2333                         
2334                         if( displist_has_faces(lb)==0) {
2335                                 draw_index_wire= 0;
2336                                 drawDispListwire(lb);
2337                                 draw_index_wire= 1;
2338                         }
2339                         else {
2340                                 if(dt==OB_SHADED) {
2341                                         if(ob->disp.first==0) shadeDispList(ob);
2342                                         drawDispListshaded(lb, ob);
2343                                 }
2344                                 else {
2345                                         init_gl_materials(ob);
2346                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2347                                         drawDispListsolid(lb, ob);
2348                                 }
2349                                 if(ob==G.obedit) {
2350                                         cpack(0);
2351                                         draw_index_wire= 0;
2352                                         drawDispListwire(lb);
2353                                         draw_index_wire= 1;
2354                                 }
2355                         }
2356                         index3_nors_incr= 1;
2357                 }
2358                 else {
2359                         draw_index_wire= 0;
2360                         drawDispListwire(lb);
2361                         draw_index_wire= 1;
2362                 }
2363                 break;
2364         case OB_SURF:
2365         
2366                 lb= &((Curve *)ob->data)->disp;
2367                 
2368                 if(solid) {
2369                         dl= lb->first;
2370                         if(dl==0) return;
2371                         
2372                         if(dl->nors==0) addnormalsDispList(ob, lb);
2373                         
2374                         if(dt==OB_SHADED) {
2375                                 if(ob->disp.first==0) shadeDispList(ob);
2376                                 drawDispListshaded(lb, ob);
2377                         }
2378                         else {
2379                                 init_gl_materials(ob);
2380                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2381                         
2382                                 drawDispListsolid(lb, ob);
2383                         }
2384                 }
2385                 else {
2386                         drawDispListwire(lb);
2387                 }
2388                 break;
2389         case OB_MBALL:
2390                 
2391                 if( is_basis_mball(ob)) {
2392                         lb= &ob->disp;
2393                         if(lb->first==0) makeDispListMBall(ob);
2394         
2395                         if(solid) {
2396                                 
2397                                 if(dt==OB_SHADED) {
2398                                         dl= lb->first;
2399                                         if(dl && dl->col1==0) shadeDispList(ob);
2400                                         drawDispListshaded(lb, ob);
2401                                 }
2402                                 else {
2403                                         init_gl_materials(ob);
2404                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2405                                 
2406                                         drawDispListsolid(lb, ob);      
2407                                 }
2408                         }
2409                         else{
2410                                 /* MetaBalls use DL_INDEX4 type of DispList */
2411                                 drawDispListwire(lb);
2412                         }
2413                 }
2414                 break;
2415         }
2416         
2417 }
2418
2419 /* ******************************** */
2420
2421
2422 static void draw_particle_system(Object *ob, PartEff *paf)
2423 {
2424         Particle *pa;
2425         float ptime, ctime, vec[3], vec1[3];
2426         int a;
2427         
2428         pa= paf->keys;
2429         if(pa==0) {
2430                 build_particle_system(ob);
2431                 pa= paf->keys;
2432                 if(pa==0) return;
2433         }
2434         
2435         myloadmatrix(G.vd->viewmat);
2436         
2437         if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
2438         else ptime= 0.0;
2439         ctime= bsystem_time(ob, 0, (float)(G.scene->r.cfra), ptime);
2440
2441         glPointSize(1.0);
2442         if(paf->stype!=PAF_VECT) glBegin(GL_POINTS);
2443
2444         for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
2445                 
2446                 if(ctime > pa->time) {
2447                         if(ctime < pa->time+pa->lifetime) {
2448                         
2449                                 if(paf->stype==PAF_VECT) {
2450                                         where_is_particle(paf, pa, ctime, vec);
2451                                         where_is_particle(paf, pa, ctime+1.0, vec1);
2452                 
2453
2454                                         glBegin(GL_LINE_STRIP);
2455                                                 glVertex3fv(vec);
2456                                                 glVertex3fv(vec1);
2457                                         glEnd();
2458                                         
2459                                 }
2460                                 else {
2461                                         where_is_particle(paf, pa, ctime, vec);
2462                                         
2463                                         glVertex3fv(vec);
2464                                                 
2465                                 }
2466                         }
2467                 }
2468         }
2469         if(paf->stype!=PAF_VECT) glEnd();
2470         
2471         mymultmatrix(ob->obmat);        // bring back local matrix for dtx
2472 }
2473
2474 static void draw_static_particle_system(Object *ob, PartEff *paf)
2475 {
2476         Particle *pa;
2477         float ctime, mtime, vec[3], vec1[3];
2478         int a;
2479         
2480         pa= paf->keys;
2481         if(pa==0) {
2482                 build_particle_system(ob);
2483                 pa= paf->keys;
2484                 if(pa==0) return;
2485         }
2486         
2487         glPointSize(1.0);
2488         if(paf->stype!=PAF_VECT) glBegin(GL_POINTS);
2489
2490         for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
2491                 
2492                 where_is_particle(paf, pa, pa->time, vec1);
2493                 
2494                 mtime= pa->time+pa->lifetime+paf->staticstep-1;
2495                 
2496                 for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
2497                         
2498                         /* make sure hair grows until the end.. */ 
2499                         if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
2500                         
2501                         if(paf->stype==PAF_VECT) {
2502                                 where_is_particle(paf, pa, ctime+1, vec);
2503
2504                                 glBegin(GL_LINE_STRIP);
2505                                         glVertex3fv(vec);
2506                                         glVertex3fv(vec1);
2507                                 glEnd();
2508                                 
2509                                 VECCOPY(vec1, vec);
2510                         }
2511                         else {
2512                                 where_is_particle(paf, pa, ctime, vec);
2513                                 
2514                                 glVertex3fv(vec);
2515                                         
2516                         }
2517                 }
2518         }
2519         if(paf->stype!=PAF_VECT) glEnd();
2520
2521 }
2522
2523 unsigned int nurbcol[8]= {
2524         0, 0x9090, 0x409030, 0x603080, 0, 0x40fff0, 0x40c033, 0xA090F0 };
2525
2526 static void tekenhandlesN(Nurb *nu, short sel)
2527 {
2528         BezTriple *bezt;
2529         float *fp;
2530         unsigned int *col;
2531         int a;
2532
2533         if(nu->hide) return;
2534         if( (nu->type & 7)==1) {
2535                 if(sel) col= nurbcol+4;
2536                 else col= nurbcol;
2537
2538                 bezt= nu->bezt;
2539                 a= nu->pntsu;
2540                 while(a--) {
2541                         if(bezt->hide==0) {
2542                                 if( (bezt->f2 & 1)==sel) {
2543                                         fp= bezt->vec[0];
2544                                         cpack(col[bezt->h1]);
2545
2546                                         glBegin(GL_LINE_STRIP); 
2547                                         glVertex3fv(fp);
2548                                         glVertex3fv(fp+3); 
2549                                         glEnd();
2550                                         cpack(col[bezt->h2]);
2551
2552                                         glBegin(GL_LINE_STRIP); 
2553                                         glVertex3fv(fp+3); 
2554                                         glVertex3fv(fp+6); 
2555                                         glEnd();
2556                                 }
2557                                 else if( (bezt->f1 & 1)==sel) {
2558                                         fp= bezt->vec[0];
2559                                         cpack(col[bezt->h1]);
2560
2561                                         glBegin(GL_LINE_STRIP); 
2562                                         glVertex3fv(fp); 
2563                                         glVertex3fv(fp+3); 
2564                                         glEnd();
2565                                 }
2566                                 else if( (bezt->f3 & 1)==sel) {
2567                                         fp= bezt->vec[1];
2568                                         cpack(col[bezt->h2]);
2569
2570                                         glBegin(GL_LINE_STRIP); 
2571                                         glVertex3fv(fp); 
2572                                         glVertex3fv(fp+3); 
2573                                         glEnd();
2574                                 }
2575                         }
2576                         bezt++;
2577                 }
2578         }
2579 }
2580
2581 static void tekenvertsN(Nurb *nu, short sel)
2582 {
2583         BezTriple *bezt;
2584         BPoint *bp;
2585         float size;
2586         int a;
2587
2588         if(nu->hide) return;
2589
2590         if(sel) BIF_ThemeColor(TH_VERTEX_SELECT);
2591         else BIF_ThemeColor(TH_VERTEX);
2592
2593         size= BIF_GetThemeValuef(TH_VERTEX_SIZE);
2594         glPointSize(size);
2595         
2596         bglBegin(GL_POINTS);
2597         
2598         if((nu->type & 7)==1) {
2599
2600                 bezt= nu->bezt;
2601                 a= nu->pntsu;
2602                 while(a--) {
2603                         if(bezt->hide==0) {
2604                                 if((bezt->f1 & 1)==sel) bglVertex3fv(bezt->vec[0]);
2605                                 if((bezt->f2 & 1)==sel) bglVertex3fv(bezt->vec[1]);
2606                                 if((bezt->f3 & 1)==sel) bglVertex3fv(bezt->vec[2]);
2607                         }
2608                         bezt++;
2609                 }
2610         }
2611         else {
2612                 bp= nu->bp;
2613                 a= nu->pntsu*nu->pntsv;
2614                 while(a--) {
2615                         if(bp->hide==0) {
2616                                 if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec);
2617                         }
2618                         bp++;
2619                 }
2620         }
2621         
2622         bglEnd();
2623         glPointSize(1.0);
2624 }
2625
2626 static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
2627 {
2628         Nurb *nu;
2629         BPoint *bp, *bp1;
2630         int a, b, ofs;
2631         
2632         nu= nurb;
2633         while(nu) {
2634                 if(nu->hide==0) {
2635                         switch(nu->type & 7) {
2636                         case CU_POLY:
2637                                 cpack(nurbcol[3]);
2638                                 bp= nu->bp;
2639                                 for(b=0; b<nu->pntsv; b++) {
2640                                         if(nu->flagu & 1) glBegin(GL_LINE_LOOP);
2641
2642                                         else glBegin(GL_LINE_STRIP);
2643
2644                                         for(a=0; a<nu->pntsu; a++, bp++) {
2645                                                 glVertex3fv(bp->vec);
2646                                         }
2647
2648                                         if(nu->flagu & 1) glEnd();
2649                                         else glEnd();
2650                                 }
2651                                 break;
2652                         case CU_NURBS:
2653
2654                                 bp= nu->bp;
2655                                 for(b=0; b<nu->pntsv; b++) {
2656                                         bp1= bp;
2657                                         bp++;
2658                                         for(a=nu->pntsu-1; a>0; a--, bp++) {
2659                                                 if(bp->hide==0 && bp1->hide==0) {
2660                                                         if(sel) {
2661                                                                 if( (bp->f1 & 1) && ( bp1->f1 & 1) ) {
2662                                                                         cpack(nurbcol[5]);
2663                 
2664                                                                         glBegin(GL_LINE_STRIP);
2665                                                                         glVertex3fv(bp->vec); 
2666                                                                         glVertex3fv(bp1->vec);
2667                                                                         glEnd();
2668                                                                 }
2669                                                         }
2670                                                         else {
2671                                                                 if( (bp->f1 & 1) && ( bp1->f1 & 1) );
2672                                                                 else {
2673                                                                         cpack(nurbcol[1]);
2674                 
2675                                                                         glBegin(GL_LINE_STRIP);
2676                                                                         glVertex3fv(bp->vec); 
2677                                                                         glVertex3fv(bp1->vec);
2678                                                                         glEnd();
2679                                                                 }
2680                                                         }
2681                                                 }
2682                                                 bp1= bp;
2683                                         }
2684                                 }
2685                                 if(nu->pntsv > 1) {     /* surface */
2686
2687                                         ofs= nu->pntsu;
2688                                         for(b=0; b<nu->pntsu; b++) {
2689                                                 bp1= nu->bp+b;
2690                                                 bp= bp1+ofs;
2691                                                 for(a=nu->pntsv-1; a>0; a--, bp+=ofs) {
2692                                                         if(bp->hide==0 && bp1->hide==0) {
2693                                                                 if(sel) {
2694                                                                         if( (bp->f1 & 1) && ( bp1->f1 & 1) ) {
2695                                                                                 cpack(nurbcol[7]);
2696                         
2697                                                                                 glBegin(GL_LINE_STRIP);
2698                                                                                 glVertex3fv(bp->vec); 
2699                                                                                 glVertex3fv(bp1->vec);
2700                                                                                 glEnd();
2701                                                                         }
2702                                                                 }
2703                                                                 else {
2704                                                                         if( (bp->f1 & 1) && ( bp1->f1 & 1) );
2705                                                                         else {
2706                                                                                 cpack(nurbcol[3]);
2707                         
2708                                                                                 glBegin(GL_LINE_STRIP);
2709                                                                                 glVertex3fv(bp->vec); 
2710                                                                                 glVertex3fv(bp1->vec);
2711                                                                                 glEnd();
2712                                                                         }
2713                                                                 }
2714                                                         }
2715                                                         bp1= bp;
2716                                                 }
2717                                         }
2718
2719                                 }
2720                                 break;
2721                         }
2722                 }
2723                 nu= nu->next;
2724         }
2725 }
2726
2727 static void drawnurb(Object *ob, Nurb *nurb, int dt)
2728 {
2729         Curve *cu = ob->data;
2730         Nurb *nu;
2731         BevList *bl;
2732
2733         /* first non-selected handles */
2734         for(nu=nurb; nu; nu=nu->next) {
2735                 if((nu->type & 7)==CU_BEZIER) {
2736                         tekenhandlesN(nu, 0);
2737                 }
2738         }
2739         
2740         /* then DispList */
2741         
2742         BIF_ThemeColor(TH_WIRE);
2743         drawDispList(ob, dt);
2744
2745         draw_editnurb(ob, nurb, 0);
2746         draw_editnurb(ob, nurb, 1);
2747
2748         if(cu->flag & CU_3D) {
2749                 BIF_ThemeColor(TH_WIRE);
2750                 glBegin(GL_LINES);
2751                 for (bl=cu->bev.first,nu=nurb; nu && bl; bl=bl->next,nu=nu->next) {
2752                         BevPoint *bevp= (BevPoint *)(&bl+1);            
2753                         int nr= bl->nr;
2754                         int skip= nu->resolu/16;
2755                         
2756                         while (nr-->0) {
2757                                 float ox = G.scene->editbutsize*bevp->mat[0][0];
2758                                 float oy = G.scene->editbutsize*bevp->mat[0][1];
2759                                 float oz = G.scene->editbutsize*bevp->mat[0][2];
2760
2761                                 glVertex3f(bevp->x - ox, bevp->y - oy, bevp->z - oz);
2762                                 glVertex3f(bevp->x + ox, bevp->y + oy, bevp->z + oz);
2763                                 
2764                                 bevp += skip+1;
2765                                 nr -= skip;
2766                         }
2767                 }
2768                 glEnd();
2769         }
2770
2771         if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
2772         
2773         for(nu=nurb; nu; nu=nu->next) {
2774                 if((nu->type & 7)==1) tekenhandlesN(nu, 1);
2775                 tekenvertsN(nu, 0);
2776         }
2777
2778         for(nu=nurb; nu; nu=nu->next) {
2779                 tekenvertsN(nu, 1);
2780         }
2781         
2782         if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); 
2783 }
2784
2785 static void tekentextcurs(void)
2786 {
2787         cpack(0);
2788
2789         glBegin(GL_QUADS);
2790         glVertex2fv(G.textcurs[0]);
2791         glVertex2fv(G.textcurs[1]);
2792         glVertex2fv(G.textcurs[2]);
2793         glVertex2fv(G.textcurs[3]);
2794         glEnd();
2795 }
2796
2797 static void drawspiral(float *cent, float rad, float tmat[][4], int start)
2798 {
2799         float vec[3], vx[3], vy[3];
2800         int a, tot=32;
2801         char inverse=0;
2802         /* 32 values of sin function (still same result!) */
2803         static float si[32] = {0.00000000,
2804                 0.20129852,
2805                 0.39435585,
2806                 0.57126821,
2807                 0.72479278,
2808                 0.84864425,
2809                 0.93775213,
2810                 0.98846832,
2811                 0.99871650,
2812                 0.96807711,
2813                 0.89780453,
2814                 0.79077573,
2815                 0.65137248,
2816                 0.48530196,
2817                 0.29936312,
2818                 0.10116832,
2819                 -0.10116832,
2820                 -0.29936312,
2821                 -0.48530196,
2822                 -0.65137248,
2823                 -0.79077573,
2824                 -0.89780453,
2825                 -0.96807711,
2826                 -0.99871650,
2827                 -0.98846832,
2828                 -0.93775213,
2829                 -0.84864425,
2830                 -0.72479278,
2831                 -0.57126821,
2832                 -0.39435585,
2833                 -0.20129852,
2834                 0.00000000};
2835         /* 32 values of cos function (still same result!) */
2836         static float co[32] ={1.00000000,
2837                 0.97952994,
2838                 0.91895781,
2839                 0.82076344,
2840                 0.68896691,
2841                 0.52896401,
2842                 0.34730525,
2843                 0.15142777,
2844                 -0.05064916,
2845                 -0.25065253,
2846                 -0.44039415,
2847                 -0.61210598,
2848                 -0.75875812,
2849                 -0.87434661,
2850                 -0.95413925,
2851                 -0.99486932,
2852                 -0.99486932,
2853                 -0.95413925,
2854                 -0.87434661,
2855                 -0.75875812,
2856                 -0.61210598,
2857                 -0.44039415,
2858                 -0.25065253,
2859                 -0.05064916,
2860                 0.15142777,
2861                 0.34730525,
2862                 0.52896401,
2863                 0.68896691,
2864                 0.82076344,
2865                 0.91895781,
2866                 0.97952994,
2867                 1.00000000};
2868                 
2869         if (start < 0) {
2870                 inverse = 1;
2871                 start *= -1;
2872         }
2873
2874         VECCOPY(vx, tmat[0]);
2875         VECCOPY(vy, tmat[1]);
2876         VecMulf(vx, rad);
2877         VecMulf(vy, rad);
2878
2879         VECCOPY(vec, cent);
2880
2881         if (inverse==0) {
2882                 for(a=0; a<tot; a++) {
2883                         if (a+start>31)
2884                                 start=-a + 1;
2885                         glBegin(GL_LINES);                                                      
2886                         glVertex3fv(vec);
2887                         vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)a/(float)tot) + *(co+a+start) * (vy[0] * (float)a/(float)tot);
2888                         vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)a/(float)tot) + *(co+a+start) * (vy[1] * (float)a/(float)tot);
2889                         vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)a/(float)tot) + *(co+a+start) * (vy[2] * (float)a/(float)tot);
2890                         glVertex3fv(vec);
2891                         glEnd();
2892                 }
2893         }
2894         else {
2895                 a=0;
2896                 vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
2897                 vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
2898                 vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
2899                 for(a=0; a<tot; a++) {
2900                         if (a+start>31)
2901                                 start=-a + 1;
2902                         glBegin(GL_LINES);                                                      
2903                         glVertex3fv(vec);
2904                         vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
2905                         vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
2906                         vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
2907                         glVertex3fv(vec);
2908                         glEnd();
2909                 }
2910         }
2911 }
2912
2913 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
2914 {
2915         float vec[3], vx[3], vy[3];
2916         int a, tot=32;
2917
2918         /* 32 values of sin function (still same result!) */
2919         static float si[32] = {0.00000000,
2920                 0.20129852,
2921                 0.39435585,
2922                 0.57126821,
2923                 0.72479278,
2924                 0.84864425,
2925                 0.93775213,
2926                 0.98846832,
2927                 0.99871650,
2928                 0.96807711,
2929                 0.89780453,
2930                 0.79077573,
2931                 0.65137248,
2932                 0.48530196,
2933                 0.29936312,
2934                 0.10116832,
2935                 -0.10116832,
2936                 -0.29936312,
2937                 -0.48530196,
2938                 -0.65137248,
2939                 -0.79077573,
2940                 -0.89780453,
2941                 -0.96807711,
2942                 -0.99871650,
2943                 -0.98846832,
2944                 -0.93775213,
2945                 -0.84864425,
2946                 -0.72479278,
2947                 -0.57126821,
2948                 -0.39435585,
2949                 -0.20129852,
2950                 0.00000000};
2951         /* 32 values of cos function (still same result!) */
2952         static float co[32] ={1.00000000,
2953                 0.97952994,
2954                 0.91895781,
2955                 0.82076344,
2956                 0.68896691,
2957                 0.52896401,
2958                 0.34730525,
2959                 0.15142777,
2960                 -0.05064916,
2961                 -0.25065253,
2962                 -0.44039415,
2963                 -0.61210598,
2964                 -0.75875812,
2965                 -0.87434661,
2966                 -0.95413925,
2967                 -0.99486932,
2968                 -0.99486932,
2969                 -0.95413925,
2970                 -0.87434661,
2971                 -0.75875812,
2972                 -0.61210598,
2973                 -0.44039415,
2974                 -0.25065253,
2975                 -0.05064916,
2976                 0.15142777,
2977                 0.34730525,
2978                 0.52896401,
2979                 0.68896691,
2980                 0.82076344,
2981                 0.91895781,
2982                 0.97952994,
2983                 1.00000000};
2984                 
2985         VECCOPY(vx, tmat[0]);
2986         VECCOPY(vy, tmat[1]);
2987         VecMulf(vx, rad);
2988         VecMulf(vy, rad);
2989         
2990         glBegin(mode);
2991         for(a=0; a<tot; a++) {
2992                 vec[0]= cent[0] + *(si+a) * vx[0] + *(co+a) * vy[0];
2993                 vec[1]= cent[1] + *(si+a) * vx[1] + *(co+a) * vy[1];
2994                 vec[2]= cent[2] + *(si+a) * vx[2] + *(co+a) * vy[2];
2995                 glVertex3fv(vec);
2996         }
2997         glEnd();
2998 }
2999
3000 static void drawmball(Object *ob, int dt)
3001 {
3002         MetaBall *mb;
3003         MetaElem *ml;
3004         float imat[4][4], tmat[4][4];
3005         int code= 1;
3006         
3007         mb= ob->data;
3008
3009         if(ob==G.obedit) {
3010                 BIF_ThemeColor(TH_WIRE);
3011                 if((G.f & G_PICKSEL)==0 ) drawDispList(ob, dt);
3012                 ml= editelems.first;
3013         }
3014         else {
3015                 drawDispList(ob, dt);
3016                 ml= mb->elems.first;
3017         }
3018
3019         /* in case solid draw, reset wire colors */
3020         if(ob!=G.obedit && (ob->flag & SELECT)) {
3021                 if(ob==OBACT) BIF_ThemeColor(TH_ACTIVE);
3022                 else BIF_ThemeColor(TH_SELECT);
3023         }
3024         else BIF_ThemeColor(TH_WIRE);
3025
3026         mygetmatrix(tmat);
3027         Mat4Invert(imat, tmat);
3028         Normalise(imat[0]);
3029         Normalise(imat[1]);
3030         
3031         while(ml) {
3032         
3033                 /* draw radius */
3034                 if(ob==G.obedit) {
3035                         if((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0);
3036                         else cpack(0x3030A0);
3037                         
3038                         if(G.f & G_PICKSEL) {
3039                                 ml->selcol1= code;
3040                                 glLoadName(code++);
3041                         }
3042                 }
3043                 drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
3044
3045                 /* draw stiffness */
3046                 if(ob==G.obedit) {
3047                         if((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0);
3048                         else cpack(0x30A030);
3049                         
3050                         if(G.f & G_PICKSEL) {
3051                                 ml->selcol2= code;
3052                                 glLoadName(code++);
3053                         }
3054                         drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad*atan(ml->s)/M_PI_2, imat);
3055                 }
3056                 
3057                 ml= ml->next;
3058         }
3059 }
3060
3061 static void draw_forcefield(Object *ob)
3062 {
3063         PartDeflect *pd= ob->pd;
3064         float imat[4][4], tmat[4][4];
3065         float vec[3]= {0.0, 0.0, 0.0};
3066         
3067         /* calculus here, is reused in PFIELD_FORCE */
3068         mygetmatrix(tmat);
3069         Mat4Invert(imat, tmat);
3070 //      Normalise(imat[0]);             // we don't do this because field doesnt scale either... apart from wind!
3071 //      Normalise(imat[1]);
3072         
3073         if(pd->flag & PFIELD_USEMAX) {
3074                 setlinestyle(3);
3075                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
3076                 drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
3077                 setlinestyle(0);
3078         }
3079         if (pd->forcefield == PFIELD_WIND) {
3080                 float force_val;
3081                 
3082                 Mat4One(tmat);
3083                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
3084                 
3085                 if (has_ipo_code(ob->ipo, OB_PD_FSTR))
3086                         force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
3087                 else 
3088                         force_val = pd->f_strength;
3089                 force_val*= 0.1;
3090                 drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
3091                 vec[2]= 0.5*force_val;
3092                 drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
3093                 vec[2]= 1.0*force_val;
3094                 drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
3095                 vec[2]= 1.5*force_val;
3096                 drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
3097                 
3098         }
3099         else if (pd->forcefield == PFIELD_FORCE) {
3100                 float ffall_val;
3101
3102                 if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
3103                         ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
3104                 else 
3105                         ffall_val = pd->f_power;
3106
3107                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
3108                 drawcircball(GL_LINE_LOOP, vec, 1.0, imat);
3109                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val));
3110                 drawcircball(GL_LINE_LOOP, vec, 1.5, imat);
3111                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
3112                 drawcircball(GL_LINE_LOOP, vec, 2.0, imat);
3113         }
3114         else if (pd->forcefield == PFIELD_VORTEX) {
3115                 float ffall_val, force_val;
3116
3117                 Mat4One(imat);
3118                 if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
3119                         ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
3120                 else 
3121                         ffall_val = pd->f_power;
3122
3123                 if (has_ipo_code(ob->ipo, OB_PD_FSTR))
3124                         force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
3125                 else 
3126                         force_val = pd->f_strength;
3127
3128                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
3129                 if (force_val < 0) {
3130                         drawspiral(vec, 1.0, imat, 1);
3131                         drawspiral(vec, 1.0, imat, 16);
3132                 }
3133                 else {
3134                         drawspiral(vec, 1.0, imat, -1);
3135                         drawspiral(vec, 1.0, imat, -16);
3136                 }
3137         }
3138         
3139 }