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