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