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