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