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_speaker_types.h"
49 #include "DNA_world_types.h"
50 #include "DNA_armature_types.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 "smoke_API.h"
81 #include "IMB_imbuf.h"
82 #include "IMB_imbuf_types.h"
85 #include "BIF_glutil.h"
88 #include "GPU_extensions.h"
91 #include "ED_particle.h"
92 #include "ED_screen.h"
93 #include "ED_sculpt.h"
95 #include "ED_curve.h" /* for ED_curve_editnurbs */
97 #include "UI_resources.h"
100 #include "wm_subwindow.h"
103 #include "view3d_intern.h" // own include
106 /* this condition has been made more complex since editmode can draw textures */
107 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
108 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
109 (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
111 static void draw_bounding_volume(Scene *scene, Object *ob);
113 static void drawcube_size(float size);
114 static void drawcircle_size(float size);
115 static void draw_empty_sphere(float size);
116 static void draw_empty_cone(float size);
118 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
120 if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
123 if(G.f & G_BACKBUFSEL)
126 if((vd->flag & V3D_ZBUF_SELECT) == 0)
129 /* if its drawing textures with zbuf sel, then dont draw dots */
130 if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
133 if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
139 /* ************* only use while object drawing **************
140 * or after running ED_view3d_init_mats_rv3d
142 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
144 RegionView3D *rv3d= ar->regiondata;
145 float fx, fy, vec4[4];
149 /* clipplanes in eye space */
150 if(rv3d->rflag & RV3D_CLIPPING) {
151 if(ED_view3d_test_clipping(rv3d, vec, local))
155 copy_v3_v3(vec4, vec);
158 mul_m4_v4(rv3d->persmatob, vec4);
160 /* clipplanes in window space */
161 if( vec4[3] > (float)BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
162 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
164 if( fx>0 && fx<ar->winx) {
166 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
168 if(fy > 0.0f && fy < (float)ar->winy) {
169 adr[0]= (short)floorf(fx);
170 adr[1]= (short)floorf(fy);
176 /* only use while object drawing */
177 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
179 RegionView3D *rv3d= ar->regiondata;
180 float fx, fy, vec4[4];
184 copy_v3_v3(vec4, vec);
187 mul_m4_v4(rv3d->persmatob, vec4);
189 if( vec4[3] > (float)BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
190 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
192 if( fx>-32700 && fx<32700) {
194 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
196 if(fy > -32700.0f && fy < 32700.0f) {
197 adr[0]= (short)floorf(fx);
198 adr[1]= (short)floorf(fy);
204 /* ************************ */
206 /* check for glsl drawing */
208 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
210 if(!GPU_glsl_support())
214 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
216 if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
219 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
222 static int check_material_alpha(Base *base, Mesh *me, int glsl)
224 if(base->flag & OB_FROMDUPLI)
233 return (glsl || (base->object->dtx & OB_DRAWTRANSP));
237 static unsigned int colortab[24]=
238 {0x0, 0xFF88FF, 0xFFBBFF,
239 0x403000, 0xFFFF88, 0xFFFFBB,
240 0x104040, 0x66CCCC, 0x77CCCC,
241 0x104010, 0x55BB55, 0x66FF66,
246 static float cube[8][3] = {
257 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
258 /* 32 values of sin function (still same result!) */
259 static float sinval[32] = {
294 /* 32 values of cos function (still same result!) */
295 static float cosval[32] ={
330 static void draw_xyz_wire(const float c[3], float size, int axis)
332 float v1[3]= {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
333 float dim = size * 0.1f;
334 float dx[3], dy[3], dz[3];
336 dx[0]=dim; dx[1]=0.f; dx[2]=0.f;
337 dy[0]=0.f; dy[1]=dim; dy[2]=0.f;
338 dz[0]=0.f; dz[1]=0.f; dz[2]=dim;
344 /* bottom left to top right */
345 sub_v3_v3v3(v1, c, dx);
347 add_v3_v3v3(v2, c, dx);
353 /* top left to bottom right */
366 /* bottom left to top right */
367 mul_v3_fl(dx, 0.75f);
368 sub_v3_v3v3(v1, c, dx);
370 add_v3_v3v3(v2, c, dx);
376 /* top left to center */
387 glBegin(GL_LINE_STRIP);
389 /* start at top left */
390 sub_v3_v3v3(v1, c, dx);
391 add_v3_v3v3(v1, c, dz);
416 void drawaxes(float size, char drawtype)
419 float v1[3]= {0.0, 0.0, 0.0};
420 float v2[3]= {0.0, 0.0, 0.0};
421 float v3[3]= {0.0, 0.0, 0.0};
426 for (axis=0; axis<3; axis++) {
434 /* reset v1 & v2 to zero */
435 v1[axis]= v2[axis]= 0.0f;
440 case OB_SINGLE_ARROW:
443 /* in positive z direction only */
450 glBegin(GL_TRIANGLES);
452 v2[0]= size * 0.035f; v2[1] = size * 0.035f;
453 v3[0]= size * -0.035f; v3[1] = size * 0.035f;
454 v2[2]= v3[2]= size * 0.75f;
456 for (axis=0; axis<4; axis++) {
478 drawcircle_size(size);
481 case OB_EMPTY_SPHERE:
482 draw_empty_sphere(size);
486 draw_empty_cone(size);
491 for (axis=0; axis<3; axis++) {
492 const int arrow_axis= (axis==0) ? 1:0;
500 v1[axis]= size*0.85f;
501 v1[arrow_axis]= -size*0.08f;
505 v1[arrow_axis]= size*0.08f;
511 v2[axis]+= size*0.125f;
513 draw_xyz_wire(v2, size, axis);
516 /* reset v1 & v2 to zero */
517 v1[arrow_axis]= v1[axis]= v2[axis]= 0.0f;
524 /* Function to draw an Image on a empty Object */
525 static void draw_empty_image(Object *ob)
527 Image *ima = (Image*)ob->data;
528 ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
530 float scale, ofs_x, ofs_y, sca_x, sca_y;
533 if(ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
534 IMB_rect_from_float(ibuf);
537 /* Get the buffer dimensions so we can fallback to fake ones */
538 if(ibuf && ibuf->rect) {
547 /* Get the image aspect even if the buffer is invalid */
549 if(ima->aspx > ima->aspy) {
551 sca_y= ima->aspy / ima->aspx;
553 else if(ima->aspx < ima->aspy) {
554 sca_x= ima->aspx / ima->aspy;
567 /* Calculate the scale center based on objects origin */
568 ofs_x= ob->ima_ofs[0] * ima_x;
569 ofs_y= ob->ima_ofs[1] * ima_y;
571 glMatrixMode(GL_MODELVIEW);
574 /* Make sure we are drawing at the origin */
575 glTranslatef(0.0f, 0.0f, 0.0f);
577 /* Calculate Image scale */
578 scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
580 /* Set the object scale */
581 glScalef(scale * sca_x, scale * sca_y, 1.0f);
583 if(ibuf && ibuf->rect) {
584 /* Setup GL params */
586 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
588 /* Use the object color and alpha */
591 /* Draw the Image on the screen */
592 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
593 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
598 UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
600 /* Calculate the outline vertex positions */
601 glBegin(GL_LINE_LOOP);
602 glVertex2f(ofs_x, ofs_y);
603 glVertex2f(ofs_x + ima_x, ofs_y);
604 glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
605 glVertex2f(ofs_x, ofs_y + ima_y);
608 /* Reset GL settings */
609 glMatrixMode(GL_MODELVIEW);
613 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
615 float vec[3], vx[3], vy[3];
618 mul_v3_v3fl(vx, tmat[0], rad);
619 mul_v3_v3fl(vy, tmat[1], rad);
622 for(a=0; a<tot; a++) {
623 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
624 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
625 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
631 /* circle for object centers, special_color is for library or ob users */
632 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
634 const float size= ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
636 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
637 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
641 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
643 else glColor4ub(0x55, 0xCC, 0xCC, 155);
646 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
647 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
648 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
650 drawcircball(GL_POLYGON, co, size, rv3d->viewinv);
652 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
653 drawcircball(GL_LINE_LOOP, co, size, rv3d->viewinv);
656 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
659 /* *********** text drawing for object/particles/armature ************* */
660 static ListBase CachedText[3];
661 static int CachedTextLevel= 0;
663 typedef struct ViewCachedString {
664 struct ViewCachedString *next, *prev;
674 /* str is allocated past the end */
677 void view3d_cached_text_draw_begin(void)
679 ListBase *strings= &CachedText[CachedTextLevel];
680 strings->first= strings->last= NULL;
684 void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4])
686 int alloc_len= strlen(str) + 1;
687 ListBase *strings= &CachedText[CachedTextLevel-1];
688 ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
690 BLI_addtail(strings, vos);
691 copy_v3_v3(vos->vec, co);
692 vos->col.pack= *((int *)col);
695 vos->str_len= alloc_len-1;
697 /* allocate past the end */
698 memcpy(++vos, str, alloc_len);
701 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
703 RegionView3D *rv3d= ar->regiondata;
704 ListBase *strings= &CachedText[CachedTextLevel-1];
705 ViewCachedString *vos;
708 /* project first and test */
709 for(vos= strings->first; vos; vos= vos->next) {
710 if(mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
711 mul_m4_v3(mat, vos->vec);
712 view3d_project_short_clip(ar, vos->vec, vos->sco, 0);
713 if(vos->sco[0]!=IS_CLIPPED)
718 int col_pack_prev= 0;
721 bglMats mats; /* ZBuffer depth vars */
728 if(rv3d->rflag & RV3D_CLIPPING)
730 glDisable(GL_CLIP_PLANE0+a);
732 glMatrixMode(GL_PROJECTION);
734 glMatrixMode(GL_MODELVIEW);
736 ED_region_pixelspace(ar);
739 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
743 for(vos= strings->first; vos; vos= vos->next) {
744 #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
745 if(v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
746 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
747 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
753 if(vos->sco[0]!=IS_CLIPPED) {
754 const char *str= (char *)(vos+1);
756 if(col_pack_prev != vos->col.pack) {
757 glColor3ubv(vos->col.ub);
758 col_pack_prev= vos->col.pack;
760 if(vos->flag & V3D_CACHE_TEXT_ASCII) {
761 BLF_draw_default_ascii((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
764 BLF_draw_default((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
770 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
774 glMatrixMode(GL_PROJECTION);
776 glMatrixMode(GL_MODELVIEW);
779 if(rv3d->rflag & RV3D_CLIPPING)
781 glEnable(GL_CLIP_PLANE0+a);
785 BLI_freelistN(strings);
790 /* ******************** primitive drawing ******************* */
792 static void drawcube(void)
795 glBegin(GL_LINE_STRIP);
796 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
797 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
798 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
801 glBegin(GL_LINE_STRIP);
802 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
805 glBegin(GL_LINE_STRIP);
806 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
809 glBegin(GL_LINE_STRIP);
810 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
814 /* draws a cube on given the scaling of the cube, assuming that
815 * all required matrices have been set (used for drawing empties)
817 static void drawcube_size(float size)
819 glBegin(GL_LINE_STRIP);
820 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
821 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
822 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
825 glBegin(GL_LINE_STRIP);
826 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
829 glBegin(GL_LINE_STRIP);
830 glVertex3f(-size,size,size); glVertex3f(size,size,size);
833 glBegin(GL_LINE_STRIP);
834 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
838 /* this is an unused (old) cube-drawing function based on a given size */
840 static void drawcube_size(float *size)
844 glScalef(size[0], size[1], size[2]);
847 glBegin(GL_LINE_STRIP);
848 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
849 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
850 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
853 glBegin(GL_LINE_STRIP);
854 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
857 glBegin(GL_LINE_STRIP);
858 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
861 glBegin(GL_LINE_STRIP);
862 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
869 static void drawshadbuflimits(Lamp *la, float mat[][4])
871 float sta[3], end[3], lavec[3];
873 negate_v3_v3(lavec, mat[2]);
876 madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
877 madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
879 glBegin(GL_LINE_STRIP);
894 static void spotvolume(float *lvec, float *vvec, float inp)
896 /* camera is at 0,0,0 */
897 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
900 normalize_v3(vvec); /* is this the correct vector ? */
902 cross_v3_v3v3(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
903 cross_v3_v3v3(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
905 /* vectors are exactly aligned, use the X axis, this is arbitrary */
906 if(normalize_v3(plane) == 0.0f)
909 /* now we've got two equations: one of a cone and one of a plane, but we have
910 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
912 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
913 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
915 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
922 angle = saacos(plane[2])/2.0f;
931 quat_to_mat3(mat1,q);
933 /* rotate lamp vector now over acos(inp) degrees */
934 copy_v3_v3(vvec, lvec);
938 si = sqrt(1-inp*inp);
944 mul_m3_m3m3(mat3,mat2,mat1);
948 mul_m3_m3m3(mat4,mat2,mat1);
951 mul_m3_m3m3(mat2,mat1,mat3);
952 mul_m3_v3(mat2,lvec);
953 mul_m3_m3m3(mat2,mat1,mat4);
954 mul_m3_v3(mat2,vvec);
959 static void draw_spot_cone(Lamp *la, float x, float z)
963 glBegin(GL_TRIANGLE_FAN);
964 glVertex3f(0.0f, 0.0f, -x);
966 if(la->mode & LA_SQUARE) {
968 glVertex3f(-z, z, 0);
969 glVertex3f(-z, -z, 0);
970 glVertex3f(z, -z, 0);
977 for(a=0; a<33; a++) {
978 angle= a*M_PI*2/(33-1);
979 glVertex3f(z*cosf(angle), z*sinf(angle), 0);
986 static void draw_transp_spot_volume(Lamp *la, float x, float z)
988 glEnable(GL_CULL_FACE);
992 /* draw backside darkening */
993 glCullFace(GL_FRONT);
995 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
996 glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
998 draw_spot_cone(la, x, z);
1000 /* draw front side lighting */
1001 glCullFace(GL_BACK);
1003 glBlendFunc(GL_ONE, GL_ONE);
1004 glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1006 draw_spot_cone(la, x, z);
1009 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1010 glDisable(GL_BLEND);
1012 glDisable(GL_CULL_FACE);
1013 glCullFace(GL_BACK);
1016 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
1018 Object *ob= base->object;
1019 const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1021 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
1023 float imat[4][4], curcol[4];
1024 unsigned char col[4];
1025 /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1026 /* the moment of view3d_draw_transp() call */
1027 const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
1028 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);
1030 if(drawcone && !v3d->transp) {
1031 /* in this case we need to draw delayed */
1032 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1036 /* we first draw only the screen aligned & fixed scale stuff */
1038 glLoadMatrixf(rv3d->viewmat);
1040 /* lets calculate the scale: */
1041 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
1043 /* and view aligned matrix: */
1044 copy_m4_m4(imat, rv3d->viewinv);
1045 normalize_v3(imat[0]);
1046 normalize_v3(imat[1]);
1049 copy_v3_v3(vec, ob->obmat[3]);
1051 /* for AA effects */
1052 glGetFloatv(GL_CURRENT_COLOR, curcol);
1056 if(lampsize > 0.0f) {
1059 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1060 else glColor4ub(0x77, 0xCC, 0xCC, 155);
1065 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1066 glDisable(GL_BLEND);
1067 drawcircball(GL_POLYGON, vec, lampsize, imat);
1074 circrad = 3.0f*lampsize;
1077 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1079 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1080 if(la->type!=LA_HEMI) {
1081 if( (la->mode & LA_SHAD_RAY) ||
1082 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
1084 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
1093 /* draw the pretty sun rays */
1094 if(la->type==LA_SUN) {
1095 float v1[3], v2[3], mat[3][3];
1098 /* setup a 45 degree rotation matrix */
1099 vec_rot_to_mat3(mat, imat[2], (float)M_PI/4.0f);
1102 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1103 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1106 glTranslatef(vec[0], vec[1], vec[2]);
1111 for (axis=0; axis<8; axis++) {
1119 glTranslatef(-vec[0], -vec[1], -vec[2]);
1123 if (la->type==LA_LOCAL) {
1124 if(la->mode & LA_SPHERE) {
1125 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1127 /* yafray: for photonlight also draw lightcone as for spot */
1130 glPopMatrix(); /* back in object space */
1134 /* skip drawing extra info */
1136 else if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
1137 lvec[0]=lvec[1]= 0.0;
1139 x = rv3d->persmat[0][2];
1140 y = rv3d->persmat[1][2];
1141 z = rv3d->persmat[2][2];
1142 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
1143 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
1144 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
1146 y = cosf(la->spotsize*(float)(M_PI/360.0));
1147 spotvolume(lvec, vvec, y);
1152 /* draw the angled sides of the cone */
1153 glBegin(GL_LINE_STRIP);
1159 z = x*sqrtf(1.0f - y*y);
1162 /* draw the circle/square at the end of the cone */
1163 glTranslatef(0.0, 0.0 , x);
1164 if(la->mode & LA_SQUARE) {
1166 float z_abs= fabs(z);
1168 tvec[0]= tvec[1]= z_abs;
1171 glBegin(GL_LINE_LOOP);
1173 tvec[1]= -z_abs; /* neg */
1175 tvec[0]= -z_abs; /* neg */
1177 tvec[1]= z_abs; /* pos */
1181 else circ(0.0, 0.0, fabsf(z));
1183 /* draw the circle/square representing spotbl */
1184 if(la->type==LA_SPOT) {
1185 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
1186 /* hide line if it is zero size or overlaps with outer border,
1187 previously it adjusted to always to show it but that seems
1188 confusing because it doesn't show the actual blend size */
1189 if (spotblcirc != 0 && spotblcirc != fabsf(z))
1190 circ(0.0, 0.0, spotblcirc);
1194 draw_transp_spot_volume(la, x, z);
1196 /* draw clip start, useful for wide cones where its not obvious where the start is */
1197 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
1198 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1201 float clipsta_fac= la->clipsta / -x;
1203 interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1204 interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1206 glBegin(GL_LINE_STRIP);
1207 glVertex3fv(lvec_clip);
1208 glVertex3fv(vvec_clip);
1212 else if ELEM(la->type, LA_HEMI, LA_SUN) {
1214 /* draw the line from the circle along the dist */
1215 glBegin(GL_LINE_STRIP);
1222 if(la->type==LA_HEMI) {
1223 /* draw the hemisphere curves */
1224 short axis, steps, dir;
1225 float outdist, zdist, mul;
1227 outdist = 0.14; mul = 1.4; dir = 1;
1230 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1231 for (axis=0; axis<4; axis++) {
1232 float v[3]= {0.0, 0.0, 0.0};
1235 glBegin(GL_LINE_STRIP);
1237 for (steps=0; steps<6; steps++) {
1238 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
1239 /* make the arcs start at the edge of the energy circle */
1240 if (steps == 0) v[0] = dir*circrad;
1241 else v[0] = v[0] + dir*(steps*outdist);
1242 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
1243 /* make the arcs start at the edge of the energy circle */
1244 if (steps == 0) v[1] = dir*circrad;
1245 else v[1] = v[1] + dir*(steps*outdist);
1248 v[2] = v[2] - steps*zdist;
1252 zdist = zdist * mul;
1256 /* flip the direction */
1260 } else if(la->type==LA_AREA) {
1262 if(la->area_shape==LA_AREA_SQUARE)
1263 fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
1264 else if(la->area_shape==LA_AREA_RECT)
1265 fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
1267 glBegin(GL_LINE_STRIP);
1268 glVertex3f(0.0,0.0,-circrad);
1269 glVertex3f(0.0,0.0,-la->dist);
1273 /* and back to viewspace */
1274 glLoadMatrixf(rv3d->viewmat);
1275 copy_v3_v3(vec, ob->obmat[3]);
1279 if((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1280 drawshadbuflimits(la, ob->obmat);
1283 UI_GetThemeColor4ubv(TH_LAMP, col);
1288 if (vec[2]>0) vec[2] -= circrad;
1289 else vec[2] += circrad;
1291 glBegin(GL_LINE_STRIP);
1303 glDisable(GL_BLEND);
1305 /* restore for drawing extra stuff */
1310 static void draw_limit_line(float sta, float end, unsigned int col)
1313 glVertex3f(0.0, 0.0, -sta);
1314 glVertex3f(0.0, 0.0, -end);
1320 glVertex3f(0.0, 0.0, -sta);
1321 glVertex3f(0.0, 0.0, -end);
1327 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1328 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1329 static void draw_focus_cross(float dist, float size)
1332 glVertex3f(-size, 0.f, -dist);
1333 glVertex3f(size, 0.f, -dist);
1334 glVertex3f(0.f, -size, -dist);
1335 glVertex3f(0.f, size, -dist);
1339 #ifdef VIEW3D_CAMERA_BORDER_HACK
1340 float view3d_camera_border_hack_col[4];
1341 short view3d_camera_border_hack_test= FALSE;
1344 /* flag similar to draw_object() */
1345 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1347 /* a standing up pyramid with (0,0,0) as top */
1349 float vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1352 const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1354 const float scax= 1.0f / len_v3(ob->obmat[0]);
1355 const float scay= 1.0f / len_v3(ob->obmat[1]);
1356 const float scaz= 1.0f / len_v3(ob->obmat[2]);
1358 #ifdef VIEW3D_CAMERA_BORDER_HACK
1359 if(is_view && !(G.f & G_PICKSEL)) {
1360 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1361 view3d_camera_border_hack_test= TRUE;
1367 aspx= (float) scene->r.xsch*scene->r.xasp;
1368 aspy= (float) scene->r.ysch*scene->r.yasp;
1379 glDisable(GL_LIGHTING);
1380 glDisable(GL_CULL_FACE);
1382 if(cam->type==CAM_ORTHO) {
1383 facx= 0.5f * cam->ortho_scale * caspx * scax;
1384 facy= 0.5f * cam->ortho_scale * caspy * scay;
1385 shx= cam->shiftx * cam->ortho_scale * scax;
1386 shy= cam->shifty * cam->ortho_scale * scay;
1387 depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
1389 drawsize= 0.5f * cam->ortho_scale;
1392 /* that way it's always visible - clipsta+0.1 */
1394 drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
1397 /* fixed depth, variable size (avoids exceeding clipping range) */
1398 depth = -(cam->clipsta + 0.1f);
1399 fac = depth / (cam->lens/-16.0f * scaz);
1402 /* fixed size, variable depth (stays a reasonable size in the 3D view) */
1403 depth= drawsize * cam->lens/-16.0f * scaz;
1407 facx= fac * caspx * scax;
1408 facy= fac * caspy * scay;
1409 shx= cam->shiftx*fac*2 * scax;
1410 shy= cam->shifty*fac*2 * scay;
1413 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
1414 vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1415 vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1416 vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1417 vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1420 glBegin(GL_LINE_LOOP);
1421 glVertex3fv(vec[1]);
1422 glVertex3fv(vec[2]);
1423 glVertex3fv(vec[3]);
1424 glVertex3fv(vec[4]);
1430 /* center point to camera frame */
1431 glBegin(GL_LINE_STRIP);
1432 glVertex3fv(vec[2]);
1433 glVertex3fv(vec[0]);
1434 glVertex3fv(vec[1]);
1435 glVertex3fv(vec[4]);
1436 glVertex3fv(vec[0]);
1437 glVertex3fv(vec[3]);
1445 /* draw an outline arrow for inactive cameras and filled
1446 * for active cameras. We actually draw both outline+filled
1447 * for active cameras so the wire can be seen side-on */
1449 if (i==0) glBegin(GL_LINE_LOOP);
1450 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1453 vec[0][0]= shx + ((-0.7f * drawsize) * scax);
1454 vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
1455 glVertex3fv(vec[0]); /* left */
1457 vec[0][0]= shx + ((0.7f * drawsize) * scax);
1458 glVertex3fv(vec[0]); /* right */
1461 vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
1462 glVertex3fv(vec[0]); /* top */
1468 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1472 /* draw in normalized object matrix space */
1473 copy_m4_m4(nobmat, ob->obmat);
1474 normalize_m4(nobmat);
1477 glLoadMatrixf(rv3d->viewmat);
1478 glMultMatrixf(nobmat);
1480 if(cam->flag & CAM_SHOWLIMITS) {
1481 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1482 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1483 draw_focus_cross(dof_camera(ob), cam->drawsize);
1487 if(cam->flag & CAM_SHOWMIST)
1488 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1495 /* flag similar to draw_object() */
1496 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), Object *UNUSED(ob), int UNUSED(flag))
1498 //Speaker *spk = ob->data;
1505 for(j = 0; j < 3; j++) {
1506 vec[2] = 0.25f * j -0.125f;
1508 glBegin(GL_LINE_LOOP);
1509 for(i = 0; i < 16; i++) {
1510 vec[0] = cosf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1511 vec[1] = sinf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1517 for(j = 0; j < 4; j++) {
1518 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1519 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1520 glBegin(GL_LINE_STRIP);
1521 for(i = 0; i < 3; i++) {
1527 vec[2] = 0.25f * i -0.125f;
1533 glDisable(GL_BLEND);
1536 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1538 BPoint *bp = lt->def;
1539 float *co = dl?dl->verts:NULL;
1542 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1543 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1544 bglBegin(GL_POINTS);
1546 for(w=0; w<lt->pntsw; w++) {
1547 int wxt = (w==0 || w==lt->pntsw-1);
1548 for(v=0; v<lt->pntsv; v++) {
1549 int vxt = (v==0 || v==lt->pntsv-1);
1550 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1551 int uxt = (u==0 || u==lt->pntsu-1);
1552 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1554 if((bp->f1 & SELECT)==sel) {
1555 bglVertex3fv(dl?co:bp->vec);
1567 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1569 Object *obedit= vc->obedit;
1570 Lattice *lt= obedit->data;
1571 BPoint *bp = lt->editlatt->latt->def;
1572 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1573 float *co = dl?dl->verts:NULL;
1574 int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1575 short s[2] = {IS_CLIPPED, 0};
1577 ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1579 for (i=0; i<N; i++, bp++, co+=3) {
1581 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1582 if (s[0] != IS_CLIPPED)
1583 func(userData, bp, s[0], s[1]);
1588 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1590 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1594 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1596 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1602 glVertex3fv(&dl->verts[index*3]);
1604 glVertex3fv(lt->def[index].vec);
1608 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1609 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1611 Lattice *lt= ob->data;
1614 int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1616 /* now we default make displist, this will modifiers work for non animated case */
1617 if(ob->disp.first==NULL)
1618 lattice_calc_modifiers(scene, ob);
1619 dl= find_displist(&ob->disp, DL_VERTS);
1622 lt= lt->editlatt->latt;
1626 if(ob->defbase.first && lt->dvert) {
1627 use_wcol= ob->actdef;
1628 glShadeModel(GL_SMOOTH);
1633 for(w=0; w<lt->pntsw; w++) {
1634 int wxt = (w==0 || w==lt->pntsw-1);
1635 for(v=0; v<lt->pntsv; v++) {
1636 int vxt = (v==0 || v==lt->pntsv-1);
1637 for(u=0; u<lt->pntsu; u++) {
1638 int uxt = (u==0 || u==lt->pntsu-1);
1640 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1641 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1642 drawlattice__point(lt, dl, u, v, w, use_wcol);
1644 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1645 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1646 drawlattice__point(lt, dl, u, v, w, use_wcol);
1648 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1649 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1650 drawlattice__point(lt, dl, u, v, w, use_wcol);
1657 /* restoration for weight colors */
1659 glShadeModel(GL_FLAT);
1662 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1664 lattice_draw_verts(lt, dl, 0);
1665 lattice_draw_verts(lt, dl, 1);
1667 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1671 /* ***************** ******************** */
1673 /* Note! - foreach funcs should be called while drawing or directly after
1674 * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1675 * but would not give correct results with dupli's for eg. which dont
1676 * use the object matrix in the useual way */
1677 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1679 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1680 EditVert *eve = EM_get_vert_for_index(index);
1683 short s[2]= {IS_CLIPPED, 0};
1685 if (data->clipVerts) {
1686 view3d_project_short_clip(data->vc.ar, co, s, 1);
1688 view3d_project_short_noclip(data->vc.ar, co, s);
1691 if (s[0]!=IS_CLIPPED)
1692 data->func(data->userData, eve, s[0], s[1], index);
1696 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1698 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1699 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1703 data.userData = userData;
1704 data.clipVerts = clipVerts;
1707 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1709 EM_init_index_arrays(vc->em, 1, 0, 0);
1710 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1711 EM_free_index_arrays();
1716 static void mesh_obmode_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1718 struct { void (*func)(void *userData, MVert *mv, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1719 Mesh *me = data->vc.obact->data;
1720 MVert *mv = me->mvert+index;
1721 //MVert *dmv = CDDM_get_verts(data->vc.obact->derivedFinal)+index;
1722 //MVert *mv = CDDM_get_verts(data->vc.obact->derivedFinal)+index;
1723 if ((mv->flag & ME_HIDE)==0) {
1724 short s[2]= {IS_CLIPPED, 0};
1726 if (data->clipVerts) {
1727 view3d_project_short_clip(data->vc.ar, co, s, 1);
1729 view3d_project_short_noclip(data->vc.ar, co, s);
1732 if (s[0]!=IS_CLIPPED)
1733 data->func(data->userData, mv, s[0], s[1], index);
1737 void mesh_obmode_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, MVert *mv, int x, int y, int index), void *userData, int clipVerts)
1739 struct { void (*func)(void *userData, MVert *mv, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1740 DerivedMesh *dm = mesh_get_derived_final(vc->scene, vc->obact, CD_MASK_BAREMESH);
1744 data.userData = userData;
1745 data.clipVerts = clipVerts;
1748 ED_view3d_local_clipping(vc->rv3d, vc->obact->obmat); /* for local clipping lookups */
1750 dm->foreachMappedVert(dm, mesh_obmode_foreachScreenVert__mapFunc, &data);
1754 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1756 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;
1757 EditEdge *eed = EM_get_edge_for_index(index);
1761 if (data->clipVerts==1) {
1762 view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1763 view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1765 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1766 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1768 if (data->clipVerts==2) {
1769 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1770 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1775 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1779 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)
1781 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1782 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1786 data.userData = userData;
1787 data.clipVerts = clipVerts;
1790 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1792 EM_init_index_arrays(vc->em, 0, 1, 0);
1793 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1794 EM_free_index_arrays();
1799 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1801 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1802 EditFace *efa = EM_get_face_for_index(index);
1805 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1806 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1808 data->func(data->userData, efa, s[0], s[1], index);
1812 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1814 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1815 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1819 data.userData = userData;
1822 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1824 EM_init_index_arrays(vc->em, 0, 0, 1);
1825 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1826 EM_free_index_arrays();
1831 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1833 Curve *cu= vc->obedit->data;
1834 short s[2] = {IS_CLIPPED, 0};
1837 ListBase *nurbs= ED_curve_editnurbs(cu);
1839 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1841 for (nu= nurbs->first; nu; nu=nu->next) {
1842 if(nu->type == CU_BEZIER) {
1843 for (i=0; i<nu->pntsu; i++) {
1844 BezTriple *bezt = &nu->bezt[i];
1848 if(cu->drawflag & CU_HIDE_HANDLES) {
1849 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1850 if (s[0] != IS_CLIPPED)
1851 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1853 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1854 if (s[0] != IS_CLIPPED)
1855 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1856 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1857 if (s[0] != IS_CLIPPED)
1858 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1859 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1860 if (s[0] != IS_CLIPPED)
1861 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1867 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1868 BPoint *bp = &nu->bp[i];
1871 view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1872 if (s[0] != IS_CLIPPED)
1873 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1880 /* ************** DRAW MESH ****************** */
1882 /* First section is all the "simple" draw routines,
1883 * ones that just pass some sort of primitive to GL,
1884 * with perhaps various options to control lighting,
1887 * These routines should not have user interface related
1891 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1893 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1894 EditFace *efa = EM_get_face_for_index(index);
1896 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1898 glVertex3f( cent[0] + no[0]*ts->normalsize,
1899 cent[1] + no[1]*ts->normalsize,
1900 cent[2] + no[2]*ts->normalsize);
1903 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1906 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1910 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1912 EditFace *efa = EM_get_face_for_index(index);
1913 int sel = *((int*) userData);
1915 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1919 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1921 bglBegin(GL_POINTS);
1922 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1926 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1928 Scene *scene= (Scene *)userData;
1929 ToolSettings *ts= scene->toolsettings;
1930 EditVert *eve = EM_get_vert_for_index(index);
1936 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1937 co[1] + no_f[1]*ts->normalsize,
1938 co[2] + no_f[2]*ts->normalsize);
1940 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1941 co[1] + no_s[1]*ts->normalsize/32767.0f,
1942 co[2] + no_s[2]*ts->normalsize/32767.0f);
1946 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1949 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1953 /* Draw verts with color set based on selection */
1954 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1956 struct { int sel; EditVert *eve_act; } * data = userData;
1957 EditVert *eve = EM_get_vert_for_index(index);
1959 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1960 /* draw active larger - need to stop/start point drawing for this :/ */
1961 if (eve==data->eve_act) {
1962 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1963 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1968 bglBegin(GL_POINTS);
1972 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1974 bglBegin(GL_POINTS);
1981 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1983 struct { int sel; EditVert *eve_act; } data;
1985 data.eve_act = eve_act;
1987 bglBegin(GL_POINTS);
1988 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1992 /* Draw edges with color set based on selection */
1993 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1995 EditEdge *eed = EM_get_edge_for_index(index);
1996 //unsigned char **cols = userData, *col;
1997 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
2001 if (eed==data->eed_act) {
2002 glColor4ubv(data->actCol);
2004 if (eed->f&SELECT) {
2007 col = data->baseCol;
2009 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
2010 if (col[3]==0) return 0;
2019 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
2021 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
2023 data.baseCol = baseCol;
2024 data.selCol = selCol;
2025 data.actCol = actCol;
2026 data.eed_act = eed_act;
2027 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2031 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
2033 return EM_get_edge_for_index(index)->h==0;
2035 static void draw_dm_edges(DerivedMesh *dm)
2037 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2040 /* Draw edges with color interpolated based on selection */
2041 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2043 return EM_get_edge_for_index(index)->h==0;
2045 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2047 EditEdge *eed = EM_get_edge_for_index(index);
2048 unsigned char **cols = userData;
2049 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2050 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2052 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
2053 col0[1] + (col1[1]-col0[1])*t,
2054 col0[2] + (col1[2]-col0[2])*t,
2055 col0[3] + (col1[3]-col0[3])*t);
2058 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2060 unsigned char *cols[2];
2063 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2066 /* Draw only seam edges */
2067 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2069 EditEdge *eed = EM_get_edge_for_index(index);
2071 return (eed->h==0 && eed->seam);
2073 static void draw_dm_edges_seams(DerivedMesh *dm)
2075 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2078 /* Draw only sharp edges */
2079 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2081 EditEdge *eed = EM_get_edge_for_index(index);
2083 return (eed->h==0 && eed->sharp);
2085 static void draw_dm_edges_sharp(DerivedMesh *dm)
2087 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2091 /* Draw faces with color set based on selection
2092 * return 2 for the active face so it renders with stipple enabled */
2093 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2095 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2096 EditFace *efa = EM_get_face_for_index(index);
2100 if (efa == data->efa_act) {
2101 glColor4ubv(data->cols[2]);
2102 return 2; /* stipple */
2104 col = data->cols[(efa->f&SELECT)?1:0];
2105 if (col[3]==0) return 0;
2113 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2115 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2116 EditFace *efa = EM_get_face_for_index(index);
2117 EditFace *next_efa = EM_get_face_for_index(next_index);
2118 unsigned char *col, *next_col;
2123 if(efa == data->efa_act || next_efa == data->efa_act)
2126 col = data->cols[(efa->f&SELECT)?1:0];
2127 next_col = data->cols[(next_efa->f&SELECT)?1:0];
2129 if(col[3]==0 || next_col[3]==0)
2132 return col == next_col;
2135 /* also draws the active face */
2136 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
2138 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2139 data.cols[0] = baseCol;
2140 data.cols[1] = selCol;
2141 data.cols[2] = actCol;
2142 data.efa_act = efa_act;
2144 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
2147 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2149 EditEdge *eed = EM_get_edge_for_index(index);
2151 if (eed->h==0 && eed->crease != 0.0f) {
2152 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2158 static void draw_dm_creases(DerivedMesh *dm)
2161 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2165 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2167 EditEdge *eed = EM_get_edge_for_index(index);
2169 if (eed->h==0 && eed->bweight != 0.0f) {
2170 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2176 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2178 EditVert *eve = EM_get_vert_for_index(index);
2180 if (eve->h==0 && eve->bweight != 0.0f) {
2181 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2185 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2187 ToolSettings *ts= scene->toolsettings;
2189 if (ts->selectmode & SCE_SELECT_VERTEX) {
2190 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2191 bglBegin(GL_POINTS);
2192 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2197 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2202 /* Second section of routines: Combine first sets to form fancy
2203 * drawing routines (for example rendering twice to get overlays).
2205 * Also includes routines that are basic drawing but are too
2206 * specialized to be split out (like drawing creases or measurements).
2209 /* EditMesh drawing routines*/
2211 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2213 ToolSettings *ts= scene->toolsettings;
2216 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2218 for (sel=0; sel<2; sel++) {
2219 unsigned char col[4], fcol[4];
2222 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2223 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2225 for (pass=0; pass<2; pass++) {
2226 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2227 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2230 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2231 glDisable(GL_DEPTH_TEST);
2238 size = (size > 2.1f ? size/2.0f:size);
2239 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2240 col[3] = fcol[3] = 100;
2242 col[3] = fcol[3] = 255;
2245 if(ts->selectmode & SCE_SELECT_VERTEX) {
2248 draw_dm_verts(cageDM, sel, eve_act);
2251 if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2254 draw_dm_face_centers(cageDM, sel);
2258 glDisable(GL_BLEND);
2259 glEnable(GL_DEPTH_TEST);
2264 if(v3d->zbuf) glDepthMask(1);
2268 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2270 ToolSettings *ts= scene->toolsettings;
2272 unsigned char wireCol[4], selCol[4], actCol[4];
2274 /* since this function does transparant... */
2275 UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2276 UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2277 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2279 /* when sel only is used, dont render wire, only selected, this is used for
2280 * textured draw mode when the 'edges' option is disabled */
2284 for (pass=0; pass<2; pass++) {
2285 /* show wires in transparant when no zbuf clipping for select */
2287 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2289 glDisable(GL_DEPTH_TEST);
2291 if (!sel_only) wireCol[3] = 85;
2297 if (!sel_only) wireCol[3] = 255;
2300 if(ts->selectmode == SCE_SELECT_FACE) {
2301 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2303 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2304 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2305 glShadeModel(GL_SMOOTH);
2306 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2307 glShadeModel(GL_FLAT);
2309 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2314 glColor4ubv(wireCol);
2315 draw_dm_edges(cageDM);
2320 glDisable(GL_BLEND);
2321 glEnable(GL_DEPTH_TEST);
2326 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2331 float v1[3], v2[3], v3[3], v4[3], vmid[3];
2333 char val[32]; /* Stores the measurement display text here */
2334 const char *conv_float; /* Use a float conversion matching the grid size */
2335 unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2336 float area; /* area of the face */
2337 float grid= unit->system ? unit->scale_length : v3d->grid;
2338 const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2339 const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2340 const int do_moving= G.moving;
2342 /* make the precision of the pronted value proportionate to the gridsize */
2344 if (grid < 0.01f) conv_float= "%.6g";
2345 else if (grid < 0.1f) conv_float= "%.5g";
2346 else if (grid < 1.0f) conv_float= "%.4g";
2347 else if (grid < 10.0f) conv_float= "%.3g";
2348 else conv_float= "%.2g";
2350 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2351 glDisable(GL_DEPTH_TEST);
2353 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2355 if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2356 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2358 for(eed= em->edges.first; eed; eed= eed->next) {
2359 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2360 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2361 copy_v3_v3(v1, eed->v1->co);
2362 copy_v3_v3(v2, eed->v2->co);
2364 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2367 mul_mat3_m4_v3(ob->obmat, v1);
2368 mul_mat3_m4_v3(ob->obmat, v2);
2371 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2373 sprintf(val, conv_float, len_v3v3(v1, v2));
2375 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2380 if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2381 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2382 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2384 for(efa= em->faces.first; efa; efa= efa->next) {
2385 if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2386 copy_v3_v3(v1, efa->v1->co);
2387 copy_v3_v3(v2, efa->v2->co);
2388 copy_v3_v3(v3, efa->v3->co);
2390 copy_v3_v3(v4, efa->v4->co);
2393 mul_mat3_m4_v3(ob->obmat, v1);
2394 mul_mat3_m4_v3(ob->obmat, v2);
2395 mul_mat3_m4_v3(ob->obmat, v3);
2396 if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2400 area= area_quad_v3(v1, v2, v3, v4);
2402 area = area_tri_v3(v1, v2, v3);
2405 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2407 sprintf(val, conv_float, area);
2409 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2414 if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2415 EditEdge *e1, *e2, *e3, *e4;
2416 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2417 for(efa= em->faces.first; efa; efa= efa->next) {
2418 copy_v3_v3(v1, efa->v1->co);
2419 copy_v3_v3(v2, efa->v2->co);
2420 copy_v3_v3(v3, efa->v3->co);
2422 copy_v3_v3(v4, efa->v4->co);
2428 mul_mat3_m4_v3(ob->obmat, v1);
2429 mul_mat3_m4_v3(ob->obmat, v2);
2430 mul_mat3_m4_v3(ob->obmat, v3);
2431 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2437 if(efa->e4) e4= efa->e4; else e4= e3;
2439 /* Calculate the angles */
2441 if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2443 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2444 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2445 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2447 if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2449 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2450 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2451 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2453 if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2456 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2458 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2459 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2460 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2464 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2465 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2466 interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2467 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2473 /* useful for debugging index vs shape key index */
2478 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2479 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2480 sprintf(val, "%d:%d", j, eve->keyindex);
2481 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2487 glEnable(GL_DEPTH_TEST);
2488 bglPolygonOffset(rv3d->dist, 0.0f);
2492 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2494 EditFace *efa = EM_get_face_for_index(index);
2497 GPU_enable_material(efa->mat_nr+1, NULL);
2504 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2506 EditFace *efa = EM_get_face_for_index(index);
2511 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2513 Mesh *me = ob->data;
2514 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2515 EditEdge *eed_act = NULL;
2516 EditVert *eve_act = NULL;
2518 if (em->selected.last) {
2519 EditSelection *ese = em->selected.last;
2520 /* face is handeled above */
2521 /*if (ese->type == EDITFACE ) {
2522 efa_act = (EditFace *)ese->data;
2523 } else */ if ( ese->type == EDITEDGE ) {
2524 eed_act = (EditEdge *)ese->data;
2525 } else if ( ese->type == EDITVERT ) {
2526 eve_act = (EditVert *)ese->data;
2530 EM_init_index_arrays(em, 1, 1, 1);
2533 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2534 if(draw_glsl_material(scene, ob, v3d, dt)) {
2535 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2537 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2538 draw_em_fancy__setGLSLFaceOpts, NULL);
2539 GPU_disable_material();
2541 glFrontFace(GL_CCW);
2544 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2548 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2549 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2551 glEnable(GL_LIGHTING);
2552 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2554 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
2556 glFrontFace(GL_CCW);
2557 glDisable(GL_LIGHTING);
2560 // Setup for drawing wire over, disable zbuffer
2561 // write to show selected edge wires better
2562 UI_ThemeColor(TH_WIRE);
2564 bglPolygonOffset(rv3d->dist, 1.0);
2568 if (cageDM!=finalDM) {
2569 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2570 finalDM->drawEdges(finalDM, 1, 0);
2574 if(me->drawflag & ME_DRAWFACES) { /* transp faces */
2575 unsigned char col1[4], col2[4], col3[4];
2577 UI_GetThemeColor4ubv(TH_FACE, col1);
2578 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2579 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2582 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2584 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2585 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2588 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2590 glDisable(GL_BLEND);
2591 glDepthMask(1); // restore write in zbuffer
2592 } else if (efa_act) {
2593 /* even if draw faces is off it would be nice to draw the stipple face
2594 * Make all other faces zero alpha except for the active
2596 unsigned char col1[4], col2[4], col3[4];
2597 col1[3] = col2[3] = 0; /* dont draw */
2598 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2601 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2603 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2605 glDisable(GL_BLEND);
2606 glDepthMask(1); // restore write in zbuffer
2610 /* here starts all fancy draw-extra over */
2611 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2612 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2614 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2615 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2618 if(me->drawflag & ME_DRAWSEAMS) {
2619 UI_ThemeColor(TH_EDGE_SEAM);
2622 draw_dm_edges_seams(cageDM);
2628 if(me->drawflag & ME_DRAWSHARP) {
2629 UI_ThemeColor(TH_EDGE_SHARP);
2632 draw_dm_edges_sharp(cageDM);
2638 if(me->drawflag & ME_DRAWCREASES) {
2639 draw_dm_creases(cageDM);
2641 if(me->drawflag & ME_DRAWBWEIGHTS) {
2642 draw_dm_bweights(scene, cageDM);
2645 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2648 // XXX retopo_matrix_update(v3d);
2650 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2652 if(me->drawflag & ME_DRAWNORMALS) {
2653 UI_ThemeColor(TH_NORMAL);
2654 draw_dm_face_normals(scene, cageDM);
2656 if(me->drawflag & ME_DRAW_VNORMALS) {
2657 UI_ThemeColor(TH_VNORMAL);
2658 draw_dm_vert_normals(scene, cageDM);
2661 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2662 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2667 bglPolygonOffset(rv3d->dist, 0.0);
2668 GPU_disable_material();
2671 EM_free_index_arrays();
2674 /* Mesh drawing routines */
2676 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2679 if(v3d->transp==0) { // not when we draw the transparent pass
2680 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2683 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2684 drawFacesSolid() doesn't draw the transparent faces */
2685 if(ob->dtx & OB_DRAWTRANSP) {
2686 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2687 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2688 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2689 GPU_disable_material();
2692 dm->drawEdges(dm, 0, 1);
2700 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2706 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2708 Object *ob= base->object;
2709 Mesh *me = ob->data;
2710 Material *ma= give_current_material(ob, 1);
2711 const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2712 const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2714 int /* totvert,*/ totedge, totface;
2715 DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2720 if (ob->dtx&OB_DRAWWIRE) {
2721 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2724 /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2725 totedge = dm->getNumEdges(dm);
2726 totface = dm->getNumFaces(dm);
2728 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2730 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2732 // Unwanted combination.
2733 if (is_paint_sel) draw_wire = 0;
2735 if(dt==OB_BOUNDBOX) {
2736 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2737 draw_bounding_volume(scene, ob);
2739 else if(hasHaloMat || (totface==0 && totedge==0)) {
2744 else if(dt==OB_WIRE || totface==0) {
2745 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2747 else if( (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2748 CHECK_OB_DRAWTEXTURE(v3d, dt))
2750 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2751 draw_mesh_object_outline(v3d, ob, dm);
2754 if(draw_glsl_material(scene, ob, v3d, dt)) {
2755 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2757 dm->drawFacesGLSL(dm, GPU_enable_material);
2758 // if(get_ob_property(ob, "Text"))
2759 // XXX draw_mesh_text(ob, 1);
2760 GPU_disable_material();
2762 glFrontFace(GL_CCW);
2765 draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2769 if(base->flag & SELECT)
2770 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2772 UI_ThemeColor(TH_WIRE);
2774 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2775 dm->drawLooseEdges(dm);
2778 else if(dt==OB_SOLID) {
2779 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2780 /* weight paint in solid mode, special case. focus on making the weights clear
2781 * rather than the shading, this is also forced in wire view */
2782 GPU_enable_material(0, NULL);
2783 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
2785 bglPolygonOffset(rv3d->dist, 1.0);
2786 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2789 glColor4ub(255, 255, 255, 96);
2790 glEnable(GL_LINE_STIPPLE);
2791 glLineStipple(1, 0xAAAA);
2793 dm->drawEdges(dm, 1, 1);
2795 bglPolygonOffset(rv3d->dist, 0.0);
2797 glDisable(GL_LINE_STIPPLE);
2799 GPU_disable_material();
2801 /* since we already draw wire as wp guide, dont draw over the top */
2807 if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2808 draw_mesh_object_outline(v3d, ob, dm);
2810 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2812 glEnable(GL_LIGHTING);
2813 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2815 if(ob->sculpt && (p=paint_get_active(scene))) {
2817 float (*fpl)[4] = NULL;
2818 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2820 if(ob->sculpt->partial_redraw) {
2821 if(ar->do_draw & RGN_DRAW_PARTIAL) {
2822 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2824 ob->sculpt->partial_redraw = 0;
2828 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2831 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2833 GPU_disable_material();
2835 glFrontFace(GL_CCW);
2836 glDisable(GL_LIGHTING);
2838 if(base->flag & SELECT) {
2839 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2841 UI_ThemeColor(TH_WIRE);
2843 if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2844 dm->drawLooseEdges(dm);
2847 else if(dt==OB_SHADED) {
2849 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2850 /* enforce default material settings */
2851 GPU_enable_material(0, NULL);
2853 /* but set default spec */
2854 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2855 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2856 glColor3ub(120, 120, 120);
2857 glDisable(GL_COLOR_MATERIAL);
2859 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2860 glEnable(GL_LIGHTING);
2861 glEnable(GL_COLOR_MATERIAL);
2863 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
2864 glDisable(GL_COLOR_MATERIAL);
2865 glDisable(GL_LIGHTING);
2867 GPU_disable_material();
2869 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2871 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material, NULL);
2873 glColor3f(1.0f, 1.0f, 1.0f);
2874 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material, NULL);
2880 /* set default draw color back for wire or for draw-extra later on */
2882 if(base->flag & SELECT) {
2883 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2884 UI_ThemeColor(TH_GROUP_ACTIVE);
2885 else if(ob->flag & OB_FROMGROUP)
2886 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2887 else if(flag!=DRAW_CONSTCOLOR)
2888 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2890 glColor3ub(80,80,80);
2892 if (ob->flag & OB_FROMGROUP)
2893 UI_ThemeColor(TH_GROUP);
2895 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2896 glColor3ub(80,80,80);
2898 UI_ThemeColor(TH_WIRE);
2904 /* When using wireframe object traw in particle edit mode
2905 * the mesh gets in the way of seeing the particles, fade the wire color
2906 * with the background. */
2907 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2908 float col_wire[4], col_bg[4], col[3];
2910 UI_GetThemeColor3fv(TH_BACK, col_bg);
2911 glGetFloatv(GL_CURRENT_COLOR, col_wire);
2912 interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2916 /* If drawing wire and drawtype is not OB_WIRE then we are
2917 * overlaying the wires.
2919 * UPDATE bug #10290 - With this wire-only objects can draw
2920 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2922 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2923 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2925 if (dt!=OB_WIRE && draw_wire==2) {
2926 bglPolygonOffset(rv3d->dist, 1.0);
2927 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2930 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2931 dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2933 if (dt!=OB_WIRE && draw_wire==2) {
2935 bglPolygonOffset(rv3d->dist, 0.0);
2939 if(paint_vertsel_test(ob) && dm->drawSelectedVerts) {
2940 glColor3f(0.0f, 0.0f, 0.0f);
2941 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
2942 dm->drawSelectedVerts(dm);
2948 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2949 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2951 Object *ob= base->object;
2952 Object *obedit= scene->obedit;
2954 EditMesh *em= me->edit_mesh;
2955 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
2957 /* If we are drawing shadows and any of the materials don't cast a shadow,
2958 * then don't draw the object */
2959 if (v3d->flag2 & V3D_RENDER_SHADOW) {
2960 for(i=0; i<ob->totcol; ++i) {
2961 Material *ma= give_current_material(ob, i);
2962 if (ma && !(ma->mode & MA_SHADBUF)) {
2968 if(obedit && ob!=obedit && ob->data==obedit->data) {
2969 if(ob_get_key(ob) || ob_get_key(obedit));
2970 else if(ob->modifiers.first || obedit->modifiers.first);
2974 if(ob==obedit || drawlinked) {
2975 DerivedMesh *finalDM, *cageDM;
2978 finalDM = cageDM = editmesh_get_derived_base(ob, em);
2980 cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2981 scene->customdata_mask);
2984 // no transp in editmode, the fancy draw over goes bad then
2985 glsl = draw_glsl_material(scene, ob, v3d, dt);
2986 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2989 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2991 GPU_end_object_materials();
2993 if (obedit!=ob && finalDM)
2994 finalDM->release(finalDM);
2997 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2998 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2999 glsl = draw_glsl_material(scene, ob, v3d, dt);
3000 check_alpha = check_material_alpha(base, me, glsl);
3002 if(dt==OB_SOLID || glsl) {
3003 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
3004 (check_alpha)? &do_alpha_pass: NULL);
3007 draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
3009 GPU_end_object_materials();
3011 if(me->totvert==0) retval= 1;
3015 /* GPU_begin_object_materials checked if this is needed */
3017 if(ob->dtx & OB_DRAWXRAY) {
3018 add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
3021 add_view3d_after(&v3d->afterdraw_transp, base, flag);
3024 else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
3025 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
3026 if(v3d->xray == 0 && v3d->transp == 0) {
3027 add_view3d_after(&v3d->afterdraw_xray, base, flag);
3034 /* ************** DRAW DISPLIST ****************** */
3036 static int draw_index_wire= 1;
3037 static int index3_nors_incr= 1;
3039 /* returns 1 when nothing was drawn */
3040 static int drawDispListwire(ListBase *dlbase)
3046 if(dlbase==NULL) return 1;
3048 glEnableClientState(GL_VERTEX_ARRAY);
3049 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
3051 for(dl= dlbase->first; dl; dl= dl->next) {
3052 if(dl->parts==0 || dl->nr==0)
3060 glVertexPointer(3, GL_FLOAT, 0, data);
3062 for(parts=0; parts<dl->parts; parts++)
3063 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3068 glVertexPointer(3, GL_FLOAT, 0, data);
3070 for(parts=0; parts<dl->parts; parts++)
3071 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3076 glVertexPointer(3, GL_FLOAT, 0, data);
3078 for(parts=0; parts<dl->parts; parts++) {
3079 if(dl->flag & DL_CYCL_U)
3080 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3082 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3085 for(nr=0; nr<dl->nr; nr++) {
3088 data= ( dl->verts )+3*nr;
3091 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
3092 else glBegin(GL_LINE_STRIP);