easier to re-apply the replacement table then merge from 2.4x, same as 23023
[blender.git] / source / blender / editors / space_view3d / drawobject.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, full recode and added functions
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <string.h>
29 #include <math.h>
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include "MEM_guardedalloc.h"
36
37 #include "IMB_imbuf.h"
38
39
40
41
42 #include "DNA_armature_types.h"
43 #include "DNA_boid_types.h"
44 #include "DNA_camera_types.h"
45 #include "DNA_curve_types.h"
46 #include "DNA_constraint_types.h" // for drawing constraint
47 #include "DNA_effect_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_material_types.h"
51 #include "DNA_mesh_types.h"
52 #include "DNA_meshdata_types.h"
53 #include "DNA_meta_types.h"
54 #include "DNA_modifier_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_object_force.h"
57 #include "DNA_object_fluidsim.h"
58 #include "DNA_particle_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_screen_types.h"
62 #include "DNA_smoke_types.h"
63 #include "DNA_userdef_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_world_types.h"
66
67 #include "BLI_blenlib.h"
68 #include "BLI_arithb.h"
69 #include "BLI_editVert.h"
70 #include "BLI_edgehash.h"
71 #include "BLI_rand.h"
72
73 #include "BKE_anim.h"                   //for the where_on_path function
74 #include "BKE_curve.h"
75 #include "BKE_constraint.h" // for the get_constraint_target function
76 #include "BKE_DerivedMesh.h"
77 #include "BKE_deform.h"
78 #include "BKE_displist.h"
79 #include "BKE_effect.h"
80 #include "BKE_font.h"
81 #include "BKE_global.h"
82 #include "BKE_image.h"
83 #include "BKE_key.h"
84 #include "BKE_lattice.h"
85 #include "BKE_mesh.h"
86 #include "BKE_material.h"
87 #include "BKE_mball.h"
88 #include "BKE_modifier.h"
89 #include "BKE_object.h"
90 #include "BKE_paint.h"
91 #include "BKE_particle.h"
92 #include "BKE_pointcache.h"
93 #include "BKE_property.h"
94 #include "BKE_smoke.h"
95 #include "BKE_unit.h"
96 #include "BKE_utildefines.h"
97 #include "smoke_API.h"
98
99 #include "BIF_gl.h"
100 #include "BIF_glutil.h"
101
102 #include "GPU_draw.h"
103 #include "GPU_material.h"
104 #include "GPU_extensions.h"
105
106 #include "ED_mesh.h"
107 #include "ED_particle.h"
108 #include "ED_screen.h"
109 #include "ED_types.h"
110 #include "ED_util.h"
111
112 #include "UI_resources.h"
113 #include "UI_interface_icons.h"
114
115 #include "WM_api.h"
116 #include "BLF_api.h"
117
118 #include "view3d_intern.h"      // own include
119
120
121 /* this condition has been made more complex since editmode can draw textures */
122 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
123 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
124         (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
125
126 #define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \
127 (       (sce->toolsettings->selectmode & SCE_SELECT_FACE) && \
128         (vd->drawtype<=OB_SOLID) && \
129         (((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \
130         )
131
132 static void draw_bounding_volume(Scene *scene, Object *ob);
133
134 static void drawcube_size(float size);
135 static void drawcircle_size(float size);
136 static void draw_empty_sphere(float size);
137 static void draw_empty_cone(float size);
138
139
140 /* ************* only use while object drawing ************** */
141 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
142 {
143         RegionView3D *rv3d= ar->regiondata;
144         float fx, fy, vec4[4];
145         
146         adr[0]= IS_CLIPPED;
147         
148         /* clipplanes in eye space */
149         if(rv3d->rflag & RV3D_CLIPPING) {
150                 VECCOPY(vec4, vec);
151                 Mat4MulVecfl(rv3d->viewmatob, vec4);
152                 if(view3d_test_clipping(rv3d, vec4))
153                         return;
154         }
155         
156         VECCOPY(vec4, vec);
157         vec4[3]= 1.0;
158         
159         Mat4MulVec4fl(rv3d->persmatob, vec4);
160         
161         /* clipplanes in window space */
162         if( vec4[3]>BL_NEAR_CLIP ) {    /* is the NEAR clipping cutoff for picking */
163                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
164                 
165                 if( fx>0 && fx<ar->winx) {
166                         
167                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
168                         
169                         if(fy>0.0 && fy< (float)ar->winy) {
170                                 adr[0]= (short)floor(fx); 
171                                 adr[1]= (short)floor(fy);
172                         }
173                 }
174         }
175 }
176
177 /* only use while object drawing */
178 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
179 {
180         RegionView3D *rv3d= ar->regiondata;
181         float fx, fy, vec4[4];
182         
183         adr[0]= IS_CLIPPED;
184         
185         VECCOPY(vec4, vec);
186         vec4[3]= 1.0;
187         
188         Mat4MulVec4fl(rv3d->persmatob, vec4);
189         
190         if( vec4[3]>BL_NEAR_CLIP ) {    /* is the NEAR clipping cutoff for picking */
191                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
192                 
193                 if( fx>-32700 && fx<32700) {
194                         
195                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
196                         
197                         if(fy>-32700.0 && fy<32700.0) {
198                                 adr[0]= (short)floor(fx); 
199                                 adr[1]= (short)floor(fy);
200                         }
201                 }
202         }
203 }
204
205 /* ************************ */
206
207 /* check for glsl drawing */
208
209 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
210 {
211         if(!GPU_extensions_minimum_support())
212                 return 0;
213         if(G.f & G_PICKSEL)
214                 return 0;
215         if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
216                 return 0;
217         if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
218                 return 0;
219         
220         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt >= OB_SHADED);
221 }
222
223 static int check_material_alpha(Base *base, Mesh *me, int glsl)
224 {
225         if(base->flag & OB_FROMDUPLI)
226                 return 0;
227
228         if(G.f & G_PICKSEL)
229                 return 0;
230                         
231         if(me->edit_mesh)
232                 return 0;
233         
234         return (glsl || (base->object->dtx & OB_DRAWTRANSP));
235 }
236
237         /***/
238 static unsigned int colortab[24]=
239         {0x0,           0xFF88FF, 0xFFBBFF, 
240          0x403000,      0xFFFF88, 0xFFFFBB, 
241          0x104040,      0x66CCCC, 0x77CCCC, 
242          0x104010,      0x55BB55, 0x66FF66, 
243          0xFFFFFF
244 };
245
246
247 static float cube[8][3] = {
248         {-1.0, -1.0, -1.0},
249         {-1.0, -1.0,  1.0},
250         {-1.0,  1.0,  1.0},
251         {-1.0,  1.0, -1.0},
252         { 1.0, -1.0, -1.0},
253         { 1.0, -1.0,  1.0},
254         { 1.0,  1.0,  1.0},
255         { 1.0,  1.0, -1.0},
256 };
257
258 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
259 /* 32 values of sin function (still same result!) */
260 static float sinval[32] = {
261         0.00000000,
262         0.20129852,
263         0.39435585,
264         0.57126821,
265         0.72479278,
266         0.84864425,
267         0.93775213,
268         0.98846832,
269         0.99871650,
270         0.96807711,
271         0.89780453,
272         0.79077573,
273         0.65137248,
274         0.48530196,
275         0.29936312,
276         0.10116832,
277         -0.10116832,
278         -0.29936312,
279         -0.48530196,
280         -0.65137248,
281         -0.79077573,
282         -0.89780453,
283         -0.96807711,
284         -0.99871650,
285         -0.98846832,
286         -0.93775213,
287         -0.84864425,
288         -0.72479278,
289         -0.57126821,
290         -0.39435585,
291         -0.20129852,
292         0.00000000
293 };
294
295 /* 32 values of cos function (still same result!) */
296 static float cosval[32] ={
297         1.00000000,
298         0.97952994,
299         0.91895781,
300         0.82076344,
301         0.68896691,
302         0.52896401,
303         0.34730525,
304         0.15142777,
305         -0.05064916,
306         -0.25065253,
307         -0.44039415,
308         -0.61210598,
309         -0.75875812,
310         -0.87434661,
311         -0.95413925,
312         -0.99486932,
313         -0.99486932,
314         -0.95413925,
315         -0.87434661,
316         -0.75875812,
317         -0.61210598,
318         -0.44039415,
319         -0.25065253,
320         -0.05064916,
321         0.15142777,
322         0.34730525,
323         0.52896401,
324         0.68896691,
325         0.82076344,
326         0.91895781,
327         0.97952994,
328         1.00000000
329 };
330
331 /* flag is same as for draw_object */
332 void drawaxes(float size, int flag, char drawtype)
333 {
334         int axis;
335         float v1[3]= {0.0, 0.0, 0.0};
336         float v2[3]= {0.0, 0.0, 0.0};
337         float v3[3]= {0.0, 0.0, 0.0};
338
339         if(G.f & G_RENDER_SHADOW)
340                 return;
341         
342         switch(drawtype) {
343         
344         case OB_PLAINAXES:
345                 for (axis=0; axis<3; axis++) {
346                         float v1[3]= {0.0, 0.0, 0.0};
347                         float v2[3]= {0.0, 0.0, 0.0};
348                         
349                         glBegin(GL_LINES);
350
351                         v1[axis]= size;
352                         v2[axis]= -size;
353                         glVertex3fv(v1);
354                         glVertex3fv(v2);
355                         
356                         glEnd();
357                 }
358                 break;
359         case OB_SINGLE_ARROW:
360         
361                 glBegin(GL_LINES);
362                 /* in positive z direction only */
363                 v1[2]= size;
364                 glVertex3fv(v1);
365                 glVertex3fv(v2);
366                 glEnd();
367                 
368                 /* square pyramid */
369                 glBegin(GL_TRIANGLES);
370                 
371                 v2[0]= size*0.035; v2[1] = size*0.035;
372                 v3[0]= size*-0.035; v3[1] = size*0.035;
373                 v2[2]= v3[2]= size*0.75;
374                 
375                 for (axis=0; axis<4; axis++) {
376                         if (axis % 2 == 1) {
377                                 v2[0] *= -1;
378                                 v3[1] *= -1;
379                         } else {
380                                 v2[1] *= -1;
381                                 v3[0] *= -1;
382                         }
383                         
384                         glVertex3fv(v1);
385                         glVertex3fv(v2);
386                         glVertex3fv(v3);
387                         
388                 }
389                 glEnd();
390                 
391                 break;
392         case OB_CUBE:
393                 drawcube_size(size);
394                 break;
395                 
396         case OB_CIRCLE:
397                 drawcircle_size(size);
398                 break;
399         
400         case OB_EMPTY_SPHERE:
401                  draw_empty_sphere(size);
402              break;
403
404         case OB_EMPTY_CONE:
405                  draw_empty_cone(size);
406              break;
407
408         case OB_ARROWS:
409         default:
410                 for (axis=0; axis<3; axis++) {
411                         float v1[3]= {0.0, 0.0, 0.0};
412                         float v2[3]= {0.0, 0.0, 0.0};
413                         int arrow_axis= (axis==0)?1:0;
414                         
415                         glBegin(GL_LINES);
416
417                         v2[axis]= size;
418                         glVertex3fv(v1);
419                         glVertex3fv(v2);
420                                 
421                         v1[axis]= size*0.8;
422                         v1[arrow_axis]= -size*0.125;
423                         glVertex3fv(v1);
424                         glVertex3fv(v2);
425                                 
426                         v1[arrow_axis]= size*0.125;
427                         glVertex3fv(v1);
428                         glVertex3fv(v2);
429
430                         glEnd();
431                                 
432                         v2[axis]+= size*0.125;
433                         
434                         // patch for 3d cards crashing on glSelect for text drawing (IBM)
435                         if((flag & DRAW_PICKING) == 0) {
436                                 if (axis==0)
437                                         view3d_object_text_draw_add(v2[0], v2[1], v2[2], "x", 0);
438                                 else if (axis==1)
439                                         view3d_object_text_draw_add(v2[0], v2[1], v2[2], "y", 0);
440                                 else
441                                         view3d_object_text_draw_add(v2[0], v2[1], v2[2], "z", 0);
442                         }
443                 }
444                 break;
445         }
446 }
447
448 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
449 {
450         float vec[3], vx[3], vy[3];
451         int a, tot=32;
452         
453         VECCOPY(vx, tmat[0]);
454         VECCOPY(vy, tmat[1]);
455         VecMulf(vx, rad);
456         VecMulf(vy, rad);
457         
458         glBegin(mode);
459         for(a=0; a<tot; a++) {
460                 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
461                 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
462                 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
463                 glVertex3fv(vec);
464         }
465         glEnd();
466 }
467
468 /* circle for object centers, special_color is for library or ob users */
469 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, float *vec, int selstate, int special_color)
470 {
471         float size;
472         
473         size= rv3d->persmat[0][3]*vec[0]+ rv3d->persmat[1][3]*vec[1]+ rv3d->persmat[2][3]*vec[2]+ rv3d->persmat[3][3];
474         size*= rv3d->pixsize*((float)U.obcenter_dia*0.5f);
475
476         /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
477         if(v3d->zbuf)  glDepthFunc(GL_ALWAYS);
478         glEnable(GL_BLEND);
479         
480         if(special_color) {
481                 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
482
483                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
484         }
485         else {
486                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
487                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
488                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
489         }
490         drawcircball(GL_POLYGON, vec, size, rv3d->viewinv);
491         
492         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
493         drawcircball(GL_LINE_LOOP, vec, size, rv3d->viewinv);
494         
495         glDisable(GL_BLEND);
496         if(v3d->zbuf)  glDepthFunc(GL_LEQUAL);
497 }
498
499 /* *********** text drawing for object ************* */
500 static ListBase strings= {NULL, NULL};
501
502 typedef struct ViewObjectString {
503         struct ViewObjectString *next, *prev;
504         float vec[3], col[4];
505         char str[128]; 
506         short mval[2];
507         short xoffs;
508 } ViewObjectString;
509
510
511 void view3d_object_text_draw_add(float x, float y, float z, char *str, short xoffs)
512 {
513         ViewObjectString *vos= MEM_callocN(sizeof(ViewObjectString), "ViewObjectString");
514
515         BLI_addtail(&strings, vos);
516         BLI_strncpy(vos->str, str, 128);
517         vos->vec[0]= x;
518         vos->vec[1]= y;
519         vos->vec[2]= z;
520         glGetFloatv(GL_CURRENT_COLOR, vos->col);
521         vos->xoffs= xoffs;
522 }
523
524 static void view3d_object_text_draw(View3D *v3d, ARegion *ar)
525 {
526         ViewObjectString *vos;
527         int tot= 0;
528         
529         /* project first and test */
530         for(vos= strings.first; vos; vos= vos->next) {
531                 view3d_project_short_clip(ar, vos->vec, vos->mval);
532                 if(vos->mval[0]!=IS_CLIPPED)
533                         tot++;
534         }
535         
536         if(tot) {
537                 RegionView3D *rv3d= ar->regiondata;
538                 int a;
539                 
540                 if(rv3d->rflag & RV3D_CLIPPING)
541                         for(a=0; a<6; a++)
542                                 glDisable(GL_CLIP_PLANE0+a);
543                 
544                 wmPushMatrix();
545                 ED_region_pixelspace(ar);
546                 
547                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
548                 
549                 for(vos= strings.first; vos; vos= vos->next) {
550                         if(vos->mval[0]!=IS_CLIPPED) {
551                                 glColor3fv(vos->col);
552                                 BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], 0.0, vos->str);
553                         }
554                 }
555                 
556                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
557                 
558                 wmPopMatrix();
559
560                 if(rv3d->rflag & RV3D_CLIPPING)
561                         for(a=0; a<6; a++)
562                                 glEnable(GL_CLIP_PLANE0+a);
563         }
564         
565         if(strings.first) 
566                 BLI_freelistN(&strings);
567 }
568
569 static void drawcube(void)
570 {
571
572         glBegin(GL_LINE_STRIP);
573                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
574                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
575                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
576         glEnd();
577
578         glBegin(GL_LINE_STRIP);
579                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
580         glEnd();
581
582         glBegin(GL_LINE_STRIP);
583                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
584         glEnd();
585
586         glBegin(GL_LINE_STRIP);
587                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
588         glEnd();
589 }
590
591 /* draws a cube on given the scaling of the cube, assuming that 
592  * all required matrices have been set (used for drawing empties)
593  */
594 static void drawcube_size(float size)
595 {
596         glBegin(GL_LINE_STRIP);
597                 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
598                 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
599                 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
600         glEnd();
601
602         glBegin(GL_LINE_STRIP);
603                 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
604         glEnd();
605
606         glBegin(GL_LINE_STRIP);
607                 glVertex3f(-size,size,size); glVertex3f(size,size,size);
608         glEnd();
609
610         glBegin(GL_LINE_STRIP);
611                 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
612         glEnd();
613 }
614
615 /* this is an unused (old) cube-drawing function based on a given size */
616 #if 0
617 static void drawcube_size(float *size)
618 {
619
620         glPushMatrix();
621         glScalef(size[0],  size[1],  size[2]);
622         
623
624         glBegin(GL_LINE_STRIP);
625                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
626                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
627                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
628         glEnd();
629
630         glBegin(GL_LINE_STRIP);
631                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
632         glEnd();
633
634         glBegin(GL_LINE_STRIP);
635                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
636         glEnd();
637
638         glBegin(GL_LINE_STRIP);
639                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
640         glEnd();
641         
642         glPopMatrix();
643 }
644 #endif
645
646 static void drawshadbuflimits(Lamp *la, float mat[][4])
647 {
648         float sta[3], end[3], lavec[3];
649
650         lavec[0]= -mat[2][0];
651         lavec[1]= -mat[2][1];
652         lavec[2]= -mat[2][2];
653         Normalize(lavec);
654
655         sta[0]= mat[3][0]+ la->clipsta*lavec[0];
656         sta[1]= mat[3][1]+ la->clipsta*lavec[1];
657         sta[2]= mat[3][2]+ la->clipsta*lavec[2];
658
659         end[0]= mat[3][0]+ la->clipend*lavec[0];
660         end[1]= mat[3][1]+ la->clipend*lavec[1];
661         end[2]= mat[3][2]+ la->clipend*lavec[2];
662
663
664         glBegin(GL_LINE_STRIP);
665                 glVertex3fv(sta);
666                 glVertex3fv(end);
667         glEnd();
668
669         glPointSize(3.0);
670         bglBegin(GL_POINTS);
671         bglVertex3fv(sta);
672         bglVertex3fv(end);
673         bglEnd();
674         glPointSize(1.0);
675 }
676
677
678
679 static void spotvolume(float *lvec, float *vvec, float inp)
680 {
681         /* camera is at 0,0,0 */
682         float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
683
684         Normalize(lvec);
685         Normalize(vvec);                                /* is this the correct vector ? */
686
687         Crossf(temp,vvec,lvec);         /* equation for a plane through vvec en lvec */
688         Crossf(plane,lvec,temp);                /* a plane perpendicular to this, parrallel with lvec */
689
690         Normalize(plane);
691
692         /* now we've got two equations: one of a cone and one of a plane, but we have
693         three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
694
695         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
696         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
697
698         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
699         
700         q[1] = plane[1] ; 
701         q[2] = -plane[0] ; 
702         q[3] = 0 ;
703         Normalize(&q[1]);
704
705         angle = saacos(plane[2])/2.0;
706         co = cos(angle);
707         si = sqrt(1-co*co);
708
709         q[0] =  co;
710         q[1] *= si;
711         q[2] *= si;
712         q[3] =  0;
713
714         QuatToMat3(q,mat1);
715
716         /* rotate lamp vector now over acos(inp) degrees */
717
718         vvec[0] = lvec[0] ; 
719         vvec[1] = lvec[1] ; 
720         vvec[2] = lvec[2] ;
721
722         Mat3One(mat2);
723         co = inp;
724         si = sqrt(1-inp*inp);
725
726         mat2[0][0] =  co;
727         mat2[1][0] = -si;
728         mat2[0][1] =  si;
729         mat2[1][1] =  co;
730         Mat3MulMat3(mat3,mat2,mat1);
731
732         mat2[1][0] =  si;
733         mat2[0][1] = -si;
734         Mat3MulMat3(mat4,mat2,mat1);
735         Mat3Transp(mat1);
736
737         Mat3MulMat3(mat2,mat1,mat3);
738         Mat3MulVecfl(mat2,lvec);
739         Mat3MulMat3(mat2,mat1,mat4);
740         Mat3MulVecfl(mat2,vvec);
741
742         return;
743 }
744
745 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
746 {
747         Lamp *la;
748         float vec[3], lvec[3], vvec[3], circrad, x,y,z;
749         float pixsize, lampsize;
750         float imat[4][4], curcol[4];
751         char col[4];
752
753         if(G.f & G_RENDER_SHADOW)
754                 return;
755         
756         la= ob->data;
757         
758         /* we first draw only the screen aligned & fixed scale stuff */
759         glPushMatrix();
760         wmLoadMatrix(rv3d->viewmat);
761
762         /* lets calculate the scale: */
763         pixsize= rv3d->persmat[0][3]*ob->obmat[3][0]+ rv3d->persmat[1][3]*ob->obmat[3][1]+ rv3d->persmat[2][3]*ob->obmat[3][2]+ rv3d->persmat[3][3];
764         pixsize*= rv3d->pixsize;
765         lampsize= pixsize*((float)U.obcenter_dia*0.5f);
766
767         /* and view aligned matrix: */
768         Mat4CpyMat4(imat, rv3d->viewinv);
769         Normalize(imat[0]);
770         Normalize(imat[1]);
771         
772         /* for AA effects */
773         glGetFloatv(GL_CURRENT_COLOR, curcol);
774         curcol[3]= 0.6;
775         glColor4fv(curcol);
776         
777         if(ob->id.us>1) {
778                 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
779                 else glColor4ub(0x77, 0xCC, 0xCC, 155);
780         }
781         
782         /* Inner Circle */
783         VECCOPY(vec, ob->obmat[3]);
784         glEnable(GL_BLEND);
785         drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
786         glDisable(GL_BLEND);
787         drawcircball(GL_POLYGON, vec, lampsize, imat);
788         
789         /* restore */
790         if(ob->id.us>1)
791                 glColor4fv(curcol);
792                 
793         /* Outer circle */
794         circrad = 3.0f*lampsize;
795         drawcircball(GL_LINE_LOOP, vec, circrad, imat);
796         
797         setlinestyle(3);
798
799         /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
800         if (la->type!=LA_HEMI) {
801                 if ((la->mode & LA_SHAD_RAY) ||
802                         ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
803                 {
804                         drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
805                 }
806         }
807         
808         /* draw the pretty sun rays */
809         if(la->type==LA_SUN) {
810                 float v1[3], v2[3], mat[3][3];
811                 short axis;
812                 
813                 /* setup a 45 degree rotation matrix */
814                 VecRotToMat3(imat[2], M_PI/4.0f, mat);
815                 
816                 /* vectors */
817                 VECCOPY(v1, imat[0]);
818                 VecMulf(v1, circrad*1.2f);
819                 VECCOPY(v2, imat[0]);
820                 VecMulf(v2, circrad*2.5f);
821                 
822                 /* center */
823                 glTranslatef(vec[0], vec[1], vec[2]);
824                 
825                 setlinestyle(3);
826                 
827                 glBegin(GL_LINES);
828                 for (axis=0; axis<8; axis++) {
829                         glVertex3fv(v1);
830                         glVertex3fv(v2);
831                         Mat3MulVecfl(mat, v1);
832                         Mat3MulVecfl(mat, v2);
833                 }
834                 glEnd();
835                 
836                 glTranslatef(-vec[0], -vec[1], -vec[2]);
837
838         }               
839         
840         if (la->type==LA_LOCAL) {
841                 if(la->mode & LA_SPHERE) {
842                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
843                 }
844                 /* yafray: for photonlight also draw lightcone as for spot */
845         }
846         
847         glPopMatrix();  /* back in object space */
848         vec[0]= vec[1]= vec[2]= 0.0f;
849         
850         if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {  
851                 lvec[0]=lvec[1]= 0.0; 
852                 lvec[2] = 1.0;
853                 x = rv3d->persmat[0][2];
854                 y = rv3d->persmat[1][2];
855                 z = rv3d->persmat[2][2];
856                 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
857                 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
858                 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
859
860                 y = cos( M_PI*la->spotsize/360.0 );
861                 spotvolume(lvec, vvec, y);
862                 x = -la->dist;
863                 lvec[0] *=  x ; 
864                 lvec[1] *=  x ; 
865                 lvec[2] *=  x;
866                 vvec[0] *= x ; 
867                 vvec[1] *= x ; 
868                 vvec[2] *= x;
869
870                 /* draw the angled sides of the cone */
871                 glBegin(GL_LINE_STRIP);
872                         glVertex3fv(vvec);
873                         glVertex3fv(vec);
874                         glVertex3fv(lvec);
875                 glEnd();
876                 
877                 z = x*sqrt(1.0 - y*y);
878                 x *= y;
879
880                 /* draw the circle/square at the end of the cone */
881                 glTranslatef(0.0, 0.0 ,  x);
882                 if(la->mode & LA_SQUARE) {
883                         vvec[0]= fabs(z);
884                         vvec[1]= fabs(z);
885                         vvec[2]= 0.0;
886                         glBegin(GL_LINE_LOOP);
887                                 glVertex3fv(vvec);
888                                 vvec[1]= -fabs(z);
889                                 glVertex3fv(vvec);
890                                 vvec[0]= -fabs(z);
891                                 glVertex3fv(vvec);
892                                 vvec[1]= fabs(z);
893                                 glVertex3fv(vvec);
894                         glEnd();
895                 }
896                 else circ(0.0, 0.0, fabs(z));
897                 
898                 /* draw the circle/square representing spotbl */
899                 if(la->type==LA_SPOT) {
900                         float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
901                         /* make sure the line is always visible - prevent it from reaching the outer border (or 0) 
902                          * values are kinda arbitrary - just what seemed to work well */
903                         if (spotblcirc == 0) spotblcirc = 0.15;
904                         else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
905                         circ(0.0, 0.0, spotblcirc);
906                 }
907                 
908         }
909         else if ELEM(la->type, LA_HEMI, LA_SUN) {
910                 
911                 /* draw the line from the circle along the dist */
912                 glBegin(GL_LINE_STRIP);
913                         vec[2] = -circrad;
914                         glVertex3fv(vec); 
915                         vec[2]= -la->dist; 
916                         glVertex3fv(vec);
917                 glEnd();
918                 
919                 if(la->type==LA_HEMI) {
920                         /* draw the hemisphere curves */
921                         short axis, steps, dir;
922                         float outdist, zdist, mul;
923                         vec[0]=vec[1]=vec[2]= 0.0;
924                         outdist = 0.14; mul = 1.4; dir = 1;
925                         
926                         setlinestyle(4);
927                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
928                         for (axis=0; axis<4; axis++) {
929                                 float v[3]= {0.0, 0.0, 0.0};
930                                 zdist = 0.02;
931                                 
932                                 glBegin(GL_LINE_STRIP);
933                                 
934                                 for (steps=0; steps<6; steps++) {
935                                         if (axis == 0 || axis == 1) {           /* x axis up, x axis down */    
936                                                 /* make the arcs start at the edge of the energy circle */
937                                                 if (steps == 0) v[0] = dir*circrad;
938                                                 else v[0] = v[0] + dir*(steps*outdist);
939                                         } else if (axis == 2 || axis == 3) {            /* y axis up, y axis down */
940                                                 /* make the arcs start at the edge of the energy circle */
941                                                 if (steps == 0) v[1] = dir*circrad;
942                                                 else v[1] = v[1] + dir*(steps*outdist); 
943                                         }
944                 
945                                         v[2] = v[2] - steps*zdist;
946                                         
947                                         glVertex3fv(v);
948                                         
949                                         zdist = zdist * mul;
950                                 }
951                                 
952                                 glEnd();
953                                 /* flip the direction */
954                                 dir = -dir;
955                         }
956                 }
957         } else if(la->type==LA_AREA) {
958                 setlinestyle(3);
959                 if(la->area_shape==LA_AREA_SQUARE) 
960                         fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
961                 else if(la->area_shape==LA_AREA_RECT) 
962                         fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
963
964                 glBegin(GL_LINE_STRIP); 
965                 glVertex3f(0.0,0.0,-circrad);
966                 glVertex3f(0.0,0.0,-la->dist);
967                 glEnd();
968         }
969         
970         /* and back to viewspace */
971         wmLoadMatrix(rv3d->viewmat);
972         VECCOPY(vec, ob->obmat[3]);
973
974         setlinestyle(0);
975         
976         if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
977                 drawshadbuflimits(la, ob->obmat);
978         }
979         
980         UI_GetThemeColor4ubv(TH_LAMP, col);
981         glColor4ub(col[0], col[1], col[2], col[3]);
982          
983         glEnable(GL_BLEND);
984         
985         if (vec[2]>0) vec[2] -= circrad;
986         else vec[2] += circrad;
987         
988         glBegin(GL_LINE_STRIP);
989                 glVertex3fv(vec); 
990                 vec[2]= 0; 
991                 glVertex3fv(vec);
992         glEnd();
993         
994         glPointSize(2.0);
995         glBegin(GL_POINTS);
996                 glVertex3fv(vec);
997         glEnd();
998         glPointSize(1.0);
999         
1000         glDisable(GL_BLEND);
1001         
1002         /* restore for drawing extra stuff */
1003         glColor3fv(curcol);
1004
1005 }
1006
1007 static void draw_limit_line(float sta, float end, unsigned int col)
1008 {
1009         glBegin(GL_LINES);
1010         glVertex3f(0.0, 0.0, -sta);
1011         glVertex3f(0.0, 0.0, -end);
1012         glEnd();
1013
1014         glPointSize(3.0);
1015         glBegin(GL_POINTS);
1016         cpack(col);
1017         glVertex3f(0.0, 0.0, -sta);
1018         glVertex3f(0.0, 0.0, -end);
1019         glEnd();
1020         glPointSize(1.0);
1021 }               
1022
1023
1024 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1025 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1026 static void draw_focus_cross(float dist, float size)
1027 {
1028         glBegin(GL_LINES);
1029         glVertex3f(-size, 0.f, -dist);
1030         glVertex3f(size, 0.f, -dist);
1031         glVertex3f(0.f, -size, -dist);
1032         glVertex3f(0.f, size, -dist);
1033         glEnd();
1034 }
1035
1036 /* flag similar to draw_object() */
1037 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1038 {
1039         /* a standing up pyramid with (0,0,0) as top */
1040         Camera *cam;
1041         World *wrld;
1042         float vec[8][4], tmat[4][4], fac, facx, facy, depth;
1043         int i;
1044
1045         if(G.f & G_RENDER_SHADOW)
1046                 return;
1047
1048         cam= ob->data;
1049         
1050         glDisable(GL_LIGHTING);
1051         glDisable(GL_CULL_FACE);
1052         
1053         if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
1054                 facx= 0.5*cam->ortho_scale*1.28;
1055                 facy= 0.5*cam->ortho_scale*1.024;
1056                 depth= -cam->clipsta-0.1;
1057         }
1058         else {
1059                 fac= cam->drawsize;
1060                 if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1061                 
1062                 depth= - fac*cam->lens/16.0;
1063                 facx= fac*1.28;
1064                 facy= fac*1.024;
1065         }
1066         
1067         vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001;       /* GLBUG: for picking at iris Entry (well thats old!) */
1068         vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
1069         vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
1070         vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
1071         vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
1072
1073         glBegin(GL_LINE_LOOP);
1074                 glVertex3fv(vec[1]); 
1075                 glVertex3fv(vec[2]); 
1076                 glVertex3fv(vec[3]); 
1077                 glVertex3fv(vec[4]);
1078         glEnd();
1079         
1080
1081         if(rv3d->persp>=2 && ob==v3d->camera) return;
1082         
1083         glBegin(GL_LINE_STRIP);
1084                 glVertex3fv(vec[2]); 
1085                 glVertex3fv(vec[0]);
1086                 glVertex3fv(vec[1]);
1087                 glVertex3fv(vec[4]);
1088                 glVertex3fv(vec[0]);
1089                 glVertex3fv(vec[3]); 
1090         glEnd();
1091
1092
1093         /* arrow on top */
1094         vec[0][2]= depth;
1095
1096         
1097         /* draw an outline arrow for inactive cameras and filled
1098          * for active cameras. We actually draw both outline+filled
1099          * for active cameras so the wire can be seen side-on */        
1100         for (i=0;i<2;i++) {
1101                 if (i==0) glBegin(GL_LINE_LOOP);
1102                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1103                 else break;
1104                 
1105                 vec[0][0]= -0.7*cam->drawsize;
1106                 vec[0][1]= 1.1*cam->drawsize;
1107                 glVertex3fv(vec[0]);
1108                 
1109                 vec[0][0]= 0.0; 
1110                 vec[0][1]= 1.8*cam->drawsize;
1111                 glVertex3fv(vec[0]);
1112                 
1113                 vec[0][0]= 0.7*cam->drawsize; 
1114                 vec[0][1]= 1.1*cam->drawsize;
1115                 glVertex3fv(vec[0]);
1116         
1117                 glEnd();
1118         }
1119
1120         if(flag==0) {
1121                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1122                         wmLoadMatrix(rv3d->viewmat);
1123                         Mat4CpyMat4(vec, ob->obmat);
1124                         Mat4Ortho(vec);
1125                         wmMultMatrix(vec);
1126
1127                         Mat4SwapMat4(rv3d->persmat, tmat);
1128                         wmGetSingleMatrix(rv3d->persmat);
1129
1130                         if(cam->flag & CAM_SHOWLIMITS) {
1131                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1132                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1133                                 draw_focus_cross(dof_camera(ob), cam->drawsize);
1134                         }
1135
1136                         wrld= scene->world;
1137                         if(cam->flag & CAM_SHOWMIST) 
1138                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1139                                 
1140                         Mat4SwapMat4(rv3d->persmat, tmat);
1141                 }
1142         }
1143 }
1144
1145 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1146 {
1147         BPoint *bp = lt->def;
1148         float *co = dl?dl->verts:NULL;
1149         int u, v, w;
1150
1151         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1152         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1153         bglBegin(GL_POINTS);
1154
1155         for(w=0; w<lt->pntsw; w++) {
1156                 int wxt = (w==0 || w==lt->pntsw-1);
1157                 for(v=0; v<lt->pntsv; v++) {
1158                         int vxt = (v==0 || v==lt->pntsv-1);
1159                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1160                                 int uxt = (u==0 || u==lt->pntsu-1);
1161                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1162                                         if(bp->hide==0) {
1163                                                 if((bp->f1 & SELECT)==sel) {
1164                                                         bglVertex3fv(dl?co:bp->vec);
1165                                                 }
1166                                         }
1167                                 }
1168                         }
1169                 }
1170         }
1171         
1172         glPointSize(1.0);
1173         bglEnd();       
1174 }
1175
1176 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1177 {
1178         Object *obedit= vc->obedit;
1179         Lattice *lt= obedit->data;
1180         BPoint *bp = lt->editlatt->def;
1181         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1182         float *co = dl?dl->verts:NULL;
1183         int i, N = lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
1184         short s[2] = {IS_CLIPPED, 0};
1185
1186         for (i=0; i<N; i++, bp++, co+=3) {
1187                 if (bp->hide==0) {
1188                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s);
1189                         if (s[0] != IS_CLIPPED)
1190                                 func(userData, bp, s[0], s[1]);
1191                 }
1192         }
1193 }
1194
1195 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1196 {
1197         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1198
1199         if(use_wcol) {
1200                 float col[3];
1201                 MDeformWeight *mdw= get_defweight (lt->dvert+index, use_wcol-1);
1202                 
1203                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1204                 glColor3fv(col);
1205
1206         }
1207         
1208         if (dl) {
1209                 glVertex3fv(&dl->verts[index*3]);
1210         } else {
1211                 glVertex3fv(lt->def[index].vec);
1212         }
1213 }
1214
1215 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1216 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1217 {
1218         Lattice *lt= ob->data;
1219         DispList *dl;
1220         int u, v, w;
1221         int use_wcol= 0;
1222
1223         /* now we default make displist, this will modifiers work for non animated case */
1224         if(ob->disp.first==NULL)
1225                 lattice_calc_modifiers(scene, ob);
1226         dl= find_displist(&ob->disp, DL_VERTS);
1227         
1228         if(lt->editlatt) {
1229                 cpack(0x004000);
1230                 
1231                 if(ob->defbase.first && lt->dvert) {
1232                         use_wcol= ob->actdef;
1233                         glShadeModel(GL_SMOOTH);
1234                 }
1235         }
1236         
1237         if(lt->editlatt) lt= lt->editlatt;
1238         
1239         glBegin(GL_LINES);
1240         for(w=0; w<lt->pntsw; w++) {
1241                 int wxt = (w==0 || w==lt->pntsw-1);
1242                 for(v=0; v<lt->pntsv; v++) {
1243                         int vxt = (v==0 || v==lt->pntsv-1);
1244                         for(u=0; u<lt->pntsu; u++) {
1245                                 int uxt = (u==0 || u==lt->pntsu-1);
1246
1247                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1248                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1249                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1250                                 }
1251                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1252                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1253                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1254                                 }
1255                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1256                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1257                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1258                                 }
1259                         }
1260                 }
1261         }               
1262         glEnd();
1263         
1264         /* restoration for weight colors */
1265         if(use_wcol)
1266                 glShadeModel(GL_FLAT);
1267
1268         if( ((Lattice *)ob->data)->editlatt ) {
1269                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1270                 
1271                 lattice_draw_verts(lt, dl, 0);
1272                 lattice_draw_verts(lt, dl, 1);
1273                 
1274                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1275         }
1276 }
1277
1278 /* ***************** ******************** */
1279
1280 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1281 {
1282         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1283         EditVert *eve = EM_get_vert_for_index(index);
1284
1285         if (eve->h==0) {
1286                 short s[2]= {IS_CLIPPED, 0};
1287
1288                 if (data->clipVerts) {
1289                         view3d_project_short_clip(data->vc.ar, co, s);
1290                 } else {
1291                         view3d_project_short_noclip(data->vc.ar, co, s);
1292                 }
1293
1294                 if (s[0]!=IS_CLIPPED)
1295                         data->func(data->userData, eve, s[0], s[1], index);
1296         }
1297 }
1298
1299 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1300 {
1301         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1302         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1303         
1304         data.vc= *vc;
1305         data.func = func;
1306         data.userData = userData;
1307         data.clipVerts = clipVerts;
1308
1309         EM_init_index_arrays(vc->em, 1, 0, 0);
1310         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1311         EM_free_index_arrays();
1312
1313         dm->release(dm);
1314 }
1315
1316 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1317 {
1318         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1319         EditEdge *eed = EM_get_edge_for_index(index);
1320         short s[2][2];
1321
1322         if (eed->h==0) {
1323                 if (data->clipVerts==1) {
1324                         view3d_project_short_clip(data->vc.ar, v0co, s[0]);
1325                         view3d_project_short_clip(data->vc.ar, v1co, s[1]);
1326                 } else {
1327                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1328                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1329
1330                         if (data->clipVerts==2) {
1331                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy)) 
1332                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
1333                                                 return;
1334                         }
1335                 }
1336
1337                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1338         }
1339 }
1340
1341 void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
1342 {
1343         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1344         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1345
1346         data.vc= *vc;
1347         data.func = func;
1348         data.userData = userData;
1349         data.clipVerts = clipVerts;
1350
1351         EM_init_index_arrays(vc->em, 0, 1, 0);
1352         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1353         EM_free_index_arrays();
1354
1355         dm->release(dm);
1356 }
1357
1358 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1359 {
1360         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1361         EditFace *efa = EM_get_face_for_index(index);
1362         short s[2];
1363
1364         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1365                 view3d_project_short_clip(data->vc.ar, cent, s);
1366
1367                 data->func(data->userData, efa, s[0], s[1], index);
1368         }
1369 }
1370
1371 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1372 {
1373         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1374         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1375
1376         data.vc= *vc;
1377         data.func = func;
1378         data.userData = userData;
1379
1380         EM_init_index_arrays(vc->em, 0, 0, 1);
1381         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1382         EM_free_index_arrays();
1383
1384         dm->release(dm);
1385 }
1386
1387 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1388 {
1389         Curve *cu= vc->obedit->data;
1390         short s[2] = {IS_CLIPPED, 0};
1391         Nurb *nu;
1392         int i;
1393
1394         for (nu= cu->editnurb->first; nu; nu=nu->next) {
1395                 if((nu->type & 7)==CU_BEZIER) {
1396                         for (i=0; i<nu->pntsu; i++) {
1397                                 BezTriple *bezt = &nu->bezt[i];
1398
1399                                 if(bezt->hide==0) {
1400                                         if (G.f & G_HIDDENHANDLES) {
1401                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1402                                                 if (s[0] != IS_CLIPPED)
1403                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1404                                         } else {
1405                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s);
1406                                                 if (s[0] != IS_CLIPPED)
1407                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1408                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1409                                                 if (s[0] != IS_CLIPPED)
1410                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1411                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s);
1412                                                 if (s[0] != IS_CLIPPED)
1413                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1414                                         }
1415                                 }
1416                         }
1417                 }
1418                 else {
1419                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1420                                 BPoint *bp = &nu->bp[i];
1421
1422                                 if(bp->hide==0) {
1423                                         view3d_project_short_clip(vc->ar, bp->vec, s);
1424                                         if (s[0] != IS_CLIPPED)
1425                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1426                                 }
1427                         }
1428                 }
1429         }
1430 }
1431
1432 /* ************** DRAW MESH ****************** */
1433
1434 /* First section is all the "simple" draw routines, 
1435  * ones that just pass some sort of primitive to GL,
1436  * with perhaps various options to control lighting,
1437  * color, etc.
1438  *
1439  * These routines should not have user interface related
1440  * logic!!!
1441  */
1442
1443 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1444 {
1445         ToolSettings *ts= ((Scene *)userData)->toolsettings;
1446         EditFace *efa = EM_get_face_for_index(index);
1447
1448         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1449                 glVertex3fv(cent);
1450                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
1451                                         cent[1] + no[1]*ts->normalsize,
1452                                         cent[2] + no[2]*ts->normalsize);
1453         }
1454 }
1455 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
1456 {
1457         glBegin(GL_LINES);
1458         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1459         glEnd();
1460 }
1461
1462 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1463 {
1464         EditFace *efa = EM_get_face_for_index(index);
1465         int sel = *((int*) userData);
1466
1467         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1468                 bglVertex3fv(cent);
1469         }
1470 }
1471 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1472 {
1473         bglBegin(GL_POINTS);
1474         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1475         bglEnd();
1476 }
1477
1478 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1479 {
1480         Scene *scene= (Scene *)userData;
1481         ToolSettings *ts= scene->toolsettings;
1482         EditVert *eve = EM_get_vert_for_index(index);
1483
1484         if (eve->h==0) {
1485                 glVertex3fv(co);
1486
1487                 if (no_f) {
1488                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
1489                                                 co[1] + no_f[1]*ts->normalsize,
1490                                                 co[2] + no_f[2]*ts->normalsize);
1491                 } else {
1492                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
1493                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
1494                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
1495                 }
1496         }
1497 }
1498 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1499 {
1500         glBegin(GL_LINES);
1501         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1502         glEnd();
1503 }
1504
1505         /* Draw verts with color set based on selection */
1506 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1507 {
1508         struct { int sel; EditVert *eve_act; } * data = userData;
1509         EditVert *eve = EM_get_vert_for_index(index);
1510
1511         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1512                 /* draw active larger - need to stop/start point drawing for this :/ */
1513                 if (eve==data->eve_act) {
1514                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1515                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1516                         
1517                         bglEnd();
1518                         
1519                         glPointSize(size);
1520                         bglBegin(GL_POINTS);
1521                         bglVertex3fv(co);
1522                         bglEnd();
1523                         
1524                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1525                         glPointSize(size);
1526                         bglBegin(GL_POINTS);
1527                 } else {
1528                         bglVertex3fv(co);
1529                 }
1530         }
1531 }
1532 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1533 {
1534         struct { int sel; EditVert *eve_act; } data;
1535         data.sel = sel;
1536         data.eve_act = eve_act;
1537         
1538         bglBegin(GL_POINTS);
1539         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1540         bglEnd();
1541 }
1542
1543         /* Draw edges with color set based on selection */
1544 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1545 {
1546         EditEdge *eed = EM_get_edge_for_index(index);
1547         //unsigned char **cols = userData, *col;
1548         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1549         unsigned char *col;
1550
1551         if (eed->h==0) {
1552                 if (eed==data->eed_act) {
1553                         glColor4ubv(data->actCol);
1554                 } else {
1555                         if (eed->f&SELECT) {
1556                                 col = data->selCol;
1557                         } else {
1558                                 col = data->baseCol;
1559                         }
1560                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1561                         if (col[3]==0) return 0;
1562                         
1563                         glColor4ubv(col);
1564                 }
1565                 return 1;
1566         } else {
1567                 return 0;
1568         }
1569 }
1570 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1571 {
1572         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1573         
1574         data.baseCol = baseCol;
1575         data.selCol = selCol;
1576         data.actCol = actCol;
1577         data.eed_act = eed_act;
1578         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1579 }
1580
1581         /* Draw edges */
1582 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1583 {
1584         return EM_get_edge_for_index(index)->h==0;
1585 }
1586 static void draw_dm_edges(DerivedMesh *dm) 
1587 {
1588         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1589 }
1590
1591         /* Draw edges with color interpolated based on selection */
1592 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1593 {
1594         return EM_get_edge_for_index(index)->h==0;
1595 }
1596 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1597 {
1598         EditEdge *eed = EM_get_edge_for_index(index);
1599         unsigned char **cols = userData;
1600         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1601         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1602
1603         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1604                                 col0[1] + (col1[1]-col0[1])*t,
1605                                 col0[2] + (col1[2]-col0[2])*t,
1606                                 col0[3] + (col1[3]-col0[3])*t);
1607 }
1608 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1609 {
1610         unsigned char *cols[2];
1611         cols[0] = baseCol;
1612         cols[1] = selCol;
1613         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1614 }
1615
1616         /* Draw only seam edges */
1617 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1618 {
1619         EditEdge *eed = EM_get_edge_for_index(index);
1620
1621         return (eed->h==0 && eed->seam);
1622 }
1623 static void draw_dm_edges_seams(DerivedMesh *dm)
1624 {
1625         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1626 }
1627
1628         /* Draw only sharp edges */
1629 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1630 {
1631         EditEdge *eed = EM_get_edge_for_index(index);
1632
1633         return (eed->h==0 && eed->sharp);
1634 }
1635 static void draw_dm_edges_sharp(DerivedMesh *dm)
1636 {
1637         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1638 }
1639
1640
1641         /* Draw faces with color set based on selection
1642          * return 2 for the active face so it renders with stipple enabled */
1643 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1644 {
1645         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1646         EditFace *efa = EM_get_face_for_index(index);
1647         unsigned char *col;
1648         
1649         if (efa->h==0) {
1650                 if (efa == data->efa_act) {
1651                         glColor4ubv(data->cols[2]);
1652                         return 2; /* stipple */
1653                 } else {
1654                         col = data->cols[(efa->f&SELECT)?1:0];
1655                         if (col[3]==0) return 0;
1656                         glColor4ubv(col);
1657                         return 1;
1658                 }
1659         }
1660         return 0;
1661 }
1662
1663 /* also draws the active face */
1664 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
1665 {
1666         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1667         data.cols[0] = baseCol;
1668         data.cols[1] = selCol;
1669         data.cols[2] = actCol;
1670         data.efa_act = efa_act;
1671         
1672         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
1673 }
1674
1675 static int draw_dm_creases__setDrawOptions(void *userData, int index)
1676 {
1677         EditEdge *eed = EM_get_edge_for_index(index);
1678
1679         if (eed->h==0 && eed->crease!=0.0) {
1680                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
1681                 return 1;
1682         } else {
1683                 return 0;
1684         }
1685 }
1686 static void draw_dm_creases(DerivedMesh *dm)
1687 {
1688         glLineWidth(3.0);
1689         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1690         glLineWidth(1.0);
1691 }
1692
1693 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
1694 {
1695         EditEdge *eed = EM_get_edge_for_index(index);
1696
1697         if (eed->h==0 && eed->bweight!=0.0) {
1698                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1699                 return 1;
1700         } else {
1701                 return 0;
1702         }
1703 }
1704 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1705 {
1706         EditVert *eve = EM_get_vert_for_index(index);
1707
1708         if (eve->h==0 && eve->bweight!=0.0) {
1709                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1710                 bglVertex3fv(co);
1711         }
1712 }
1713 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1714 {
1715         ToolSettings *ts= scene->toolsettings;
1716
1717         if (ts->selectmode & SCE_SELECT_VERTEX) {
1718                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1719                 bglBegin(GL_POINTS);
1720                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1721                 bglEnd();
1722         }
1723         else {
1724                 glLineWidth(3.0);
1725                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1726                 glLineWidth(1.0);
1727         }
1728 }
1729
1730 /* Second section of routines: Combine first sets to form fancy
1731  * drawing routines (for example rendering twice to get overlays).
1732  *
1733  * Also includes routines that are basic drawing but are too
1734  * specialized to be split out (like drawing creases or measurements).
1735  */
1736
1737 /* EditMesh drawing routines*/
1738
1739 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
1740 {
1741         ToolSettings *ts= scene->toolsettings;
1742         int sel;
1743
1744         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
1745
1746         for (sel=0; sel<2; sel++) {
1747                 char col[4], fcol[4];
1748                 int pass;
1749
1750                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1751                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1752
1753                 for (pass=0; pass<2; pass++) {
1754                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1755                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1756
1757                         if (pass==0) {
1758                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1759                                         glDisable(GL_DEPTH_TEST);
1760                                                 
1761                                         glEnable(GL_BLEND);
1762                                 } else {
1763                                         continue;
1764                                 }
1765
1766                                 size = (size>2.1?size/2.0:size);
1767                                 fsize = (fsize>2.1?fsize/2.0:fsize);
1768                                 col[3] = fcol[3] = 100;
1769                         } else {
1770                                 col[3] = fcol[3] = 255;
1771                         }
1772                                 
1773                         if(ts->selectmode & SCE_SELECT_VERTEX) {
1774                                 glPointSize(size);
1775                                 glColor4ubv((GLubyte *)col);
1776                                 draw_dm_verts(cageDM, sel, eve_act);
1777                         }
1778                         
1779                         if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
1780                                 glPointSize(fsize);
1781                                 glColor4ubv((GLubyte *)fcol);
1782                                 draw_dm_face_centers(cageDM, sel);
1783                         }
1784                         
1785                         if (pass==0) {
1786                                 glDisable(GL_BLEND);
1787                                 glEnable(GL_DEPTH_TEST);
1788                         }
1789                 }
1790         }
1791
1792         if(v3d->zbuf) glDepthMask(1);
1793         glPointSize(1.0);
1794 }
1795
1796 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1797 {
1798         ToolSettings *ts= scene->toolsettings;
1799         int pass;
1800         unsigned char wireCol[4], selCol[4], actCol[4];
1801
1802         /* since this function does transparant... */
1803         UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
1804         UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
1805         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
1806         
1807         /* when sel only is used, dont render wire, only selected, this is used for
1808          * textured draw mode when the 'edges' option is disabled */
1809         if (sel_only)
1810                 wireCol[3] = 0;
1811
1812         for (pass=0; pass<2; pass++) {
1813                         /* show wires in transparant when no zbuf clipping for select */
1814                 if (pass==0) {
1815                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
1816                                 glEnable(GL_BLEND);
1817                                 glDisable(GL_DEPTH_TEST);
1818                                 selCol[3] = 85;
1819                                 if (!sel_only) wireCol[3] = 85;
1820                         } else {
1821                                 continue;
1822                         }
1823                 } else {
1824                         selCol[3] = 255;
1825                         if (!sel_only) wireCol[3] = 255;
1826                 }
1827
1828                 if(ts->selectmode == SCE_SELECT_FACE) {
1829                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1830                 }       
1831                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
1832                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
1833                                 glShadeModel(GL_SMOOTH);
1834                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
1835                                 glShadeModel(GL_FLAT);
1836                         } else {
1837                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1838                         }
1839                 }
1840                 else {
1841                         if (!sel_only) {
1842                                 glColor4ubv(wireCol);
1843                                 draw_dm_edges(cageDM);
1844                         }
1845                 }
1846
1847                 if (pass==0) {
1848                         glDisable(GL_BLEND);
1849                         glEnable(GL_DEPTH_TEST);
1850                 }
1851         }
1852 }       
1853
1854 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
1855 {
1856         Mesh *me= ob->data;
1857         EditEdge *eed;
1858         EditFace *efa;
1859         float v1[3], v2[3], v3[3], v4[3], x, y, z;
1860         float fvec[3];
1861         char val[32]; /* Stores the measurement display text here */
1862         char conv_float[5]; /* Use a float conversion matching the grid size */
1863         float area, col[3]; /* area of the face,  color of the text to draw */
1864         float grid= unit->system ? unit->scale_length : v3d->grid;
1865         int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
1866         if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
1867                 return;
1868
1869         /* make the precission of the pronted value proportionate to the gridsize */
1870
1871         if (grid < 0.01f)
1872                 strcpy(conv_float, "%.6f");
1873         else if (grid < 0.1f)
1874                 strcpy(conv_float, "%.5f");
1875         else if (grid < 1.0f)
1876                 strcpy(conv_float, "%.4f");
1877         else if (grid < 10.0f)
1878                 strcpy(conv_float, "%.3f");
1879         else
1880                 strcpy(conv_float, "%.2f");
1881         
1882         
1883         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
1884                 glDisable(GL_DEPTH_TEST);
1885
1886         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
1887         
1888         if(me->drawflag & ME_DRAW_EDGELEN) {
1889                 UI_GetThemeColor3fv(TH_TEXT, col);
1890                 /* make color a bit more red */
1891                 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
1892                 else col[0]= col[0]*0.7f + 0.3f;
1893                 glColor3fv(col);
1894                 
1895                 for(eed= em->edges.first; eed; eed= eed->next) {
1896                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1897                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1898                                 VECCOPY(v1, eed->v1->co);
1899                                 VECCOPY(v2, eed->v2->co);
1900                                 
1901                                 x= 0.5f*(v1[0]+v2[0]);
1902                                 y= 0.5f*(v1[1]+v2[1]);
1903                                 z= 0.5f*(v1[2]+v2[2]);
1904                                 
1905                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1906                                         Mat4MulVecfl(ob->obmat, v1);
1907                                         Mat4MulVecfl(ob->obmat, v2);
1908                                 }
1909                                 if(unit->system)
1910                                         bUnit_AsString(val, sizeof(val), VecLenf(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
1911                                 else
1912                                         sprintf(val, conv_float, VecLenf(v1, v2));
1913                                 
1914                                 view3d_object_text_draw_add(x, y, z, val, 0);
1915                         }
1916                 }
1917         }
1918
1919         if(me->drawflag & ME_DRAW_FACEAREA) {
1920 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
1921                 
1922                 UI_GetThemeColor3fv(TH_TEXT, col);
1923                 /* make color a bit more green */
1924                 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
1925                 else col[1]= col[1]*0.7f + 0.3f;
1926                 glColor3fv(col);
1927                 
1928                 for(efa= em->faces.first; efa; efa= efa->next) {
1929                         if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
1930                                 VECCOPY(v1, efa->v1->co);
1931                                 VECCOPY(v2, efa->v2->co);
1932                                 VECCOPY(v3, efa->v3->co);
1933                                 if (efa->v4) {
1934                                         VECCOPY(v4, efa->v4->co);
1935                                 }
1936                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1937                                         Mat4MulVecfl(ob->obmat, v1);
1938                                         Mat4MulVecfl(ob->obmat, v2);
1939                                         Mat4MulVecfl(ob->obmat, v3);
1940                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1941                                 }
1942                                 
1943                                 if (efa->v4)
1944                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
1945                                 else
1946                                         area = AreaT3Dfl(v1, v2, v3);
1947
1948                                 if(unit->system)
1949                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
1950                                 else
1951                                         sprintf(val, conv_float, area);
1952
1953                                 view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
1954                         }
1955                 }
1956         }
1957
1958         if(me->drawflag & ME_DRAW_EDGEANG) {
1959                 EditEdge *e1, *e2, *e3, *e4;
1960                 
1961                 UI_GetThemeColor3fv(TH_TEXT, col);
1962                 /* make color a bit more blue */
1963                 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
1964                 else col[2]= col[2]*0.7f + 0.3f;
1965                 glColor3fv(col);
1966                 
1967                 for(efa= em->faces.first; efa; efa= efa->next) {
1968                         VECCOPY(v1, efa->v1->co);
1969                         VECCOPY(v2, efa->v2->co);
1970                         VECCOPY(v3, efa->v3->co);
1971                         if(efa->v4) {
1972                                 VECCOPY(v4, efa->v4->co); 
1973                         }
1974                         else {
1975                                 VECCOPY(v4, v3);
1976                         }
1977                         if(v3d->flag & V3D_GLOBAL_STATS) {
1978                                 Mat4MulVecfl(ob->obmat, v1);
1979                                 Mat4MulVecfl(ob->obmat, v2);
1980                                 Mat4MulVecfl(ob->obmat, v3);
1981                                 Mat4MulVecfl(ob->obmat, v4);
1982                         }
1983                         
1984                         e1= efa->e1;
1985                         e2= efa->e2;
1986                         e3= efa->e3;
1987                         if(efa->e4) e4= efa->e4; else e4= e3;
1988                         
1989                         /* Calculate the angles */
1990                                 
1991                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
1992                                 /* Vec 1 */
1993                                 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
1994                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8f);
1995                                 view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
1996                         }
1997                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
1998                                 /* Vec 2 */
1999                                 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
2000                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8f);
2001                                 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2002                         }
2003                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2004                                 /* Vec 3 */
2005                                 if(efa->v4) 
2006                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
2007                                 else
2008                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
2009                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8f);
2010                                 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2011                         }
2012                                 /* Vec 4 */
2013                         if(efa->v4) {
2014                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2015                                         sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
2016                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8f);
2017                                         view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2018                                 }
2019                         }
2020                 }
2021         }    
2022         
2023         if(v3d->zbuf) {
2024                 glEnable(GL_DEPTH_TEST);
2025                 bglPolygonOffset(rv3d->dist, 0.0f);
2026         }
2027 }
2028
2029 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2030 {
2031         EditFace *efa = EM_get_face_for_index(index);
2032
2033         if (efa->h==0) {
2034                 GPU_enable_material(efa->mat_nr+1, NULL);
2035                 return 1;
2036         }
2037         else
2038                 return 0;
2039 }
2040
2041 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2042 {
2043         EditFace *efa = EM_get_face_for_index(index);
2044
2045         return (efa->h==0);
2046 }
2047
2048 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2049 {
2050         Mesh *me = ob->data;
2051         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2052         EditEdge *eed_act = NULL;
2053         EditVert *eve_act = NULL;
2054         
2055         if (em->selected.last) {
2056                 EditSelection *ese = em->selected.last;
2057                 /* face is handeled above */
2058                 /*if (ese->type == EDITFACE ) {
2059                         efa_act = (EditFace *)ese->data;
2060                 } else */ if ( ese->type == EDITEDGE ) {
2061                         eed_act = (EditEdge *)ese->data;
2062                 } else if ( ese->type == EDITVERT ) {
2063                         eve_act = (EditVert *)ese->data;
2064                 }
2065         }
2066         
2067         EM_init_index_arrays(em, 1, 1, 1);
2068
2069         if(dt>OB_WIRE) {
2070                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2071                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2072                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2073
2074                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2075                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2076                                 GPU_disable_material();
2077
2078                                 glFrontFace(GL_CCW);
2079                         }
2080                         else {
2081                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2082                         }
2083                 }
2084                 else {
2085                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2086
2087                         glEnable(GL_LIGHTING);
2088                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2089
2090                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2091
2092                         glFrontFace(GL_CCW);
2093                         glDisable(GL_LIGHTING);
2094                 }
2095                         
2096                 // Setup for drawing wire over, disable zbuffer
2097                 // write to show selected edge wires better
2098                 UI_ThemeColor(TH_WIRE);
2099
2100                 bglPolygonOffset(rv3d->dist, 1.0);
2101                 glDepthMask(0);
2102         } 
2103         else {
2104                 if (cageDM!=finalDM) {
2105                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2106                         finalDM->drawEdges(finalDM, 1);
2107                 }
2108         }
2109         
2110         if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2111                 unsigned char col1[4], col2[4], col3[4];
2112                         
2113                 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2114                 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2115                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2116                 
2117                 glEnable(GL_BLEND);
2118                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2119                 
2120                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2121                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2122                         col1[3] = 0;
2123                 
2124                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2125
2126                 glDisable(GL_BLEND);
2127                 glDepthMask(1);         // restore write in zbuffer
2128         } else if (efa_act) {
2129                 /* even if draw faces is off it would be nice to draw the stipple face
2130                  * Make all other faces zero alpha except for the active
2131                  * */
2132                 unsigned char col1[4], col2[4], col3[4];
2133                 col1[3] = col2[3] = 0; /* dont draw */
2134                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2135                 
2136                 glEnable(GL_BLEND);
2137                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2138                 
2139                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2140
2141                 glDisable(GL_BLEND);
2142                 glDepthMask(1);         // restore write in zbuffer
2143                 
2144         }
2145
2146         /* here starts all fancy draw-extra over */
2147         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2148                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2149                 
2150                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2151                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2152                 
2153         } else {
2154                 if(me->drawflag & ME_DRAWSEAMS) {
2155                         UI_ThemeColor(TH_EDGE_SEAM);
2156                         glLineWidth(2);
2157         
2158                         draw_dm_edges_seams(cageDM);
2159         
2160                         glColor3ub(0,0,0);
2161                         glLineWidth(1);
2162                 }
2163                 
2164                 if(me->drawflag & ME_DRAWSHARP) {
2165                         UI_ThemeColor(TH_EDGE_SHARP);
2166                         glLineWidth(2);
2167         
2168                         draw_dm_edges_sharp(cageDM);
2169         
2170                         glColor3ub(0,0,0);
2171                         glLineWidth(1);
2172                 }
2173         
2174                 if(me->drawflag & ME_DRAWCREASES) {
2175                         draw_dm_creases(cageDM);
2176                 }
2177                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2178                         draw_dm_bweights(scene, cageDM);
2179                 }
2180         
2181                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2182         }
2183         if(em) {
2184 // XXX          retopo_matrix_update(v3d);
2185
2186                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2187
2188                 if(me->drawflag & ME_DRAWNORMALS) {
2189                         UI_ThemeColor(TH_NORMAL);
2190                         draw_dm_face_normals(scene, cageDM);
2191                 }
2192                 if(me->drawflag & ME_DRAW_VNORMALS) {
2193                         UI_ThemeColor(TH_NORMAL);
2194                         draw_dm_vert_normals(scene, cageDM);
2195                 }
2196
2197                 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2198                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2199         }
2200
2201         if(dt>OB_WIRE) {
2202                 glDepthMask(1);
2203                 bglPolygonOffset(rv3d->dist, 0.0);
2204                 GPU_disable_material();
2205         }
2206
2207         EM_free_index_arrays();
2208 }
2209
2210 /* Mesh drawing routines */
2211
2212 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2213 {
2214         
2215         if(v3d->transp==0) {    // not when we draw the transparent pass
2216                 glLineWidth(2.0);
2217                 glDepthMask(0);
2218                 
2219                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2220                    drawFacesSolid() doesn't draw the transparent faces */
2221                 if(ob->dtx & OB_DRAWTRANSP) {
2222                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2223                         dm->drawFacesSolid(dm, GPU_enable_material);
2224                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2225                         GPU_disable_material();
2226                 }
2227                 else {
2228                         dm->drawEdges(dm, 0);
2229                 }
2230                                         
2231                 glLineWidth(1.0);
2232                 glDepthMask(1);
2233         }
2234 }
2235
2236 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2237 {
2238         *drawSmooth_r = 1;
2239         return 1;
2240 }
2241
2242 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2243 {
2244         Object *ob= base->object;
2245         Mesh *me = ob->data;
2246         Material *ma= give_current_material(ob, 1);
2247         int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2248         int draw_wire = 0;
2249         int totvert, totedge, totface;
2250         DispList *dl;
2251         DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2252
2253         if(!dm)
2254                 return;
2255         
2256         if (ob->dtx&OB_DRAWWIRE) {
2257                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2258         }
2259         
2260         totvert = dm->getNumVerts(dm);
2261         totedge = dm->getNumEdges(dm);
2262         totface = dm->getNumFaces(dm);
2263         
2264         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2265         if(dt!=OB_SHADED)
2266                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2267
2268                 // Unwanted combination.
2269         if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2270
2271         if(dt==OB_BOUNDBOX) {
2272                 draw_bounding_volume(scene, ob);
2273         }
2274         else if(hasHaloMat || (totface==0 && totedge==0)) {
2275                 glPointSize(1.5);
2276                 dm->drawVerts(dm);
2277                 glPointSize(1.0);
2278         }
2279         else if(dt==OB_WIRE || totface==0) {
2280                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2281         }
2282         else if(        (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2283                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2284         {
2285                 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2286
2287                 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2288                         draw_mesh_object_outline(v3d, ob, dm);
2289                 }
2290
2291                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2292                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2293
2294                         dm->drawFacesGLSL(dm, GPU_enable_material);
2295 //                      if(get_ob_property(ob, "Text"))
2296 // XXX                          draw_mesh_text(ob, 1);
2297                         GPU_disable_material();
2298
2299                         glFrontFace(GL_CCW);
2300                 }
2301                 else {
2302                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2303                 }
2304
2305                 if(!faceselect) {
2306                         if(base->flag & SELECT)
2307                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2308                         else
2309                                 UI_ThemeColor(TH_WIRE);
2310
2311                         dm->drawLooseEdges(dm);
2312                 }
2313         }
2314         else if(dt==OB_SOLID) {
2315                 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2316                         draw_mesh_object_outline(v3d, ob, dm);
2317
2318                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2319
2320                 glEnable(GL_LIGHTING);
2321                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2322
2323                 dm->drawFacesSolid(dm, GPU_enable_material);
2324                 GPU_disable_material();
2325
2326                 glFrontFace(GL_CCW);
2327                 glDisable(GL_LIGHTING);
2328
2329                 if(base->flag & SELECT) {
2330                         UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2331                 } else {
2332                         UI_ThemeColor(TH_WIRE);
2333                 }
2334                 dm->drawLooseEdges(dm);
2335         }
2336         else if(dt==OB_SHADED) {
2337                 int do_draw= 1; /* to resolve all G.f settings below... */
2338                 
2339                 if(ob==OBACT) {
2340                         do_draw= 0;
2341                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2342                                 /* enforce default material settings */
2343                                 GPU_enable_material(0, NULL);
2344                                 
2345                                 /* but set default spec */
2346                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2347                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2348                                 glColor3ub(120, 120, 120);
2349                                 glDisable(GL_COLOR_MATERIAL);
2350                                 /* diffuse */
2351                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2352                                 glEnable(GL_LIGHTING);
2353                                 glEnable(GL_COLOR_MATERIAL);
2354
2355                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2356                                 glDisable(GL_COLOR_MATERIAL);
2357                                 glDisable(GL_LIGHTING);
2358
2359                                 GPU_disable_material();
2360                         }
2361                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2362                                 if(me->mcol)
2363                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2364                                 else {
2365                                         glColor3f(1.0f, 1.0f, 1.0f);
2366                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2367                                 }
2368                         }
2369                         else do_draw= 1;
2370                 }
2371                 if(do_draw) {
2372                         dl = ob->disp.first;
2373                         if (!dl || !dl->col1) {
2374                                 /* release and reload derivedmesh because it might be freed in
2375                                    shadeDispList due to a different datamask */
2376                                 dm->release(dm);
2377                                 shadeDispList(scene, base);
2378                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2379                                 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2380                         }
2381
2382                         if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2383                                 draw_mesh_object_outline(v3d, ob, dm);
2384                         }
2385
2386                                 /* False for dupliframe objects */
2387                         if (dl) {
2388                                 unsigned int *obCol1 = dl->col1;
2389                                 unsigned int *obCol2 = dl->col2;
2390
2391                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2392                         }
2393
2394                         if(base->flag & SELECT) {
2395                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2396                         } else {
2397                                 UI_ThemeColor(TH_WIRE);
2398                         }
2399                         dm->drawLooseEdges(dm);
2400                 }
2401         }
2402         
2403         /* set default draw color back for wire or for draw-extra later on */
2404         if (dt!=OB_WIRE) {
2405                 if(base->flag & SELECT) {
2406                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2407                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2408                         else if(ob->flag & OB_FROMGROUP) 
2409                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2410                         else if(flag!=DRAW_CONSTCOLOR)
2411                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2412                         else
2413                                 glColor3ub(80,80,80);
2414                 } else {
2415                         if (ob->flag & OB_FROMGROUP) 
2416                                 UI_ThemeColor(TH_GROUP);
2417                         else {
2418                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2419                                         glColor3ub(80,80,80);
2420                                 else
2421                                         UI_ThemeColor(TH_WIRE);
2422                         }
2423                 }
2424         }
2425         if (draw_wire) {
2426                         /* If drawing wire and drawtype is not OB_WIRE then we are
2427                                 * overlaying the wires.
2428                                 *
2429                                 * UPDATE bug #10290 - With this wire-only objects can draw
2430                                 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2431                                 * 
2432                                 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2433                                 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2434                                 */
2435                 if (dt!=OB_WIRE && draw_wire==2) {
2436                         bglPolygonOffset(rv3d->dist, 1.0);
2437                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2438                 }
2439                 
2440                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2441                 
2442                 if (dt!=OB_WIRE && draw_wire==2) {
2443                         glDepthMask(1);
2444                         bglPolygonOffset(rv3d->dist, 0.0);
2445                 }
2446         }
2447
2448         dm->release(dm);
2449 }
2450
2451 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2452 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2453 {
2454         Object *ob= base->object;
2455         Object *obedit= scene->obedit;
2456         Mesh *me= ob->data;
2457         EditMesh *em= me->edit_mesh;
2458         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2459         
2460         if(obedit && ob!=obedit && ob->data==obedit->data) {
2461                 if(ob_get_key(ob));
2462                 else drawlinked= 1;
2463         }
2464         
2465         if(ob==obedit || drawlinked) {
2466                 DerivedMesh *finalDM, *cageDM;
2467                 
2468                 if (obedit!=ob)
2469                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2470                 else
2471                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2472                                                         v3d->customdata_mask);
2473
2474                 if(dt>OB_WIRE) {
2475                         // no transp in editmode, the fancy draw over goes bad then
2476                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2477                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2478                 }
2479
2480                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2481
2482                 GPU_end_object_materials();
2483
2484                 if (obedit!=ob && finalDM)
2485                         finalDM->release(finalDM);
2486         }
2487 //      else if(!em && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2488 //              OBACT==ob && !sculpt_modifiers_active(ob)) {
2489 // XXX          sculptmode_draw_mesh(0);
2490 //      }
2491         else {
2492                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2493                 if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2494                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2495                         check_alpha = check_material_alpha(base, me, glsl);
2496
2497                         if(dt==OB_SOLID || glsl) {
2498                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2499                                         (check_alpha)? &do_alpha_pass: NULL);
2500                         }
2501
2502                         draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag);
2503
2504                         GPU_end_object_materials();
2505                         
2506                         if(me->totvert==0) retval= 1;
2507                 }
2508         }
2509         
2510         /* GPU_begin_object_materials checked if this is needed */
2511         if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
2512         
2513         return retval;
2514 }
2515
2516 /* ************** DRAW DISPLIST ****************** */
2517
2518 static int draw_index_wire= 1;
2519 static int index3_nors_incr= 1;
2520
2521 /* returns 1 when nothing was drawn */
2522 static int drawDispListwire(ListBase *dlbase)
2523 {
2524         DispList *dl;
2525         int parts, nr;
2526         float *data;
2527
2528         if(dlbase==NULL) return 1;
2529         
2530         glDisableClientState(GL_NORMAL_ARRAY);
2531         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2532
2533         for(dl= dlbase->first; dl; dl= dl->next) {
2534                 if(dl->parts==0 || dl->nr==0)
2535                         continue;
2536                 
2537                 data= dl->verts;
2538         
2539                 switch(dl->type) {
2540                 case DL_SEGM:
2541                         
2542                         glVertexPointer(3, GL_FLOAT, 0, data);
2543                         
2544                         for(parts=0; parts<dl->parts; parts++)
2545                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2546                                 
2547                         break;
2548                 case DL_POLY:
2549                         
2550                         glVertexPointer(3, GL_FLOAT, 0, data);
2551                         
2552                         for(parts=0; parts<dl->parts; parts++)
2553                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2554                         
2555                         break;
2556                 case DL_SURF:
2557                         
2558                         glVertexPointer(3, GL_FLOAT, 0, data);
2559                         
2560                         for(parts=0; parts<dl->parts; parts++) {
2561                                 if(dl->flag & DL_CYCL_U) 
2562                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2563                                 else
2564                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2565                         }
2566                         
2567                         for(nr=0; nr<dl->nr; nr++) {
2568                                 int ofs= 3*dl->nr;
2569                                 
2570                                 data= (  dl->verts )+3*nr;
2571                                 parts= dl->parts;
2572
2573                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2574                                 else glBegin(GL_LINE_STRIP);
2575                                 
2576                                 while(parts--) {
2577                                         glVertex3fv(data);
2578                                         data+=ofs;
2579                                 }
2580                                 glEnd();
2581                                 
2582                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2583 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2584 //                              if(dl->flag & DL_CYCL_V) 
2585 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2586 //                              else
2587 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2588                         }
2589                         break;
2590                         
2591                 case DL_INDEX3:
2592                         if(draw_index_wire) {
2593                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2594                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2595                         }
2596                         break;
2597                         
2598                 case DL_INDEX4:
2599                         if(draw_index_wire) {
2600                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2601                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2602                         }
2603                         break;
2604                 }
2605         }
2606         
2607         glEnableClientState(GL_NORMAL_ARRAY);
2608         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2609         
2610         return 0;
2611 }
2612
2613 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2614 {
2615         DispList *dl;
2616         GPUVertexAttribs gattribs;
2617         float *data, curcol[4];
2618         float *ndata;
2619         
2620         if(lb==NULL) return;
2621         
2622         /* for drawing wire */
2623         glGetFloatv(GL_CURRENT_COLOR, curcol);
2624
2625         glEnable(GL_LIGHTING);
2626         
2627         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2628         else glFrontFace(GL_CCW);
2629         
2630         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2631                 glShadeModel(GL_SMOOTH);
2632         }
2633         
2634         dl= lb->first;
2635         while(dl) {
2636                 data= dl->verts;
2637                 ndata= dl->nors;
2638
2639                 switch(dl->type) {
2640                 case DL_SEGM:
2641                         if(ob->type==OB_SURF) {
2642                                 int nr;
2643
2644                                 glDisable(GL_LIGHTING);
2645                                 glColor3fv(curcol);
2646                                 
2647                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2648                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2649
2650                                 glBegin(GL_LINE_STRIP);
2651                                 for(nr= dl->nr; nr; nr--, data+=3)
2652                                         glVertex3fv(data);
2653                                 glEnd();
2654
2655                                 glEnable(GL_LIGHTING);
2656                         }
2657                         break;
2658                 case DL_POLY:
2659                         if(ob->type==OB_SURF) {
2660                                 int nr;
2661                                 
2662                                 UI_ThemeColor(TH_WIRE);
2663                                 glDisable(GL_LIGHTING);
2664                                 
2665                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2666                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2667                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2668                                 
2669                                 glBegin(GL_LINE_LOOP);
2670                                 for(nr= dl->nr; nr; nr--, data+=3)
2671                                         glVertex3fv(data);
2672                                 glEnd();
2673                                 
2674                                 glEnable(GL_LIGHTING);
2675                                 break;
2676                         }
2677                 case DL_SURF:
2678                         
2679                         if(dl->index) {
2680                                 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2681                                 
2682                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2683                                 else glShadeModel(GL_FLAT);
2684                                 
2685                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2686                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2687                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2688                         }                       
2689                         break;
2690
2691                 case DL_INDEX3:
2692                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2693                         
2694                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2695                         
2696                         /* voor polys only one normal needed */
2697                         if(index3_nors_incr==0) {
2698                                 glDisableClientState(GL_NORMAL_ARRAY);
2699                                 glNormal3fv(ndata);
2700                         }
2701                         else
2702                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2703                         
2704                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2705                         
2706                         if(index3_nors_incr==0)
2707                                 glEnableClientState(GL_NORMAL_ARRAY);
2708
2709                         break;
2710
2711                 case DL_INDEX4:
2712                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2713                         
2714                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2715                         glNormalPointer(GL_FLOAT, 0, dl->nors);
2716                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2717
2718                         break;
2719                 }
2720                 dl= dl->next;
2721         }
2722
2723         glShadeModel(GL_FLAT);
2724         glDisable(GL_LIGHTING);
2725         glFrontFace(GL_CCW);
2726 }
2727
2728 static void drawDispListshaded(ListBase *lb, Object *ob)
2729 {
2730         DispList *dl, *dlob;
2731         unsigned int *cdata;
2732
2733         if(lb==NULL) return;
2734
2735         glShadeModel(GL_SMOOTH);
2736         glDisableClientState(GL_NORMAL_ARRAY);
2737         glEnableClientState(GL_COLOR_ARRAY);
2738         
2739         dl= lb->first;
2740         dlob= ob->disp.first;
2741         while(dl && dlob) {
2742                 
2743                 cdata= dlob->col1;
2744                 if(cdata==NULL) break;
2745                 
2746                 switch(dl->type) {
2747                 case DL_SURF:
2748                         if(dl->index) {
2749                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2750                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2751                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2752                         }                       
2753                         break;
2754
2755                 case DL_INDEX3:
2756                         
2757                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2758                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2759                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2760                         break;
2761
2762                 case DL_INDEX4:
2763                         
2764                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2765                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2766                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2767                         break;
2768                 }
2769                 
2770                 dl= dl->next;
2771                 dlob= dlob->next;
2772         }
2773         
2774         glShadeModel(GL_FLAT);
2775         glEnableClientState(GL_NORMAL_ARRAY);
2776         glDisableClientState(GL_COLOR_ARRAY);
2777 }
2778
2779 /* returns 1 when nothing was drawn */
2780 static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
2781 {
2782         Object *ob= base->object;
2783         ListBase *lb=0;
2784         DispList *dl;
2785         Curve *cu;
2786         int solid, retval= 0;
2787         
2788         solid= (dt > OB_WIRE);
2789
2790         switch(ob->type) {
2791         case OB_FONT:
2792         case OB_CURVE:
2793                 cu= ob->data;
2794                 
2795                 lb= &cu->disp;
2796                 
2797                 if(solid) {
2798                         dl= lb->first;
2799                         if(dl==NULL) return 1;
2800                         
2801                         if(dl->nors==0) addnormalsDispList(ob, lb);
2802                         index3_nors_incr= 0;
2803                         
2804                         if( displist_has_faces(lb)==0) {
2805                                 draw_index_wire= 0;
2806                                 drawDispListwire(lb);
2807                                 draw_index_wire= 1;
2808                         }
2809                         else {
2810                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2811                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2812                                         drawDispListsolid(lb, ob, 1);
2813                                         GPU_end_object_materials();
2814                                 }
2815                                 else if(dt == OB_SHADED) {
2816                                         if(ob->disp.first==0) shadeDispList(scene, base);
2817                                         drawDispListshaded(lb, ob);
2818                                 }
2819                                 else {
2820                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2821                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2822                                         drawDispListsolid(lb, ob, 0);
2823                                         GPU_end_object_materials();
2824                                 }
2825                                 if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
2826                                         cpack(0);
2827                                         draw_index_wire= 0;
2828                                         drawDispListwire(lb);
2829                                         draw_index_wire= 1;
2830                                 }
2831                         }
2832                         index3_nors_incr= 1;
2833                 }
2834                 else {
2835                         draw_index_wire= 0;
2836                         retval= drawDispListwire(lb);
2837                         draw_index_wire= 1;
2838                 }
2839                 break;
2840         case OB_SURF:
2841         
2842                 lb= &((Curve *)ob->data)->disp;
2843                 
2844                 if(solid) {
2845                         dl= lb->first;
2846                         if(dl==NULL) return 1;
2847                         
2848                         if(dl->nors==NULL) addnormalsDispList(ob, lb);
2849                         
2850                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2851                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2852                                 drawDispListsolid(lb, ob, 1);
2853                                 GPU_end_object_materials();
2854                         }
2855                         else if(dt==OB_SHADED) {
2856                                 if(ob->disp.first==NULL) shadeDispList(scene, base);
2857                                 drawDispListshaded(lb, ob);
2858                         }
2859                         else {
2860                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2861                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2862                                 drawDispListsolid(lb, ob, 0);
2863                                 GPU_end_object_materials();
2864                         }
2865                 }
2866                 else {
2867                         retval= drawDispListwire(lb);
2868                 }
2869                 break;
2870         case OB_MBALL:
2871                 
2872                 if( is_basis_mball(ob)) {
2873                         lb= &ob->disp;
2874                         if(lb->first==NULL) makeDispListMBall(scene, ob);
2875                         if(lb->first==NULL) return 1;
2876                         
2877                         if(solid) {
2878                                 
2879                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2880                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2881                                         drawDispListsolid(lb, ob, 1);
2882                                         GPU_end_object_materials();
2883                                 }
2884                                 else if(dt == OB_SHADED) {
2885                                         dl= lb->first;
2886                                         if(dl && dl->col1==0) shadeDispList(scene, base);
2887                                         drawDispListshaded(lb, ob);
2888                                 }
2889                                 else {
2890                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2891                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2892                                         drawDispListsolid(lb, ob, 0);
2893                                         GPU_end_object_materials();
2894                                 }
2895                         }
2896                         else{
2897                                 /* MetaBalls use DL_INDEX4 type of DispList */
2898                                 retval= drawDispListwire(lb);
2899                         }
2900                 }
2901                 break;
2902         }
2903         
2904         return retval;
2905 }
2906
2907 /* *********** text drawing for particles ************* */
2908 static ListBase pstrings= {NULL, NULL};
2909
2910 typedef struct ViewParticleString {
2911         struct ViewParticleString *next, *prev;
2912         float vec[3], col[4];
2913         char str[128]; 
2914         short mval[2];
2915         short xoffs;
2916 } ViewParticleString;
2917
2918
2919 void view3d_particle_text_draw_add(float x, float y, float z, char *str, short xoffs)
2920 {
2921         ViewObjectString *vos= MEM_callocN(sizeof(ViewObjectString), "ViewObjectString");
2922
2923         BLI_addtail(&pstrings, vos);
2924         BLI_strncpy(vos->str, str, 128);
2925         vos->vec[0]= x;
2926         vos->vec[1]= y;
2927         vos->vec[2]= z;
2928         glGetFloatv(GL_CURRENT_COLOR, vos->col);
2929         vos->xoffs= xoffs;
2930 }
2931
2932 static void view3d_particle_text_draw(View3D *v3d, ARegion *ar)
2933 {
2934         ViewObjectString *vos;
2935         int tot= 0;
2936         
2937         /* project first and test */
2938         for(vos= pstrings.first; vos; vos= vos->next) {
2939                 project_short(ar, vos->vec, vos->mval);
2940                 if(vos->mval[0]!=IS_CLIPPED)
2941                         tot++;
2942         }
2943         
2944         if(tot) {
2945                 RegionView3D *rv3d= ar->regiondata;
2946                 int a;
2947                 
2948                 if(rv3d->rflag & RV3D_CLIPPING)
2949                         for(a=0; a<6; a++)
2950                                 glDisable(GL_CLIP_PLANE0+a);
2951                 
2952                 wmPushMatrix();
2953                 ED_region_pixelspace(ar);
2954                 
2955                 if(v3d->zbuf) glDepthMask(0);
2956
2957                 for(vos= pstrings.first; vos; vos= vos->next) {
2958                         if(vos->mval[0]!=IS_CLIPPED) {
2959                                 glColor3fv(vos->col);
2960                                 BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], 2.0, vos->str);
2961                         }
2962                 }
2963                 
2964                 if(v3d->zbuf) glDepthMask(1);
2965                 
2966                 wmPopMatrix();
2967
2968                 if(rv3d->rflag & RV3D_CLIPPING)
2969                         for(a=0; a<6; a++)
2970                                 glEnable(GL_CLIP_PLANE0+a);
2971         }
2972         
2973         if(pstrings.first) 
2974                 BLI_freelistN(&pstrings);
2975 }
2976 typedef struct ParticleDrawData {
2977         float *vdata, *vd;
2978         float *ndata, *nd;
2979         float *cdata, *cd;
2980         float *vedata, *ved;
2981         float *ma_r, *ma_g, *ma_b;
2982 } ParticleDrawData;
2983 static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd)
2984 {
2985         float vec[3], vec2[3];
2986         float *vd = pdd->vd;
2987         float *cd = pdd->cd;
2988         float ma_r=0.0f;
2989         float ma_g=0.0f;
2990         float ma_b=0.0f;
2991
2992         if(pdd->ma_r) {
2993                 ma_r = *pdd->ma_r;
2994                 ma_g = *pdd->ma_g;
2995                 ma_b = *pdd->ma_b;
2996         }
2997
2998         switch(draw_as){
2999                 case PART_DRAW_DOT:
3000                 {
3001                         if(vd) {
3002                                 VECCOPY(vd,state->co) pdd->vd+=3;
3003                         }
3004                         if(cd) {
3005                                 cd[0]=ma_r;
3006                                 cd[1]=ma_g;
3007                                 cd[2]=ma_b;
3008                                 pdd->cd+=3;
3009                         }
3010                         break;
3011                 }
3012                 case PART_DRAW_CROSS:
3013                 case PART_DRAW_AXIS:
3014                 {
3015                         vec[0]=2.0f*pixsize;
3016                         vec[1]=vec[2]=0.0;
3017                         QuatMulVecf(state->rot,vec);
3018                         if(draw_as==PART_DRAW_AXIS) {
3019                                 cd[1]=cd[2]=cd[4]=cd[5]=0.0;
3020                                 cd[0]=cd[3]=1.0;
3021                                 cd[6]=cd[8]=cd[9]=cd[11]=0.0;
3022                                 cd[7]=cd[10]=1.0;
3023                                 cd[13]=cd[12]=cd[15]=cd[16]=0.0;
3024                                 cd[14]=cd[17]=1.0;
3025                                 cd+=18;
3026
3027                                 VECCOPY(vec2,state->co);
3028                         }
3029                         else {
3030                                 if(cd) {
3031                                         cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r;
3032                                         cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g;
3033                                         cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b;
3034                                         pdd->cd+=18;
3035                                 }
3036                                 VECSUB(vec2,state->co,vec);
3037                         }
3038
3039                         VECADD(vec,state->co,vec);
3040                         VECCOPY(pdd->vd,vec); pdd->vd+=3;
3041                         VECCOPY(pdd->vd,vec2); pdd->vd+=3;
3042                                 
3043                         vec[1]=2.0f*pixsize;
3044                         vec[0]=vec[2]=0.0;
3045                         QuatMulVecf(state->rot,vec);
3046                         if(draw_as==PART_DRAW_AXIS){
3047                                 VECCOPY(vec2,state->co);
3048                         }               
3049                         else VECSUB(vec2,state->co,vec);
3050
3051                         VECADD(vec,state->co,vec);
3052                         VECCOPY(pdd->vd,vec); pdd->vd+=3;
3053                         VECCOPY(pdd->vd,vec2);&