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 *****
28 /** \file blender/editors/space_view3d/drawobject.c
36 #include "MEM_guardedalloc.h"
38 #include "DNA_camera_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_constraint_types.h" // for drawing constraint
41 #include "DNA_lamp_types.h"
42 #include "DNA_lattice_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_meta_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_smoke_types.h"
48 #include "DNA_world_types.h"
49 #include "DNA_armature_types.h"
51 #include "BLI_utildefines.h"
52 #include "BLI_blenlib.h"
54 #include "BLI_editVert.h"
55 #include "BLI_edgehash.h"
57 #include "BLI_utildefines.h"
59 #include "BKE_anim.h" //for the where_on_path function
60 #include "BKE_constraint.h" // for the get_constraint_target function
61 #include "BKE_DerivedMesh.h"
62 #include "BKE_deform.h"
63 #include "BKE_displist.h"
65 #include "BKE_global.h"
66 #include "BKE_image.h"
68 #include "BKE_lattice.h"
70 #include "BKE_material.h"
71 #include "BKE_mball.h"
72 #include "BKE_modifier.h"
73 #include "BKE_object.h"
74 #include "BKE_paint.h"
75 #include "BKE_particle.h"
76 #include "BKE_pointcache.h"
79 #include "BKE_tessmesh.h"
81 #include "smoke_API.h"
83 #include "IMB_imbuf.h"
84 #include "IMB_imbuf_types.h"
87 #include "BIF_glutil.h"
90 #include "GPU_extensions.h"
93 #include "ED_particle.h"
94 #include "ED_screen.h"
95 #include "ED_sculpt.h"
97 #include "ED_curve.h" /* for ED_curve_editnurbs */
99 #include "UI_resources.h"
102 #include "wm_subwindow.h"
105 #include "view3d_intern.h" // own include
108 /* this condition has been made more complex since editmode can draw textures */
109 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
110 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
111 (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
113 static void draw_bounding_volume(Scene *scene, Object *ob);
115 static void drawcube_size(float size);
116 static void drawcircle_size(float size);
117 static void draw_empty_sphere(float size);
118 static void draw_empty_cone(float size);
120 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
122 if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
125 if(G.f & G_BACKBUFSEL)
128 if((vd->flag & V3D_ZBUF_SELECT) == 0)
131 /* if its drawing textures with zbuf sel, then dont draw dots */
132 if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
135 if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
141 /* ************* only use while object drawing **************
142 * or after running ED_view3d_init_mats_rv3d
144 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
146 RegionView3D *rv3d= ar->regiondata;
147 float fx, fy, vec4[4];
151 /* clipplanes in eye space */
152 if(rv3d->rflag & RV3D_CLIPPING) {
153 if(ED_view3d_test_clipping(rv3d, vec, local))
157 copy_v3_v3(vec4, vec);
160 mul_m4_v4(rv3d->persmatob, vec4);
162 /* clipplanes in window space */
163 if( vec4[3] > (float)BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
164 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
166 if( fx>0 && fx<ar->winx) {
168 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
170 if(fy > 0.0f && fy < (float)ar->winy) {
171 adr[0]= (short)floorf(fx);
172 adr[1]= (short)floorf(fy);
178 /* only use while object drawing */
179 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
181 RegionView3D *rv3d= ar->regiondata;
182 float fx, fy, vec4[4];
186 copy_v3_v3(vec4, vec);
189 mul_m4_v4(rv3d->persmatob, vec4);
191 if( vec4[3] > (float)BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
192 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
194 if( fx>-32700 && fx<32700) {
196 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
198 if(fy > -32700.0f && fy < 32700.0f) {
199 adr[0]= (short)floorf(fx);
200 adr[1]= (short)floorf(fy);
206 /* ************************ */
208 /* check for glsl drawing */
210 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
212 if(!GPU_glsl_support())
216 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
218 if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
221 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
224 static int check_material_alpha(Base *base, Mesh *me, int glsl)
226 if(base->flag & OB_FROMDUPLI)
235 return (glsl || (base->object->dtx & OB_DRAWTRANSP));
239 static unsigned int colortab[24]=
240 {0x0, 0xFF88FF, 0xFFBBFF,
241 0x403000, 0xFFFF88, 0xFFFFBB,
242 0x104040, 0x66CCCC, 0x77CCCC,
243 0x104010, 0x55BB55, 0x66FF66,
248 static float cube[8][3] = {
259 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
260 /* 32 values of sin function (still same result!) */
261 static float sinval[32] = {
296 /* 32 values of cos function (still same result!) */
297 static float cosval[32] ={
332 static void draw_xyz_wire(const float c[3], float size, int axis)
334 float v1[3]= {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
335 float dim = size * 0.1f;
336 float dx[3], dy[3], dz[3];
338 dx[0]=dim; dx[1]=0.f; dx[2]=0.f;
339 dy[0]=0.f; dy[1]=dim; dy[2]=0.f;
340 dz[0]=0.f; dz[1]=0.f; dz[2]=dim;
346 /* bottom left to top right */
347 sub_v3_v3v3(v1, c, dx);
349 add_v3_v3v3(v2, c, dx);
355 /* top left to bottom right */
368 /* bottom left to top right */
369 mul_v3_fl(dx, 0.75f);
370 sub_v3_v3v3(v1, c, dx);
372 add_v3_v3v3(v2, c, dx);
378 /* top left to center */
389 glBegin(GL_LINE_STRIP);
391 /* start at top left */
392 sub_v3_v3v3(v1, c, dx);
393 add_v3_v3v3(v1, c, dz);
418 void drawaxes(float size, char drawtype)
421 float v1[3]= {0.0, 0.0, 0.0};
422 float v2[3]= {0.0, 0.0, 0.0};
423 float v3[3]= {0.0, 0.0, 0.0};
428 for (axis=0; axis<3; axis++) {
436 /* reset v1 & v2 to zero */
437 v1[axis]= v2[axis]= 0.0f;
442 case OB_SINGLE_ARROW:
445 /* in positive z direction only */
452 glBegin(GL_TRIANGLES);
454 v2[0]= size * 0.035f; v2[1] = size * 0.035f;
455 v3[0]= size * -0.035f; v3[1] = size * 0.035f;
456 v2[2]= v3[2]= size * 0.75f;
458 for (axis=0; axis<4; axis++) {
480 drawcircle_size(size);
483 case OB_EMPTY_SPHERE:
484 draw_empty_sphere(size);
488 draw_empty_cone(size);
493 for (axis=0; axis<3; axis++) {
494 const int arrow_axis= (axis==0) ? 1:0;
502 v1[axis]= size*0.85f;
503 v1[arrow_axis]= -size*0.08f;
507 v1[arrow_axis]= size*0.08f;
513 v2[axis]+= size*0.125f;
515 draw_xyz_wire(v2, size, axis);
518 /* reset v1 & v2 to zero */
519 v1[arrow_axis]= v1[axis]= v2[axis]= 0.0f;
526 /* Function to draw an Image on a empty Object */
527 static void draw_empty_image(Object *ob)
529 Image *ima = (Image*)ob->data;
530 ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
532 float scale, ofs_x, ofs_y, sca_x, sca_y;
535 if(ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
536 IMB_rect_from_float(ibuf);
539 /* Get the buffer dimensions so we can fallback to fake ones */
540 if(ibuf && ibuf->rect) {
549 /* Get the image aspect even if the buffer is invalid */
551 if(ima->aspx > ima->aspy) {
553 sca_y= ima->aspy / ima->aspx;
555 else if(ima->aspx < ima->aspy) {
556 sca_x= ima->aspx / ima->aspy;
569 /* Calculate the scale center based on objects origin */
570 ofs_x= ob->ima_ofs[0] * ima_x;
571 ofs_y= ob->ima_ofs[1] * ima_y;
573 glMatrixMode(GL_MODELVIEW);
576 /* Make sure we are drawing at the origin */
577 glTranslatef(0.0f, 0.0f, 0.0f);
579 /* Calculate Image scale */
580 scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
582 /* Set the object scale */
583 glScalef(scale * sca_x, scale * sca_y, 1.0f);
585 if(ibuf && ibuf->rect) {
586 /* Setup GL params */
588 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
590 /* Use the object color and alpha */
593 /* Draw the Image on the screen */
594 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
595 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
600 UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
602 /* Calculate the outline vertex positions */
603 glBegin(GL_LINE_LOOP);
604 glVertex2f(ofs_x, ofs_y);
605 glVertex2f(ofs_x + ima_x, ofs_y);
606 glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
607 glVertex2f(ofs_x, ofs_y + ima_y);
610 /* Reset GL settings */
611 glMatrixMode(GL_MODELVIEW);
615 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
617 float vec[3], vx[3], vy[3];
620 mul_v3_v3fl(vx, tmat[0], rad);
621 mul_v3_v3fl(vy, tmat[1], rad);
624 for(a=0; a<tot; a++) {
625 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
626 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
627 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
633 /* circle for object centers, special_color is for library or ob users */
634 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
636 const float size= ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
638 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
639 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
643 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
645 else glColor4ub(0x55, 0xCC, 0xCC, 155);
648 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
649 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
650 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
652 drawcircball(GL_POLYGON, co, size, rv3d->viewinv);
654 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
655 drawcircball(GL_LINE_LOOP, co, size, rv3d->viewinv);
658 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
661 /* *********** text drawing for object/particles/armature ************* */
662 static ListBase CachedText[3];
663 static int CachedTextLevel= 0;
665 typedef struct ViewCachedString {
666 struct ViewCachedString *next, *prev;
676 /* str is allocated past the end */
679 void view3d_cached_text_draw_begin(void)
681 ListBase *strings= &CachedText[CachedTextLevel];
682 strings->first= strings->last= NULL;
686 void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4])
688 int alloc_len= strlen(str) + 1;
689 ListBase *strings= &CachedText[CachedTextLevel-1];
690 ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
692 BLI_addtail(strings, vos);
693 copy_v3_v3(vos->vec, co);
694 vos->col.pack= *((int *)col);
697 vos->str_len= alloc_len-1;
699 /* allocate past the end */
700 memcpy(++vos, str, alloc_len);
703 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
705 RegionView3D *rv3d= ar->regiondata;
706 ListBase *strings= &CachedText[CachedTextLevel-1];
707 ViewCachedString *vos;
710 /* project first and test */
711 for(vos= strings->first; vos; vos= vos->next) {
712 if(mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
713 mul_m4_v3(mat, vos->vec);
714 view3d_project_short_clip(ar, vos->vec, vos->sco, 0);
715 if(vos->sco[0]!=IS_CLIPPED)
720 int col_pack_prev= 0;
723 bglMats mats; /* ZBuffer depth vars */
730 if(rv3d->rflag & RV3D_CLIPPING)
732 glDisable(GL_CLIP_PLANE0+a);
734 glMatrixMode(GL_PROJECTION);
736 glMatrixMode(GL_MODELVIEW);
738 ED_region_pixelspace(ar);
741 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
745 for(vos= strings->first; vos; vos= vos->next) {
746 #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
747 if(v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
748 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
749 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
755 if(vos->sco[0]!=IS_CLIPPED) {
756 const char *str= (char *)(vos+1);
758 if(col_pack_prev != vos->col.pack) {
759 glColor3ubv(vos->col.ub);
760 col_pack_prev= vos->col.pack;
762 if(vos->flag & V3D_CACHE_TEXT_ASCII) {
763 BLF_draw_default_ascii((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
766 BLF_draw_default((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
772 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
776 glMatrixMode(GL_PROJECTION);
778 glMatrixMode(GL_MODELVIEW);
781 if(rv3d->rflag & RV3D_CLIPPING)
783 glEnable(GL_CLIP_PLANE0+a);
787 BLI_freelistN(strings);
792 /* ******************** primitive drawing ******************* */
794 static void drawcube(void)
797 glBegin(GL_LINE_STRIP);
798 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
799 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
800 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
803 glBegin(GL_LINE_STRIP);
804 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
807 glBegin(GL_LINE_STRIP);
808 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
811 glBegin(GL_LINE_STRIP);
812 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
816 /* draws a cube on given the scaling of the cube, assuming that
817 * all required matrices have been set (used for drawing empties)
819 static void drawcube_size(float size)
821 glBegin(GL_LINE_STRIP);
822 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
823 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
824 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
827 glBegin(GL_LINE_STRIP);
828 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
831 glBegin(GL_LINE_STRIP);
832 glVertex3f(-size,size,size); glVertex3f(size,size,size);
835 glBegin(GL_LINE_STRIP);
836 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
840 /* this is an unused (old) cube-drawing function based on a given size */
842 static void drawcube_size(float *size)
846 glScalef(size[0], size[1], size[2]);
849 glBegin(GL_LINE_STRIP);
850 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
851 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
852 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
855 glBegin(GL_LINE_STRIP);
856 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
859 glBegin(GL_LINE_STRIP);
860 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
863 glBegin(GL_LINE_STRIP);
864 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
871 static void drawshadbuflimits(Lamp *la, float mat[][4])
873 float sta[3], end[3], lavec[3];
875 negate_v3_v3(lavec, mat[2]);
878 madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
879 madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
881 glBegin(GL_LINE_STRIP);
896 static void spotvolume(float *lvec, float *vvec, float inp)
898 /* camera is at 0,0,0 */
899 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
902 normalize_v3(vvec); /* is this the correct vector ? */
904 cross_v3_v3v3(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
905 cross_v3_v3v3(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
907 /* vectors are exactly aligned, use the X axis, this is arbitrary */
908 if(normalize_v3(plane) == 0.0f)
911 /* now we've got two equations: one of a cone and one of a plane, but we have
912 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
914 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
915 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
917 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
924 angle = saacos(plane[2])/2.0f;
933 quat_to_mat3(mat1,q);
935 /* rotate lamp vector now over acos(inp) degrees */
936 copy_v3_v3(vvec, lvec);
940 si = sqrt(1-inp*inp);
946 mul_m3_m3m3(mat3,mat2,mat1);
950 mul_m3_m3m3(mat4,mat2,mat1);
953 mul_m3_m3m3(mat2,mat1,mat3);
954 mul_m3_v3(mat2,lvec);
955 mul_m3_m3m3(mat2,mat1,mat4);
956 mul_m3_v3(mat2,vvec);
961 static void draw_spot_cone(Lamp *la, float x, float z)
965 glBegin(GL_TRIANGLE_FAN);
966 glVertex3f(0.0f, 0.0f, -x);
968 if(la->mode & LA_SQUARE) {
970 glVertex3f(-z, z, 0);
971 glVertex3f(-z, -z, 0);
972 glVertex3f(z, -z, 0);
979 for(a=0; a<33; a++) {
980 angle= a*M_PI*2/(33-1);
981 glVertex3f(z*cosf(angle), z*sinf(angle), 0);
988 static void draw_transp_spot_volume(Lamp *la, float x, float z)
990 glEnable(GL_CULL_FACE);
994 /* draw backside darkening */
995 glCullFace(GL_FRONT);
997 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
998 glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1000 draw_spot_cone(la, x, z);
1002 /* draw front side lighting */
1003 glCullFace(GL_BACK);
1005 glBlendFunc(GL_ONE, GL_ONE);
1006 glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1008 draw_spot_cone(la, x, z);
1011 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1012 glDisable(GL_BLEND);
1014 glDisable(GL_CULL_FACE);
1015 glCullFace(GL_BACK);
1018 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
1020 Object *ob= base->object;
1021 const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1023 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
1025 float imat[4][4], curcol[4];
1026 unsigned char col[4];
1027 /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1028 /* the moment of view3d_draw_transp() call */
1029 const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
1030 const short drawcone= (dt>OB_WIRE && !(G.f & G_PICKSEL) && (la->type == LA_SPOT) && (la->mode & LA_SHOW_CONE) && !(base->flag & OB_FROMDUPLI) && !is_view);
1032 if(drawcone && !v3d->transp) {
1033 /* in this case we need to draw delayed */
1034 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1038 /* we first draw only the screen aligned & fixed scale stuff */
1040 glLoadMatrixf(rv3d->viewmat);
1042 /* lets calculate the scale: */
1043 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
1045 /* and view aligned matrix: */
1046 copy_m4_m4(imat, rv3d->viewinv);
1047 normalize_v3(imat[0]);
1048 normalize_v3(imat[1]);
1051 copy_v3_v3(vec, ob->obmat[3]);
1053 /* for AA effects */
1054 glGetFloatv(GL_CURRENT_COLOR, curcol);
1058 if(lampsize > 0.0f) {
1061 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1062 else glColor4ub(0x77, 0xCC, 0xCC, 155);
1067 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1068 glDisable(GL_BLEND);
1069 drawcircball(GL_POLYGON, vec, lampsize, imat);
1076 circrad = 3.0f*lampsize;
1079 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1081 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1082 if(la->type!=LA_HEMI) {
1083 if( (la->mode & LA_SHAD_RAY) ||
1084 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
1086 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
1095 /* draw the pretty sun rays */
1096 if(la->type==LA_SUN) {
1097 float v1[3], v2[3], mat[3][3];
1100 /* setup a 45 degree rotation matrix */
1101 vec_rot_to_mat3(mat, imat[2], (float)M_PI/4.0f);
1104 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1105 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1108 glTranslatef(vec[0], vec[1], vec[2]);
1113 for (axis=0; axis<8; axis++) {
1121 glTranslatef(-vec[0], -vec[1], -vec[2]);
1125 if (la->type==LA_LOCAL) {
1126 if(la->mode & LA_SPHERE) {
1127 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1129 /* yafray: for photonlight also draw lightcone as for spot */
1132 glPopMatrix(); /* back in object space */
1136 /* skip drawing extra info */
1138 else if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
1139 lvec[0]=lvec[1]= 0.0;
1141 x = rv3d->persmat[0][2];
1142 y = rv3d->persmat[1][2];
1143 z = rv3d->persmat[2][2];
1144 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
1145 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
1146 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
1148 y = cosf(la->spotsize*(float)(M_PI/360.0));
1149 spotvolume(lvec, vvec, y);
1154 /* draw the angled sides of the cone */
1155 glBegin(GL_LINE_STRIP);
1161 z = x*sqrtf(1.0f - y*y);
1164 /* draw the circle/square at the end of the cone */
1165 glTranslatef(0.0, 0.0 , x);
1166 if(la->mode & LA_SQUARE) {
1168 float z_abs= fabs(z);
1170 tvec[0]= tvec[1]= z_abs;
1173 glBegin(GL_LINE_LOOP);
1175 tvec[1]= -z_abs; /* neg */
1177 tvec[0]= -z_abs; /* neg */
1179 tvec[1]= z_abs; /* pos */
1183 else circ(0.0, 0.0, fabsf(z));
1185 /* draw the circle/square representing spotbl */
1186 if(la->type==LA_SPOT) {
1187 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
1188 /* hide line if it is zero size or overlaps with outer border,
1189 previously it adjusted to always to show it but that seems
1190 confusing because it doesn't show the actual blend size */
1191 if (spotblcirc != 0 && spotblcirc != fabsf(z))
1192 circ(0.0, 0.0, spotblcirc);
1196 draw_transp_spot_volume(la, x, z);
1198 /* draw clip start, useful for wide cones where its not obvious where the start is */
1199 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
1200 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1203 float clipsta_fac= la->clipsta / -x;
1205 interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1206 interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1208 glBegin(GL_LINE_STRIP);
1209 glVertex3fv(lvec_clip);
1210 glVertex3fv(vvec_clip);
1214 else if ELEM(la->type, LA_HEMI, LA_SUN) {
1216 /* draw the line from the circle along the dist */
1217 glBegin(GL_LINE_STRIP);
1224 if(la->type==LA_HEMI) {
1225 /* draw the hemisphere curves */
1226 short axis, steps, dir;
1227 float outdist, zdist, mul;
1229 outdist = 0.14; mul = 1.4; dir = 1;
1232 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1233 for (axis=0; axis<4; axis++) {
1234 float v[3]= {0.0, 0.0, 0.0};
1237 glBegin(GL_LINE_STRIP);
1239 for (steps=0; steps<6; steps++) {
1240 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
1241 /* make the arcs start at the edge of the energy circle */
1242 if (steps == 0) v[0] = dir*circrad;
1243 else v[0] = v[0] + dir*(steps*outdist);
1244 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
1245 /* make the arcs start at the edge of the energy circle */
1246 if (steps == 0) v[1] = dir*circrad;
1247 else v[1] = v[1] + dir*(steps*outdist);
1250 v[2] = v[2] - steps*zdist;
1254 zdist = zdist * mul;
1258 /* flip the direction */
1262 } else if(la->type==LA_AREA) {
1264 if(la->area_shape==LA_AREA_SQUARE)
1265 fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
1266 else if(la->area_shape==LA_AREA_RECT)
1267 fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
1269 glBegin(GL_LINE_STRIP);
1270 glVertex3f(0.0,0.0,-circrad);
1271 glVertex3f(0.0,0.0,-la->dist);
1275 /* and back to viewspace */
1276 glLoadMatrixf(rv3d->viewmat);
1277 copy_v3_v3(vec, ob->obmat[3]);
1281 if((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1282 drawshadbuflimits(la, ob->obmat);
1285 UI_GetThemeColor4ubv(TH_LAMP, col);
1290 if (vec[2]>0) vec[2] -= circrad;
1291 else vec[2] += circrad;
1293 glBegin(GL_LINE_STRIP);
1305 glDisable(GL_BLEND);
1307 /* restore for drawing extra stuff */
1312 static void draw_limit_line(float sta, float end, unsigned int col)
1315 glVertex3f(0.0, 0.0, -sta);
1316 glVertex3f(0.0, 0.0, -end);
1322 glVertex3f(0.0, 0.0, -sta);
1323 glVertex3f(0.0, 0.0, -end);
1329 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1330 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1331 static void draw_focus_cross(float dist, float size)
1334 glVertex3f(-size, 0.f, -dist);
1335 glVertex3f(size, 0.f, -dist);
1336 glVertex3f(0.f, -size, -dist);
1337 glVertex3f(0.f, size, -dist);
1341 #ifdef VIEW3D_CAMERA_BORDER_HACK
1342 float view3d_camera_border_hack_col[4];
1343 short view3d_camera_border_hack_test= FALSE;
1346 /* flag similar to draw_object() */
1347 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1349 /* a standing up pyramid with (0,0,0) as top */
1351 float vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1354 const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1356 const float scax= 1.0f / len_v3(ob->obmat[0]);
1357 const float scay= 1.0f / len_v3(ob->obmat[1]);
1358 const float scaz= 1.0f / len_v3(ob->obmat[2]);
1360 #ifdef VIEW3D_CAMERA_BORDER_HACK
1361 if(is_view && !(G.f & G_PICKSEL)) {
1362 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1363 view3d_camera_border_hack_test= TRUE;
1369 aspx= (float) scene->r.xsch*scene->r.xasp;
1370 aspy= (float) scene->r.ysch*scene->r.yasp;
1381 glDisable(GL_LIGHTING);
1382 glDisable(GL_CULL_FACE);
1384 if(cam->type==CAM_ORTHO) {
1385 facx= 0.5f * cam->ortho_scale * caspx * scax;
1386 facy= 0.5f * cam->ortho_scale * caspy * scay;
1387 shx= cam->shiftx * cam->ortho_scale * scax;
1388 shy= cam->shifty * cam->ortho_scale * scay;
1389 depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
1391 drawsize= 0.5f * cam->ortho_scale;
1394 /* that way it's always visible - clipsta+0.1 */
1396 drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
1399 /* fixed depth, variable size (avoids exceeding clipping range) */
1400 depth = -(cam->clipsta + 0.1f);
1401 fac = depth / (cam->lens/-16.0f * scaz);
1404 /* fixed size, variable depth (stays a reasonable size in the 3D view) */
1405 depth= drawsize * cam->lens/-16.0f * scaz;
1409 facx= fac * caspx * scax;
1410 facy= fac * caspy * scay;
1411 shx= cam->shiftx*fac*2 * scax;
1412 shy= cam->shifty*fac*2 * scay;
1415 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
1416 vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1417 vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1418 vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1419 vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1422 glBegin(GL_LINE_LOOP);
1423 glVertex3fv(vec[1]);
1424 glVertex3fv(vec[2]);
1425 glVertex3fv(vec[3]);
1426 glVertex3fv(vec[4]);
1432 /* center point to camera frame */
1433 glBegin(GL_LINE_STRIP);
1434 glVertex3fv(vec[2]);
1435 glVertex3fv(vec[0]);
1436 glVertex3fv(vec[1]);
1437 glVertex3fv(vec[4]);
1438 glVertex3fv(vec[0]);
1439 glVertex3fv(vec[3]);
1447 /* draw an outline arrow for inactive cameras and filled
1448 * for active cameras. We actually draw both outline+filled
1449 * for active cameras so the wire can be seen side-on */
1451 if (i==0) glBegin(GL_LINE_LOOP);
1452 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1455 vec[0][0]= shx + ((-0.7f * drawsize) * scax);
1456 vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
1457 glVertex3fv(vec[0]); /* left */
1459 vec[0][0]= shx + ((0.7f * drawsize) * scax);
1460 glVertex3fv(vec[0]); /* right */
1463 vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
1464 glVertex3fv(vec[0]); /* top */
1470 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1474 /* draw in normalized object matrix space */
1475 copy_m4_m4(nobmat, ob->obmat);
1476 normalize_m4(nobmat);
1479 glLoadMatrixf(rv3d->viewmat);
1480 glMultMatrixf(nobmat);
1482 if(cam->flag & CAM_SHOWLIMITS) {
1483 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1484 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1485 draw_focus_cross(dof_camera(ob), cam->drawsize);
1489 if(cam->flag & CAM_SHOWMIST)
1490 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1497 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1499 BPoint *bp = lt->def;
1500 float *co = dl?dl->verts:NULL;
1503 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1504 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1505 bglBegin(GL_POINTS);
1507 for(w=0; w<lt->pntsw; w++) {
1508 int wxt = (w==0 || w==lt->pntsw-1);
1509 for(v=0; v<lt->pntsv; v++) {
1510 int vxt = (v==0 || v==lt->pntsv-1);
1511 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1512 int uxt = (u==0 || u==lt->pntsu-1);
1513 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1515 if((bp->f1 & SELECT)==sel) {
1516 bglVertex3fv(dl?co:bp->vec);
1528 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1530 Object *obedit= vc->obedit;
1531 Lattice *lt= obedit->data;
1532 BPoint *bp = lt->editlatt->latt->def;
1533 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1534 float *co = dl?dl->verts:NULL;
1535 int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1536 short s[2] = {IS_CLIPPED, 0};
1538 ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1540 for (i=0; i<N; i++, bp++, co+=3) {
1542 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1543 if (s[0] != IS_CLIPPED)
1544 func(userData, bp, s[0], s[1]);
1549 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1551 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1555 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1557 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1563 glVertex3fv(&dl->verts[index*3]);
1565 glVertex3fv(lt->def[index].vec);
1569 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1570 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1572 Lattice *lt= ob->data;
1575 int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1577 /* now we default make displist, this will modifiers work for non animated case */
1578 if(ob->disp.first==NULL)
1579 lattice_calc_modifiers(scene, ob);
1580 dl= find_displist(&ob->disp, DL_VERTS);
1583 lt= lt->editlatt->latt;
1587 if(ob->defbase.first && lt->dvert) {
1588 use_wcol= ob->actdef;
1589 glShadeModel(GL_SMOOTH);
1594 for(w=0; w<lt->pntsw; w++) {
1595 int wxt = (w==0 || w==lt->pntsw-1);
1596 for(v=0; v<lt->pntsv; v++) {
1597 int vxt = (v==0 || v==lt->pntsv-1);
1598 for(u=0; u<lt->pntsu; u++) {
1599 int uxt = (u==0 || u==lt->pntsu-1);
1601 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1602 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1603 drawlattice__point(lt, dl, u, v, w, use_wcol);
1605 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1606 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1607 drawlattice__point(lt, dl, u, v, w, use_wcol);
1609 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1610 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1611 drawlattice__point(lt, dl, u, v, w, use_wcol);
1618 /* restoration for weight colors */
1620 glShadeModel(GL_FLAT);
1623 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1625 lattice_draw_verts(lt, dl, 0);
1626 lattice_draw_verts(lt, dl, 1);
1628 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1632 /* ***************** ******************** */
1634 /* Note! - foreach funcs should be called while drawing or directly after
1635 * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1636 * but would not give correct results with dupli's for eg. which dont
1637 * use the object matrix in the useual way */
1638 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1640 struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1641 BMVert *eve = EDBM_get_vert_for_index(data->vc.em, index);
1643 if (!BM_TestHFlag(eve, BM_HIDDEN)) {
1644 short s[2]= {IS_CLIPPED, 0};
1646 if (data->clipVerts) {
1647 view3d_project_short_clip(data->vc.ar, co, s, 1);
1650 mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
1651 project_short_noclip(data->vc.ar, co2, s);
1654 if (s[0]!=IS_CLIPPED)
1655 data->func(data->userData, eve, s[0], s[1], index);
1659 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BMVert *eve, int x, int y, int index), void *userData, int clipVerts)
1661 struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
1662 DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1666 data.userData = userData;
1667 data.clipVerts = clipVerts;
1669 EDBM_init_index_arrays(vc->em, 1, 0, 0);
1671 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1673 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1674 EDBM_free_index_arrays(vc->em);
1679 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1681 struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1682 BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index);
1684 if (!BM_TestHFlag(eed, BM_HIDDEN)) {
1687 if (data->clipVerts==1) {
1688 view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1689 view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1691 float v1_co[3], v2_co[3];
1693 mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
1694 mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
1696 project_short_noclip(data->vc.ar, v1_co, s[0]);
1697 project_short_noclip(data->vc.ar, v2_co, s[1]);
1699 if (data->clipVerts==2) {
1700 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1701 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1706 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1710 void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
1712 struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
1713 DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1717 data.userData = userData;
1718 data.clipVerts = clipVerts;
1720 EDBM_init_index_arrays(vc->em, 0, 1, 0);
1722 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1724 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1725 EDBM_free_index_arrays(vc->em);
1730 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1732 struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } *data = userData;
1733 BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
1735 if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
1739 mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
1740 project_short(data->vc.ar, cent2, s);
1742 if (s[0] != IS_CLIPPED) {
1743 data->func(data->userData, efa, s[0], s[1], index);
1748 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, BMFace *efa, int x, int y, int index), void *userData)
1750 struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } data;
1751 DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1755 data.userData = userData;
1757 EDBM_init_index_arrays(vc->em, 0, 0, 1);
1759 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1761 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1762 EDBM_free_index_arrays(vc->em);
1767 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1769 Curve *cu= vc->obedit->data;
1770 short s[2] = {IS_CLIPPED, 0};
1773 ListBase *nurbs= ED_curve_editnurbs(cu);
1775 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1777 for (nu= nurbs->first; nu; nu=nu->next) {
1778 if(nu->type == CU_BEZIER) {
1779 for (i=0; i<nu->pntsu; i++) {
1780 BezTriple *bezt = &nu->bezt[i];
1784 if(cu->drawflag & CU_HIDE_HANDLES) {
1785 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1786 if (s[0] != IS_CLIPPED)
1787 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1789 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1790 if (s[0] != IS_CLIPPED)
1791 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1792 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1793 if (s[0] != IS_CLIPPED)
1794 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1795 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1796 if (s[0] != IS_CLIPPED)
1797 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1803 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1804 BPoint *bp = &nu->bp[i];
1807 view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1808 if (s[0] != IS_CLIPPED)
1809 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1816 /* ************** DRAW MESH ****************** */
1818 /* First section is all the "simple" draw routines,
1819 * ones that just pass some sort of primitive to GL,
1820 * with perhaps various options to control lighting,
1823 * These routines should not have user interface related
1827 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1829 Scene *scene= ((void **)userData)[0];
1830 BMEditMesh *em = ((void **)userData)[1];
1831 BMFace *efa = EDBM_get_face_for_index(em, index);
1832 ToolSettings *ts= scene->toolsettings;
1834 if (!BM_TestHFlag(efa, BM_HIDDEN)) {
1836 glVertex3f( cent[0] + no[0]*ts->normalsize,
1837 cent[1] + no[1]*ts->normalsize,
1838 cent[2] + no[2]*ts->normalsize);
1841 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
1843 void *ptrs[2] = {scene, em};
1846 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, ptrs);
1850 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1852 BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index);
1853 int sel = *(((int **)userData)[1]);
1855 if (efa && !BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)==sel) {
1859 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
1861 void *ptrs[2] = {em, &sel};
1863 bglBegin(GL_POINTS);
1864 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
1868 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1870 Scene *scene= ((void **)userData)[0];
1871 ToolSettings *ts= scene->toolsettings;
1872 BMEditMesh *em = ((void **)userData)[1];
1873 BMVert *eve = EDBM_get_vert_for_index(em, index);
1875 if (!BM_TestHFlag(eve, BM_HIDDEN)) {
1879 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1880 co[1] + no_f[1]*ts->normalsize,
1881 co[2] + no_f[2]*ts->normalsize);
1883 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1884 co[1] + no_s[1]*ts->normalsize/32767.0f,
1885 co[2] + no_s[2]*ts->normalsize/32767.0f);
1889 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
1891 void *ptrs[2] = {scene, em};
1894 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, ptrs);
1898 /* Draw verts with color set based on selection */
1899 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1901 struct { BMEditMesh *em; int sel; BMVert *eve_act; } *data = userData;
1902 BMVert *eve = EDBM_get_vert_for_index(data->em, index);
1904 if (!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)==data->sel) {
1905 /* draw active larger - need to stop/start point drawing for this :/ */
1906 if (eve==data->eve_act) {
1907 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1908 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1913 bglBegin(GL_POINTS);
1917 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1919 bglBegin(GL_POINTS);
1926 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
1928 struct { BMEditMesh *em; int sel; BMVert *eve_act; } data;
1930 data.eve_act = eve_act;
1933 bglBegin(GL_POINTS);
1934 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1937 bglBegin(GL_POINTS);
1938 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1942 /* Draw edges with color set based on selection */
1943 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1946 //unsigned char **cols = userData, *col;
1947 struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } * data = userData;
1950 eed = EDBM_get_edge_for_index(data->em, index);
1952 if (!BM_TestHFlag(eed, BM_HIDDEN)) {
1953 if (eed==data->eed_act) {
1954 glColor4ubv(data->actCol);
1956 if (BM_TestHFlag(eed, BM_SELECT)) {
1959 col = data->baseCol;
1961 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1962 if (col[3]==0) return 0;
1971 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
1972 unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
1974 struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } data;
1976 data.baseCol = baseCol;
1977 data.selCol = selCol;
1978 data.actCol = actCol;
1980 data.eed_act = eed_act;
1981 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1985 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1987 return !BM_TestHFlag(EDBM_get_edge_for_index(userData, index), BM_HIDDEN);
1989 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
1991 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
1994 /* Draw edges with color interpolated based on selection */
1995 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1997 return !BM_TestHFlag(EDBM_get_edge_for_index(((void**)userData)[0], index), BM_HIDDEN);
1999 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2001 BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], index);
2002 unsigned char **cols = userData;
2003 unsigned char *col0 = cols[(BM_TestHFlag(eed->v1, BM_SELECT))?2:1];
2004 unsigned char *col1 = cols[(BM_TestHFlag(eed->v2, BM_SELECT))?2:1];
2006 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
2007 col0[1] + (col1[1]-col0[1])*t,
2008 col0[2] + (col1[2]-col0[2])*t,
2009 col0[3] + (col1[3]-col0[3])*t);
2012 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2014 void *cols[3] = {em, baseCol, selCol};
2016 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2019 /* Draw only seam edges */
2020 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2022 BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2024 return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SEAM);
2027 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2029 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2032 /* Draw only sharp edges */
2033 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2035 BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2037 return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SHARP);
2039 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2041 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2045 /* Draw faces with color set based on selection
2046 * return 2 for the active face so it renders with stipple enabled */
2047 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2049 struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} *data = userData;
2050 BMFace *efa = EDBM_get_face_for_index(data->em, index);
2056 if (!BM_TestHFlag(efa, BM_HIDDEN)) {
2057 if (efa == data->efa_act) {
2058 glColor4ubv(data->cols[2]);
2060 return 2; /* stipple */
2062 col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
2063 if (col[3]==0) return 0;
2073 /* also draws the active face */
2074 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2075 unsigned char *selCol, unsigned char *actCol, BMFace *efa_act, Mesh *me)
2077 struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data;
2079 data.cols[0] = baseCol;
2081 data.cols[1] = selCol;
2082 data.cols[2] = actCol;
2083 data.efa_act = efa_act;
2086 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
2089 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2091 BMEditMesh *em = userData;
2092 BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2093 float *crease = eed ? bm_get_cd_float(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2098 if (!BM_TestHFlag(eed, BM_HIDDEN) && *crease!=0.0f) {
2099 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2105 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2108 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2112 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2114 BMEditMesh *em = userData;
2115 BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2116 float *bweight = bm_get_cd_float(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2121 if (!BM_TestHFlag(eed, BM_HIDDEN) && *bweight!=0.0f) {
2122 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2128 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2130 BMEditMesh *em = userData;
2131 BMVert *eve = EDBM_get_vert_for_index(userData, index);
2132 float *bweight = bm_get_cd_float(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2137 if (!BM_TestHFlag(eve, BM_HIDDEN) && *bweight!=0.0f) {
2138 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2142 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2144 ToolSettings *ts= scene->toolsettings;
2146 if (ts->selectmode & SCE_SELECT_VERTEX) {
2147 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2148 bglBegin(GL_POINTS);
2149 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2154 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2159 /* Second section of routines: Combine first sets to form fancy
2160 * drawing routines (for example rendering twice to get overlays).
2162 * Also includes routines that are basic drawing but are too
2163 * specialized to be split out (like drawing creases or measurements).
2166 /* EditMesh drawing routines*/
2168 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2169 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
2171 ToolSettings *ts= scene->toolsettings;
2174 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2176 for (sel=0; sel<2; sel++) {
2177 unsigned char col[4], fcol[4];
2180 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2181 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2183 for (pass=0; pass<2; pass++) {
2184 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2185 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2188 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2189 glDisable(GL_DEPTH_TEST);
2196 size = (size > 2.1f ? size/2.0f:size);
2197 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2198 col[3] = fcol[3] = 100;
2200 col[3] = fcol[3] = 255;
2203 if(ts->selectmode & SCE_SELECT_VERTEX) {
2206 draw_dm_verts(em, cageDM, sel, eve_act);
2209 if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2212 draw_dm_face_centers(em, cageDM, sel);
2216 glDisable(GL_BLEND);
2217 glEnable(GL_DEPTH_TEST);
2222 if(v3d->zbuf) glDepthMask(1);
2226 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2227 Mesh *me, DerivedMesh *cageDM, short sel_only,
2230 ToolSettings *ts= scene->toolsettings;
2232 unsigned char wireCol[4], selCol[4], actCol[4];
2234 /* since this function does transparant... */
2235 UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2236 UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2237 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2239 /* when sel only is used, dont render wire, only selected, this is used for
2240 * textured draw mode when the 'edges' option is disabled */
2244 for (pass=0; pass<2; pass++) {
2245 /* show wires in transparant when no zbuf clipping for select */
2247 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2249 glDisable(GL_DEPTH_TEST);
2251 if (!sel_only) wireCol[3] = 85;
2257 if (!sel_only) wireCol[3] = 255;
2260 if(ts->selectmode == SCE_SELECT_FACE) {
2261 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2263 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2264 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2265 glShadeModel(GL_SMOOTH);
2266 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2267 glShadeModel(GL_FLAT);
2269 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2274 glColor4ubv(wireCol);
2275 draw_dm_edges(em, cageDM);
2280 glDisable(GL_BLEND);
2281 glEnable(GL_DEPTH_TEST);
2286 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d,
2287 Object *ob, BMEditMesh *em, UnitSettings *unit)
2290 float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2291 char val[32]; /* Stores the measurement display text here */
2292 const char *conv_float; /* Use a float conversion matching the grid size */
2293 unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2294 float area; /* area of the face */
2295 float grid= unit->system ? unit->scale_length : v3d->grid;
2296 const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2297 const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2298 const int do_moving= G.moving;
2303 /* make the precision of the pronted value proportionate to the gridsize */
2305 if (grid < 0.01f) conv_float= "%.6g";
2306 else if (grid < 0.1f) conv_float= "%.5g";
2307 else if (grid < 1.0f) conv_float= "%.4g";
2308 else if (grid < 10.0f) conv_float= "%.3g";
2309 else conv_float= "%.2g";
2311 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2312 glDisable(GL_DEPTH_TEST);
2314 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2316 if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2319 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2321 eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2322 for(; eed; eed=BMIter_Step(&iter)) {
2323 /* draw selected edges, or edges next to selected verts while draging */
2324 if(BM_TestHFlag(eed, BM_SELECT) ||
2325 (do_moving && (BM_TestHFlag(eed->v1, BM_SELECT) || BM_TestHFlag(eed->v2, BM_SELECT) ))) {
2327 copy_v3_v3(v1, eed->v1->co);
2328 copy_v3_v3(v2, eed->v2->co);
2330 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2333 mul_mat3_m4_v3(ob->obmat, v1);
2334 mul_mat3_m4_v3(ob->obmat, v2);
2337 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2339 sprintf(val, conv_float, len_v3v3(v1, v2));
2341 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2346 if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2347 /* would be nice to use BM_face_area, but that is for 2d faces
2348 so instead add up tessalation triangle areas */
2352 #define DRAW_EM_MEASURE_STATS_FACEAREA(void)\
2353 if (BM_TestHFlag(f, BM_SELECT)) {\
2354 mul_v3_fl(vmid, 1.0/n);\
2356 bUnit_AsString(val, sizeof(val), area*unit->scale_length,\
2357 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);\
2359 sprintf(val, conv_float, area);\
2360 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);\
2363 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2369 for(i = 0; i < em->tottri; i++) {
2370 BMLoop **l = em->looptris[i];
2371 if(f && l[0]->f != f) {
2372 DRAW_EM_MEASURE_STATS_FACEAREA();
2379 copy_v3_v3(v1, l[0]->v->co);
2380 copy_v3_v3(v2, l[1]->v->co);
2381 copy_v3_v3(v3, l[2]->v->co);
2383 mul_mat3_m4_v3(ob->obmat, v1);
2384 mul_mat3_m4_v3(ob->obmat, v2);
2385 mul_mat3_m4_v3(ob->obmat, v3);
2387 area += area_tri_v3(v1, v2, v3);
2388 add_v3_v3(vmid, v1);
2389 add_v3_v3(vmid, v2);
2390 add_v3_v3(vmid, v3);
2395 DRAW_EM_MEASURE_STATS_FACEAREA();
2397 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2400 if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2403 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2406 for(efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
2407 efa; efa=BMIter_Step(&iter)) {
2411 BM_Compute_Face_Center(em->bm, efa, vmid);
2413 for(loop = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
2414 loop; loop = BMIter_Step(&liter)) {
2416 float v1[3], v2[3], v3[3];
2418 copy_v3_v3(v1, loop->prev->v->co);
2419 copy_v3_v3(v2, loop->v->co);
2420 copy_v3_v3(v3, loop->next->v->co);
2423 mul_mat3_m4_v3(ob->obmat, v1);
2424 mul_mat3_m4_v3(ob->obmat, v2);
2425 mul_mat3_m4_v3(ob->obmat, v3);
2428 if(BM_TestHFlag(efa, BM_SELECT) ||
2429 (do_moving && BM_TestHFlag(loop->v, BM_SELECT))){
2430 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2431 interp_v3_v3v3(fvec, vmid, v2, 0.8f);
2432 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2438 /* useful for debugging index vs shape key index */
2443 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2444 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2445 sprintf(val, "%d:%d", j, eve->keyindex);
2446 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2452 glEnable(GL_DEPTH_TEST);
2453 bglPolygonOffset(rv3d->dist, 0.0f);
2457 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
2459 BMFace *efa = EDBM_get_face_for_index(userData, index);
2461 if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
2462 GPU_enable_material(efa->mat_nr+1, NULL);
2469 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2471 BMFace *efa = EDBM_get_face_for_index(userData, index);
2473 return !BM_TestHFlag(efa, BM_HIDDEN);
2476 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
2477 BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2480 Mesh *me = ob->data;
2481 BMFace *efa_act = EDBM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2482 BMEdge *eed_act = NULL;
2483 BMVert *eve_act = NULL;
2485 if (em->bm->selected.last) {
2486 BMEditSelection *ese = em->bm->selected.last;
2487 /* face is handeled above */
2488 /*if (ese->type == EDITFACE ) {
2489 efa_act = (EditFace *)ese->data;
2490 } else */ if ( ese->type == EDITEDGE ) {
2491 eed_act = (BMEdge *)ese->data;
2492 } else if ( ese->type == EDITVERT ) {
2493 eve_act = (BMVert *)ese->data;
2497 EDBM_init_index_arrays(em, 1, 1, 1);
2500 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2501 if(draw_glsl_material(scene, ob, v3d, dt)) {
2502 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2504 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2505 draw_em_fancy__setGLSLFaceOpts, em);
2506 GPU_disable_material();
2508 glFrontFace(GL_CCW);
2511 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2515 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2516 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2518 glEnable(GL_LIGHTING);
2519 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2520 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, me->edit_btmesh, 0, GPU_enable_material);
2522 glFrontFace(GL_CCW);
2523 glDisable(GL_LIGHTING);
2526 // Setup for drawing wire over, disable zbuffer
2527 // write to show selected edge wires better
2528 UI_ThemeColor(TH_WIRE);
2530 bglPolygonOffset(rv3d->dist, 1.0);
2534 if (cageDM!=finalDM) {
2535 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2536 finalDM->drawEdges(finalDM, 1, 0);
2540 if(me->drawflag & ME_DRAWFACES) { /* transp faces */
2541 unsigned char col1[4], col2[4], col3[4];
2543 UI_GetThemeColor4ubv(TH_FACE, col1);
2544 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2545 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2548 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2550 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2551 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2554 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
2556 glDisable(GL_BLEND);
2557 glDepthMask(1); // restore write in zbuffer
2558 } else if (efa_act) {
2559 /* even if draw faces is off it would be nice to draw the stipple face
2560 * Make all other faces zero alpha except for the active
2562 unsigned char col1[4], col2[4], col3[4];
2563 col1[3] = col2[3] = 0; /* dont draw */
2564 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2567 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2569 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
2571 glDisable(GL_BLEND);
2572 glDepthMask(1); // restore write in zbuffer
2576 /* here starts all fancy draw-extra over */
2577 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2578 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2580 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2581 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
2584 if(me->drawflag & ME_DRAWSEAMS) {
2585 UI_ThemeColor(TH_EDGE_SEAM);
2588 draw_dm_edges_seams(em, cageDM);
2594 if(me->drawflag & ME_DRAWSHARP) {
2595 UI_ThemeColor(TH_EDGE_SHARP);
2598 draw_dm_edges_sharp(em, cageDM);
2604 if(me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
2605 draw_dm_creases(em, cageDM);
2607 if(me->drawflag & ME_DRAWBWEIGHTS) {
2608 draw_dm_bweights(em, scene, cageDM);
2611 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
2614 // XXX retopo_matrix_update(v3d);
2616 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2618 if(me->drawflag & ME_DRAWNORMALS) {
2619 UI_ThemeColor(TH_NORMAL);
2620 draw_dm_face_normals(em, scene, cageDM);
2622 if(me->drawflag & ME_DRAW_VNORMALS) {
2623 UI_ThemeColor(TH_VNORMAL);
2624 draw_dm_vert_normals(em, scene, cageDM);
2627 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2628 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2633 bglPolygonOffset(rv3d->dist, 0.0);
2634 GPU_disable_material();
2637 EDBM_free_index_arrays(em);
2640 /* Mesh drawing routines */
2642 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2645 if(v3d->transp==0) { // not when we draw the transparent pass
2646 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2649 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2650 drawFacesSolid() doesn't draw the transparent faces */
2651 if(ob->dtx & OB_DRAWTRANSP) {
2652 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2653 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2654 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2655 GPU_disable_material();
2658 dm->drawEdges(dm, 0, 1);
2666 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2672 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2674 Object *ob= base->object;
2675 Mesh *me = ob->data;
2676 Material *ma= give_current_material(ob, 1);
2677 const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2678 const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2680 int /* totvert,*/ totedge, totface;
2681 DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2686 if (ob->dtx&OB_DRAWWIRE) {
2687 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2690 /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2691 totedge = dm->getNumEdges(dm);
2692 totface = dm->getNumTessFaces(dm);
2694 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2696 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2698 // Unwanted combination.
2699 if (is_paint_sel) draw_wire = 0;
2701 if(dt==OB_BOUNDBOX) {
2702 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2703 draw_bounding_volume(scene, ob);
2705 else if(hasHaloMat || (totface==0 && totedge==0)) {
2710 else if(dt==OB_WIRE || totface==0) {
2711 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2713 else if( (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2714 CHECK_OB_DRAWTEXTURE(v3d, dt))
2716 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2717 draw_mesh_object_outline(v3d, ob, dm);
2720 if(draw_glsl_material(scene, ob, v3d, dt)) {
2721 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2723 dm->drawFacesGLSL(dm, GPU_enable_material);
2724 // if(get_ob_property(ob, "Text"))
2725 // XXX draw_mesh_text(ob, 1);
2726 GPU_disable_material();
2728 glFrontFace(GL_CCW);
2731 draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2735 if(base->flag & SELECT)
2736 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2738 UI_ThemeColor(TH_WIRE);
2740 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2741 dm->drawLooseEdges(dm);
2744 else if(dt==OB_SOLID) {
2745 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2746 /* weight paint in solid mode, special case. focus on making the weights clear
2747 * rather than the shading, this is also forced in wire view */
2748 GPU_enable_material(0, NULL);
2749 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2751 bglPolygonOffset(rv3d->dist, 1.0);
2752 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2755 glColor4ub(255, 255, 255, 96);
2756 glEnable(GL_LINE_STIPPLE);
2757 glLineStipple(1, 0xAAAA);
2759 dm->drawEdges(dm, 1, 1);
2761 bglPolygonOffset(rv3d->dist, 0.0);
2763 glDisable(GL_LINE_STIPPLE);
2765 GPU_disable_material();
2767 /* since we already draw wire as wp guide, dont draw over the top */
2773 if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2774 draw_mesh_object_outline(v3d, ob, dm);
2776 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2778 glEnable(GL_LIGHTING);
2779 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2781 if(ob->sculpt && (p=paint_get_active(scene))) {
2783 float (*fpl)[4] = NULL;
2784 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2786 if(ob->sculpt->partial_redraw) {
2787 if(ar->do_draw & RGN_DRAW_PARTIAL) {
2788 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2790 ob->sculpt->partial_redraw = 0;
2794 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2797 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2799 GPU_disable_material();
2801 glFrontFace(GL_CCW);
2802 glDisable(GL_LIGHTING);
2804 if(base->flag & SELECT) {
2805 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2807 UI_ThemeColor(TH_WIRE);
2809 if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2810 dm->drawLooseEdges(dm);
2813 else if(dt==OB_SHADED) {
2815 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2816 /* enforce default material settings */
2817 GPU_enable_material(0, NULL);
2819 /* but set default spec */
2820 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2821 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2822 glColor3ub(120, 120, 120);
2823 glDisable(GL_COLOR_MATERIAL);
2825 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2826 glEnable(GL_LIGHTING);
2827 glEnable(GL_COLOR_MATERIAL);
2829 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2830 glDisable(GL_COLOR_MATERIAL);
2831 glDisable(GL_LIGHTING);
2833 GPU_disable_material();
2835 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2837 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
2839 glColor3f(1.0f, 1.0f, 1.0f);
2840 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
2846 /* set default draw color back for wire or for draw-extra later on */
2848 if(base->flag & SELECT) {
2849 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2850 UI_ThemeColor(TH_GROUP_ACTIVE);
2851 else if(ob->flag & OB_FROMGROUP)
2852 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2853 else if(flag!=DRAW_CONSTCOLOR)
2854 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2856 glColor3ub(80,80,80);
2858 if (ob->flag & OB_FROMGROUP)
2859 UI_ThemeColor(TH_GROUP);
2861 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2862 glColor3ub(80,80,80);
2864 UI_ThemeColor(TH_WIRE);
2870 /* When using wireframe object traw in particle edit mode
2871 * the mesh gets in the way of seeing the particles, fade the wire color
2872 * with the background. */
2873 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2874 float col_wire[4], col_bg[4], col[3];
2876 UI_GetThemeColor3fv(TH_BACK, col_bg);
2877 glGetFloatv(GL_CURRENT_COLOR, col_wire);
2878 interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2882 /* If drawing wire and drawtype is not OB_WIRE then we are
2883 * overlaying the wires.
2885 * UPDATE bug #10290 - With this wire-only objects can draw
2886 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2888 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2889 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2891 if (dt!=OB_WIRE && draw_wire==2) {
2892 bglPolygonOffset(rv3d->dist, 1.0);
2893 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2896 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2897 dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2899 if (dt!=OB_WIRE && draw_wire==2) {
2901 bglPolygonOffset(rv3d->dist, 0.0);
2908 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2909 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2911 Object *ob= base->object;
2912 Object *obedit= scene->obedit;
2914 BMEditMesh *em= me->edit_btmesh;
2915 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
2917 /* If we are drawing shadows and any of the materials don't cast a shadow,
2918 * then don't draw the object */
2919 if (v3d->flag2 & V3D_RENDER_SHADOW) {
2920 for(i=0; i<ob->totcol; ++i) {
2921 Material *ma= give_current_material(ob, i);
2922 if (ma && !(ma->mode & MA_SHADBUF)) {
2928 if(obedit && ob!=obedit && ob->data==obedit->data) {
2929 if(ob_get_key(ob) || ob_get_key(obedit));
2930 else if(ob->modifiers.first || obedit->modifiers.first);
2934 if(ob==obedit || drawlinked) {
2935 DerivedMesh *finalDM, *cageDM;
2938 finalDM = cageDM = editbmesh_get_derived_base(ob, em);
2940 cageDM = editbmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2941 scene->customdata_mask);
2944 // no transp in editmode, the fancy draw over goes bad then
2945 glsl = draw_glsl_material(scene, ob, v3d, dt);
2946 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2949 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2951 GPU_end_object_materials();
2953 if (obedit!=ob && finalDM)
2954 finalDM->release(finalDM);
2957 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2958 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2959 glsl = draw_glsl_material(scene, ob, v3d, dt);
2960 check_alpha = check_material_alpha(base, me, glsl);
2962 if(dt==OB_SOLID || glsl) {
2963 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2964 (check_alpha)? &do_alpha_pass: NULL);
2967 draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2969 GPU_end_object_materials();
2971 if(me->totvert==0) retval= 1;
2975 /* GPU_begin_object_materials checked if this is needed */
2977 if(ob->dtx & OB_DRAWXRAY) {
2978 add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2981 add_view3d_after(&v3d->afterdraw_transp, base, flag);
2984 else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2985 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2986 if(v3d->xray == 0 && v3d->transp == 0) {
2987 add_view3d_after(&v3d->afterdraw_xray, base, flag);
2994 /* ************** DRAW DISPLIST ****************** */
2996 static int draw_index_wire= 1;
2997 static int index3_nors_incr= 1;
2999 /* returns 1 when nothing was drawn */
3000 static int drawDispListwire(ListBase *dlbase)
3006 if(dlbase==NULL) return 1;
3008 glEnableClientState(GL_VERTEX_ARRAY);
3009 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
3011 for(dl= dlbase->first; dl; dl= dl->next) {
3012 if(dl->parts==0 || dl->nr==0)
3020 glVertexPointer(3, GL_FLOAT, 0, data);
3022 for(parts=0; parts<dl->parts; parts++)
3023 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3028 glVertexPointer(3, GL_FLOAT, 0, data);
3030 for(parts=0; parts<dl->parts; parts++)
3031 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);