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