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