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, const float vec[3], 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, const float vec[3], 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(const float size[3])
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[3], float vvec[3], const 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 = sqrtf(1.0f-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_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1718 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;
1719 EditEdge *eed = EM_get_edge_for_index(index);
1723 if (data->clipVerts==1) {
1724 view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1725 view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1727 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1728 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1730 if (data->clipVerts==2) {
1731 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1732 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1737 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1741 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)
1743 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1744 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1748 data.userData = userData;
1749 data.clipVerts = clipVerts;
1752 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1754 EM_init_index_arrays(vc->em, 0, 1, 0);
1755 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1756 EM_free_index_arrays();
1761 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1763 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1764 EditFace *efa = EM_get_face_for_index(index);
1767 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1768 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1770 data->func(data->userData, efa, s[0], s[1], index);
1774 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1776 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1777 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1781 data.userData = userData;
1784 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1786 EM_init_index_arrays(vc->em, 0, 0, 1);
1787 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1788 EM_free_index_arrays();
1793 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1795 Curve *cu= vc->obedit->data;
1796 short s[2] = {IS_CLIPPED, 0};
1799 ListBase *nurbs= ED_curve_editnurbs(cu);
1801 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1803 for (nu= nurbs->first; nu; nu=nu->next) {
1804 if(nu->type == CU_BEZIER) {
1805 for (i=0; i<nu->pntsu; i++) {
1806 BezTriple *bezt = &nu->bezt[i];
1810 if(cu->drawflag & CU_HIDE_HANDLES) {
1811 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1812 if (s[0] != IS_CLIPPED)
1813 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1815 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1816 if (s[0] != IS_CLIPPED)
1817 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1818 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1819 if (s[0] != IS_CLIPPED)
1820 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1821 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1822 if (s[0] != IS_CLIPPED)
1823 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1829 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1830 BPoint *bp = &nu->bp[i];
1833 view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1834 if (s[0] != IS_CLIPPED)
1835 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1842 /* ************** DRAW MESH ****************** */
1844 /* First section is all the "simple" draw routines,
1845 * ones that just pass some sort of primitive to GL,
1846 * with perhaps various options to control lighting,
1849 * These routines should not have user interface related
1853 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1855 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1856 EditFace *efa = EM_get_face_for_index(index);
1858 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1860 glVertex3f( cent[0] + no[0]*ts->normalsize,
1861 cent[1] + no[1]*ts->normalsize,
1862 cent[2] + no[2]*ts->normalsize);
1865 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1868 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1872 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1874 EditFace *efa = EM_get_face_for_index(index);
1875 int sel = *((int*) userData);
1877 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1881 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1883 bglBegin(GL_POINTS);
1884 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1888 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1890 Scene *scene= (Scene *)userData;
1891 ToolSettings *ts= scene->toolsettings;
1892 EditVert *eve = EM_get_vert_for_index(index);
1898 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1899 co[1] + no_f[1]*ts->normalsize,
1900 co[2] + no_f[2]*ts->normalsize);
1902 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1903 co[1] + no_s[1]*ts->normalsize/32767.0f,
1904 co[2] + no_s[2]*ts->normalsize/32767.0f);
1908 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1911 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1915 /* Draw verts with color set based on selection */
1916 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1918 struct { int sel; EditVert *eve_act; } * data = userData;
1919 EditVert *eve = EM_get_vert_for_index(index);
1921 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1922 /* draw active larger - need to stop/start point drawing for this :/ */
1923 if (eve==data->eve_act) {
1924 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1925 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1930 bglBegin(GL_POINTS);
1934 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1936 bglBegin(GL_POINTS);
1943 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1945 struct { int sel; EditVert *eve_act; } data;
1947 data.eve_act = eve_act;
1949 bglBegin(GL_POINTS);
1950 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1954 /* Draw edges with color set based on selection */
1955 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1957 EditEdge *eed = EM_get_edge_for_index(index);
1958 //unsigned char **cols = userData, *col;
1959 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1963 if (eed==data->eed_act) {
1964 glColor4ubv(data->actCol);
1966 if (eed->f&SELECT) {
1969 col = data->baseCol;
1971 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1972 if (col[3]==0) return 0;
1981 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1983 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1985 data.baseCol = baseCol;
1986 data.selCol = selCol;
1987 data.actCol = actCol;
1988 data.eed_act = eed_act;
1989 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1993 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
1995 return EM_get_edge_for_index(index)->h==0;
1997 static void draw_dm_edges(DerivedMesh *dm)
1999 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2002 /* Draw edges with color interpolated based on selection */
2003 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2005 return EM_get_edge_for_index(index)->h==0;
2007 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2009 EditEdge *eed = EM_get_edge_for_index(index);
2010 unsigned char **cols = userData;
2011 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2012 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2014 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
2015 col0[1] + (col1[1]-col0[1])*t,
2016 col0[2] + (col1[2]-col0[2])*t,
2017 col0[3] + (col1[3]-col0[3])*t);
2020 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2022 unsigned char *cols[2];
2025 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2028 /* Draw only seam edges */
2029 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2031 EditEdge *eed = EM_get_edge_for_index(index);
2033 return (eed->h==0 && eed->seam);
2035 static void draw_dm_edges_seams(DerivedMesh *dm)
2037 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2040 /* Draw only sharp edges */
2041 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2043 EditEdge *eed = EM_get_edge_for_index(index);
2045 return (eed->h==0 && eed->sharp);
2047 static void draw_dm_edges_sharp(DerivedMesh *dm)
2049 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2053 /* Draw faces with color set based on selection
2054 * return 2 for the active face so it renders with stipple enabled */
2055 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2057 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2058 EditFace *efa = EM_get_face_for_index(index);
2062 if (efa == data->efa_act) {
2063 glColor4ubv(data->cols[2]);
2064 return 2; /* stipple */
2066 col = data->cols[(efa->f&SELECT)?1:0];
2067 if (col[3]==0) return 0;
2075 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2077 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2078 EditFace *efa = EM_get_face_for_index(index);
2079 EditFace *next_efa = EM_get_face_for_index(next_index);
2080 unsigned char *col, *next_col;
2085 if(efa == data->efa_act || next_efa == data->efa_act)
2088 col = data->cols[(efa->f&SELECT)?1:0];
2089 next_col = data->cols[(next_efa->f&SELECT)?1:0];
2091 if(col[3]==0 || next_col[3]==0)
2094 return col == next_col;
2097 /* also draws the active face */
2098 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
2100 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2101 data.cols[0] = baseCol;
2102 data.cols[1] = selCol;
2103 data.cols[2] = actCol;
2104 data.efa_act = efa_act;
2106 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
2109 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2111 EditEdge *eed = EM_get_edge_for_index(index);
2113 if (eed->h==0 && eed->crease != 0.0f) {
2114 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2120 static void draw_dm_creases(DerivedMesh *dm)
2123 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2127 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2129 EditEdge *eed = EM_get_edge_for_index(index);
2131 if (eed->h==0 && eed->bweight != 0.0f) {
2132 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2138 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2140 EditVert *eve = EM_get_vert_for_index(index);
2142 if (eve->h==0 && eve->bweight != 0.0f) {
2143 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2147 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2149 ToolSettings *ts= scene->toolsettings;
2151 if (ts->selectmode & SCE_SELECT_VERTEX) {
2152 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2153 bglBegin(GL_POINTS);
2154 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2159 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2164 /* Second section of routines: Combine first sets to form fancy
2165 * drawing routines (for example rendering twice to get overlays).
2167 * Also includes routines that are basic drawing but are too
2168 * specialized to be split out (like drawing creases or measurements).
2171 /* EditMesh drawing routines*/
2173 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2175 ToolSettings *ts= scene->toolsettings;
2178 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2180 for (sel=0; sel<2; sel++) {
2181 unsigned char col[4], fcol[4];
2184 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2185 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2187 for (pass=0; pass<2; pass++) {
2188 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2189 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2192 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2193 glDisable(GL_DEPTH_TEST);
2200 size = (size > 2.1f ? size/2.0f:size);
2201 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2202 col[3] = fcol[3] = 100;
2204 col[3] = fcol[3] = 255;
2207 if(ts->selectmode & SCE_SELECT_VERTEX) {
2210 draw_dm_verts(cageDM, sel, eve_act);
2213 if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2216 draw_dm_face_centers(cageDM, sel);
2220 glDisable(GL_BLEND);
2221 glEnable(GL_DEPTH_TEST);
2226 if(v3d->zbuf) glDepthMask(1);
2230 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2232 ToolSettings *ts= scene->toolsettings;
2234 unsigned char wireCol[4], selCol[4], actCol[4];
2236 /* since this function does transparant... */
2237 UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2238 UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2239 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2241 /* when sel only is used, dont render wire, only selected, this is used for
2242 * textured draw mode when the 'edges' option is disabled */
2246 for (pass=0; pass<2; pass++) {
2247 /* show wires in transparant when no zbuf clipping for select */
2249 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2251 glDisable(GL_DEPTH_TEST);
2253 if (!sel_only) wireCol[3] = 85;
2259 if (!sel_only) wireCol[3] = 255;
2262 if(ts->selectmode == SCE_SELECT_FACE) {
2263 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2265 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2266 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2267 glShadeModel(GL_SMOOTH);
2268 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2269 glShadeModel(GL_FLAT);
2271 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2276 glColor4ubv(wireCol);
2277 draw_dm_edges(cageDM);
2282 glDisable(GL_BLEND);
2283 glEnable(GL_DEPTH_TEST);
2288 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2293 float v1[3], v2[3], v3[3], v4[3], vmid[3];
2295 char val[32]; /* Stores the measurement display text here */
2296 const char *conv_float; /* Use a float conversion matching the grid size */
2297 unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2298 float area; /* area of the face */
2299 float grid= unit->system ? unit->scale_length : v3d->grid;
2300 const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2301 const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2302 const int do_moving= G.moving;
2304 /* make the precision of the pronted value proportionate to the gridsize */
2306 if (grid < 0.01f) conv_float= "%.6g";
2307 else if (grid < 0.1f) conv_float= "%.5g";
2308 else if (grid < 1.0f) conv_float= "%.4g";
2309 else if (grid < 10.0f) conv_float= "%.3g";
2310 else conv_float= "%.2g";
2312 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2313 glDisable(GL_DEPTH_TEST);
2315 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2317 if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2318 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2320 for(eed= em->edges.first; eed; eed= eed->next) {
2321 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2322 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2323 copy_v3_v3(v1, eed->v1->co);
2324 copy_v3_v3(v2, eed->v2->co);
2326 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2329 mul_mat3_m4_v3(ob->obmat, v1);
2330 mul_mat3_m4_v3(ob->obmat, v2);
2333 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2335 sprintf(val, conv_float, len_v3v3(v1, v2));
2337 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2342 if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2343 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2344 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2346 for(efa= em->faces.first; efa; efa= efa->next) {
2347 if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2348 copy_v3_v3(v1, efa->v1->co);
2349 copy_v3_v3(v2, efa->v2->co);
2350 copy_v3_v3(v3, efa->v3->co);
2352 copy_v3_v3(v4, efa->v4->co);
2355 mul_mat3_m4_v3(ob->obmat, v1);
2356 mul_mat3_m4_v3(ob->obmat, v2);
2357 mul_mat3_m4_v3(ob->obmat, v3);
2358 if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2362 area= area_quad_v3(v1, v2, v3, v4);
2364 area = area_tri_v3(v1, v2, v3);
2367 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2369 sprintf(val, conv_float, area);
2371 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2376 if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2377 EditEdge *e1, *e2, *e3, *e4;
2378 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2379 for(efa= em->faces.first; efa; efa= efa->next) {
2380 copy_v3_v3(v1, efa->v1->co);
2381 copy_v3_v3(v2, efa->v2->co);
2382 copy_v3_v3(v3, efa->v3->co);
2384 copy_v3_v3(v4, efa->v4->co);
2390 mul_mat3_m4_v3(ob->obmat, v1);
2391 mul_mat3_m4_v3(ob->obmat, v2);
2392 mul_mat3_m4_v3(ob->obmat, v3);
2393 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2399 if(efa->e4) e4= efa->e4; else e4= e3;
2401 /* Calculate the angles */
2403 if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2405 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2406 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2407 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2409 if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2411 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2412 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2413 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2415 if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2418 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2420 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2421 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2422 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2426 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2427 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2428 interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2429 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2435 /* useful for debugging index vs shape key index */
2440 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2441 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2442 sprintf(val, "%d:%d", j, eve->keyindex);
2443 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2449 glEnable(GL_DEPTH_TEST);
2450 bglPolygonOffset(rv3d->dist, 0.0f);
2454 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2456 EditFace *efa = EM_get_face_for_index(index);
2459 GPU_enable_material(efa->mat_nr+1, NULL);
2466 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2468 EditFace *efa = EM_get_face_for_index(index);
2473 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2475 Mesh *me = ob->data;
2476 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2477 EditEdge *eed_act = NULL;
2478 EditVert *eve_act = NULL;
2480 if (em->selected.last) {
2481 EditSelection *ese = em->selected.last;
2482 /* face is handeled above */
2483 /*if (ese->type == EDITFACE ) {
2484 efa_act = (EditFace *)ese->data;
2485 } else */ if ( ese->type == EDITEDGE ) {
2486 eed_act = (EditEdge *)ese->data;
2487 } else if ( ese->type == EDITVERT ) {
2488 eve_act = (EditVert *)ese->data;
2492 EM_init_index_arrays(em, 1, 1, 1);
2495 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2496 if(draw_glsl_material(scene, ob, v3d, dt)) {
2497 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2499 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2500 draw_em_fancy__setGLSLFaceOpts, NULL);
2501 GPU_disable_material();
2503 glFrontFace(GL_CCW);
2506 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2510 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2511 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2513 glEnable(GL_LIGHTING);
2514 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2516 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
2518 glFrontFace(GL_CCW);
2519 glDisable(GL_LIGHTING);
2522 // Setup for drawing wire over, disable zbuffer
2523 // write to show selected edge wires better
2524 UI_ThemeColor(TH_WIRE);
2526 bglPolygonOffset(rv3d->dist, 1.0);
2530 if (cageDM!=finalDM) {
2531 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2532 finalDM->drawEdges(finalDM, 1, 0);
2536 if(me->drawflag & ME_DRAWFACES) { /* transp faces */
2537 unsigned char col1[4], col2[4], col3[4];
2539 UI_GetThemeColor4ubv(TH_FACE, col1);
2540 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2541 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2544 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2546 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2547 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2550 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2552 glDisable(GL_BLEND);
2553 glDepthMask(1); // restore write in zbuffer
2554 } else if (efa_act) {
2555 /* even if draw faces is off it would be nice to draw the stipple face
2556 * Make all other faces zero alpha except for the active
2558 unsigned char col1[4], col2[4], col3[4];
2559 col1[3] = col2[3] = 0; /* dont draw */
2560 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2563 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2565 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2567 glDisable(GL_BLEND);
2568 glDepthMask(1); // restore write in zbuffer
2572 /* here starts all fancy draw-extra over */
2573 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2574 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2576 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2577 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2580 if(me->drawflag & ME_DRAWSEAMS) {
2581 UI_ThemeColor(TH_EDGE_SEAM);
2584 draw_dm_edges_seams(cageDM);
2590 if(me->drawflag & ME_DRAWSHARP) {
2591 UI_ThemeColor(TH_EDGE_SHARP);
2594 draw_dm_edges_sharp(cageDM);
2600 if(me->drawflag & ME_DRAWCREASES) {
2601 draw_dm_creases(cageDM);
2603 if(me->drawflag & ME_DRAWBWEIGHTS) {
2604 draw_dm_bweights(scene, cageDM);
2607 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2610 // XXX retopo_matrix_update(v3d);
2612 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2614 if(me->drawflag & ME_DRAWNORMALS) {
2615 UI_ThemeColor(TH_NORMAL);
2616 draw_dm_face_normals(scene, cageDM);
2618 if(me->drawflag & ME_DRAW_VNORMALS) {
2619 UI_ThemeColor(TH_VNORMAL);
2620 draw_dm_vert_normals(scene, cageDM);
2623 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2624 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2629 bglPolygonOffset(rv3d->dist, 0.0);
2630 GPU_disable_material();
2633 EM_free_index_arrays();
2636 /* Mesh drawing routines */
2638 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2641 if(v3d->transp==0) { // not when we draw the transparent pass
2642 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2645 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2646 drawFacesSolid() doesn't draw the transparent faces */
2647 if(ob->dtx & OB_DRAWTRANSP) {
2648 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2649 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2650 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2651 GPU_disable_material();
2654 dm->drawEdges(dm, 0, 1);
2662 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2668 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2670 Object *ob= base->object;
2671 Mesh *me = ob->data;
2672 Material *ma= give_current_material(ob, 1);
2673 const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2674 const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2676 int /* totvert,*/ totedge, totface;
2677 DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2682 if (ob->dtx&OB_DRAWWIRE) {
2683 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2686 /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2687 totedge = dm->getNumEdges(dm);
2688 totface = dm->getNumFaces(dm);
2690 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2692 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2694 // Unwanted combination.
2695 if (is_paint_sel) draw_wire = 0;
2697 if(dt==OB_BOUNDBOX) {
2698 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2699 draw_bounding_volume(scene, ob);
2701 else if(hasHaloMat || (totface==0 && totedge==0)) {
2706 else if(dt==OB_WIRE || totface==0) {
2707 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2709 else if( (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2710 CHECK_OB_DRAWTEXTURE(v3d, dt))
2712 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2713 draw_mesh_object_outline(v3d, ob, dm);
2716 if(draw_glsl_material(scene, ob, v3d, dt)) {
2717 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2719 dm->drawFacesGLSL(dm, GPU_enable_material);
2720 // if(get_ob_property(ob, "Text"))
2721 // XXX draw_mesh_text(ob, 1);
2722 GPU_disable_material();
2724 glFrontFace(GL_CCW);
2727 draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2731 if(base->flag & SELECT)
2732 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2734 UI_ThemeColor(TH_WIRE);
2736 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2737 dm->drawLooseEdges(dm);
2740 else if(dt==OB_SOLID) {
2741 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2742 /* weight paint in solid mode, special case. focus on making the weights clear
2743 * rather than the shading, this is also forced in wire view */
2744 GPU_enable_material(0, NULL);
2745 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
2747 bglPolygonOffset(rv3d->dist, 1.0);
2748 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2751 glColor4ub(255, 255, 255, 96);
2752 glEnable(GL_LINE_STIPPLE);
2753 glLineStipple(1, 0xAAAA);
2755 dm->drawEdges(dm, 1, 1);
2757 bglPolygonOffset(rv3d->dist, 0.0);
2759 glDisable(GL_LINE_STIPPLE);
2761 GPU_disable_material();
2763 /* since we already draw wire as wp guide, dont draw over the top */
2769 if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2770 draw_mesh_object_outline(v3d, ob, dm);
2772 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2774 glEnable(GL_LIGHTING);
2775 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2777 if(ob->sculpt && (p=paint_get_active(scene))) {
2779 float (*fpl)[4] = NULL;
2780 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2782 if(ob->sculpt->partial_redraw) {
2783 if(ar->do_draw & RGN_DRAW_PARTIAL) {
2784 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2786 ob->sculpt->partial_redraw = 0;
2790 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2793 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2795 GPU_disable_material();
2797 glFrontFace(GL_CCW);
2798 glDisable(GL_LIGHTING);
2800 if(base->flag & SELECT) {
2801 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2803 UI_ThemeColor(TH_WIRE);
2805 if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2806 dm->drawLooseEdges(dm);
2809 else if(dt==OB_SHADED) {
2811 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2812 /* enforce default material settings */
2813 GPU_enable_material(0, NULL);
2815 /* but set default spec */
2816 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2817 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2818 glColor3ub(120, 120, 120);
2819 glDisable(GL_COLOR_MATERIAL);
2821 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2822 glEnable(GL_LIGHTING);
2823 glEnable(GL_COLOR_MATERIAL);
2825 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
2826 glDisable(GL_COLOR_MATERIAL);
2827 glDisable(GL_LIGHTING);
2829 GPU_disable_material();
2831 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2833 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material, NULL);
2835 glColor3f(1.0f, 1.0f, 1.0f);
2836 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material, NULL);
2842 /* set default draw color back for wire or for draw-extra later on */
2844 if(base->flag & SELECT) {
2845 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2846 UI_ThemeColor(TH_GROUP_ACTIVE);
2847 else if(ob->flag & OB_FROMGROUP)
2848 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2849 else if(flag!=DRAW_CONSTCOLOR)
2850 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2852 glColor3ub(80,80,80);
2854 if (ob->flag & OB_FROMGROUP)
2855 UI_ThemeColor(TH_GROUP);
2857 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2858 glColor3ub(80,80,80);
2860 UI_ThemeColor(TH_WIRE);
2866 /* When using wireframe object traw in particle edit mode
2867 * the mesh gets in the way of seeing the particles, fade the wire color
2868 * with the background. */
2869 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2870 float col_wire[4], col_bg[4], col[3];
2872 UI_GetThemeColor3fv(TH_BACK, col_bg);
2873 glGetFloatv(GL_CURRENT_COLOR, col_wire);
2874 interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2878 /* If drawing wire and drawtype is not OB_WIRE then we are
2879 * overlaying the wires.
2881 * UPDATE bug #10290 - With this wire-only objects can draw
2882 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2884 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2885 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2887 if (dt!=OB_WIRE && draw_wire==2) {
2888 bglPolygonOffset(rv3d->dist, 1.0);
2889 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2892 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2893 dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2895 if (dt!=OB_WIRE && draw_wire==2) {
2897 bglPolygonOffset(rv3d->dist, 0.0);
2904 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2905 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2907 Object *ob= base->object;
2908 Object *obedit= scene->obedit;
2910 EditMesh *em= me->edit_mesh;
2911 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
2913 /* If we are drawing shadows and any of the materials don't cast a shadow,
2914 * then don't draw the object */
2915 if (v3d->flag2 & V3D_RENDER_SHADOW) {
2916 for(i=0; i<ob->totcol; ++i) {
2917 Material *ma= give_current_material(ob, i);
2918 if (ma && !(ma->mode & MA_SHADBUF)) {
2924 if(obedit && ob!=obedit && ob->data==obedit->data) {
2925 if(ob_get_key(ob) || ob_get_key(obedit));
2926 else if(ob->modifiers.first || obedit->modifiers.first);
2930 if(ob==obedit || drawlinked) {
2931 DerivedMesh *finalDM, *cageDM;
2934 finalDM = cageDM = editmesh_get_derived_base(ob, em);
2936 cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2937 scene->customdata_mask);
2940 // no transp in editmode, the fancy draw over goes bad then
2941 glsl = draw_glsl_material(scene, ob, v3d, dt);
2942 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2945 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2947 GPU_end_object_materials();
2949 if (obedit!=ob && finalDM)
2950 finalDM->release(finalDM);
2953 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2954 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2955 glsl = draw_glsl_material(scene, ob, v3d, dt);
2956 check_alpha = check_material_alpha(base, me, glsl);
2958 if(dt==OB_SOLID || glsl) {
2959 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2960 (check_alpha)? &do_alpha_pass: NULL);
2963 draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2965 GPU_end_object_materials();
2967 if(me->totvert==0) retval= 1;
2971 /* GPU_begin_object_materials checked if this is needed */
2973 if(ob->dtx & OB_DRAWXRAY) {
2974 add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2977 add_view3d_after(&v3d->afterdraw_transp, base, flag);
2980 else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2981 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2982 if(v3d->xray == 0 && v3d->transp == 0) {
2983 add_view3d_after(&v3d->afterdraw_xray, base, flag);
2990 /* ************** DRAW DISPLIST ****************** */
2992 static int draw_index_wire= 1;
2993 static int index3_nors_incr= 1;
2995 /* returns 1 when nothing was drawn */
2996 static int drawDispListwire(ListBase *dlbase)
3002 if(dlbase==NULL) return 1;
3004 glEnableClientState(GL_VERTEX_ARRAY);
3005 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
3007 for(dl= dlbase->first; dl; dl= dl->next) {
3008 if(dl->parts==0 || dl->nr==0)
3016 glVertexPointer(3, GL_FLOAT, 0, data);
3018 for(parts=0; parts<dl->parts; parts++)
3019 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3024 glVertexPointer(3, GL_FLOAT, 0, data);