4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation, full recode and added functions
25 * ***** END GPL LICENSE BLOCK *****
31 #include "MEM_guardedalloc.h"
33 #include "DNA_camera_types.h"
34 #include "DNA_curve_types.h"
35 #include "DNA_constraint_types.h" // for drawing constraint
36 #include "DNA_lamp_types.h"
37 #include "DNA_lattice_types.h"
38 #include "DNA_material_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_meta_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_smoke_types.h"
43 #include "DNA_world_types.h"
45 #include "BLI_blenlib.h"
47 #include "BLI_editVert.h"
48 #include "BLI_edgehash.h"
51 #include "BKE_anim.h" //for the where_on_path function
52 #include "BKE_constraint.h" // for the get_constraint_target function
53 #include "BKE_DerivedMesh.h"
54 #include "BKE_deform.h"
55 #include "BKE_displist.h"
57 #include "BKE_global.h"
58 #include "BKE_image.h"
60 #include "BKE_lattice.h"
62 #include "BKE_material.h"
63 #include "BKE_mball.h"
64 #include "BKE_modifier.h"
65 #include "BKE_object.h"
66 #include "BKE_paint.h"
67 #include "BKE_particle.h"
68 #include "BKE_pointcache.h"
70 #include "BKE_utildefines.h"
71 #include "smoke_API.h"
74 #include "BIF_glutil.h"
77 #include "GPU_extensions.h"
80 #include "ED_particle.h"
81 #include "ED_screen.h"
82 #include "ED_sculpt.h"
84 #include "ED_curve.h" /* for ED_curve_editnurbs */
86 #include "UI_resources.h"
89 #include "wm_subwindow.h"
92 #include "view3d_intern.h" // own include
95 /* this condition has been made more complex since editmode can draw textures */
96 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
97 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
98 (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
100 static void draw_bounding_volume(Scene *scene, Object *ob);
102 static void drawcube_size(float size);
103 static void drawcircle_size(float size);
104 static void draw_empty_sphere(float size);
105 static void draw_empty_cone(float size);
107 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
109 if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
112 if(G.f & G_BACKBUFSEL)
115 if((vd->flag & V3D_ZBUF_SELECT) == 0)
118 /* if its drawing textures with zbuf sel, then dont draw dots */
119 if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
122 if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
128 /* ************* only use while object drawing **************
129 * or after running ED_view3d_init_mats_rv3d
131 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
133 RegionView3D *rv3d= ar->regiondata;
134 float fx, fy, vec4[4];
138 /* clipplanes in eye space */
139 if(rv3d->rflag & RV3D_CLIPPING) {
140 if(view3d_test_clipping(rv3d, vec, local))
144 copy_v3_v3(vec4, vec);
147 mul_m4_v4(rv3d->persmatob, vec4);
149 /* clipplanes in window space */
150 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
151 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
153 if( fx>0 && fx<ar->winx) {
155 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
157 if(fy>0.0 && fy< (float)ar->winy) {
158 adr[0]= (short)floor(fx);
159 adr[1]= (short)floor(fy);
165 /* only use while object drawing */
166 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
168 RegionView3D *rv3d= ar->regiondata;
169 float fx, fy, vec4[4];
173 copy_v3_v3(vec4, vec);
176 mul_m4_v4(rv3d->persmatob, vec4);
178 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
179 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
181 if( fx>-32700 && fx<32700) {
183 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
185 if(fy>-32700.0 && fy<32700.0) {
186 adr[0]= (short)floor(fx);
187 adr[1]= (short)floor(fy);
193 /* ************************ */
195 /* check for glsl drawing */
197 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
199 if(!GPU_glsl_support())
203 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
205 if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
208 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt >= OB_SHADED);
211 static int check_material_alpha(Base *base, Mesh *me, int glsl)
213 if(base->flag & OB_FROMDUPLI)
222 return (glsl || (base->object->dtx & OB_DRAWTRANSP));
226 static unsigned int colortab[24]=
227 {0x0, 0xFF88FF, 0xFFBBFF,
228 0x403000, 0xFFFF88, 0xFFFFBB,
229 0x104040, 0x66CCCC, 0x77CCCC,
230 0x104010, 0x55BB55, 0x66FF66,
235 static float cube[8][3] = {
246 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
247 /* 32 values of sin function (still same result!) */
248 static float sinval[32] = {
283 /* 32 values of cos function (still same result!) */
284 static float cosval[32] ={
319 static void draw_xyz_wire(float *c, float size, int axis)
321 float v1[3]= {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
322 float dim = size * 0.1;
323 float dx[3]={dim, 0.0, 0.0}, dy[3]={0.0, dim, 0.0}, dz[3]={0.0, 0.0, dim};
329 /* bottom left to top right */
330 sub_v3_v3v3(v1, c, dx);
332 add_v3_v3v3(v2, c, dx);
338 /* top left to bottom right */
351 /* bottom left to top right */
352 mul_v3_fl(dx, 0.75f);
353 sub_v3_v3v3(v1, c, dx);
355 add_v3_v3v3(v2, c, dx);
361 /* top left to center */
372 glBegin(GL_LINE_STRIP);
374 /* start at top left */
375 sub_v3_v3v3(v1, c, dx);
376 add_v3_v3v3(v1, c, dz);
401 void drawaxes(float size, char drawtype)
404 float v1[3]= {0.0, 0.0, 0.0};
405 float v2[3]= {0.0, 0.0, 0.0};
406 float v3[3]= {0.0, 0.0, 0.0};
411 for (axis=0; axis<3; axis++) {
412 float v1[3]= {0.0, 0.0, 0.0};
413 float v2[3]= {0.0, 0.0, 0.0};
425 case OB_SINGLE_ARROW:
428 /* in positive z direction only */
435 glBegin(GL_TRIANGLES);
437 v2[0]= size*0.035; v2[1] = size*0.035;
438 v3[0]= size*-0.035; v3[1] = size*0.035;
439 v2[2]= v3[2]= size*0.75;
441 for (axis=0; axis<4; axis++) {
463 drawcircle_size(size);
466 case OB_EMPTY_SPHERE:
467 draw_empty_sphere(size);
471 draw_empty_cone(size);
476 for (axis=0; axis<3; axis++) {
477 float v1[3]= {0.0, 0.0, 0.0};
478 float v2[3]= {0.0, 0.0, 0.0};
479 int arrow_axis= (axis==0)?1:0;
488 v1[arrow_axis]= -size*0.08;
492 v1[arrow_axis]= size*0.08;
498 v2[axis]+= size*0.125;
500 draw_xyz_wire(v2, size, axis);
506 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
508 float vec[3], vx[3], vy[3];
511 mul_v3_v3fl(vx, tmat[0], rad);
512 mul_v3_v3fl(vy, tmat[1], rad);
515 for(a=0; a<tot; a++) {
516 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
517 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
518 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
524 /* circle for object centers, special_color is for library or ob users */
525 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, float *co, int selstate, int special_color)
527 float vec[3]= {rv3d->persmat[0][3], rv3d->persmat[1][3], rv3d->persmat[2][3]};
528 float size= rv3d->pixsize*((float)U.obcenter_dia*0.5f);
529 size *= dot_v3v3(vec, co) + rv3d->persmat[3][3];
531 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
532 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
536 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
538 else glColor4ub(0x55, 0xCC, 0xCC, 155);
541 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
542 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
543 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
545 drawcircball(GL_POLYGON, co, size, rv3d->viewinv);
547 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
548 drawcircball(GL_LINE_LOOP, co, size, rv3d->viewinv);
551 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
554 /* *********** text drawing for object/particles/armature ************* */
555 static ListBase CachedText[3];
556 static int CachedTextLevel= 0;
558 typedef struct ViewCachedString {
559 struct ViewCachedString *next, *prev;
560 float vec[3], col[4];
567 void view3d_cached_text_draw_begin()
569 ListBase *strings= &CachedText[CachedTextLevel];
570 strings->first= strings->last= NULL;
574 void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag)
576 ListBase *strings= &CachedText[CachedTextLevel-1];
577 ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString), "ViewCachedString");
579 BLI_addtail(strings, vos);
580 BLI_strncpy(vos->str, str, 128);
581 copy_v3_v3(vos->vec, co);
582 glGetFloatv(GL_CURRENT_COLOR, vos->col);
587 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
589 RegionView3D *rv3d= ar->regiondata;
590 ListBase *strings= &CachedText[CachedTextLevel-1];
591 ViewCachedString *vos;
594 /* project first and test */
595 for(vos= strings->first; vos; vos= vos->next) {
596 if(mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
597 mul_m4_v3(mat, vos->vec);
598 view3d_project_short_clip(ar, vos->vec, vos->mval, 0);
599 if(vos->mval[0]!=IS_CLIPPED)
605 bglMats mats; /* ZBuffer depth vars */
612 if(rv3d->rflag & RV3D_CLIPPING)
614 glDisable(GL_CLIP_PLANE0+a);
616 glMatrixMode(GL_PROJECTION);
618 glMatrixMode(GL_MODELVIEW);
620 ED_region_pixelspace(ar);
623 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
627 for(vos= strings->first; vos; vos= vos->next) {
628 #if 0 // too slow, reading opengl info while drawing is very bad, better to see if we cn use the zbuffer while in pixel space - campbell
629 if(v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
630 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
631 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
637 if(vos->mval[0]!=IS_CLIPPED) {
638 glColor3fv(vos->col);
639 BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], (depth_write)? 0.0f: 2.0f, vos->str);
644 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
648 glMatrixMode(GL_PROJECTION);
650 glMatrixMode(GL_MODELVIEW);
653 if(rv3d->rflag & RV3D_CLIPPING)
655 glEnable(GL_CLIP_PLANE0+a);
659 BLI_freelistN(strings);
664 /* ******************** primitive drawing ******************* */
666 static void drawcube(void)
669 glBegin(GL_LINE_STRIP);
670 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
671 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
672 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
675 glBegin(GL_LINE_STRIP);
676 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
679 glBegin(GL_LINE_STRIP);
680 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
683 glBegin(GL_LINE_STRIP);
684 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
688 /* draws a cube on given the scaling of the cube, assuming that
689 * all required matrices have been set (used for drawing empties)
691 static void drawcube_size(float size)
693 glBegin(GL_LINE_STRIP);
694 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
695 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
696 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
699 glBegin(GL_LINE_STRIP);
700 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
703 glBegin(GL_LINE_STRIP);
704 glVertex3f(-size,size,size); glVertex3f(size,size,size);
707 glBegin(GL_LINE_STRIP);
708 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
712 /* this is an unused (old) cube-drawing function based on a given size */
714 static void drawcube_size(float *size)
718 glScalef(size[0], size[1], size[2]);
721 glBegin(GL_LINE_STRIP);
722 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
723 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
724 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
727 glBegin(GL_LINE_STRIP);
728 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
731 glBegin(GL_LINE_STRIP);
732 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
735 glBegin(GL_LINE_STRIP);
736 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
743 static void drawshadbuflimits(Lamp *la, float mat[][4])
745 float sta[3], end[3], lavec[3];
747 negate_v3_v3(lavec, mat[2]);
750 madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
751 madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
753 glBegin(GL_LINE_STRIP);
768 static void spotvolume(float *lvec, float *vvec, float inp)
770 /* camera is at 0,0,0 */
771 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
774 normalize_v3(vvec); /* is this the correct vector ? */
776 cross_v3_v3v3(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
777 cross_v3_v3v3(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
781 /* now we've got two equations: one of a cone and one of a plane, but we have
782 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
784 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
785 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
787 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
794 angle = saacos(plane[2])/2.0;
803 quat_to_mat3(mat1,q);
805 /* rotate lamp vector now over acos(inp) degrees */
806 copy_v3_v3(vvec, lvec);
810 si = sqrt(1-inp*inp);
816 mul_m3_m3m3(mat3,mat2,mat1);
820 mul_m3_m3m3(mat4,mat2,mat1);
823 mul_m3_m3m3(mat2,mat1,mat3);
824 mul_m3_v3(mat2,lvec);
825 mul_m3_m3m3(mat2,mat1,mat4);
826 mul_m3_v3(mat2,vvec);
831 static void draw_spot_cone(Lamp *la, float x, float z)
835 glBegin(GL_TRIANGLE_FAN);
836 glVertex3f(0.0f, 0.0f, -x);
838 if(la->mode & LA_SQUARE) {
840 glVertex3f(-z, z, 0);
841 glVertex3f(-z, -z, 0);
842 glVertex3f(z, -z, 0);
849 for(a=0; a<33; a++) {
850 angle= a*M_PI*2/(33-1);
851 glVertex3f(z*cos(angle), z*sin(angle), 0);
858 static void draw_transp_spot_volume(Lamp *la, float x, float z)
860 glEnable(GL_CULL_FACE);
864 /* draw backside darkening */
865 glCullFace(GL_FRONT);
867 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
868 glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
870 draw_spot_cone(la, x, z);
872 /* draw front side lighting */
875 glBlendFunc(GL_ONE, GL_ONE);
876 glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
878 draw_spot_cone(la, x, z);
881 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
884 glDisable(GL_CULL_FACE);
888 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
890 Object *ob= base->object;
892 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
893 float pixsize, lampsize;
894 float imat[4][4], curcol[4];
896 int drawcone= (dt>OB_WIRE && !(G.f & G_PICKSEL) && la->type == LA_SPOT && (la->mode & LA_SHOW_CONE));
898 if(drawcone && !v3d->transp) {
899 /* in this case we need to draw delayed */
900 add_view3d_after(&v3d->afterdraw_transp, base, flag);
904 /* we first draw only the screen aligned & fixed scale stuff */
906 glLoadMatrixf(rv3d->viewmat);
908 /* lets calculate the scale: */
909 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];
910 pixsize*= rv3d->pixsize;
911 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
913 /* and view aligned matrix: */
914 copy_m4_m4(imat, rv3d->viewinv);
915 normalize_v3(imat[0]);
916 normalize_v3(imat[1]);
919 copy_v3_v3(vec, ob->obmat[3]);
922 glGetFloatv(GL_CURRENT_COLOR, curcol);
926 if(lampsize > 0.0f) {
929 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
930 else glColor4ub(0x77, 0xCC, 0xCC, 155);
935 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
937 drawcircball(GL_POLYGON, vec, lampsize, imat);
944 circrad = 3.0f*lampsize;
947 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
949 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
950 if(la->type!=LA_HEMI) {
951 if( (la->mode & LA_SHAD_RAY) ||
952 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
954 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
963 /* draw the pretty sun rays */
964 if(la->type==LA_SUN) {
965 float v1[3], v2[3], mat[3][3];
968 /* setup a 45 degree rotation matrix */
969 vec_rot_to_mat3( mat,imat[2], M_PI/4.0f);
972 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
973 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
976 glTranslatef(vec[0], vec[1], vec[2]);
981 for (axis=0; axis<8; axis++) {
989 glTranslatef(-vec[0], -vec[1], -vec[2]);
993 if (la->type==LA_LOCAL) {
994 if(la->mode & LA_SPHERE) {
995 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
997 /* yafray: for photonlight also draw lightcone as for spot */
1000 glPopMatrix(); /* back in object space */
1003 if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
1004 lvec[0]=lvec[1]= 0.0;
1006 x = rv3d->persmat[0][2];
1007 y = rv3d->persmat[1][2];
1008 z = rv3d->persmat[2][2];
1009 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
1010 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
1011 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
1013 y = cos( M_PI*la->spotsize/360.0 );
1014 spotvolume(lvec, vvec, y);
1019 /* draw the angled sides of the cone */
1020 glBegin(GL_LINE_STRIP);
1026 z = x*sqrt(1.0 - y*y);
1029 /* draw the circle/square at the end of the cone */
1030 glTranslatef(0.0, 0.0 , x);
1031 if(la->mode & LA_SQUARE) {
1033 float z_abs= fabs(z);
1035 tvec[0]= tvec[1]= z_abs;
1038 glBegin(GL_LINE_LOOP);
1040 tvec[1]= -z_abs; /* neg */
1042 tvec[0]= -z_abs; /* neg */
1044 tvec[1]= z_abs; /* pos */
1048 else circ(0.0, 0.0, fabs(z));
1050 /* draw the circle/square representing spotbl */
1051 if(la->type==LA_SPOT) {
1052 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
1053 /* hide line if it is zero size or overlaps with outer border,
1054 previously it adjusted to always to show it but that seems
1055 confusing because it doesn't show the actual blend size */
1056 if (spotblcirc != 0 && spotblcirc != fabs(z))
1057 circ(0.0, 0.0, spotblcirc);
1061 draw_transp_spot_volume(la, x, z);
1063 /* draw clip start, useful for wide cones where its not obvious where the start is */
1064 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
1065 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1068 float clipsta_fac= la->clipsta / -x;
1070 interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1071 interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1073 glBegin(GL_LINE_STRIP);
1074 glVertex3fv(lvec_clip);
1075 glVertex3fv(vvec_clip);
1079 else if ELEM(la->type, LA_HEMI, LA_SUN) {
1081 /* draw the line from the circle along the dist */
1082 glBegin(GL_LINE_STRIP);
1089 if(la->type==LA_HEMI) {
1090 /* draw the hemisphere curves */
1091 short axis, steps, dir;
1092 float outdist, zdist, mul;
1094 outdist = 0.14; mul = 1.4; dir = 1;
1097 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1098 for (axis=0; axis<4; axis++) {
1099 float v[3]= {0.0, 0.0, 0.0};
1102 glBegin(GL_LINE_STRIP);
1104 for (steps=0; steps<6; steps++) {
1105 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
1106 /* make the arcs start at the edge of the energy circle */
1107 if (steps == 0) v[0] = dir*circrad;
1108 else v[0] = v[0] + dir*(steps*outdist);
1109 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
1110 /* make the arcs start at the edge of the energy circle */
1111 if (steps == 0) v[1] = dir*circrad;
1112 else v[1] = v[1] + dir*(steps*outdist);
1115 v[2] = v[2] - steps*zdist;
1119 zdist = zdist * mul;
1123 /* flip the direction */
1127 } else if(la->type==LA_AREA) {
1129 if(la->area_shape==LA_AREA_SQUARE)
1130 fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
1131 else if(la->area_shape==LA_AREA_RECT)
1132 fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
1134 glBegin(GL_LINE_STRIP);
1135 glVertex3f(0.0,0.0,-circrad);
1136 glVertex3f(0.0,0.0,-la->dist);
1140 /* and back to viewspace */
1141 glLoadMatrixf(rv3d->viewmat);
1142 copy_v3_v3(vec, ob->obmat[3]);
1146 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1147 drawshadbuflimits(la, ob->obmat);
1150 UI_GetThemeColor4ubv(TH_LAMP, col);
1151 glColor4ub(col[0], col[1], col[2], col[3]);
1155 if (vec[2]>0) vec[2] -= circrad;
1156 else vec[2] += circrad;
1158 glBegin(GL_LINE_STRIP);
1170 glDisable(GL_BLEND);
1172 /* restore for drawing extra stuff */
1177 static void draw_limit_line(float sta, float end, unsigned int col)
1180 glVertex3f(0.0, 0.0, -sta);
1181 glVertex3f(0.0, 0.0, -end);
1187 glVertex3f(0.0, 0.0, -sta);
1188 glVertex3f(0.0, 0.0, -end);
1194 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1195 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1196 static void draw_focus_cross(float dist, float size)
1199 glVertex3f(-size, 0.f, -dist);
1200 glVertex3f(size, 0.f, -dist);
1201 glVertex3f(0.f, -size, -dist);
1202 glVertex3f(0.f, size, -dist);
1206 /* flag similar to draw_object() */
1207 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1209 /* a standing up pyramid with (0,0,0) as top */
1212 float nobmat[4][4], vec[8][4], fac, facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1216 aspx= (float) scene->r.xsch*scene->r.xasp;
1217 aspy= (float) scene->r.ysch*scene->r.yasp;
1228 glDisable(GL_LIGHTING);
1229 glDisable(GL_CULL_FACE);
1231 if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
1232 facx= 0.5*cam->ortho_scale*caspx;
1233 facy= 0.5*cam->ortho_scale*caspy;
1234 shx= cam->shiftx * cam->ortho_scale;
1235 shy= cam->shifty * cam->ortho_scale;
1236 depth= -cam->clipsta-0.1;
1240 if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1242 depth= - fac*cam->lens/16.0;
1245 shx= cam->shiftx*fac*2;
1246 shy= cam->shifty*fac*2;
1249 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */
1250 vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1251 vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1252 vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1253 vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1255 glBegin(GL_LINE_LOOP);
1256 glVertex3fv(vec[1]);
1257 glVertex3fv(vec[2]);
1258 glVertex3fv(vec[3]);
1259 glVertex3fv(vec[4]);
1263 if(rv3d->persp>=2 && ob==v3d->camera) return;
1265 glBegin(GL_LINE_STRIP);
1266 glVertex3fv(vec[2]);
1267 glVertex3fv(vec[0]);
1268 glVertex3fv(vec[1]);
1269 glVertex3fv(vec[4]);
1270 glVertex3fv(vec[0]);
1271 glVertex3fv(vec[3]);
1279 /* draw an outline arrow for inactive cameras and filled
1280 * for active cameras. We actually draw both outline+filled
1281 * for active cameras so the wire can be seen side-on */
1283 if (i==0) glBegin(GL_LINE_LOOP);
1284 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1287 vec[0][0]= shx + (-0.7 * cam->drawsize);
1288 vec[0][1]= shy + (cam->drawsize * (caspy + 0.1));
1289 glVertex3fv(vec[0]); /* left */
1291 vec[0][0]= shx + (0.7 * cam->drawsize);
1292 glVertex3fv(vec[0]); /* right */
1295 vec[0][1]= shy + (1.1 * cam->drawsize * (caspy + 0.7));
1296 glVertex3fv(vec[0]); /* top */
1302 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1303 /* draw in normalized object matrix space */
1304 copy_m4_m4(nobmat, ob->obmat);
1305 normalize_m4(nobmat);
1308 glLoadMatrixf(rv3d->viewmat);
1309 glMultMatrixf(nobmat);
1311 if(cam->flag & CAM_SHOWLIMITS) {
1312 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1313 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1314 draw_focus_cross(dof_camera(ob), cam->drawsize);
1318 if(cam->flag & CAM_SHOWMIST)
1319 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1326 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1328 BPoint *bp = lt->def;
1329 float *co = dl?dl->verts:NULL;
1332 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1333 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1334 bglBegin(GL_POINTS);
1336 for(w=0; w<lt->pntsw; w++) {
1337 int wxt = (w==0 || w==lt->pntsw-1);
1338 for(v=0; v<lt->pntsv; v++) {
1339 int vxt = (v==0 || v==lt->pntsv-1);
1340 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1341 int uxt = (u==0 || u==lt->pntsu-1);
1342 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1344 if((bp->f1 & SELECT)==sel) {
1345 bglVertex3fv(dl?co:bp->vec);
1357 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1359 Object *obedit= vc->obedit;
1360 Lattice *lt= obedit->data;
1361 BPoint *bp = lt->editlatt->latt->def;
1362 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1363 float *co = dl?dl->verts:NULL;
1364 int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1365 short s[2] = {IS_CLIPPED, 0};
1367 ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1369 for (i=0; i<N; i++, bp++, co+=3) {
1371 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1372 if (s[0] != IS_CLIPPED)
1373 func(userData, bp, s[0], s[1]);
1378 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1380 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1384 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1386 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1392 glVertex3fv(&dl->verts[index*3]);
1394 glVertex3fv(lt->def[index].vec);
1398 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1399 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1401 Lattice *lt= ob->data;
1404 int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1406 /* now we default make displist, this will modifiers work for non animated case */
1407 if(ob->disp.first==NULL)
1408 lattice_calc_modifiers(scene, ob);
1409 dl= find_displist(&ob->disp, DL_VERTS);
1412 lt= lt->editlatt->latt;
1416 if(ob->defbase.first && lt->dvert) {
1417 use_wcol= ob->actdef;
1418 glShadeModel(GL_SMOOTH);
1423 for(w=0; w<lt->pntsw; w++) {
1424 int wxt = (w==0 || w==lt->pntsw-1);
1425 for(v=0; v<lt->pntsv; v++) {
1426 int vxt = (v==0 || v==lt->pntsv-1);
1427 for(u=0; u<lt->pntsu; u++) {
1428 int uxt = (u==0 || u==lt->pntsu-1);
1430 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1431 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1432 drawlattice__point(lt, dl, u, v, w, use_wcol);
1434 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1435 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1436 drawlattice__point(lt, dl, u, v, w, use_wcol);
1438 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1439 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1440 drawlattice__point(lt, dl, u, v, w, use_wcol);
1447 /* restoration for weight colors */
1449 glShadeModel(GL_FLAT);
1452 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1454 lattice_draw_verts(lt, dl, 0);
1455 lattice_draw_verts(lt, dl, 1);
1457 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1461 /* ***************** ******************** */
1463 /* Note! - foreach funcs should be called while drawing or directly after
1464 * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1465 * but would not give correct results with dupli's for eg. which dont
1466 * use the object matrix in the useual way */
1467 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1469 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1470 EditVert *eve = EM_get_vert_for_index(index);
1473 short s[2]= {IS_CLIPPED, 0};
1475 if (data->clipVerts) {
1476 view3d_project_short_clip(data->vc.ar, co, s, 1);
1478 view3d_project_short_noclip(data->vc.ar, co, s);
1481 if (s[0]!=IS_CLIPPED)
1482 data->func(data->userData, eve, s[0], s[1], index);
1486 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1488 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1489 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1493 data.userData = userData;
1494 data.clipVerts = clipVerts;
1497 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1499 EM_init_index_arrays(vc->em, 1, 0, 0);
1500 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1501 EM_free_index_arrays();
1506 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1508 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;
1509 EditEdge *eed = EM_get_edge_for_index(index);
1513 if (data->clipVerts==1) {
1514 view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1515 view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1517 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1518 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1520 if (data->clipVerts==2) {
1521 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1522 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1527 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1531 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)
1533 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1534 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1538 data.userData = userData;
1539 data.clipVerts = clipVerts;
1542 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1544 EM_init_index_arrays(vc->em, 0, 1, 0);
1545 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1546 EM_free_index_arrays();
1551 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1553 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1554 EditFace *efa = EM_get_face_for_index(index);
1557 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1558 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1560 data->func(data->userData, efa, s[0], s[1], index);
1564 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1566 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1567 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1571 data.userData = userData;
1574 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1576 EM_init_index_arrays(vc->em, 0, 0, 1);
1577 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1578 EM_free_index_arrays();
1583 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1585 Curve *cu= vc->obedit->data;
1586 short s[2] = {IS_CLIPPED, 0};
1589 ListBase *nurbs= ED_curve_editnurbs(cu);
1591 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1593 for (nu= nurbs->first; nu; nu=nu->next) {
1594 if(nu->type == CU_BEZIER) {
1595 for (i=0; i<nu->pntsu; i++) {
1596 BezTriple *bezt = &nu->bezt[i];
1600 if(cu->drawflag & CU_HIDE_HANDLES) {
1601 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1602 if (s[0] != IS_CLIPPED)
1603 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1605 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1606 if (s[0] != IS_CLIPPED)
1607 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1608 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1609 if (s[0] != IS_CLIPPED)
1610 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1611 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1612 if (s[0] != IS_CLIPPED)
1613 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1619 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1620 BPoint *bp = &nu->bp[i];
1623 view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1624 if (s[0] != IS_CLIPPED)
1625 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1632 /* ************** DRAW MESH ****************** */
1634 /* First section is all the "simple" draw routines,
1635 * ones that just pass some sort of primitive to GL,
1636 * with perhaps various options to control lighting,
1639 * These routines should not have user interface related
1643 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1645 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1646 EditFace *efa = EM_get_face_for_index(index);
1648 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1650 glVertex3f( cent[0] + no[0]*ts->normalsize,
1651 cent[1] + no[1]*ts->normalsize,
1652 cent[2] + no[2]*ts->normalsize);
1655 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1658 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1662 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1664 EditFace *efa = EM_get_face_for_index(index);
1665 int sel = *((int*) userData);
1667 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1671 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1673 bglBegin(GL_POINTS);
1674 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1678 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1680 Scene *scene= (Scene *)userData;
1681 ToolSettings *ts= scene->toolsettings;
1682 EditVert *eve = EM_get_vert_for_index(index);
1688 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1689 co[1] + no_f[1]*ts->normalsize,
1690 co[2] + no_f[2]*ts->normalsize);
1692 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1693 co[1] + no_s[1]*ts->normalsize/32767.0f,
1694 co[2] + no_s[2]*ts->normalsize/32767.0f);
1698 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1701 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1705 /* Draw verts with color set based on selection */
1706 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1708 struct { int sel; EditVert *eve_act; } * data = userData;
1709 EditVert *eve = EM_get_vert_for_index(index);
1711 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1712 /* draw active larger - need to stop/start point drawing for this :/ */
1713 if (eve==data->eve_act) {
1714 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1715 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1720 bglBegin(GL_POINTS);
1724 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1726 bglBegin(GL_POINTS);
1733 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1735 struct { int sel; EditVert *eve_act; } data;
1737 data.eve_act = eve_act;
1739 bglBegin(GL_POINTS);
1740 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1744 /* Draw edges with color set based on selection */
1745 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1747 EditEdge *eed = EM_get_edge_for_index(index);
1748 //unsigned char **cols = userData, *col;
1749 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1753 if (eed==data->eed_act) {
1754 glColor4ubv(data->actCol);
1756 if (eed->f&SELECT) {
1759 col = data->baseCol;
1761 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1762 if (col[3]==0) return 0;
1771 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1773 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1775 data.baseCol = baseCol;
1776 data.selCol = selCol;
1777 data.actCol = actCol;
1778 data.eed_act = eed_act;
1779 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1783 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
1785 return EM_get_edge_for_index(index)->h==0;
1787 static void draw_dm_edges(DerivedMesh *dm)
1789 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1792 /* Draw edges with color interpolated based on selection */
1793 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
1795 return EM_get_edge_for_index(index)->h==0;
1797 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1799 EditEdge *eed = EM_get_edge_for_index(index);
1800 unsigned char **cols = userData;
1801 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1802 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1804 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
1805 col0[1] + (col1[1]-col0[1])*t,
1806 col0[2] + (col1[2]-col0[2])*t,
1807 col0[3] + (col1[3]-col0[3])*t);
1810 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1812 unsigned char *cols[2] = {baseCol, selCol};
1814 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1817 /* Draw only seam edges */
1818 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
1820 EditEdge *eed = EM_get_edge_for_index(index);
1822 return (eed->h==0 && eed->seam);
1824 static void draw_dm_edges_seams(DerivedMesh *dm)
1826 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1829 /* Draw only sharp edges */
1830 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
1832 EditEdge *eed = EM_get_edge_for_index(index);
1834 return (eed->h==0 && eed->sharp);
1836 static void draw_dm_edges_sharp(DerivedMesh *dm)
1838 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1842 /* Draw faces with color set based on selection
1843 * return 2 for the active face so it renders with stipple enabled */
1844 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
1846 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1847 EditFace *efa = EM_get_face_for_index(index);
1851 if (efa == data->efa_act) {
1852 glColor4ubv(data->cols[2]);
1853 return 2; /* stipple */
1855 col = data->cols[(efa->f&SELECT)?1:0];
1856 if (col[3]==0) return 0;
1864 /* also draws the active face */
1865 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
1867 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1868 data.cols[0] = baseCol;
1869 data.cols[1] = selCol;
1870 data.cols[2] = actCol;
1871 data.efa_act = efa_act;
1873 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
1876 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
1878 EditEdge *eed = EM_get_edge_for_index(index);
1880 if (eed->h==0 && eed->crease!=0.0) {
1881 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
1887 static void draw_dm_creases(DerivedMesh *dm)
1890 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1894 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
1896 EditEdge *eed = EM_get_edge_for_index(index);
1898 if (eed->h==0 && eed->bweight!=0.0) {
1899 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1905 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1907 EditVert *eve = EM_get_vert_for_index(index);
1909 if (eve->h==0 && eve->bweight!=0.0) {
1910 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1914 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1916 ToolSettings *ts= scene->toolsettings;
1918 if (ts->selectmode & SCE_SELECT_VERTEX) {
1919 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1920 bglBegin(GL_POINTS);
1921 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1926 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1931 /* Second section of routines: Combine first sets to form fancy
1932 * drawing routines (for example rendering twice to get overlays).
1934 * Also includes routines that are basic drawing but are too
1935 * specialized to be split out (like drawing creases or measurements).
1938 /* EditMesh drawing routines*/
1940 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
1942 ToolSettings *ts= scene->toolsettings;
1945 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
1947 for (sel=0; sel<2; sel++) {
1948 char col[4], fcol[4];
1951 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1952 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1954 for (pass=0; pass<2; pass++) {
1955 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1956 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1959 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1960 glDisable(GL_DEPTH_TEST);
1967 size = (size>2.1?size/2.0:size);
1968 fsize = (fsize>2.1?fsize/2.0:fsize);
1969 col[3] = fcol[3] = 100;
1971 col[3] = fcol[3] = 255;
1974 if(ts->selectmode & SCE_SELECT_VERTEX) {
1976 glColor4ubv((GLubyte *)col);
1977 draw_dm_verts(cageDM, sel, eve_act);
1980 if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
1982 glColor4ubv((GLubyte *)fcol);
1983 draw_dm_face_centers(cageDM, sel);
1987 glDisable(GL_BLEND);
1988 glEnable(GL_DEPTH_TEST);
1993 if(v3d->zbuf) glDepthMask(1);
1997 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1999 ToolSettings *ts= scene->toolsettings;
2001 unsigned char wireCol[4], selCol[4], actCol[4];
2003 /* since this function does transparant... */
2004 UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
2005 UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
2006 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
2008 /* when sel only is used, dont render wire, only selected, this is used for
2009 * textured draw mode when the 'edges' option is disabled */
2013 for (pass=0; pass<2; pass++) {
2014 /* show wires in transparant when no zbuf clipping for select */
2016 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2018 glDisable(GL_DEPTH_TEST);
2020 if (!sel_only) wireCol[3] = 85;
2026 if (!sel_only) wireCol[3] = 255;
2029 if(ts->selectmode == SCE_SELECT_FACE) {
2030 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2032 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2033 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2034 glShadeModel(GL_SMOOTH);
2035 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2036 glShadeModel(GL_FLAT);
2038 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2043 glColor4ubv(wireCol);
2044 draw_dm_edges(cageDM);
2049 glDisable(GL_BLEND);
2050 glEnable(GL_DEPTH_TEST);
2055 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2060 float v1[3], v2[3], v3[3], v4[3], vmid[3];
2062 char val[32]; /* Stores the measurement display text here */
2063 char conv_float[5]; /* Use a float conversion matching the grid size */
2064 float area, col[3]; /* area of the face, color of the text to draw */
2065 float grid= unit->system ? unit->scale_length : v3d->grid;
2066 const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2067 const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2068 const int do_moving= G.moving;
2070 if(v3d->flag2 & V3D_RENDER_OVERRIDE)
2073 /* make the precision of the pronted value proportionate to the gridsize */
2076 strcpy(conv_float, "%.6f");
2077 else if (grid < 0.1f)
2078 strcpy(conv_float, "%.5f");
2079 else if (grid < 1.0f)
2080 strcpy(conv_float, "%.4f");
2081 else if (grid < 10.0f)
2082 strcpy(conv_float, "%.3f");
2084 strcpy(conv_float, "%.2f");
2087 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2088 glDisable(GL_DEPTH_TEST);
2090 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2092 if(me->drawflag & ME_DRAW_EDGELEN) {
2093 UI_GetThemeColor3fv(TH_TEXT, col);
2094 /* make color a bit more red */
2095 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
2096 else col[0]= col[0]*0.7f + 0.3f;
2099 for(eed= em->edges.first; eed; eed= eed->next) {
2100 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2101 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2102 copy_v3_v3(v1, eed->v1->co);
2103 copy_v3_v3(v2, eed->v2->co);
2105 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2108 mul_mat3_m4_v3(ob->obmat, v1);
2109 mul_mat3_m4_v3(ob->obmat, v2);
2112 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2114 sprintf(val, conv_float, len_v3v3(v1, v2));
2116 view3d_cached_text_draw_add(vmid, val, 0, 0);
2121 if(me->drawflag & ME_DRAW_FACEAREA) {
2122 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2124 UI_GetThemeColor3fv(TH_TEXT, col);
2125 /* make color a bit more green */
2126 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
2127 else col[1]= col[1]*0.7f + 0.3f;
2130 for(efa= em->faces.first; efa; efa= efa->next) {
2131 if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2132 copy_v3_v3(v1, efa->v1->co);
2133 copy_v3_v3(v2, efa->v2->co);
2134 copy_v3_v3(v3, efa->v3->co);
2136 copy_v3_v3(v4, efa->v4->co);
2139 mul_mat3_m4_v3(ob->obmat, v1);
2140 mul_mat3_m4_v3(ob->obmat, v2);
2141 mul_mat3_m4_v3(ob->obmat, v3);
2142 if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2146 area= area_quad_v3(v1, v2, v3, v4);
2148 area = area_tri_v3(v1, v2, v3);
2151 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2153 sprintf(val, conv_float, area);
2155 view3d_cached_text_draw_add(efa->cent, val, 0, 0);
2160 if(me->drawflag & ME_DRAW_EDGEANG) {
2161 EditEdge *e1, *e2, *e3, *e4;
2163 UI_GetThemeColor3fv(TH_TEXT, col);
2164 /* make color a bit more blue */
2165 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
2166 else col[2]= col[2]*0.7f + 0.3f;
2169 for(efa= em->faces.first; efa; efa= efa->next) {
2170 copy_v3_v3(v1, efa->v1->co);
2171 copy_v3_v3(v2, efa->v2->co);
2172 copy_v3_v3(v3, efa->v3->co);
2174 copy_v3_v3(v4, efa->v4->co);
2180 mul_mat3_m4_v3(ob->obmat, v1);
2181 mul_mat3_m4_v3(ob->obmat, v2);
2182 mul_mat3_m4_v3(ob->obmat, v3);
2183 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2189 if(efa->e4) e4= efa->e4; else e4= e3;
2191 /* Calculate the angles */
2193 if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2195 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v4, v1, v2)));
2196 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2197 view3d_cached_text_draw_add(fvec, val, 0, 0);
2199 if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2201 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v1, v2, v3)));
2202 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2203 view3d_cached_text_draw_add(fvec, val, 0, 0);
2205 if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2208 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v4)));
2210 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v1)));
2211 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2212 view3d_cached_text_draw_add(fvec, val, 0, 0);
2216 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2217 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v3, v4, v1)));
2218 interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2219 view3d_cached_text_draw_add(fvec, val, 0, 0);
2226 glEnable(GL_DEPTH_TEST);
2227 bglPolygonOffset(rv3d->dist, 0.0f);
2231 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2233 EditFace *efa = EM_get_face_for_index(index);
2236 GPU_enable_material(efa->mat_nr+1, NULL);
2243 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2245 EditFace *efa = EM_get_face_for_index(index);
2250 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2252 Mesh *me = ob->data;
2253 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2254 EditEdge *eed_act = NULL;
2255 EditVert *eve_act = NULL;
2257 if (em->selected.last) {
2258 EditSelection *ese = em->selected.last;
2259 /* face is handeled above */
2260 /*if (ese->type == EDITFACE ) {
2261 efa_act = (EditFace *)ese->data;
2262 } else */ if ( ese->type == EDITEDGE ) {
2263 eed_act = (EditEdge *)ese->data;
2264 } else if ( ese->type == EDITVERT ) {
2265 eve_act = (EditVert *)ese->data;
2269 EM_init_index_arrays(em, 1, 1, 1);
2272 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2273 if(draw_glsl_material(scene, ob, v3d, dt)) {
2274 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2276 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2277 draw_em_fancy__setGLSLFaceOpts, NULL);
2278 GPU_disable_material();
2280 glFrontFace(GL_CCW);
2283 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2287 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2288 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2290 glEnable(GL_LIGHTING);
2291 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2293 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0, GPU_enable_material);
2295 glFrontFace(GL_CCW);
2296 glDisable(GL_LIGHTING);
2299 // Setup for drawing wire over, disable zbuffer
2300 // write to show selected edge wires better
2301 UI_ThemeColor(TH_WIRE);
2303 bglPolygonOffset(rv3d->dist, 1.0);
2307 if (cageDM!=finalDM) {
2308 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2309 finalDM->drawEdges(finalDM, 1, 0);
2313 if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2314 unsigned char col1[4], col2[4], col3[4];
2316 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2317 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2318 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2321 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2323 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2324 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2327 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2329 glDisable(GL_BLEND);
2330 glDepthMask(1); // restore write in zbuffer
2331 } else if (efa_act) {
2332 /* even if draw faces is off it would be nice to draw the stipple face
2333 * Make all other faces zero alpha except for the active
2335 unsigned char col1[4], col2[4], col3[4];
2336 col1[3] = col2[3] = 0; /* dont draw */
2337 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2340 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2342 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2344 glDisable(GL_BLEND);
2345 glDepthMask(1); // restore write in zbuffer
2349 /* here starts all fancy draw-extra over */
2350 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2351 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2353 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2354 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2357 if(me->drawflag & ME_DRAWSEAMS) {
2358 UI_ThemeColor(TH_EDGE_SEAM);
2361 draw_dm_edges_seams(cageDM);
2367 if(me->drawflag & ME_DRAWSHARP) {
2368 UI_ThemeColor(TH_EDGE_SHARP);
2371 draw_dm_edges_sharp(cageDM);
2377 if(me->drawflag & ME_DRAWCREASES) {
2378 draw_dm_creases(cageDM);
2380 if(me->drawflag & ME_DRAWBWEIGHTS) {
2381 draw_dm_bweights(scene, cageDM);
2384 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2387 // XXX retopo_matrix_update(v3d);
2389 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2391 if(me->drawflag & ME_DRAWNORMALS) {
2392 UI_ThemeColor(TH_NORMAL);
2393 draw_dm_face_normals(scene, cageDM);
2395 if(me->drawflag & ME_DRAW_VNORMALS) {
2396 UI_ThemeColor(TH_VNORMAL);
2397 draw_dm_vert_normals(scene, cageDM);
2400 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2401 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2406 bglPolygonOffset(rv3d->dist, 0.0);
2407 GPU_disable_material();
2410 EM_free_index_arrays();
2413 /* Mesh drawing routines */
2415 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2418 if(v3d->transp==0) { // not when we draw the transparent pass
2422 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2423 drawFacesSolid() doesn't draw the transparent faces */
2424 if(ob->dtx & OB_DRAWTRANSP) {
2425 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2426 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2427 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2428 GPU_disable_material();
2431 dm->drawEdges(dm, 0, 1);
2439 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2445 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2447 Object *ob= base->object;
2448 Mesh *me = ob->data;
2449 Material *ma= give_current_material(ob, 1);
2450 int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2452 int totvert, totedge, totface;
2454 DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2459 if (ob->dtx&OB_DRAWWIRE) {
2460 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2463 totvert = dm->getNumVerts(dm);
2464 totedge = dm->getNumEdges(dm);
2465 totface = dm->getNumFaces(dm);
2467 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2469 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2471 // Unwanted combination.
2472 if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2474 if(dt==OB_BOUNDBOX) {
2475 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2476 draw_bounding_volume(scene, ob);
2478 else if(hasHaloMat || (totface==0 && totedge==0)) {
2483 else if(dt==OB_WIRE || totface==0) {
2484 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2486 else if( (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2487 CHECK_OB_DRAWTEXTURE(v3d, dt))
2489 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2490 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2491 draw_mesh_object_outline(v3d, ob, dm);
2494 if(draw_glsl_material(scene, ob, v3d, dt)) {
2495 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2497 dm->drawFacesGLSL(dm, GPU_enable_material);
2498 // if(get_ob_property(ob, "Text"))
2499 // XXX draw_mesh_text(ob, 1);
2500 GPU_disable_material();
2502 glFrontFace(GL_CCW);
2505 draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2509 if(base->flag & SELECT)
2510 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2512 UI_ThemeColor(TH_WIRE);
2514 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2515 dm->drawLooseEdges(dm);
2518 else if(dt==OB_SOLID) {
2519 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2520 /* weight paint in solid mode, special case. focus on making the weights clear
2521 * rather then the shading, this is also forced in wire view */
2522 GPU_enable_material(0, NULL);
2523 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2525 bglPolygonOffset(rv3d->dist, 1.0);
2526 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2529 glColor4ub(255, 255, 255, 96);
2530 glEnable(GL_LINE_STIPPLE);
2531 glLineStipple(1, 0xAAAA);
2533 dm->drawEdges(dm, 1, 1);
2535 bglPolygonOffset(rv3d->dist, 0.0);
2537 glDisable(GL_LINE_STIPPLE);
2539 GPU_disable_material();
2541 /* since we already draw wire as wp guide, dont draw over the top */
2547 if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2548 draw_mesh_object_outline(v3d, ob, dm);
2550 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2552 glEnable(GL_LIGHTING);
2553 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2555 if(ob->sculpt && (p=paint_get_active(scene))) {
2557 float (*fpl)[4] = NULL;
2558 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2560 if(ob->sculpt->partial_redraw) {
2561 if(ar->do_draw & RGN_DRAW_PARTIAL) {
2562 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2564 ob->sculpt->partial_redraw = 0;
2568 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2571 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2573 GPU_disable_material();
2575 glFrontFace(GL_CCW);
2576 glDisable(GL_LIGHTING);
2578 if(base->flag & SELECT) {
2579 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2581 UI_ThemeColor(TH_WIRE);
2583 if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2584 dm->drawLooseEdges(dm);
2587 else if(dt==OB_SHADED) {
2588 int do_draw= 1; /* to resolve all G.f settings below... */
2592 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2593 /* enforce default material settings */
2594 GPU_enable_material(0, NULL);
2596 /* but set default spec */
2597 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2598 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2599 glColor3ub(120, 120, 120);
2600 glDisable(GL_COLOR_MATERIAL);
2602 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2603 glEnable(GL_LIGHTING);
2604 glEnable(GL_COLOR_MATERIAL);
2606 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2607 glDisable(GL_COLOR_MATERIAL);
2608 glDisable(GL_LIGHTING);
2610 GPU_disable_material();
2612 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2614 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
2616 glColor3f(1.0f, 1.0f, 1.0f);
2617 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
2623 dl = ob->disp.first;
2624 if (!dl || !dl->col1) {
2625 /* release and reload derivedmesh because it might be freed in
2626 shadeDispList due to a different datamask */
2628 shadeDispList(scene, base);
2629 dl = find_displist(&ob->disp, DL_VERTCOL);
2630 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2633 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire) {
2634 draw_mesh_object_outline(v3d, ob, dm);
2637 /* False for dupliframe objects */
2639 unsigned int *obCol1 = dl->col1;
2640 unsigned int *obCol2 = dl->col2;
2642 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2645 if(base->flag & SELECT) {
2646 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2648 UI_ThemeColor(TH_WIRE);
2650 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2651 dm->drawLooseEdges(dm);
2655 /* set default draw color back for wire or for draw-extra later on */
2657 if(base->flag & SELECT) {
2658 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2659 UI_ThemeColor(TH_GROUP_ACTIVE);
2660 else if(ob->flag & OB_FROMGROUP)
2661 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2662 else if(flag!=DRAW_CONSTCOLOR)
2663 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2665 glColor3ub(80,80,80);
2667 if (ob->flag & OB_FROMGROUP)
2668 UI_ThemeColor(TH_GROUP);
2670 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2671 glColor3ub(80,80,80);
2673 UI_ThemeColor(TH_WIRE);
2679 /* When using wireframe object traw in particle edit mode
2680 * the mesh gets in the way of seeing the particles, fade the wire color
2681 * with the background. */
2682 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2683 float col_wire[4], col_bg[4], col[3];
2685 UI_GetThemeColor3fv(TH_BACK, col_bg);
2686 glGetFloatv(GL_CURRENT_COLOR, col_wire);
2687 interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2691 /* If drawing wire and drawtype is not OB_WIRE then we are
2692 * overlaying the wires.
2694 * UPDATE bug #10290 - With this wire-only objects can draw
2695 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2697 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2698 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2700 if (dt!=OB_WIRE && draw_wire==2) {
2701 bglPolygonOffset(rv3d->dist, 1.0);
2702 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2705 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2706 dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2708 if (dt!=OB_WIRE && draw_wire==2) {
2710 bglPolygonOffset(rv3d->dist, 0.0);
2717 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2718 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2720 Object *ob= base->object;
2721 Object *obedit= scene->obedit;
2723 EditMesh *em= me->edit_mesh;
2724 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2726 if(obedit && ob!=obedit && ob->data==obedit->data) {
2727 if(ob_get_key(ob) || ob_get_key(obedit));
2728 else if(ob->modifiers.first || obedit->modifiers.first);
2732 if(ob==obedit || drawlinked) {
2733 DerivedMesh *finalDM, *cageDM;
2736 finalDM = cageDM = editmesh_get_derived_base(ob, em);
2738 cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2739 v3d->customdata_mask);
2742 // no transp in editmode, the fancy draw over goes bad then
2743 glsl = draw_glsl_material(scene, ob, v3d, dt);
2744 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2747 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2749 GPU_end_object_materials();
2751 if (obedit!=ob && finalDM)
2752 finalDM->release(finalDM);
2755 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2756 if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2757 glsl = draw_glsl_material(scene, ob, v3d, dt);
2758 check_alpha = check_material_alpha(base, me, glsl);
2760 if(dt==OB_SOLID || glsl) {
2761 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2762 (check_alpha)? &do_alpha_pass: NULL);
2765 draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2767 GPU_end_object_materials();
2769 if(me->totvert==0) retval= 1;
2773 /* GPU_begin_object_materials checked if this is needed */
2775 if(ob->dtx & OB_DRAWXRAY) {
2776 add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2779 add_view3d_after(&v3d->afterdraw_transp, base, flag);
2782 else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2783 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2784 if(v3d->xray == 0 && v3d->transp == 0) {
2785 add_view3d_after(&v3d->afterdraw_xray, base, flag);
2792 /* ************** DRAW DISPLIST ****************** */
2794 static int draw_index_wire= 1;
2795 static int index3_nors_incr= 1;
2797 /* returns 1 when nothing was drawn */
2798 static int drawDispListwire(ListBase *dlbase)
2804 if(dlbase==NULL) return 1;
2806 glEnableClientState(GL_VERTEX_ARRAY);
2807 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2809 for(dl= dlbase->first; dl; dl= dl->next) {
2810 if(dl->parts==0 || dl->nr==0)
2818 glVertexPointer(3, GL_FLOAT, 0, data);
2820 for(parts=0; parts<dl->parts; parts++)
2821 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2826 glVertexPointer(3, GL_FLOAT, 0, data);
2828 for(parts=0; parts<dl->parts; parts++)
2829 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2834 glVertexPointer(3, GL_FLOAT, 0, data);
2836 for(parts=0; parts<dl->parts; parts++) {
2837 if(dl->flag & DL_CYCL_U)
2838 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2840 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2843 for(nr=0; nr<dl->nr; nr++) {
2846 data= ( dl->verts )+3*nr;
2849 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2850 else glBegin(GL_LINE_STRIP);
2858 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2859 // glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2860 // if(dl->flag & DL_CYCL_V)
2861 // glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2863 // glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2868 if(draw_index_wire) {
2869 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2870 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2875 if(draw_index_wire) {
2876 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2877 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2883 glDisableClientState(GL_VERTEX_ARRAY);
2884 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2889 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2892 GPUVertexAttribs gattribs;
2893 float *data, curcol[4];
2896 if(lb==NULL) return;
2898 /* for drawing wire */
2899 glGetFloatv(GL_CURRENT_COLOR, curcol);
2901 glEnable(GL_LIGHTING);
2902 glEnableClientState(GL_VERTEX_ARRAY);
2904 if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2905 else glFrontFace(GL_CCW);
2907 if(ob->type==OB_MBALL) { // mball always smooth shaded
2908 glShadeModel(GL_SMOOTH);
2918 if(ob->type==OB_SURF) {
2921 glDisable(GL_LIGHTING);
2924 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2925 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2927 glBegin(GL_LINE_STRIP);
2928 for(nr= dl->nr; nr; nr--, data+=3)
2932 glEnable(GL_LIGHTING);
2936 if(ob->type==OB_SURF) {
2939 glDisable(GL_LIGHTING);
2941 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2942 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2943 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2945 glBegin(GL_LINE_LOOP);
2946 for(nr= dl->nr; nr; nr--, data+=3)
2950 glEnable(GL_LIGHTING);
2956 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2958 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2959 else glShadeModel(GL_FLAT);
2961 glEnableClientState(GL_NORMAL_ARRAY);
2962 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2963 glNormalPointer(GL_FLOAT, 0, dl->nors);
2964 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2965 glDisableClientState(GL_NORMAL_ARRAY);
2970 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2972 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2974 /* voor polys only one normal needed */
2975 if(index3_nors_incr) {
2976 glEnableClientState(GL_NORMAL_ARRAY);
2977 glNormalPointer(GL_FLOAT, 0, dl->nors);
2982 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2984 if(index3_nors_incr)
2985 glDisableClientState(GL_NORMAL_ARRAY);
2990 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2992 glEnableClientState(GL_NORMAL_ARRAY);
2993 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2994 glNormalPointer(GL_FLOAT, 0, dl->nors);
2995 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2996 glDisableClientState(GL_NORMAL_ARRAY);
3003 glDisableClientState(GL_VERTEX_ARRAY);
3004 glShadeModel(GL_FLAT);
3005 glDisable(GL_LIGHTING);
3006 glFrontFace(GL_CCW);
3009 static void drawDispListshaded(ListBase *lb, Object *ob)
3011 DispList *dl, *dlob;
3012 unsigned int *cdata;
3014 if(lb==NULL) return;
3016 glShadeModel(GL_SMOOTH);
3017 glEnableClientState(GL_VERTEX_ARRAY);
3018 glEnableClientState(GL_COLOR_ARRAY);
3021 dlob= ob->disp.first;
3025 if(cdata==NULL) break;
3030 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3031 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
3032 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
3038 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3039 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
3040 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
3045 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3046 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
3047 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);