4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation, full recode and added functions
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/editors/space_view3d/drawobject.c
36 #include "MEM_guardedalloc.h"
38 #include "DNA_camera_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_constraint_types.h" // for drawing constraint
41 #include "DNA_lamp_types.h"
42 #include "DNA_lattice_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_meta_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_smoke_types.h"
48 #include "DNA_world_types.h"
49 #include "DNA_armature_types.h"
51 #include "BLI_blenlib.h"
53 #include "BLI_editVert.h"
54 #include "BLI_edgehash.h"
56 #include "BLI_utildefines.h"
58 #include "BKE_anim.h" //for the where_on_path function
59 #include "BKE_constraint.h" // for the get_constraint_target function
60 #include "BKE_DerivedMesh.h"
61 #include "BKE_deform.h"
62 #include "BKE_displist.h"
64 #include "BKE_global.h"
65 #include "BKE_image.h"
67 #include "BKE_lattice.h"
69 #include "BKE_material.h"
70 #include "BKE_mball.h"
71 #include "BKE_modifier.h"
72 #include "BKE_object.h"
73 #include "BKE_paint.h"
74 #include "BKE_particle.h"
75 #include "BKE_pointcache.h"
78 #include "smoke_API.h"
80 #include "IMB_imbuf.h"
81 #include "IMB_imbuf_types.h"
84 #include "BIF_glutil.h"
87 #include "GPU_extensions.h"
90 #include "ED_particle.h"
91 #include "ED_screen.h"
92 #include "ED_sculpt.h"
94 #include "ED_curve.h" /* for ED_curve_editnurbs */
96 #include "UI_resources.h"
99 #include "wm_subwindow.h"
102 #include "view3d_intern.h" // own include
105 /* this condition has been made more complex since editmode can draw textures */
106 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
107 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
108 (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
110 static void draw_bounding_volume(Scene *scene, Object *ob);
112 static void drawcube_size(float size);
113 static void drawcircle_size(float size);
114 static void draw_empty_sphere(float size);
115 static void draw_empty_cone(float size);
117 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
119 if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
122 if(G.f & G_BACKBUFSEL)
125 if((vd->flag & V3D_ZBUF_SELECT) == 0)
128 /* if its drawing textures with zbuf sel, then dont draw dots */
129 if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
132 if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
138 /* ************* only use while object drawing **************
139 * or after running ED_view3d_init_mats_rv3d
141 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
143 RegionView3D *rv3d= ar->regiondata;
144 float fx, fy, vec4[4];
148 /* clipplanes in eye space */
149 if(rv3d->rflag & RV3D_CLIPPING) {
150 if(ED_view3d_test_clipping(rv3d, vec, local))
154 copy_v3_v3(vec4, vec);
157 mul_m4_v4(rv3d->persmatob, vec4);
159 /* clipplanes in window space */
160 if( vec4[3] > (float)BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
161 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
163 if( fx>0 && fx<ar->winx) {
165 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
167 if(fy > 0.0f && fy < (float)ar->winy) {
168 adr[0]= (short)floorf(fx);
169 adr[1]= (short)floorf(fy);
175 /* only use while object drawing */
176 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
178 RegionView3D *rv3d= ar->regiondata;
179 float fx, fy, vec4[4];
183 copy_v3_v3(vec4, vec);
186 mul_m4_v4(rv3d->persmatob, vec4);
188 if( vec4[3] > (float)BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
189 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
191 if( fx>-32700 && fx<32700) {
193 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
195 if(fy > -32700.0f && fy < 32700.0f) {
196 adr[0]= (short)floorf(fx);
197 adr[1]= (short)floorf(fy);
203 /* ************************ */
205 /* check for glsl drawing */
207 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
209 if(!GPU_glsl_support())
213 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
215 if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
218 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
221 static int check_material_alpha(Base *base, Mesh *me, int glsl)
223 if(base->flag & OB_FROMDUPLI)
232 return (glsl || (base->object->dtx & OB_DRAWTRANSP));
236 static unsigned int colortab[24]=
237 {0x0, 0xFF88FF, 0xFFBBFF,
238 0x403000, 0xFFFF88, 0xFFFFBB,
239 0x104040, 0x66CCCC, 0x77CCCC,
240 0x104010, 0x55BB55, 0x66FF66,
245 static float cube[8][3] = {
256 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
257 /* 32 values of sin function (still same result!) */
258 static float sinval[32] = {
293 /* 32 values of cos function (still same result!) */
294 static float cosval[32] ={
329 static void draw_xyz_wire(const float c[3], float size, int axis)
331 float v1[3]= {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
332 float dim = size * 0.1f;
333 float dx[3], dy[3], dz[3];
335 dx[0]=dim; dx[1]=0.f; dx[2]=0.f;
336 dy[0]=0.f; dy[1]=dim; dy[2]=0.f;
337 dz[0]=0.f; dz[1]=0.f; dz[2]=dim;
343 /* bottom left to top right */
344 sub_v3_v3v3(v1, c, dx);
346 add_v3_v3v3(v2, c, dx);
352 /* top left to bottom right */
365 /* bottom left to top right */
366 mul_v3_fl(dx, 0.75f);
367 sub_v3_v3v3(v1, c, dx);
369 add_v3_v3v3(v2, c, dx);
375 /* top left to center */
386 glBegin(GL_LINE_STRIP);
388 /* start at top left */
389 sub_v3_v3v3(v1, c, dx);
390 add_v3_v3v3(v1, c, dz);
415 void drawaxes(float size, char drawtype)
418 float v1[3]= {0.0, 0.0, 0.0};
419 float v2[3]= {0.0, 0.0, 0.0};
420 float v3[3]= {0.0, 0.0, 0.0};
425 for (axis=0; axis<3; axis++) {
433 /* reset v1 & v2 to zero */
434 v1[axis]= v2[axis]= 0.0f;
439 case OB_SINGLE_ARROW:
442 /* in positive z direction only */
449 glBegin(GL_TRIANGLES);
451 v2[0]= size * 0.035f; v2[1] = size * 0.035f;
452 v3[0]= size * -0.035f; v3[1] = size * 0.035f;
453 v2[2]= v3[2]= size * 0.75f;
455 for (axis=0; axis<4; axis++) {
477 drawcircle_size(size);
480 case OB_EMPTY_SPHERE:
481 draw_empty_sphere(size);
485 draw_empty_cone(size);
490 for (axis=0; axis<3; axis++) {
491 const int arrow_axis= (axis==0) ? 1:0;
499 v1[axis]= size*0.85f;
500 v1[arrow_axis]= -size*0.08f;
504 v1[arrow_axis]= size*0.08f;
510 v2[axis]+= size*0.125f;
512 draw_xyz_wire(v2, size, axis);
515 /* reset v1 & v2 to zero */
516 v1[arrow_axis]= v1[axis]= v2[axis]= 0.0f;
523 /* Function to draw an Image on a empty Object */
524 static void draw_empty_image(Object *ob)
526 Image *ima = (Image*)ob->data;
527 ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
529 float scale, ofs_x, ofs_y, sca_x, sca_y;
532 if(ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
533 IMB_rect_from_float(ibuf);
536 /* Get the buffer dimensions so we can fallback to fake ones */
537 if(ibuf && ibuf->rect) {
546 /* Get the image aspect even if the buffer is invalid */
548 if(ima->aspx > ima->aspy) {
550 sca_y= ima->aspy / ima->aspx;
552 else if(ima->aspx < ima->aspy) {
553 sca_x= ima->aspx / ima->aspy;
566 /* Calculate the scale center based on objects origin */
567 ofs_x= ob->ima_ofs[0] * ima_x;
568 ofs_y= ob->ima_ofs[1] * ima_y;
570 glMatrixMode(GL_MODELVIEW);
573 /* Make sure we are drawing at the origin */
574 glTranslatef(0.0f, 0.0f, 0.0f);
576 /* Calculate Image scale */
577 scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
579 /* Set the object scale */
580 glScalef(scale * sca_x, scale * sca_y, 1.0f);
582 if(ibuf && ibuf->rect) {
583 /* Setup GL params */
585 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
587 /* Use the object color and alpha */
590 /* Draw the Image on the screen */
591 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
592 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
597 UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
599 /* Calculate the outline vertex positions */
600 glBegin(GL_LINE_LOOP);
601 glVertex2f(ofs_x, ofs_y);
602 glVertex2f(ofs_x + ima_x, ofs_y);
603 glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
604 glVertex2f(ofs_x, ofs_y + ima_y);
607 /* Reset GL settings */
608 glMatrixMode(GL_MODELVIEW);
612 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
614 float vec[3], vx[3], vy[3];
617 mul_v3_v3fl(vx, tmat[0], rad);
618 mul_v3_v3fl(vy, tmat[1], rad);
621 for(a=0; a<tot; a++) {
622 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
623 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
624 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
630 /* circle for object centers, special_color is for library or ob users */
631 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
633 const float size= ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
635 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
636 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
640 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
642 else glColor4ub(0x55, 0xCC, 0xCC, 155);
645 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
646 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
647 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
649 drawcircball(GL_POLYGON, co, size, rv3d->viewinv);
651 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
652 drawcircball(GL_LINE_LOOP, co, size, rv3d->viewinv);
655 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
658 /* *********** text drawing for object/particles/armature ************* */
659 static ListBase CachedText[3];
660 static int CachedTextLevel= 0;
662 typedef struct ViewCachedString {
663 struct ViewCachedString *next, *prev;
673 /* str is allocated past the end */
676 void view3d_cached_text_draw_begin(void)
678 ListBase *strings= &CachedText[CachedTextLevel];
679 strings->first= strings->last= NULL;
683 void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4])
685 int alloc_len= strlen(str) + 1;
686 ListBase *strings= &CachedText[CachedTextLevel-1];
687 ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
689 BLI_addtail(strings, vos);
690 copy_v3_v3(vos->vec, co);
691 vos->col.pack= *((int *)col);
694 vos->str_len= alloc_len-1;
696 /* allocate past the end */
697 memcpy(++vos, str, alloc_len);
700 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
702 RegionView3D *rv3d= ar->regiondata;
703 ListBase *strings= &CachedText[CachedTextLevel-1];
704 ViewCachedString *vos;
707 /* project first and test */
708 for(vos= strings->first; vos; vos= vos->next) {
709 if(mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
710 mul_m4_v3(mat, vos->vec);
711 view3d_project_short_clip(ar, vos->vec, vos->sco, 0);
712 if(vos->sco[0]!=IS_CLIPPED)
717 int col_pack_prev= 0;
720 bglMats mats; /* ZBuffer depth vars */
727 if(rv3d->rflag & RV3D_CLIPPING)
729 glDisable(GL_CLIP_PLANE0+a);
731 glMatrixMode(GL_PROJECTION);
733 glMatrixMode(GL_MODELVIEW);
735 ED_region_pixelspace(ar);
738 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
742 for(vos= strings->first; vos; vos= vos->next) {
743 #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
744 if(v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
745 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
746 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
752 if(vos->sco[0]!=IS_CLIPPED) {
753 const char *str= (char *)(vos+1);
755 if(col_pack_prev != vos->col.pack) {
756 glColor3ubv(vos->col.ub);
757 col_pack_prev= vos->col.pack;
759 if(vos->flag & V3D_CACHE_TEXT_ASCII) {
760 BLF_draw_default_ascii((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
763 BLF_draw_default((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
769 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
773 glMatrixMode(GL_PROJECTION);
775 glMatrixMode(GL_MODELVIEW);
778 if(rv3d->rflag & RV3D_CLIPPING)
780 glEnable(GL_CLIP_PLANE0+a);
784 BLI_freelistN(strings);
789 /* ******************** primitive drawing ******************* */
791 static void drawcube(void)
794 glBegin(GL_LINE_STRIP);
795 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
796 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
797 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
800 glBegin(GL_LINE_STRIP);
801 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
804 glBegin(GL_LINE_STRIP);
805 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
808 glBegin(GL_LINE_STRIP);
809 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
813 /* draws a cube on given the scaling of the cube, assuming that
814 * all required matrices have been set (used for drawing empties)
816 static void drawcube_size(float size)
818 glBegin(GL_LINE_STRIP);
819 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
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);
824 glBegin(GL_LINE_STRIP);
825 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
828 glBegin(GL_LINE_STRIP);
829 glVertex3f(-size,size,size); glVertex3f(size,size,size);
832 glBegin(GL_LINE_STRIP);
833 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
837 /* this is an unused (old) cube-drawing function based on a given size */
839 static void drawcube_size(float *size)
843 glScalef(size[0], size[1], size[2]);
846 glBegin(GL_LINE_STRIP);
847 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
848 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
849 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
852 glBegin(GL_LINE_STRIP);
853 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
856 glBegin(GL_LINE_STRIP);
857 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
860 glBegin(GL_LINE_STRIP);
861 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
868 static void drawshadbuflimits(Lamp *la, float mat[][4])
870 float sta[3], end[3], lavec[3];
872 negate_v3_v3(lavec, mat[2]);
875 madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
876 madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
878 glBegin(GL_LINE_STRIP);
893 static void spotvolume(float *lvec, float *vvec, float inp)
895 /* camera is at 0,0,0 */
896 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
899 normalize_v3(vvec); /* is this the correct vector ? */
901 cross_v3_v3v3(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
902 cross_v3_v3v3(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
904 /* vectors are exactly aligned, use the X axis, this is arbitrary */
905 if(normalize_v3(plane) == 0.0f)
908 /* now we've got two equations: one of a cone and one of a plane, but we have
909 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
911 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
912 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
914 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
921 angle = saacos(plane[2])/2.0f;
930 quat_to_mat3(mat1,q);
932 /* rotate lamp vector now over acos(inp) degrees */
933 copy_v3_v3(vvec, lvec);
937 si = sqrt(1-inp*inp);
943 mul_m3_m3m3(mat3,mat2,mat1);
947 mul_m3_m3m3(mat4,mat2,mat1);
950 mul_m3_m3m3(mat2,mat1,mat3);
951 mul_m3_v3(mat2,lvec);
952 mul_m3_m3m3(mat2,mat1,mat4);
953 mul_m3_v3(mat2,vvec);
958 static void draw_spot_cone(Lamp *la, float x, float z)
962 glBegin(GL_TRIANGLE_FAN);
963 glVertex3f(0.0f, 0.0f, -x);
965 if(la->mode & LA_SQUARE) {
967 glVertex3f(-z, z, 0);
968 glVertex3f(-z, -z, 0);
969 glVertex3f(z, -z, 0);
976 for(a=0; a<33; a++) {
977 angle= a*M_PI*2/(33-1);
978 glVertex3f(z*cosf(angle), z*sinf(angle), 0);
985 static void draw_transp_spot_volume(Lamp *la, float x, float z)
987 glEnable(GL_CULL_FACE);
991 /* draw backside darkening */
992 glCullFace(GL_FRONT);
994 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
995 glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
997 draw_spot_cone(la, x, z);
999 /* draw front side lighting */
1000 glCullFace(GL_BACK);
1002 glBlendFunc(GL_ONE, GL_ONE);
1003 glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1005 draw_spot_cone(la, x, z);
1008 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1009 glDisable(GL_BLEND);
1011 glDisable(GL_CULL_FACE);
1012 glCullFace(GL_BACK);
1015 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
1017 Object *ob= base->object;
1018 const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1020 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
1022 float imat[4][4], curcol[4];
1023 unsigned char col[4];
1024 /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1025 /* the moment of view3d_draw_transp() call */
1026 const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
1027 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);
1029 if(drawcone && !v3d->transp) {
1030 /* in this case we need to draw delayed */
1031 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1035 /* we first draw only the screen aligned & fixed scale stuff */
1037 glLoadMatrixf(rv3d->viewmat);
1039 /* lets calculate the scale: */
1040 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
1042 /* and view aligned matrix: */
1043 copy_m4_m4(imat, rv3d->viewinv);
1044 normalize_v3(imat[0]);
1045 normalize_v3(imat[1]);
1048 copy_v3_v3(vec, ob->obmat[3]);
1050 /* for AA effects */
1051 glGetFloatv(GL_CURRENT_COLOR, curcol);
1055 if(lampsize > 0.0f) {
1058 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1059 else glColor4ub(0x77, 0xCC, 0xCC, 155);
1064 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1065 glDisable(GL_BLEND);
1066 drawcircball(GL_POLYGON, vec, lampsize, imat);
1073 circrad = 3.0f*lampsize;
1076 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1078 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1079 if(la->type!=LA_HEMI) {
1080 if( (la->mode & LA_SHAD_RAY) ||
1081 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
1083 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
1092 /* draw the pretty sun rays */
1093 if(la->type==LA_SUN) {
1094 float v1[3], v2[3], mat[3][3];
1097 /* setup a 45 degree rotation matrix */
1098 vec_rot_to_mat3(mat, imat[2], (float)M_PI/4.0f);
1101 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1102 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1105 glTranslatef(vec[0], vec[1], vec[2]);
1110 for (axis=0; axis<8; axis++) {
1118 glTranslatef(-vec[0], -vec[1], -vec[2]);
1122 if (la->type==LA_LOCAL) {
1123 if(la->mode & LA_SPHERE) {
1124 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1126 /* yafray: for photonlight also draw lightcone as for spot */
1129 glPopMatrix(); /* back in object space */
1133 /* skip drawing extra info */
1135 else if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
1136 lvec[0]=lvec[1]= 0.0;
1138 x = rv3d->persmat[0][2];
1139 y = rv3d->persmat[1][2];
1140 z = rv3d->persmat[2][2];
1141 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
1142 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
1143 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
1145 y = cosf(la->spotsize*(float)(M_PI/360.0));
1146 spotvolume(lvec, vvec, y);
1151 /* draw the angled sides of the cone */
1152 glBegin(GL_LINE_STRIP);
1158 z = x*sqrtf(1.0f - y*y);
1161 /* draw the circle/square at the end of the cone */
1162 glTranslatef(0.0, 0.0 , x);
1163 if(la->mode & LA_SQUARE) {
1165 float z_abs= fabs(z);
1167 tvec[0]= tvec[1]= z_abs;
1170 glBegin(GL_LINE_LOOP);
1172 tvec[1]= -z_abs; /* neg */
1174 tvec[0]= -z_abs; /* neg */
1176 tvec[1]= z_abs; /* pos */
1180 else circ(0.0, 0.0, fabsf(z));
1182 /* draw the circle/square representing spotbl */
1183 if(la->type==LA_SPOT) {
1184 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
1185 /* hide line if it is zero size or overlaps with outer border,
1186 previously it adjusted to always to show it but that seems
1187 confusing because it doesn't show the actual blend size */
1188 if (spotblcirc != 0 && spotblcirc != fabsf(z))
1189 circ(0.0, 0.0, spotblcirc);
1193 draw_transp_spot_volume(la, x, z);
1195 /* draw clip start, useful for wide cones where its not obvious where the start is */
1196 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
1197 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1200 float clipsta_fac= la->clipsta / -x;
1202 interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1203 interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1205 glBegin(GL_LINE_STRIP);
1206 glVertex3fv(lvec_clip);
1207 glVertex3fv(vvec_clip);
1211 else if ELEM(la->type, LA_HEMI, LA_SUN) {
1213 /* draw the line from the circle along the dist */
1214 glBegin(GL_LINE_STRIP);
1221 if(la->type==LA_HEMI) {
1222 /* draw the hemisphere curves */
1223 short axis, steps, dir;
1224 float outdist, zdist, mul;
1226 outdist = 0.14; mul = 1.4; dir = 1;
1229 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1230 for (axis=0; axis<4; axis++) {
1231 float v[3]= {0.0, 0.0, 0.0};
1234 glBegin(GL_LINE_STRIP);
1236 for (steps=0; steps<6; steps++) {
1237 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
1238 /* make the arcs start at the edge of the energy circle */
1239 if (steps == 0) v[0] = dir*circrad;
1240 else v[0] = v[0] + dir*(steps*outdist);
1241 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
1242 /* make the arcs start at the edge of the energy circle */
1243 if (steps == 0) v[1] = dir*circrad;
1244 else v[1] = v[1] + dir*(steps*outdist);
1247 v[2] = v[2] - steps*zdist;
1251 zdist = zdist * mul;
1255 /* flip the direction */
1259 } else if(la->type==LA_AREA) {
1261 if(la->area_shape==LA_AREA_SQUARE)
1262 fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
1263 else if(la->area_shape==LA_AREA_RECT)
1264 fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
1266 glBegin(GL_LINE_STRIP);
1267 glVertex3f(0.0,0.0,-circrad);
1268 glVertex3f(0.0,0.0,-la->dist);
1272 /* and back to viewspace */
1273 glLoadMatrixf(rv3d->viewmat);
1274 copy_v3_v3(vec, ob->obmat[3]);
1278 if((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1279 drawshadbuflimits(la, ob->obmat);
1282 UI_GetThemeColor4ubv(TH_LAMP, col);
1287 if (vec[2]>0) vec[2] -= circrad;
1288 else vec[2] += circrad;
1290 glBegin(GL_LINE_STRIP);
1302 glDisable(GL_BLEND);
1304 /* restore for drawing extra stuff */
1309 static void draw_limit_line(float sta, float end, unsigned int col)
1312 glVertex3f(0.0, 0.0, -sta);
1313 glVertex3f(0.0, 0.0, -end);
1319 glVertex3f(0.0, 0.0, -sta);
1320 glVertex3f(0.0, 0.0, -end);
1326 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1327 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1328 static void draw_focus_cross(float dist, float size)
1331 glVertex3f(-size, 0.f, -dist);
1332 glVertex3f(size, 0.f, -dist);
1333 glVertex3f(0.f, -size, -dist);
1334 glVertex3f(0.f, size, -dist);
1338 #ifdef VIEW3D_CAMERA_BORDER_HACK
1339 float view3d_camera_border_hack_col[4];
1340 short view3d_camera_border_hack_test= FALSE;
1343 /* flag similar to draw_object() */
1344 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1346 /* a standing up pyramid with (0,0,0) as top */
1348 float vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1351 const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1353 const float scax= 1.0f / len_v3(ob->obmat[0]);
1354 const float scay= 1.0f / len_v3(ob->obmat[1]);
1355 const float scaz= 1.0f / len_v3(ob->obmat[2]);
1357 #ifdef VIEW3D_CAMERA_BORDER_HACK
1358 if(is_view && !(G.f & G_PICKSEL)) {
1359 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1360 view3d_camera_border_hack_test= TRUE;
1366 aspx= (float) scene->r.xsch*scene->r.xasp;
1367 aspy= (float) scene->r.ysch*scene->r.yasp;
1378 glDisable(GL_LIGHTING);
1379 glDisable(GL_CULL_FACE);
1381 if(cam->type==CAM_ORTHO) {
1382 facx= 0.5f * cam->ortho_scale * caspx * scax;
1383 facy= 0.5f * cam->ortho_scale * caspy * scay;
1384 shx= cam->shiftx * cam->ortho_scale * scax;
1385 shy= cam->shifty * cam->ortho_scale * scay;
1386 depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
1388 drawsize= 0.5f * cam->ortho_scale;
1391 /* that way it's always visible - clipsta+0.1 */
1393 drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
1396 /* fixed depth, variable size (avoids exceeding clipping range) */
1397 depth = -(cam->clipsta + 0.1f);
1398 fac = depth / (cam->lens/-16.0f * scaz);
1401 /* fixed size, variable depth (stays a reasonable size in the 3D view) */
1402 depth= drawsize * cam->lens/-16.0f * scaz;
1406 facx= fac * caspx * scax;
1407 facy= fac * caspy * scay;
1408 shx= cam->shiftx*fac*2 * scax;
1409 shy= cam->shifty*fac*2 * scay;
1412 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
1413 vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1414 vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1415 vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1416 vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1419 glBegin(GL_LINE_LOOP);
1420 glVertex3fv(vec[1]);
1421 glVertex3fv(vec[2]);
1422 glVertex3fv(vec[3]);
1423 glVertex3fv(vec[4]);
1429 /* center point to camera frame */
1430 glBegin(GL_LINE_STRIP);
1431 glVertex3fv(vec[2]);
1432 glVertex3fv(vec[0]);
1433 glVertex3fv(vec[1]);
1434 glVertex3fv(vec[4]);
1435 glVertex3fv(vec[0]);
1436 glVertex3fv(vec[3]);
1444 /* draw an outline arrow for inactive cameras and filled
1445 * for active cameras. We actually draw both outline+filled
1446 * for active cameras so the wire can be seen side-on */
1448 if (i==0) glBegin(GL_LINE_LOOP);
1449 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1452 vec[0][0]= shx + ((-0.7f * drawsize) * scax);
1453 vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
1454 glVertex3fv(vec[0]); /* left */
1456 vec[0][0]= shx + ((0.7f * drawsize) * scax);
1457 glVertex3fv(vec[0]); /* right */
1460 vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
1461 glVertex3fv(vec[0]); /* top */
1467 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1471 /* draw in normalized object matrix space */
1472 copy_m4_m4(nobmat, ob->obmat);
1473 normalize_m4(nobmat);
1476 glLoadMatrixf(rv3d->viewmat);
1477 glMultMatrixf(nobmat);
1479 if(cam->flag & CAM_SHOWLIMITS) {
1480 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1481 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1482 draw_focus_cross(dof_camera(ob), cam->drawsize);
1486 if(cam->flag & CAM_SHOWMIST)
1487 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1494 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1496 BPoint *bp = lt->def;
1497 float *co = dl?dl->verts:NULL;
1500 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1501 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1502 bglBegin(GL_POINTS);
1504 for(w=0; w<lt->pntsw; w++) {
1505 int wxt = (w==0 || w==lt->pntsw-1);
1506 for(v=0; v<lt->pntsv; v++) {
1507 int vxt = (v==0 || v==lt->pntsv-1);
1508 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1509 int uxt = (u==0 || u==lt->pntsu-1);
1510 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1512 if((bp->f1 & SELECT)==sel) {
1513 bglVertex3fv(dl?co:bp->vec);
1525 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1527 Object *obedit= vc->obedit;
1528 Lattice *lt= obedit->data;
1529 BPoint *bp = lt->editlatt->latt->def;
1530 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1531 float *co = dl?dl->verts:NULL;
1532 int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1533 short s[2] = {IS_CLIPPED, 0};
1535 ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1537 for (i=0; i<N; i++, bp++, co+=3) {
1539 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1540 if (s[0] != IS_CLIPPED)
1541 func(userData, bp, s[0], s[1]);
1546 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1548 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1552 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1554 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1560 glVertex3fv(&dl->verts[index*3]);
1562 glVertex3fv(lt->def[index].vec);
1566 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1567 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1569 Lattice *lt= ob->data;
1572 int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1574 /* now we default make displist, this will modifiers work for non animated case */
1575 if(ob->disp.first==NULL)
1576 lattice_calc_modifiers(scene, ob);
1577 dl= find_displist(&ob->disp, DL_VERTS);
1580 lt= lt->editlatt->latt;
1584 if(ob->defbase.first && lt->dvert) {
1585 use_wcol= ob->actdef;
1586 glShadeModel(GL_SMOOTH);
1591 for(w=0; w<lt->pntsw; w++) {
1592 int wxt = (w==0 || w==lt->pntsw-1);
1593 for(v=0; v<lt->pntsv; v++) {
1594 int vxt = (v==0 || v==lt->pntsv-1);
1595 for(u=0; u<lt->pntsu; u++) {
1596 int uxt = (u==0 || u==lt->pntsu-1);
1598 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1599 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1600 drawlattice__point(lt, dl, u, v, w, use_wcol);
1602 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1603 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1604 drawlattice__point(lt, dl, u, v, w, use_wcol);
1606 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1607 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1608 drawlattice__point(lt, dl, u, v, w, use_wcol);
1615 /* restoration for weight colors */
1617 glShadeModel(GL_FLAT);
1620 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1622 lattice_draw_verts(lt, dl, 0);
1623 lattice_draw_verts(lt, dl, 1);
1625 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1629 /* ***************** ******************** */
1631 /* Note! - foreach funcs should be called while drawing or directly after
1632 * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1633 * but would not give correct results with dupli's for eg. which dont
1634 * use the object matrix in the useual way */
1635 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1637 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1638 EditVert *eve = EM_get_vert_for_index(index);
1641 short s[2]= {IS_CLIPPED, 0};
1643 if (data->clipVerts) {
1644 view3d_project_short_clip(data->vc.ar, co, s, 1);
1646 view3d_project_short_noclip(data->vc.ar, co, s);
1649 if (s[0]!=IS_CLIPPED)
1650 data->func(data->userData, eve, s[0], s[1], index);
1654 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1656 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1657 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1661 data.userData = userData;
1662 data.clipVerts = clipVerts;
1665 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1667 EM_init_index_arrays(vc->em, 1, 0, 0);
1668 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1669 EM_free_index_arrays();
1674 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1676 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;
1677 EditEdge *eed = EM_get_edge_for_index(index);
1681 if (data->clipVerts==1) {
1682 view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1683 view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1685 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1686 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1688 if (data->clipVerts==2) {
1689 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1690 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1695 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1699 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)
1701 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1702 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1706 data.userData = userData;
1707 data.clipVerts = clipVerts;
1710 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1712 EM_init_index_arrays(vc->em, 0, 1, 0);
1713 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1714 EM_free_index_arrays();
1719 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1721 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1722 EditFace *efa = EM_get_face_for_index(index);
1725 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1726 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1728 data->func(data->userData, efa, s[0], s[1], index);
1732 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1734 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1735 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1739 data.userData = userData;
1742 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1744 EM_init_index_arrays(vc->em, 0, 0, 1);
1745 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1746 EM_free_index_arrays();
1751 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1753 Curve *cu= vc->obedit->data;
1754 short s[2] = {IS_CLIPPED, 0};
1757 ListBase *nurbs= ED_curve_editnurbs(cu);
1759 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1761 for (nu= nurbs->first; nu; nu=nu->next) {
1762 if(nu->type == CU_BEZIER) {
1763 for (i=0; i<nu->pntsu; i++) {
1764 BezTriple *bezt = &nu->bezt[i];
1768 if(cu->drawflag & CU_HIDE_HANDLES) {
1769 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1770 if (s[0] != IS_CLIPPED)
1771 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1773 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1774 if (s[0] != IS_CLIPPED)
1775 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1776 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1777 if (s[0] != IS_CLIPPED)
1778 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1779 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1780 if (s[0] != IS_CLIPPED)
1781 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1787 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1788 BPoint *bp = &nu->bp[i];
1791 view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1792 if (s[0] != IS_CLIPPED)
1793 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1800 /* ************** DRAW MESH ****************** */
1802 /* First section is all the "simple" draw routines,
1803 * ones that just pass some sort of primitive to GL,
1804 * with perhaps various options to control lighting,
1807 * These routines should not have user interface related
1811 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1813 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1814 EditFace *efa = EM_get_face_for_index(index);
1816 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1818 glVertex3f( cent[0] + no[0]*ts->normalsize,
1819 cent[1] + no[1]*ts->normalsize,
1820 cent[2] + no[2]*ts->normalsize);
1823 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1826 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1830 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1832 EditFace *efa = EM_get_face_for_index(index);
1833 int sel = *((int*) userData);
1835 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1839 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1841 bglBegin(GL_POINTS);
1842 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1846 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1848 Scene *scene= (Scene *)userData;
1849 ToolSettings *ts= scene->toolsettings;
1850 EditVert *eve = EM_get_vert_for_index(index);
1856 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1857 co[1] + no_f[1]*ts->normalsize,
1858 co[2] + no_f[2]*ts->normalsize);
1860 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1861 co[1] + no_s[1]*ts->normalsize/32767.0f,
1862 co[2] + no_s[2]*ts->normalsize/32767.0f);
1866 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1869 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1873 /* Draw verts with color set based on selection */
1874 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1876 struct { int sel; EditVert *eve_act; } * data = userData;
1877 EditVert *eve = EM_get_vert_for_index(index);
1879 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1880 /* draw active larger - need to stop/start point drawing for this :/ */
1881 if (eve==data->eve_act) {
1882 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1883 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1888 bglBegin(GL_POINTS);
1892 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1894 bglBegin(GL_POINTS);
1901 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1903 struct { int sel; EditVert *eve_act; } data;
1905 data.eve_act = eve_act;
1907 bglBegin(GL_POINTS);
1908 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1912 /* Draw edges with color set based on selection */
1913 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1915 EditEdge *eed = EM_get_edge_for_index(index);
1916 //unsigned char **cols = userData, *col;
1917 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1921 if (eed==data->eed_act) {
1922 glColor4ubv(data->actCol);
1924 if (eed->f&SELECT) {
1927 col = data->baseCol;
1929 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1930 if (col[3]==0) return 0;
1939 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1941 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1943 data.baseCol = baseCol;
1944 data.selCol = selCol;
1945 data.actCol = actCol;
1946 data.eed_act = eed_act;
1947 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1951 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
1953 return EM_get_edge_for_index(index)->h==0;
1955 static void draw_dm_edges(DerivedMesh *dm)
1957 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1960 /* Draw edges with color interpolated based on selection */
1961 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
1963 return EM_get_edge_for_index(index)->h==0;
1965 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1967 EditEdge *eed = EM_get_edge_for_index(index);
1968 unsigned char **cols = userData;
1969 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1970 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1972 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
1973 col0[1] + (col1[1]-col0[1])*t,
1974 col0[2] + (col1[2]-col0[2])*t,
1975 col0[3] + (col1[3]-col0[3])*t);
1978 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1980 unsigned char *cols[2];
1983 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1986 /* Draw only seam edges */
1987 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
1989 EditEdge *eed = EM_get_edge_for_index(index);
1991 return (eed->h==0 && eed->seam);
1993 static void draw_dm_edges_seams(DerivedMesh *dm)
1995 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1998 /* Draw only sharp edges */
1999 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2001 EditEdge *eed = EM_get_edge_for_index(index);
2003 return (eed->h==0 && eed->sharp);
2005 static void draw_dm_edges_sharp(DerivedMesh *dm)
2007 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2011 /* Draw faces with color set based on selection
2012 * return 2 for the active face so it renders with stipple enabled */
2013 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2015 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2016 EditFace *efa = EM_get_face_for_index(index);
2020 if (efa == data->efa_act) {
2021 glColor4ubv(data->cols[2]);
2022 return 2; /* stipple */
2024 col = data->cols[(efa->f&SELECT)?1:0];
2025 if (col[3]==0) return 0;
2033 /* also draws the active face */
2034 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
2036 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2037 data.cols[0] = baseCol;
2038 data.cols[1] = selCol;
2039 data.cols[2] = actCol;
2040 data.efa_act = efa_act;
2042 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
2045 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2047 EditEdge *eed = EM_get_edge_for_index(index);
2049 if (eed->h==0 && eed->crease != 0.0f) {
2050 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2056 static void draw_dm_creases(DerivedMesh *dm)
2059 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2063 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2065 EditEdge *eed = EM_get_edge_for_index(index);
2067 if (eed->h==0 && eed->bweight != 0.0f) {
2068 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2074 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2076 EditVert *eve = EM_get_vert_for_index(index);
2078 if (eve->h==0 && eve->bweight != 0.0f) {
2079 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2083 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2085 ToolSettings *ts= scene->toolsettings;
2087 if (ts->selectmode & SCE_SELECT_VERTEX) {
2088 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2089 bglBegin(GL_POINTS);
2090 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2095 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2100 /* Second section of routines: Combine first sets to form fancy
2101 * drawing routines (for example rendering twice to get overlays).
2103 * Also includes routines that are basic drawing but are too
2104 * specialized to be split out (like drawing creases or measurements).
2107 /* EditMesh drawing routines*/
2109 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2111 ToolSettings *ts= scene->toolsettings;
2114 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2116 for (sel=0; sel<2; sel++) {
2117 unsigned char col[4], fcol[4];
2120 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2121 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2123 for (pass=0; pass<2; pass++) {
2124 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2125 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2128 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2129 glDisable(GL_DEPTH_TEST);
2136 size = (size > 2.1f ? size/2.0f:size);
2137 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2138 col[3] = fcol[3] = 100;
2140 col[3] = fcol[3] = 255;
2143 if(ts->selectmode & SCE_SELECT_VERTEX) {
2146 draw_dm_verts(cageDM, sel, eve_act);
2149 if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2152 draw_dm_face_centers(cageDM, sel);
2156 glDisable(GL_BLEND);
2157 glEnable(GL_DEPTH_TEST);
2162 if(v3d->zbuf) glDepthMask(1);
2166 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2168 ToolSettings *ts= scene->toolsettings;
2170 unsigned char wireCol[4], selCol[4], actCol[4];
2172 /* since this function does transparant... */
2173 UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2174 UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2175 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2177 /* when sel only is used, dont render wire, only selected, this is used for
2178 * textured draw mode when the 'edges' option is disabled */
2182 for (pass=0; pass<2; pass++) {
2183 /* show wires in transparant when no zbuf clipping for select */
2185 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2187 glDisable(GL_DEPTH_TEST);
2189 if (!sel_only) wireCol[3] = 85;
2195 if (!sel_only) wireCol[3] = 255;
2198 if(ts->selectmode == SCE_SELECT_FACE) {
2199 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2201 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2202 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2203 glShadeModel(GL_SMOOTH);
2204 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2205 glShadeModel(GL_FLAT);
2207 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2212 glColor4ubv(wireCol);
2213 draw_dm_edges(cageDM);
2218 glDisable(GL_BLEND);
2219 glEnable(GL_DEPTH_TEST);
2224 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2229 float v1[3], v2[3], v3[3], v4[3], vmid[3];
2231 char val[32]; /* Stores the measurement display text here */
2232 const char *conv_float; /* Use a float conversion matching the grid size */
2233 unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2234 float area; /* area of the face */
2235 float grid= unit->system ? unit->scale_length : v3d->grid;
2236 const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2237 const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2238 const int do_moving= G.moving;
2240 /* make the precision of the pronted value proportionate to the gridsize */
2242 if (grid < 0.01f) conv_float= "%.6g";
2243 else if (grid < 0.1f) conv_float= "%.5g";
2244 else if (grid < 1.0f) conv_float= "%.4g";
2245 else if (grid < 10.0f) conv_float= "%.3g";
2246 else conv_float= "%.2g";
2248 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2249 glDisable(GL_DEPTH_TEST);
2251 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2253 if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2254 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2256 for(eed= em->edges.first; eed; eed= eed->next) {
2257 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2258 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2259 copy_v3_v3(v1, eed->v1->co);
2260 copy_v3_v3(v2, eed->v2->co);
2262 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2265 mul_mat3_m4_v3(ob->obmat, v1);
2266 mul_mat3_m4_v3(ob->obmat, v2);
2269 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2271 sprintf(val, conv_float, len_v3v3(v1, v2));
2273 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2278 if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2279 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2280 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2282 for(efa= em->faces.first; efa; efa= efa->next) {
2283 if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2284 copy_v3_v3(v1, efa->v1->co);
2285 copy_v3_v3(v2, efa->v2->co);
2286 copy_v3_v3(v3, efa->v3->co);
2288 copy_v3_v3(v4, efa->v4->co);
2291 mul_mat3_m4_v3(ob->obmat, v1);
2292 mul_mat3_m4_v3(ob->obmat, v2);
2293 mul_mat3_m4_v3(ob->obmat, v3);
2294 if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2298 area= area_quad_v3(v1, v2, v3, v4);
2300 area = area_tri_v3(v1, v2, v3);
2303 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2305 sprintf(val, conv_float, area);
2307 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2312 if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2313 EditEdge *e1, *e2, *e3, *e4;
2314 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2315 for(efa= em->faces.first; efa; efa= efa->next) {
2316 copy_v3_v3(v1, efa->v1->co);
2317 copy_v3_v3(v2, efa->v2->co);
2318 copy_v3_v3(v3, efa->v3->co);
2320 copy_v3_v3(v4, efa->v4->co);
2326 mul_mat3_m4_v3(ob->obmat, v1);
2327 mul_mat3_m4_v3(ob->obmat, v2);
2328 mul_mat3_m4_v3(ob->obmat, v3);
2329 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2335 if(efa->e4) e4= efa->e4; else e4= e3;
2337 /* Calculate the angles */
2339 if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2341 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2342 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2343 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2345 if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2347 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2348 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2349 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2351 if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2354 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2356 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2357 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2358 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2362 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2363 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2364 interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2365 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2371 /* useful for debugging index vs shape key index */
2376 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2377 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2378 sprintf(val, "%d:%d", j, eve->keyindex);
2379 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2385 glEnable(GL_DEPTH_TEST);
2386 bglPolygonOffset(rv3d->dist, 0.0f);
2390 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2392 EditFace *efa = EM_get_face_for_index(index);
2395 GPU_enable_material(efa->mat_nr+1, NULL);
2402 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2404 EditFace *efa = EM_get_face_for_index(index);
2409 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2411 Mesh *me = ob->data;
2412 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2413 EditEdge *eed_act = NULL;
2414 EditVert *eve_act = NULL;
2416 if (em->selected.last) {
2417 EditSelection *ese = em->selected.last;
2418 /* face is handeled above */
2419 /*if (ese->type == EDITFACE ) {
2420 efa_act = (EditFace *)ese->data;
2421 } else */ if ( ese->type == EDITEDGE ) {
2422 eed_act = (EditEdge *)ese->data;
2423 } else if ( ese->type == EDITVERT ) {
2424 eve_act = (EditVert *)ese->data;
2428 EM_init_index_arrays(em, 1, 1, 1);
2431 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2432 if(draw_glsl_material(scene, ob, v3d, dt)) {
2433 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2435 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2436 draw_em_fancy__setGLSLFaceOpts, NULL);
2437 GPU_disable_material();
2439 glFrontFace(GL_CCW);
2442 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2446 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2447 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2449 glEnable(GL_LIGHTING);
2450 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2452 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material);
2454 glFrontFace(GL_CCW);
2455 glDisable(GL_LIGHTING);
2458 // Setup for drawing wire over, disable zbuffer
2459 // write to show selected edge wires better
2460 UI_ThemeColor(TH_WIRE);
2462 bglPolygonOffset(rv3d->dist, 1.0);
2466 if (cageDM!=finalDM) {
2467 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2468 finalDM->drawEdges(finalDM, 1, 0);
2472 if(me->drawflag & ME_DRAWFACES) { /* transp faces */
2473 unsigned char col1[4], col2[4], col3[4];
2475 UI_GetThemeColor4ubv(TH_FACE, col1);
2476 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2477 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2480 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2482 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2483 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2486 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2488 glDisable(GL_BLEND);
2489 glDepthMask(1); // restore write in zbuffer
2490 } else if (efa_act) {
2491 /* even if draw faces is off it would be nice to draw the stipple face
2492 * Make all other faces zero alpha except for the active
2494 unsigned char col1[4], col2[4], col3[4];
2495 col1[3] = col2[3] = 0; /* dont draw */
2496 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2499 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2501 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2503 glDisable(GL_BLEND);
2504 glDepthMask(1); // restore write in zbuffer
2508 /* here starts all fancy draw-extra over */
2509 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2510 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2512 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2513 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2516 if(me->drawflag & ME_DRAWSEAMS) {
2517 UI_ThemeColor(TH_EDGE_SEAM);
2520 draw_dm_edges_seams(cageDM);
2526 if(me->drawflag & ME_DRAWSHARP) {
2527 UI_ThemeColor(TH_EDGE_SHARP);
2530 draw_dm_edges_sharp(cageDM);
2536 if(me->drawflag & ME_DRAWCREASES) {
2537 draw_dm_creases(cageDM);
2539 if(me->drawflag & ME_DRAWBWEIGHTS) {
2540 draw_dm_bweights(scene, cageDM);
2543 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2546 // XXX retopo_matrix_update(v3d);
2548 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2550 if(me->drawflag & ME_DRAWNORMALS) {
2551 UI_ThemeColor(TH_NORMAL);
2552 draw_dm_face_normals(scene, cageDM);
2554 if(me->drawflag & ME_DRAW_VNORMALS) {
2555 UI_ThemeColor(TH_VNORMAL);
2556 draw_dm_vert_normals(scene, cageDM);
2559 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2560 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2565 bglPolygonOffset(rv3d->dist, 0.0);
2566 GPU_disable_material();
2569 EM_free_index_arrays();
2572 /* Mesh drawing routines */
2574 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2577 if(v3d->transp==0) { // not when we draw the transparent pass
2578 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2581 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2582 drawFacesSolid() doesn't draw the transparent faces */
2583 if(ob->dtx & OB_DRAWTRANSP) {
2584 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2585 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2586 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2587 GPU_disable_material();
2590 dm->drawEdges(dm, 0, 1);
2598 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2604 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2606 Object *ob= base->object;
2607 Mesh *me = ob->data;
2608 Material *ma= give_current_material(ob, 1);
2609 const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2610 const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2612 int /* totvert,*/ totedge, totface;
2613 DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2618 if (ob->dtx&OB_DRAWWIRE) {
2619 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2622 /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2623 totedge = dm->getNumEdges(dm);
2624 totface = dm->getNumFaces(dm);
2626 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2628 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2630 // Unwanted combination.
2631 if (is_paint_sel) draw_wire = 0;
2633 if(dt==OB_BOUNDBOX) {
2634 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2635 draw_bounding_volume(scene, ob);
2637 else if(hasHaloMat || (totface==0 && totedge==0)) {
2642 else if(dt==OB_WIRE || totface==0) {
2643 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2645 else if( (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2646 CHECK_OB_DRAWTEXTURE(v3d, dt))
2648 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2649 draw_mesh_object_outline(v3d, ob, dm);
2652 if(draw_glsl_material(scene, ob, v3d, dt)) {
2653 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2655 dm->drawFacesGLSL(dm, GPU_enable_material);
2656 // if(get_ob_property(ob, "Text"))
2657 // XXX draw_mesh_text(ob, 1);
2658 GPU_disable_material();
2660 glFrontFace(GL_CCW);
2663 draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2667 if(base->flag & SELECT)
2668 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2670 UI_ThemeColor(TH_WIRE);
2672 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2673 dm->drawLooseEdges(dm);
2676 else if(dt==OB_SOLID) {
2677 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2678 /* weight paint in solid mode, special case. focus on making the weights clear
2679 * rather than the shading, this is also forced in wire view */
2680 GPU_enable_material(0, NULL);
2681 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2683 bglPolygonOffset(rv3d->dist, 1.0);
2684 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2687 glColor4ub(255, 255, 255, 96);
2688 glEnable(GL_LINE_STIPPLE);
2689 glLineStipple(1, 0xAAAA);
2691 dm->drawEdges(dm, 1, 1);
2693 bglPolygonOffset(rv3d->dist, 0.0);
2695 glDisable(GL_LINE_STIPPLE);
2697 GPU_disable_material();
2699 /* since we already draw wire as wp guide, dont draw over the top */
2705 if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2706 draw_mesh_object_outline(v3d, ob, dm);
2708 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2710 glEnable(GL_LIGHTING);
2711 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2713 if(ob->sculpt && (p=paint_get_active(scene))) {
2715 float (*fpl)[4] = NULL;
2716 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2718 if(ob->sculpt->partial_redraw) {
2719 if(ar->do_draw & RGN_DRAW_PARTIAL) {
2720 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2722 ob->sculpt->partial_redraw = 0;
2726 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2729 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2731 GPU_disable_material();
2733 glFrontFace(GL_CCW);
2734 glDisable(GL_LIGHTING);
2736 if(base->flag & SELECT) {
2737 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2739 UI_ThemeColor(TH_WIRE);
2741 if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2742 dm->drawLooseEdges(dm);
2745 else if(dt==OB_SHADED) {
2747 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2748 /* enforce default material settings */
2749 GPU_enable_material(0, NULL);
2751 /* but set default spec */
2752 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2753 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2754 glColor3ub(120, 120, 120);
2755 glDisable(GL_COLOR_MATERIAL);
2757 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2758 glEnable(GL_LIGHTING);
2759 glEnable(GL_COLOR_MATERIAL);
2761 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2762 glDisable(GL_COLOR_MATERIAL);
2763 glDisable(GL_LIGHTING);
2765 GPU_disable_material();
2767 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2769 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
2771 glColor3f(1.0f, 1.0f, 1.0f);
2772 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
2778 /* set default draw color back for wire or for draw-extra later on */
2780 if(base->flag & SELECT) {
2781 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2782 UI_ThemeColor(TH_GROUP_ACTIVE);
2783 else if(ob->flag & OB_FROMGROUP)
2784 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2785 else if(flag!=DRAW_CONSTCOLOR)
2786 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2788 glColor3ub(80,80,80);
2790 if (ob->flag & OB_FROMGROUP)
2791 UI_ThemeColor(TH_GROUP);
2793 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2794 glColor3ub(80,80,80);
2796 UI_ThemeColor(TH_WIRE);
2802 /* When using wireframe object traw in particle edit mode
2803 * the mesh gets in the way of seeing the particles, fade the wire color
2804 * with the background. */
2805 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2806 float col_wire[4], col_bg[4], col[3];
2808 UI_GetThemeColor3fv(TH_BACK, col_bg);
2809 glGetFloatv(GL_CURRENT_COLOR, col_wire);
2810 interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2814 /* If drawing wire and drawtype is not OB_WIRE then we are
2815 * overlaying the wires.
2817 * UPDATE bug #10290 - With this wire-only objects can draw
2818 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2820 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2821 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2823 if (dt!=OB_WIRE && draw_wire==2) {
2824 bglPolygonOffset(rv3d->dist, 1.0);
2825 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2828 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2829 dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2831 if (dt!=OB_WIRE && draw_wire==2) {
2833 bglPolygonOffset(rv3d->dist, 0.0);
2840 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2841 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2843 Object *ob= base->object;
2844 Object *obedit= scene->obedit;
2846 EditMesh *em= me->edit_mesh;
2847 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
2849 /* If we are drawing shadows and any of the materials don't cast a shadow,
2850 * then don't draw the object */
2851 if (v3d->flag2 & V3D_RENDER_SHADOW) {
2852 for(i=0; i<ob->totcol; ++i) {
2853 Material *ma= give_current_material(ob, i);
2854 if (ma && !(ma->mode & MA_SHADBUF)) {
2860 if(obedit && ob!=obedit && ob->data==obedit->data) {
2861 if(ob_get_key(ob) || ob_get_key(obedit));
2862 else if(ob->modifiers.first || obedit->modifiers.first);
2866 if(ob==obedit || drawlinked) {
2867 DerivedMesh *finalDM, *cageDM;
2870 finalDM = cageDM = editmesh_get_derived_base(ob, em);
2872 cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2873 scene->customdata_mask);
2876 // no transp in editmode, the fancy draw over goes bad then
2877 glsl = draw_glsl_material(scene, ob, v3d, dt);
2878 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2881 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2883 GPU_end_object_materials();
2885 if (obedit!=ob && finalDM)
2886 finalDM->release(finalDM);
2889 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2890 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2891 glsl = draw_glsl_material(scene, ob, v3d, dt);
2892 check_alpha = check_material_alpha(base, me, glsl);
2894 if(dt==OB_SOLID || glsl) {
2895 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2896 (check_alpha)? &do_alpha_pass: NULL);
2899 draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2901 GPU_end_object_materials();
2903 if(me->totvert==0) retval= 1;
2907 /* GPU_begin_object_materials checked if this is needed */
2909 if(ob->dtx & OB_DRAWXRAY) {
2910 add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2913 add_view3d_after(&v3d->afterdraw_transp, base, flag);
2916 else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2917 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2918 if(v3d->xray == 0 && v3d->transp == 0) {
2919 add_view3d_after(&v3d->afterdraw_xray, base, flag);
2926 /* ************** DRAW DISPLIST ****************** */
2928 static int draw_index_wire= 1;
2929 static int index3_nors_incr= 1;
2931 /* returns 1 when nothing was drawn */
2932 static int drawDispListwire(ListBase *dlbase)
2938 if(dlbase==NULL) return 1;
2940 glEnableClientState(GL_VERTEX_ARRAY);
2941 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2943 for(dl= dlbase->first; dl; dl= dl->next) {
2944 if(dl->parts==0 || dl->nr==0)
2952 glVertexPointer(3, GL_FLOAT, 0, data);
2954 for(parts=0; parts<dl->parts; parts++)
2955 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2960 glVertexPointer(3, GL_FLOAT, 0, data);
2962 for(parts=0; parts<dl->parts; parts++)
2963 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2968 glVertexPointer(3, GL_FLOAT, 0, data);
2970 for(parts=0; parts<dl->parts; parts++) {
2971 if(dl->flag & DL_CYCL_U)
2972 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2974 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2977 for(nr=0; nr<dl->nr; nr++) {
2980 data= ( dl->verts )+3*nr;
2983 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2984 else glBegin(GL_LINE_STRIP);
2992 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2993 // glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2994 // if(dl->flag & DL_CYCL_V)
2995 // glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2997 // glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
3002 if(draw_index_wire) {
3003 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3004 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
3009 if(draw_index_wire) {