Bugfix #2746
[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 nr, 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_SEGM:
1939                         BIF_ThemeColor(TH_WIRE);
1940                         glDisable(GL_LIGHTING);
1941
1942                         parts= dl->parts;
1943                         while(parts--) {
1944                                 nr= dl->nr;
1945                                 glBegin(GL_LINE_STRIP);
1946                                 while(nr--) {
1947                                         glVertex3fv(data);
1948                                         data+=3;
1949                                 }
1950                                 glEnd();
1951                         }
1952                         glEnable(GL_LIGHTING);
1953                         break;
1954                 case DL_POLY:
1955                         BIF_ThemeColor(TH_WIRE);
1956                         glDisable(GL_LIGHTING);
1957                         parts= dl->parts;
1958                         while(parts--) {
1959                                 nr= dl->nr;
1960                                 glBegin(GL_LINE_LOOP);
1961                                 while(nr--) {
1962                                         glVertex3fv(data);
1963                                         data+=3;
1964                                 }
1965                                 glEnd();
1966                         }
1967                         glEnable(GL_LIGHTING);
1968                         break;
1969                 case DL_SURF:
1970
1971                         set_gl_material(dl->col+1);
1972                         
1973                         if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
1974                         else glShadeModel(GL_FLAT);
1975
1976                         for(a=0; a<dl->parts; a++) {
1977                                 
1978                                 DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
1979                                 
1980                                 v1= data+ 3*p1; 
1981                                 v2= data+ 3*p2;
1982                                 v3= data+ 3*p3; 
1983                                 v4= data+ 3*p4;
1984                                 n1= ndata+ 3*p1; 
1985                                 n2= ndata+ 3*p2;
1986                                 n3= ndata+ 3*p3; 
1987                                 n4= ndata+ 3*p4;
1988                                 
1989                                 glBegin(GL_QUAD_STRIP);
1990                                 
1991                                 glNormal3fv(n2); glVertex3fv(v2);
1992                                 glNormal3fv(n4); glVertex3fv(v4);
1993
1994                                 for(; b<dl->nr; b++) {
1995                                         
1996                                         glNormal3fv(n1); glVertex3fv(v1);
1997                                         glNormal3fv(n3); glVertex3fv(v3);
1998
1999                                         v2= v1; v1+= 3;
2000                                         v4= v3; v3+= 3;
2001                                         n2= n1; n1+= 3;
2002                                         n4= n3; n3+= 3;
2003                                 }
2004                                 
2005                                 
2006                                 glEnd();
2007                         }
2008                         break;
2009
2010                 case DL_INDEX3:
2011                 
2012                         parts= dl->parts;
2013                         data= dl->verts;
2014                         ndata= dl->nors;
2015                         index= dl->index;
2016
2017                         set_gl_material(dl->col+1);
2018                                                         
2019                         /* voor polys only one normal needed */
2020                         if(index3_nors_incr==0) {
2021                                 while(parts--) {
2022
2023                                         glBegin(GL_TRIANGLES);
2024                                                 glNormal3fv(ndata);
2025                                                 glVertex3fv(data+3*index[0]);
2026                                                 glVertex3fv(data+3*index[1]);
2027                                                 glVertex3fv(data+3*index[2]);
2028                                         glEnd();
2029                                         index+= 3;
2030                                 }
2031                         }
2032                         else {
2033                                 while(parts--) {
2034
2035                                         glBegin(GL_TRIANGLES);
2036                                                 ofs= 3*index[0];
2037                                                 glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2038                                                 ofs= 3*index[1];
2039                                                 glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2040                                                 ofs= 3*index[2];
2041                                                 glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2042                                         glEnd();
2043                                         index+= 3;
2044                                 }
2045                         }
2046                         break;
2047
2048                 case DL_INDEX4:
2049
2050                         parts= dl->parts;
2051                         data= dl->verts;
2052                         ndata= dl->nors;
2053                         index= dl->index;
2054
2055                         set_gl_material(dl->col+1);
2056                 
2057                         while(parts--) {
2058
2059                                 glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
2060                                         ofs= 3*index[0];
2061                                         glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2062                                         ofs= 3*index[1];
2063                                         glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2064                                         ofs= 3*index[2];
2065                                         glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2066                                         if(index[3]) {
2067                                                 ofs= 3*index[3];
2068                                                 glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
2069                                         }
2070                                 glEnd();
2071                                 index+= 4;
2072                         }
2073                         break;
2074                 }
2075                 dl= dl->next;
2076         }
2077
2078         glShadeModel(GL_FLAT);
2079         glDisable(GL_LIGHTING);
2080         glFrontFace(GL_CCW);
2081 }
2082
2083 static void drawDispListshaded(ListBase *lb, Object *ob)
2084 {
2085         DispList *dl, *dlob;
2086         int parts, p1, p2, p3, p4, a, b, *index;
2087         float *data, *v1, *v2, *v3, *v4;
2088         unsigned int *cdata, *c1, *c2, *c3, *c4;
2089         char *cp;
2090
2091         if(lb==0) return;
2092
2093         glShadeModel(GL_SMOOTH);
2094
2095         dl= lb->first;
2096         dlob= ob->disp.first;
2097         while(dl && dlob) {
2098                 
2099                 cdata= dlob->col1;
2100                 data= dl->verts;
2101                 if(cdata==0) break;
2102                 
2103                 switch(dl->type) {
2104                 case DL_SURF:
2105
2106                         for(a=0; a<dl->parts; a++) {
2107
2108                                 DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
2109
2110                                 v1= data+ 3*p1; 
2111                                 v2= data+ 3*p2;
2112                                 v3= data+ 3*p3; 
2113                                 v4= data+ 3*p4;
2114                                 c1= cdata+ p1; 
2115                                 c2= cdata+ p2;
2116                                 c3= cdata+ p3; 
2117                                 c4= cdata+ p4;
2118
2119                                 for(; b<dl->nr; b++) {
2120
2121                                         glBegin(GL_QUADS);
2122                                                 cp= (char *)c1;
2123                                                 glColor3ub(cp[3], cp[2], cp[1]);
2124                                                 glVertex3fv(v1);
2125                                                 cp= (char *)c2;
2126                                                 glColor3ub(cp[3], cp[2], cp[1]);
2127                                                 glVertex3fv(v2);
2128                                                 cp= (char *)c4;
2129                                                 glColor3ub(cp[3], cp[2], cp[1]);
2130                                                 glVertex3fv(v4);
2131                                                 cp= (char *)c3;
2132                                                 glColor3ub(cp[3], cp[2], cp[1]);
2133                                                 glVertex3fv(v3);
2134                                         glEnd();
2135
2136                                         v2= v1; v1+= 3;
2137                                         v4= v3; v3+= 3;
2138                                         c2= c1; c1++;
2139                                         c4= c3; c3++;
2140                                 }
2141                         }
2142                         break;
2143
2144                 case DL_INDEX3:
2145                         
2146                         parts= dl->parts;
2147                         index= dl->index;
2148                         
2149                         while(parts--) {
2150
2151                                 glBegin(GL_TRIANGLES);
2152                                         cp= (char *)(cdata+index[0]);
2153                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2154                                         glVertex3fv(data+3*index[0]);
2155
2156                                         cp= (char *)(cdata+index[1]);
2157                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2158                                         glVertex3fv(data+3*index[1]);
2159
2160                                         cp= (char *)(cdata+index[2]);
2161                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2162                                         glVertex3fv(data+3*index[2]);
2163                                 glEnd();
2164                                 index+= 3;
2165                         }
2166                         break;
2167
2168                 case DL_INDEX4:
2169                 
2170                         parts= dl->parts;
2171                         index= dl->index;
2172                         while(parts--) {
2173
2174                                 glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
2175                                         cp= (char *)(cdata+index[0]);
2176                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2177                                         glVertex3fv(data+3*index[0]);
2178
2179                                         cp= (char *)(cdata+index[1]);
2180                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2181                                         glVertex3fv(data+3*index[1]);
2182
2183                                         cp= (char *)(cdata+index[2]);
2184                                         glColor3ub(cp[3], cp[2], cp[1]);                                        
2185                                         glVertex3fv(data+3*index[2]);
2186                                         
2187                                         if(index[3]) {
2188                                         
2189                                                 cp= (char *)(cdata+index[3]);
2190                                                 glColor3ub(cp[3], cp[2], cp[1]);        
2191                                                 glVertex3fv(data+3*index[3]);
2192                                         }
2193                                 glEnd();
2194                                 index+= 4;
2195                         }
2196                         break;
2197                         
2198                 }
2199                 dl= dl->next;
2200                 dlob= dlob->next;
2201         }
2202         
2203         glShadeModel(GL_FLAT);
2204 }
2205
2206 static void drawDispList(Object *ob, int dt)
2207 {
2208         ListBase *lb=0;
2209         DispList *dl;
2210         Curve *cu;
2211         int solid;
2212
2213         
2214         solid= (dt > OB_WIRE);
2215
2216         switch(ob->type) {
2217         case OB_FONT:
2218         case OB_CURVE:
2219                 cu= ob->data;
2220                 
2221                 lb= &cu->disp;
2222                 
2223                 if(solid) {
2224                         dl= lb->first;
2225                         if(dl==0) return;
2226                         
2227                         if(dl->nors==0) addnormalsDispList(ob, lb);
2228                         index3_nors_incr= 0;
2229                         
2230                         if( displist_has_faces(lb)==0) {
2231                                 draw_index_wire= 0;
2232                                 drawDispListwire(lb);
2233                                 draw_index_wire= 1;
2234                         }
2235                         else {
2236                                 if(dt==OB_SHADED) {
2237                                         if(ob->disp.first==0) shadeDispList(ob);
2238                                         drawDispListshaded(lb, ob);
2239                                 }
2240                                 else {
2241                                         init_gl_materials(ob);
2242                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2243                                         drawDispListsolid(lb, ob);
2244                                 }
2245                                 if(ob==G.obedit) {
2246                                         cpack(0);
2247                                         draw_index_wire= 0;
2248                                         drawDispListwire(lb);
2249                                         draw_index_wire= 1;
2250                                 }
2251                         }
2252                         index3_nors_incr= 1;
2253                 }
2254                 else {
2255                         draw_index_wire= 0;
2256                         drawDispListwire(lb);
2257                         draw_index_wire= 1;
2258                 }
2259                 break;
2260         case OB_SURF:
2261         
2262                 lb= &((Curve *)ob->data)->disp;
2263                 
2264                 if(solid) {
2265                         dl= lb->first;
2266                         if(dl==0) return;
2267                         
2268                         if(dl->nors==0) addnormalsDispList(ob, lb);
2269                         
2270                         if(dt==OB_SHADED) {
2271                                 if(ob->disp.first==0) shadeDispList(ob);
2272                                 drawDispListshaded(lb, ob);
2273                         }
2274                         else {
2275                                 init_gl_materials(ob);
2276                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2277                         
2278                                 drawDispListsolid(lb, ob);
2279                         }
2280                 }
2281                 else {
2282                         drawDispListwire(lb);
2283                 }
2284                 break;
2285         case OB_MBALL:
2286                 
2287                 if( is_basis_mball(ob)) {
2288                         lb= &ob->disp;
2289                         if(lb->first==0) makeDispListMBall(ob);
2290         
2291                         if(solid) {
2292                                 
2293                                 if(dt==OB_SHADED) {
2294                                         dl= lb->first;
2295                                         if(dl && dl->col1==0) shadeDispList(ob);
2296                                         drawDispListshaded(lb, ob);
2297                                 }
2298                                 else {
2299                                         init_gl_materials(ob);
2300                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2301                                 
2302                                         drawDispListsolid(lb, ob);      
2303                                 }
2304                         }
2305                         else{
2306                                 /* MetaBalls use DL_INDEX4 type of DispList */
2307                                 drawDispListwire(lb);
2308                         }
2309                 }
2310                 break;
2311         }
2312         
2313 }
2314
2315 /* ******************************** */
2316
2317
2318 static void draw_particle_system(Object *ob, PartEff *paf)
2319 {
2320         Particle *pa;
2321         float ptime, ctime, vec[3], vec1[3];
2322         int a;
2323         
2324         pa= paf->keys;
2325         if(pa==0) {
2326                 build_particle_system(ob);
2327                 pa= paf->keys;
2328                 if(pa==0) return;
2329         }
2330         
2331         myloadmatrix(G.vd->viewmat);
2332         
2333         if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
2334         else ptime= 0.0;
2335         ctime= bsystem_time(ob, 0, (float)(G.scene->r.cfra), ptime);
2336
2337         glPointSize(1.0);
2338         if(paf->stype!=PAF_VECT) glBegin(GL_POINTS);
2339
2340         for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
2341                 
2342                 if(ctime > pa->time) {
2343                         if(ctime < pa->time+pa->lifetime) {
2344                         
2345                                 if(paf->stype==PAF_VECT) {
2346                                         where_is_particle(paf, pa, ctime, vec);
2347                                         where_is_particle(paf, pa, ctime+1.0, vec1);
2348                 
2349
2350                                         glBegin(GL_LINE_STRIP);
2351                                                 glVertex3fv(vec);
2352                                                 glVertex3fv(vec1);
2353                                         glEnd();
2354                                         
2355                                 }
2356                                 else {
2357                                         where_is_particle(paf, pa, ctime, vec);
2358                                         
2359                                         glVertex3fv(vec);
2360                                                 
2361                                 }
2362                         }
2363                 }
2364         }
2365         if(paf->stype!=PAF_VECT) glEnd();
2366         
2367         mymultmatrix(ob->obmat);        // bring back local matrix for dtx
2368 }
2369
2370 static void draw_static_particle_system(Object *ob, PartEff *paf)
2371 {
2372         Particle *pa;
2373         float ctime, mtime, vec[3], vec1[3];
2374         int a;
2375         
2376         pa= paf->keys;
2377         if(pa==0) {
2378                 build_particle_system(ob);
2379                 pa= paf->keys;
2380                 if(pa==0) return;
2381         }
2382         
2383         glPointSize(1.0);
2384         if(paf->stype!=PAF_VECT) glBegin(GL_POINTS);
2385
2386         for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
2387                 
2388                 where_is_particle(paf, pa, pa->time, vec1);
2389                 
2390                 mtime= pa->time+pa->lifetime+paf->staticstep-1;
2391                 
2392                 for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
2393                         
2394                         /* make sure hair grows until the end.. */ 
2395                         if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
2396                         
2397                         if(paf->stype==PAF_VECT) {
2398                                 where_is_particle(paf, pa, ctime+1, vec);
2399
2400                                 glBegin(GL_LINE_STRIP);
2401                                         glVertex3fv(vec);
2402                                         glVertex3fv(vec1);
2403                                 glEnd();
2404                                 
2405                                 VECCOPY(vec1, vec);
2406                         }
2407                         else {
2408                                 where_is_particle(paf, pa, ctime, vec);
2409                                 
2410                                 glVertex3fv(vec);
2411                                         
2412                         }
2413                 }
2414         }
2415         if(paf->stype!=PAF_VECT) glEnd();
2416
2417 }
2418
2419 unsigned int nurbcol[8]= {
2420         0, 0x9090, 0x409030, 0x603080, 0, 0x40fff0, 0x40c033, 0xA090F0 };
2421
2422 static void tekenhandlesN(Nurb *nu, short sel)
2423 {
2424         BezTriple *bezt;
2425         float *fp;
2426         unsigned int *col;
2427         int a;
2428
2429         if(nu->hide) return;
2430         if( (nu->type & 7)==1) {
2431                 if(sel) col= nurbcol+4;
2432                 else col= nurbcol;
2433
2434                 bezt= nu->bezt;
2435                 a= nu->pntsu;
2436                 while(a--) {
2437                         if(bezt->hide==0) {
2438                                 if( (bezt->f2 & 1)==sel) {
2439                                         fp= bezt->vec[0];
2440                                         cpack(col[bezt->h1]);
2441
2442                                         glBegin(GL_LINE_STRIP); 
2443                                         glVertex3fv(fp);
2444                                         glVertex3fv(fp+3); 
2445                                         glEnd();
2446                                         cpack(col[bezt->h2]);
2447
2448                                         glBegin(GL_LINE_STRIP); 
2449                                         glVertex3fv(fp+3); 
2450                                         glVertex3fv(fp+6); 
2451                                         glEnd();
2452                                 }
2453                                 else if( (bezt->f1 & 1)==sel) {
2454                                         fp= bezt->vec[0];
2455                                         cpack(col[bezt->h1]);
2456
2457                                         glBegin(GL_LINE_STRIP); 
2458                                         glVertex3fv(fp); 
2459                                         glVertex3fv(fp+3); 
2460                                         glEnd();
2461                                 }
2462                                 else if( (bezt->f3 & 1)==sel) {
2463                                         fp= bezt->vec[1];
2464                                         cpack(col[bezt->h2]);
2465
2466                                         glBegin(GL_LINE_STRIP); 
2467                                         glVertex3fv(fp); 
2468                                         glVertex3fv(fp+3); 
2469                                         glEnd();
2470                                 }
2471                         }
2472                         bezt++;
2473                 }
2474         }
2475 }
2476
2477 static void tekenvertsN(Nurb *nu, short sel)
2478 {
2479         BezTriple *bezt;
2480         BPoint *bp;
2481         float size;
2482         int a;
2483
2484         if(nu->hide) return;
2485
2486         if(sel) BIF_ThemeColor(TH_VERTEX_SELECT);
2487         else BIF_ThemeColor(TH_VERTEX);
2488
2489         size= BIF_GetThemeValuef(TH_VERTEX_SIZE);
2490         glPointSize(size);
2491         
2492         bglBegin(GL_POINTS);
2493         
2494         if((nu->type & 7)==1) {
2495
2496                 bezt= nu->bezt;
2497                 a= nu->pntsu;
2498                 while(a--) {
2499                         if(bezt->hide==0) {
2500                                 if((bezt->f1 & 1)==sel) bglVertex3fv(bezt->vec[0]);
2501                                 if((bezt->f2 & 1)==sel) bglVertex3fv(bezt->vec[1]);
2502                                 if((bezt->f3 & 1)==sel) bglVertex3fv(bezt->vec[2]);
2503                         }
2504                         bezt++;
2505                 }
2506         }
2507         else {
2508                 bp= nu->bp;
2509                 a= nu->pntsu*nu->pntsv;
2510                 while(a--) {
2511                         if(bp->hide==0) {
2512                                 if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec);
2513                         }
2514                         bp++;
2515                 }
2516         }
2517         
2518         bglEnd();
2519         glPointSize(1.0);
2520 }
2521
2522 static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
2523 {
2524         Nurb *nu;
2525         BPoint *bp, *bp1;
2526         int a, b, ofs;
2527         
2528         nu= nurb;
2529         while(nu) {
2530                 if(nu->hide==0) {
2531                         switch(nu->type & 7) {
2532                         case CU_POLY:
2533                                 cpack(nurbcol[3]);
2534                                 bp= nu->bp;
2535                                 for(b=0; b<nu->pntsv; b++) {
2536                                         if(nu->flagu & 1) glBegin(GL_LINE_LOOP);
2537
2538                                         else glBegin(GL_LINE_STRIP);
2539
2540                                         for(a=0; a<nu->pntsu; a++, bp++) {
2541                                                 glVertex3fv(bp->vec);
2542                                         }
2543
2544                                         if(nu->flagu & 1) glEnd();
2545                                         else glEnd();
2546                                 }
2547                                 break;
2548                         case CU_NURBS:
2549
2550                                 bp= nu->bp;
2551                                 for(b=0; b<nu->pntsv; b++) {
2552                                         bp1= bp;
2553                                         bp++;
2554                                         for(a=nu->pntsu-1; a>0; a--, bp++) {
2555                                                 if(bp->hide==0 && bp1->hide==0) {
2556                                                         if(sel) {
2557                                                                 if( (bp->f1 & 1) && ( bp1->f1 & 1) ) {
2558                                                                         cpack(nurbcol[5]);
2559                 
2560                                                                         glBegin(GL_LINE_STRIP);
2561                                                                         glVertex3fv(bp->vec); 
2562                                                                         glVertex3fv(bp1->vec);
2563                                                                         glEnd();
2564                                                                 }
2565                                                         }
2566                                                         else {
2567                                                                 if( (bp->f1 & 1) && ( bp1->f1 & 1) );
2568                                                                 else {
2569                                                                         cpack(nurbcol[1]);
2570                 
2571                                                                         glBegin(GL_LINE_STRIP);
2572                                                                         glVertex3fv(bp->vec); 
2573                                                                         glVertex3fv(bp1->vec);
2574                                                                         glEnd();
2575                                                                 }
2576                                                         }
2577                                                 }
2578                                                 bp1= bp;
2579                                         }
2580                                 }
2581                                 if(nu->pntsv > 1) {     /* surface */
2582
2583                                         ofs= nu->pntsu;
2584                                         for(b=0; b<nu->pntsu; b++) {
2585                                                 bp1= nu->bp+b;
2586                                                 bp= bp1+ofs;
2587                                                 for(a=nu->pntsv-1; a>0; a--, bp+=ofs) {
2588                                                         if(bp->hide==0 && bp1->hide==0) {
2589                                                                 if(sel) {
2590                                                                         if( (bp->f1 & 1) && ( bp1->f1 & 1) ) {
2591                                                                                 cpack(nurbcol[7]);
2592                         
2593                                                                                 glBegin(GL_LINE_STRIP);
2594                                                                                 glVertex3fv(bp->vec); 
2595                                                                                 glVertex3fv(bp1->vec);
2596                                                                                 glEnd();
2597                                                                         }
2598                                                                 }
2599                                                                 else {
2600                                                                         if( (bp->f1 & 1) && ( bp1->f1 & 1) );
2601                                                                         else {
2602                                                                                 cpack(nurbcol[3]);
2603                         
2604                                                                                 glBegin(GL_LINE_STRIP);
2605                                                                                 glVertex3fv(bp->vec); 
2606                                                                                 glVertex3fv(bp1->vec);
2607                                                                                 glEnd();
2608                                                                         }
2609                                                                 }
2610                                                         }
2611                                                         bp1= bp;
2612                                                 }
2613                                         }
2614
2615                                 }
2616                                 break;
2617                         }
2618                 }
2619                 nu= nu->next;
2620         }
2621 }
2622
2623 static void drawnurb(Object *ob, Nurb *nurb, int dt)
2624 {
2625         Curve *cu = ob->data;
2626         Nurb *nu;
2627         BevList *bl;
2628
2629         /* first non-selected handles */
2630         for(nu=nurb; nu; nu=nu->next) {
2631                 if((nu->type & 7)==CU_BEZIER) {
2632                         tekenhandlesN(nu, 0);
2633                 }
2634         }
2635         
2636         /* then DispList */
2637         
2638         BIF_ThemeColor(TH_WIRE);
2639         drawDispList(ob, dt);
2640
2641         draw_editnurb(ob, nurb, 0);
2642         draw_editnurb(ob, nurb, 1);
2643
2644         if(cu->flag & CU_3D) {
2645                 BIF_ThemeColor(TH_WIRE);
2646                 glBegin(GL_LINES);
2647                 for (bl=cu->bev.first,nu=nurb; nu && bl; bl=bl->next,nu=nu->next) {
2648                         BevPoint *bevp= (BevPoint *)(bl+1);             
2649                         int nr= bl->nr;
2650                         int skip= nu->resolu/16;
2651                         
2652                         while (nr-->0) {
2653                                 float ox = G.scene->editbutsize*bevp->mat[0][0];
2654                                 float oy = G.scene->editbutsize*bevp->mat[0][1];
2655                                 float oz = G.scene->editbutsize*bevp->mat[0][2];
2656
2657                                 glVertex3f(bevp->x - ox, bevp->y - oy, bevp->z - oz);
2658                                 glVertex3f(bevp->x + ox, bevp->y + oy, bevp->z + oz);
2659                                 
2660                                 bevp += skip+1;
2661                                 nr -= skip;
2662                         }
2663                 }
2664                 glEnd();
2665         }
2666
2667         if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
2668         
2669         for(nu=nurb; nu; nu=nu->next) {
2670                 if((nu->type & 7)==1) tekenhandlesN(nu, 1);
2671                 tekenvertsN(nu, 0);
2672         }
2673
2674         for(nu=nurb; nu; nu=nu->next) {
2675                 tekenvertsN(nu, 1);
2676         }
2677         
2678         if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); 
2679 }
2680
2681 static void tekentextcurs(void)
2682 {
2683         cpack(0);
2684
2685         glBegin(GL_QUADS);
2686         glVertex2fv(G.textcurs[0]);
2687         glVertex2fv(G.textcurs[1]);
2688         glVertex2fv(G.textcurs[2]);
2689         glVertex2fv(G.textcurs[3]);
2690         glEnd();
2691 }
2692
2693 static void drawspiral(float *cent, float rad, float tmat[][4], int start)
2694 {
2695         float vec[3], vx[3], vy[3];
2696         int a, tot=32;
2697         char inverse=0;
2698         /* 32 values of sin function (still same result!) */
2699         static float si[32] = {0.00000000,
2700                 0.20129852,
2701                 0.39435585,
2702                 0.57126821,
2703                 0.72479278,
2704                 0.84864425,
2705                 0.93775213,
2706                 0.98846832,
2707                 0.99871650,
2708                 0.96807711,
2709                 0.89780453,
2710                 0.79077573,
2711                 0.65137248,
2712                 0.48530196,
2713                 0.29936312,
2714                 0.10116832,
2715                 -0.10116832,
2716                 -0.29936312,
2717                 -0.48530196,
2718                 -0.65137248,
2719                 -0.79077573,
2720                 -0.89780453,
2721                 -0.96807711,
2722                 -0.99871650,
2723                 -0.98846832,
2724                 -0.93775213,
2725                 -0.84864425,
2726                 -0.72479278,
2727                 -0.57126821,
2728                 -0.39435585,
2729                 -0.20129852,
2730                 0.00000000};
2731         /* 32 values of cos function (still same result!) */
2732         static float co[32] ={1.00000000,
2733                 0.97952994,
2734                 0.91895781,
2735                 0.82076344,
2736                 0.68896691,
2737                 0.52896401,
2738                 0.34730525,
2739                 0.15142777,
2740                 -0.05064916,
2741                 -0.25065253,
2742                 -0.44039415,
2743                 -0.61210598,
2744                 -0.75875812,
2745                 -0.87434661,
2746                 -0.95413925,
2747                 -0.99486932,
2748                 -0.99486932,
2749                 -0.95413925,
2750                 -0.87434661,
2751                 -0.75875812,
2752                 -0.61210598,
2753                 -0.44039415,
2754                 -0.25065253,
2755                 -0.05064916,
2756                 0.15142777,
2757                 0.34730525,
2758                 0.52896401,
2759                 0.68896691,
2760                 0.82076344,
2761                 0.91895781,
2762                 0.97952994,
2763                 1.00000000};
2764                 
2765         if (start < 0) {
2766                 inverse = 1;
2767                 start *= -1;
2768         }
2769
2770         VECCOPY(vx, tmat[0]);
2771         VECCOPY(vy, tmat[1]);
2772         VecMulf(vx, rad);
2773         VecMulf(vy, rad);
2774
2775         VECCOPY(vec, cent);
2776
2777         if (inverse==0) {
2778                 for(a=0; a<tot; a++) {
2779                         if (a+start>31)
2780                                 start=-a + 1;
2781                         glBegin(GL_LINES);                                                      
2782                         glVertex3fv(vec);
2783                         vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)a/(float)tot) + *(co+a+start) * (vy[0] * (float)a/(float)tot);
2784                         vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)a/(float)tot) + *(co+a+start) * (vy[1] * (float)a/(float)tot);
2785                         vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)a/(float)tot) + *(co+a+start) * (vy[2] * (float)a/(float)tot);
2786                         glVertex3fv(vec);
2787                         glEnd();
2788                 }
2789         }
2790         else {
2791                 a=0;
2792                 vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
2793                 vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
2794                 vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
2795                 for(a=0; a<tot; a++) {
2796                         if (a+start>31)
2797                                 start=-a + 1;
2798                         glBegin(GL_LINES);                                                      
2799                         glVertex3fv(vec);
2800                         vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
2801                         vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
2802                         vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
2803                         glVertex3fv(vec);
2804                         glEnd();
2805                 }
2806         }
2807 }
2808
2809 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
2810 {
2811         float vec[3], vx[3], vy[3];
2812         int a, tot=32;
2813
2814         /* 32 values of sin function (still same result!) */
2815         static float si[32] = {0.00000000,
2816                 0.20129852,
2817                 0.39435585,
2818                 0.57126821,
2819                 0.72479278,
2820                 0.84864425,
2821                 0.93775213,
2822                 0.98846832,
2823                 0.99871650,
2824                 0.96807711,
2825                 0.89780453,
2826                 0.79077573,
2827                 0.65137248,
2828                 0.48530196,
2829                 0.29936312,
2830                 0.10116832,
2831                 -0.10116832,
2832                 -0.29936312,
2833                 -0.48530196,
2834                 -0.65137248,
2835                 -0.79077573,
2836                 -0.89780453,
2837                 -0.96807711,
2838                 -0.99871650,
2839                 -0.98846832,
2840                 -0.93775213,
2841                 -0.84864425,
2842                 -0.72479278,
2843                 -0.57126821,
2844                 -0.39435585,
2845                 -0.20129852,
2846                 0.00000000};
2847         /* 32 values of cos function (still same result!) */
2848         static float co[32] ={1.00000000,
2849                 0.97952994,
2850                 0.91895781,
2851                 0.82076344,
2852                 0.68896691,
2853                 0.52896401,
2854                 0.34730525,
2855                 0.15142777,
2856                 -0.05064916,
2857                 -0.25065253,
2858                 -0.44039415,
2859                 -0.61210598,
2860                 -0.75875812,
2861                 -0.87434661,
2862                 -0.95413925,
2863                 -0.99486932,
2864                 -0.99486932,
2865                 -0.95413925,
2866                 -0.87434661,
2867                 -0.75875812,
2868                 -0.61210598,
2869                 -0.44039415,
2870                 -0.25065253,
2871                 -0.05064916,
2872                 0.15142777,
2873                 0.34730525,
2874                 0.52896401,
2875                 0.68896691,
2876                 0.82076344,
2877                 0.91895781,
2878                 0.97952994,
2879                 1.00000000};
2880                 
2881         VECCOPY(vx, tmat[0]);
2882         VECCOPY(vy, tmat[1]);
2883         VecMulf(vx, rad);
2884         VecMulf(vy, rad);
2885         
2886         glBegin(mode);
2887         for(a=0; a<tot; a++) {
2888                 vec[0]= cent[0] + *(si+a) * vx[0] + *(co+a) * vy[0];
2889                 vec[1]= cent[1] + *(si+a) * vx[1] + *(co+a) * vy[1];
2890                 vec[2]= cent[2] + *(si+a) * vx[2] + *(co+a) * vy[2];
2891                 glVertex3fv(vec);
2892         }
2893         glEnd();
2894 }
2895
2896 static void drawmball(Object *ob, int dt)
2897 {
2898         MetaBall *mb;
2899         MetaElem *ml;
2900         float imat[4][4], tmat[4][4];
2901         int code= 1;
2902         
2903         mb= ob->data;
2904
2905         if(ob==G.obedit) {
2906                 BIF_ThemeColor(TH_WIRE);
2907                 if((G.f & G_PICKSEL)==0 ) drawDispList(ob, dt);
2908                 ml= editelems.first;
2909         }
2910         else {
2911                 drawDispList(ob, dt);
2912                 ml= mb->elems.first;
2913         }
2914
2915         /* in case solid draw, reset wire colors */
2916         if(ob!=G.obedit && (ob->flag & SELECT)) {
2917                 if(ob==OBACT) BIF_ThemeColor(TH_ACTIVE);
2918                 else BIF_ThemeColor(TH_SELECT);
2919         }
2920         else BIF_ThemeColor(TH_WIRE);
2921
2922         mygetmatrix(tmat);
2923         Mat4Invert(imat, tmat);
2924         Normalise(imat[0]);
2925         Normalise(imat[1]);
2926         
2927         while(ml) {
2928         
2929                 /* draw radius */
2930                 if(ob==G.obedit) {
2931                         if((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0);
2932                         else cpack(0x3030A0);
2933                         
2934                         if(G.f & G_PICKSEL) {
2935                                 ml->selcol1= code;
2936                                 glLoadName(code++);
2937                         }
2938                 }
2939                 drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
2940
2941                 /* draw stiffness */
2942                 if(ob==G.obedit) {
2943                         if((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0);
2944                         else cpack(0x30A030);
2945                         
2946                         if(G.f & G_PICKSEL) {
2947                                 ml->selcol2= code;
2948                                 glLoadName(code++);
2949                         }
2950                         drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad*atan(ml->s)/M_PI_2, imat);
2951                 }
2952                 
2953                 ml= ml->next;
2954         }
2955 }
2956
2957 static void draw_forcefield(Object *ob)
2958 {
2959         PartDeflect *pd= ob->pd;
2960         float imat[4][4], tmat[4][4];
2961         float vec[3]= {0.0, 0.0, 0.0};
2962         
2963         /* calculus here, is reused in PFIELD_FORCE */
2964         mygetmatrix(tmat);
2965         Mat4Invert(imat, tmat);
2966 //      Normalise(imat[0]);             // we don't do this because field doesnt scale either... apart from wind!
2967 //      Normalise(imat[1]);
2968         
2969         if(pd->flag & PFIELD_USEMAX) {
2970                 setlinestyle(3);
2971                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
2972                 drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
2973                 setlinestyle(0);
2974         }
2975         if (pd->forcefield == PFIELD_WIND) {
2976                 float force_val;
2977                 
2978                 Mat4One(tmat);
2979                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
2980                 
2981                 if (has_ipo_code(ob->ipo, OB_PD_FSTR))
2982                         force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
2983                 else 
2984                         force_val = pd->f_strength;
2985                 force_val*= 0.1;
2986                 drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
2987                 vec[2]= 0.5*force_val;
2988                 drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
2989                 vec[2]= 1.0*force_val;
2990                 drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
2991                 vec[2]= 1.5*force_val;
2992                 drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
2993                 
2994         }
2995         else if (pd->forcefield == PFIELD_FORCE) {
2996                 float ffall_val;
2997
2998                 if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
2999                         ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
3000                 else 
3001                         ffall_val = pd->f_power;
3002
3003                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
3004                 drawcircball(GL_LINE_LOOP, vec, 1.0, imat);
3005                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val));
3006                 drawcircball(GL_LINE_LOOP, vec, 1.5, imat);
3007                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
3008                 drawcircball(GL_LINE_LOOP, vec, 2.0, imat);
3009         }
3010         else if (pd->forcefield == PFIELD_VORTEX) {
3011                 float ffall_val, force_val;
3012
3013                 Mat4One(imat);
3014                 if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
3015                         ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
3016                 else 
3017                         ffall_val = pd->f_power;
3018
3019                 if (has_ipo_code(ob->ipo, OB_PD_FSTR))
3020                         force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
3021                 else 
3022                         force_val = pd->f_strength;
3023
3024                 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
3025                 if (force_val < 0) {
3026                         drawspiral(vec, 1.0, imat, 1);
3027                         drawspiral(vec, 1.0, imat, 16);
3028                 }
3029                 else {
3030                         drawspiral(vec, 1.0, imat, -1);
3031                         drawspiral(vec, 1.0, imat, -16);
3032                 }
3033         }
3034         
3035 }
3036
3037 static void draw_box(float vec[8][3])
3038 {
3039         glBegin(GL_LINE_STRIP);
3040         glVertex3fv(vec[0]); glVertex3fv(vec[1]);glVertex3fv(vec[2]); glVertex3fv(vec[3]);
3041         glVertex3fv(vec[0]); glVertex3fv(vec[4]);glVertex3fv(vec[5]); glVertex3fv(vec[6]);
3042         glVertex3fv(vec[7]); glVertex3fv(vec[4]);
3043         glEnd();
3044
3045         glBegin(GL_LINES);
3046         glVertex3fv(vec[1]); glVertex3fv(vec[5]);
3047         glVertex3fv(vec[2]); glVertex3fv(vec[6]);
3048         glVertex3fv(vec[3]); glVertex3fv(vec[7]);
3049         glEnd();
3050 }
3051
3052 void get_local_bounds(Object *ob, float *centre, float *size)
3053 {
3054         BoundBox *bb= NULL;
3055         /* uses boundbox, function used by Ketsji */
3056         
3057         if(ob->type==OB_MESH) {
3058                 bb = mesh_get_bb(ob->data);
3059         }
3060         else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
3061                 bb= ( (Curve *)ob->data )->bb;
3062         }
3063         else if(ob->type==OB_MBALL) {
3064                 bb= ob->bb;
3065         }
3066         if(bb==NULL) {
3067                 centre[0]= centre[1]= centre[2]= 0.0;
3068                 VECCOPY(size, ob->size);
3069         }
3070         else {
3071                 size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
3072                 size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
3073                 size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
3074                 
3075                 centre[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
3076                 centre[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
3077                 centre[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
3078         }
3079 }
3080
3081
3082
3083 static void draw_bb_quadric(BoundBox *bb, short type)
3084 {
3085         float size[3], cent[3];
3086         GLUquadricObj *qobj = gluNewQuadric(); 
3087         
3088         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
3089         
3090         size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
3091         size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
3092         size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
3093         
3094         cent[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
3095         cent[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
3096         cent[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
3097         
3098         glPushMatrix();
3099         if(type==OB_BOUND_SPHERE) {
3100                 glTranslatef(cent[0], cent[1], cent[2]);
3101                 glScalef(size[0], size[1], size[2]);
3102                 gluSphere(qobj, 1.0, 8, 5);
3103         }       
3104         else if(type==OB_BOUND_CYLINDER) {
3105                 float radius = size[0] > size[1] ? size[0] : size[1];
3106                 glTranslatef(cent[0], cent[1], cent[2]-size[2]);
3107                 glScalef(radius, radius, 2.0*size[2]);
3108                 gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
3109         }
3110         else if(type==OB_BOUND_CONE) {
3111                 float radius = size[0] > size[1] ? size[0] : size[1];
3112                 glTranslatef(cent[0], cent[2]-size[2], cent[1]);
3113                 glScalef(radius, 2.0*size[2], radius);
3114                 glRotatef(-90., 1.0, 0.0, 0.0);
3115                 gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
3116         }
3117         glPopMatrix();
3118         
3119         gluDeleteQuadric(qobj); 
3120 }
3121
3122 static void draw_bounding_volume(Object *ob)
3123 {
3124         BoundBox *bb=0;
3125         
3126         if(ob->type==OB_MESH) {
3127                 bb= mesh_get_bb(ob->data);
3128         }
3129         else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
3130                 bb= ( (Curve *)ob->data )->bb;
3131         }
3132         else if(ob->type==OB_MBALL) {
3133                 bb= ob->bb;
3134                 if(bb==0) {
3135                         makeDispListMBall(ob);
3136                         bb= ob->bb;
3137                 }
3138         }
3139         else {
3140                 drawcube();
3141                 return;
3142         }
3143         
3144         if(bb==0) return;
3145         
3146         if(ob->boundtype==OB_BOUND_BOX) draw_box(bb->vec);
3147<