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_SHADED);
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 /* flag similar to draw_object() */
1339 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1341 /* a standing up pyramid with (0,0,0) as top */
1343 float vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1346 const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1348 const float scax= 1.0f / len_v3(ob->obmat[0]);
1349 const float scay= 1.0f / len_v3(ob->obmat[1]);
1350 const float scaz= 1.0f / len_v3(ob->obmat[2]);
1353 aspx= (float) scene->r.xsch*scene->r.xasp;
1354 aspy= (float) scene->r.ysch*scene->r.yasp;
1365 glDisable(GL_LIGHTING);
1366 glDisable(GL_CULL_FACE);
1368 if(cam->type==CAM_ORTHO) {
1369 facx= 0.5f * cam->ortho_scale * caspx * scax;
1370 facy= 0.5f * cam->ortho_scale * caspy * scay;
1371 shx= cam->shiftx * cam->ortho_scale * scax;
1372 shy= cam->shifty * cam->ortho_scale * scay;
1373 depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
1375 drawsize= 0.5f * cam->ortho_scale;
1378 /* that way it's always visible - clipsta+0.1 */
1380 drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
1383 /* fixed depth, variable size (avoids exceeding clipping range) */
1384 depth = -(cam->clipsta + 0.1f);
1385 fac = depth / (cam->lens/-16.0f * scaz);
1388 /* fixed size, variable depth (stays a reasonable size in the 3D view) */
1389 depth= drawsize * cam->lens/-16.0f * scaz;
1393 facx= fac * caspx * scax;
1394 facy= fac * caspy * scay;
1395 shx= cam->shiftx*fac*2 * scax;
1396 shy= cam->shifty*fac*2 * scay;
1399 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
1400 vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1401 vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1402 vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1403 vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1406 glBegin(GL_LINE_LOOP);
1407 glVertex3fv(vec[1]);
1408 glVertex3fv(vec[2]);
1409 glVertex3fv(vec[3]);
1410 glVertex3fv(vec[4]);
1416 /* center point to camera frame */
1417 glBegin(GL_LINE_STRIP);
1418 glVertex3fv(vec[2]);
1419 glVertex3fv(vec[0]);
1420 glVertex3fv(vec[1]);
1421 glVertex3fv(vec[4]);
1422 glVertex3fv(vec[0]);
1423 glVertex3fv(vec[3]);
1431 /* draw an outline arrow for inactive cameras and filled
1432 * for active cameras. We actually draw both outline+filled
1433 * for active cameras so the wire can be seen side-on */
1435 if (i==0) glBegin(GL_LINE_LOOP);
1436 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1439 vec[0][0]= shx + ((-0.7f * drawsize) * scax);
1440 vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
1441 glVertex3fv(vec[0]); /* left */
1443 vec[0][0]= shx + ((0.7f * drawsize) * scax);
1444 glVertex3fv(vec[0]); /* right */
1447 vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
1448 glVertex3fv(vec[0]); /* top */
1454 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1458 /* draw in normalized object matrix space */
1459 copy_m4_m4(nobmat, ob->obmat);
1460 normalize_m4(nobmat);
1463 glLoadMatrixf(rv3d->viewmat);
1464 glMultMatrixf(nobmat);
1466 if(cam->flag & CAM_SHOWLIMITS) {
1467 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1468 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1469 draw_focus_cross(dof_camera(ob), cam->drawsize);
1473 if(cam->flag & CAM_SHOWMIST)
1474 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1481 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1483 BPoint *bp = lt->def;
1484 float *co = dl?dl->verts:NULL;
1487 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1488 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1489 bglBegin(GL_POINTS);
1491 for(w=0; w<lt->pntsw; w++) {
1492 int wxt = (w==0 || w==lt->pntsw-1);
1493 for(v=0; v<lt->pntsv; v++) {
1494 int vxt = (v==0 || v==lt->pntsv-1);
1495 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1496 int uxt = (u==0 || u==lt->pntsu-1);
1497 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1499 if((bp->f1 & SELECT)==sel) {
1500 bglVertex3fv(dl?co:bp->vec);
1512 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1514 Object *obedit= vc->obedit;
1515 Lattice *lt= obedit->data;
1516 BPoint *bp = lt->editlatt->latt->def;
1517 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1518 float *co = dl?dl->verts:NULL;
1519 int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1520 short s[2] = {IS_CLIPPED, 0};
1522 ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1524 for (i=0; i<N; i++, bp++, co+=3) {
1526 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1527 if (s[0] != IS_CLIPPED)
1528 func(userData, bp, s[0], s[1]);
1533 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1535 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1539 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1541 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1547 glVertex3fv(&dl->verts[index*3]);
1549 glVertex3fv(lt->def[index].vec);
1553 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1554 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1556 Lattice *lt= ob->data;
1559 int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1561 /* now we default make displist, this will modifiers work for non animated case */
1562 if(ob->disp.first==NULL)
1563 lattice_calc_modifiers(scene, ob);
1564 dl= find_displist(&ob->disp, DL_VERTS);
1567 lt= lt->editlatt->latt;
1571 if(ob->defbase.first && lt->dvert) {
1572 use_wcol= ob->actdef;
1573 glShadeModel(GL_SMOOTH);
1578 for(w=0; w<lt->pntsw; w++) {
1579 int wxt = (w==0 || w==lt->pntsw-1);
1580 for(v=0; v<lt->pntsv; v++) {
1581 int vxt = (v==0 || v==lt->pntsv-1);
1582 for(u=0; u<lt->pntsu; u++) {
1583 int uxt = (u==0 || u==lt->pntsu-1);
1585 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1586 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1587 drawlattice__point(lt, dl, u, v, w, use_wcol);
1589 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1590 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1591 drawlattice__point(lt, dl, u, v, w, use_wcol);
1593 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1594 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1595 drawlattice__point(lt, dl, u, v, w, use_wcol);
1602 /* restoration for weight colors */
1604 glShadeModel(GL_FLAT);
1607 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1609 lattice_draw_verts(lt, dl, 0);
1610 lattice_draw_verts(lt, dl, 1);
1612 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1616 /* ***************** ******************** */
1618 /* Note! - foreach funcs should be called while drawing or directly after
1619 * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1620 * but would not give correct results with dupli's for eg. which dont
1621 * use the object matrix in the useual way */
1622 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1624 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1625 EditVert *eve = EM_get_vert_for_index(index);
1628 short s[2]= {IS_CLIPPED, 0};
1630 if (data->clipVerts) {
1631 view3d_project_short_clip(data->vc.ar, co, s, 1);
1633 view3d_project_short_noclip(data->vc.ar, co, s);
1636 if (s[0]!=IS_CLIPPED)
1637 data->func(data->userData, eve, s[0], s[1], index);
1641 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1643 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1644 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1648 data.userData = userData;
1649 data.clipVerts = clipVerts;
1652 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1654 EM_init_index_arrays(vc->em, 1, 0, 0);
1655 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1656 EM_free_index_arrays();
1661 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1663 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;
1664 EditEdge *eed = EM_get_edge_for_index(index);
1668 if (data->clipVerts==1) {
1669 view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1670 view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1672 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1673 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1675 if (data->clipVerts==2) {
1676 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1677 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1682 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1686 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)
1688 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1689 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1693 data.userData = userData;
1694 data.clipVerts = clipVerts;
1697 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1699 EM_init_index_arrays(vc->em, 0, 1, 0);
1700 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1701 EM_free_index_arrays();
1706 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1708 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1709 EditFace *efa = EM_get_face_for_index(index);
1712 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1713 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1715 data->func(data->userData, efa, s[0], s[1], index);
1719 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1721 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1722 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1726 data.userData = userData;
1729 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1731 EM_init_index_arrays(vc->em, 0, 0, 1);
1732 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1733 EM_free_index_arrays();
1738 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1740 Curve *cu= vc->obedit->data;
1741 short s[2] = {IS_CLIPPED, 0};
1744 ListBase *nurbs= ED_curve_editnurbs(cu);
1746 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1748 for (nu= nurbs->first; nu; nu=nu->next) {
1749 if(nu->type == CU_BEZIER) {
1750 for (i=0; i<nu->pntsu; i++) {
1751 BezTriple *bezt = &nu->bezt[i];
1755 if(cu->drawflag & CU_HIDE_HANDLES) {
1756 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1757 if (s[0] != IS_CLIPPED)
1758 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1760 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1761 if (s[0] != IS_CLIPPED)
1762 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1763 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1764 if (s[0] != IS_CLIPPED)
1765 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1766 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1767 if (s[0] != IS_CLIPPED)
1768 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1774 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1775 BPoint *bp = &nu->bp[i];
1778 view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1779 if (s[0] != IS_CLIPPED)
1780 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1787 /* ************** DRAW MESH ****************** */
1789 /* First section is all the "simple" draw routines,
1790 * ones that just pass some sort of primitive to GL,
1791 * with perhaps various options to control lighting,
1794 * These routines should not have user interface related
1798 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1800 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1801 EditFace *efa = EM_get_face_for_index(index);
1803 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1805 glVertex3f( cent[0] + no[0]*ts->normalsize,
1806 cent[1] + no[1]*ts->normalsize,
1807 cent[2] + no[2]*ts->normalsize);
1810 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1813 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1817 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1819 EditFace *efa = EM_get_face_for_index(index);
1820 int sel = *((int*) userData);
1822 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1826 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1828 bglBegin(GL_POINTS);
1829 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1833 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1835 Scene *scene= (Scene *)userData;
1836 ToolSettings *ts= scene->toolsettings;
1837 EditVert *eve = EM_get_vert_for_index(index);
1843 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1844 co[1] + no_f[1]*ts->normalsize,
1845 co[2] + no_f[2]*ts->normalsize);
1847 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1848 co[1] + no_s[1]*ts->normalsize/32767.0f,
1849 co[2] + no_s[2]*ts->normalsize/32767.0f);
1853 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1856 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1860 /* Draw verts with color set based on selection */
1861 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1863 struct { int sel; EditVert *eve_act; } * data = userData;
1864 EditVert *eve = EM_get_vert_for_index(index);
1866 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1867 /* draw active larger - need to stop/start point drawing for this :/ */
1868 if (eve==data->eve_act) {
1869 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1870 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1875 bglBegin(GL_POINTS);
1879 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1881 bglBegin(GL_POINTS);
1888 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1890 struct { int sel; EditVert *eve_act; } data;
1892 data.eve_act = eve_act;
1894 bglBegin(GL_POINTS);
1895 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1899 /* Draw edges with color set based on selection */
1900 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1902 EditEdge *eed = EM_get_edge_for_index(index);
1903 //unsigned char **cols = userData, *col;
1904 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1908 if (eed==data->eed_act) {
1909 glColor4ubv(data->actCol);
1911 if (eed->f&SELECT) {
1914 col = data->baseCol;
1916 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1917 if (col[3]==0) return 0;
1926 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1928 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1930 data.baseCol = baseCol;
1931 data.selCol = selCol;
1932 data.actCol = actCol;
1933 data.eed_act = eed_act;
1934 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1938 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
1940 return EM_get_edge_for_index(index)->h==0;
1942 static void draw_dm_edges(DerivedMesh *dm)
1944 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1947 /* Draw edges with color interpolated based on selection */
1948 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
1950 return EM_get_edge_for_index(index)->h==0;
1952 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1954 EditEdge *eed = EM_get_edge_for_index(index);
1955 unsigned char **cols = userData;
1956 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1957 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1959 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
1960 col0[1] + (col1[1]-col0[1])*t,
1961 col0[2] + (col1[2]-col0[2])*t,
1962 col0[3] + (col1[3]-col0[3])*t);
1965 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1967 unsigned char *cols[2];
1970 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1973 /* Draw only seam edges */
1974 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
1976 EditEdge *eed = EM_get_edge_for_index(index);
1978 return (eed->h==0 && eed->seam);
1980 static void draw_dm_edges_seams(DerivedMesh *dm)
1982 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1985 /* Draw only sharp edges */
1986 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
1988 EditEdge *eed = EM_get_edge_for_index(index);
1990 return (eed->h==0 && eed->sharp);
1992 static void draw_dm_edges_sharp(DerivedMesh *dm)
1994 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1998 /* Draw faces with color set based on selection
1999 * return 2 for the active face so it renders with stipple enabled */
2000 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2002 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2003 EditFace *efa = EM_get_face_for_index(index);
2007 if (efa == data->efa_act) {
2008 glColor4ubv(data->cols[2]);
2009 return 2; /* stipple */
2011 col = data->cols[(efa->f&SELECT)?1:0];
2012 if (col[3]==0) return 0;
2020 /* also draws the active face */
2021 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
2023 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2024 data.cols[0] = baseCol;
2025 data.cols[1] = selCol;
2026 data.cols[2] = actCol;
2027 data.efa_act = efa_act;
2029 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
2032 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2034 EditEdge *eed = EM_get_edge_for_index(index);
2036 if (eed->h==0 && eed->crease != 0.0f) {
2037 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2043 static void draw_dm_creases(DerivedMesh *dm)
2046 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2050 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2052 EditEdge *eed = EM_get_edge_for_index(index);
2054 if (eed->h==0 && eed->bweight != 0.0f) {
2055 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2061 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2063 EditVert *eve = EM_get_vert_for_index(index);
2065 if (eve->h==0 && eve->bweight != 0.0f) {
2066 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2070 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2072 ToolSettings *ts= scene->toolsettings;
2074 if (ts->selectmode & SCE_SELECT_VERTEX) {
2075 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2076 bglBegin(GL_POINTS);
2077 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2082 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2087 /* Second section of routines: Combine first sets to form fancy
2088 * drawing routines (for example rendering twice to get overlays).
2090 * Also includes routines that are basic drawing but are too
2091 * specialized to be split out (like drawing creases or measurements).
2094 /* EditMesh drawing routines*/
2096 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2098 ToolSettings *ts= scene->toolsettings;
2101 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2103 for (sel=0; sel<2; sel++) {
2104 unsigned char col[4], fcol[4];
2107 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2108 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2110 for (pass=0; pass<2; pass++) {
2111 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2112 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2115 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2116 glDisable(GL_DEPTH_TEST);
2123 size = (size > 2.1f ? size/2.0f:size);
2124 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2125 col[3] = fcol[3] = 100;
2127 col[3] = fcol[3] = 255;
2130 if(ts->selectmode & SCE_SELECT_VERTEX) {
2133 draw_dm_verts(cageDM, sel, eve_act);
2136 if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2139 draw_dm_face_centers(cageDM, sel);
2143 glDisable(GL_BLEND);
2144 glEnable(GL_DEPTH_TEST);
2149 if(v3d->zbuf) glDepthMask(1);
2153 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2155 ToolSettings *ts= scene->toolsettings;
2157 unsigned char wireCol[4], selCol[4], actCol[4];
2159 /* since this function does transparant... */
2160 UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2161 UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2162 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2164 /* when sel only is used, dont render wire, only selected, this is used for
2165 * textured draw mode when the 'edges' option is disabled */
2169 for (pass=0; pass<2; pass++) {
2170 /* show wires in transparant when no zbuf clipping for select */
2172 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2174 glDisable(GL_DEPTH_TEST);
2176 if (!sel_only) wireCol[3] = 85;
2182 if (!sel_only) wireCol[3] = 255;
2185 if(ts->selectmode == SCE_SELECT_FACE) {
2186 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2188 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2189 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2190 glShadeModel(GL_SMOOTH);
2191 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2192 glShadeModel(GL_FLAT);
2194 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2199 glColor4ubv(wireCol);
2200 draw_dm_edges(cageDM);
2205 glDisable(GL_BLEND);
2206 glEnable(GL_DEPTH_TEST);
2211 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2216 float v1[3], v2[3], v3[3], v4[3], vmid[3];
2218 char val[32]; /* Stores the measurement display text here */
2219 const char *conv_float; /* Use a float conversion matching the grid size */
2220 unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2221 float area; /* area of the face */
2222 float grid= unit->system ? unit->scale_length : v3d->grid;
2223 const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2224 const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2225 const int do_moving= G.moving;
2227 /* make the precision of the pronted value proportionate to the gridsize */
2229 if (grid < 0.01f) conv_float= "%.6g";
2230 else if (grid < 0.1f) conv_float= "%.5g";
2231 else if (grid < 1.0f) conv_float= "%.4g";
2232 else if (grid < 10.0f) conv_float= "%.3g";
2233 else conv_float= "%.2g";
2235 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2236 glDisable(GL_DEPTH_TEST);
2238 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2240 if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2241 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2243 for(eed= em->edges.first; eed; eed= eed->next) {
2244 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2245 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2246 copy_v3_v3(v1, eed->v1->co);
2247 copy_v3_v3(v2, eed->v2->co);
2249 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2252 mul_mat3_m4_v3(ob->obmat, v1);
2253 mul_mat3_m4_v3(ob->obmat, v2);
2256 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2258 sprintf(val, conv_float, len_v3v3(v1, v2));
2260 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2265 if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2266 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2267 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2269 for(efa= em->faces.first; efa; efa= efa->next) {
2270 if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2271 copy_v3_v3(v1, efa->v1->co);
2272 copy_v3_v3(v2, efa->v2->co);
2273 copy_v3_v3(v3, efa->v3->co);
2275 copy_v3_v3(v4, efa->v4->co);
2278 mul_mat3_m4_v3(ob->obmat, v1);
2279 mul_mat3_m4_v3(ob->obmat, v2);
2280 mul_mat3_m4_v3(ob->obmat, v3);
2281 if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2285 area= area_quad_v3(v1, v2, v3, v4);
2287 area = area_tri_v3(v1, v2, v3);
2290 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2292 sprintf(val, conv_float, area);
2294 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2299 if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2300 EditEdge *e1, *e2, *e3, *e4;
2301 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2302 for(efa= em->faces.first; efa; efa= efa->next) {
2303 copy_v3_v3(v1, efa->v1->co);
2304 copy_v3_v3(v2, efa->v2->co);
2305 copy_v3_v3(v3, efa->v3->co);
2307 copy_v3_v3(v4, efa->v4->co);
2313 mul_mat3_m4_v3(ob->obmat, v1);
2314 mul_mat3_m4_v3(ob->obmat, v2);
2315 mul_mat3_m4_v3(ob->obmat, v3);
2316 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2322 if(efa->e4) e4= efa->e4; else e4= e3;
2324 /* Calculate the angles */
2326 if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2328 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2329 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2330 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2332 if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2334 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2335 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2336 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2338 if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2341 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2343 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2344 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2345 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2349 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2350 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2351 interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2352 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2359 glEnable(GL_DEPTH_TEST);
2360 bglPolygonOffset(rv3d->dist, 0.0f);
2364 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2366 EditFace *efa = EM_get_face_for_index(index);
2369 GPU_enable_material(efa->mat_nr+1, NULL);
2376 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2378 EditFace *efa = EM_get_face_for_index(index);
2383 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2385 Mesh *me = ob->data;
2386 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2387 EditEdge *eed_act = NULL;
2388 EditVert *eve_act = NULL;
2390 if (em->selected.last) {
2391 EditSelection *ese = em->selected.last;
2392 /* face is handeled above */
2393 /*if (ese->type == EDITFACE ) {
2394 efa_act = (EditFace *)ese->data;
2395 } else */ if ( ese->type == EDITEDGE ) {
2396 eed_act = (EditEdge *)ese->data;
2397 } else if ( ese->type == EDITVERT ) {
2398 eve_act = (EditVert *)ese->data;
2402 EM_init_index_arrays(em, 1, 1, 1);
2405 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2406 if(draw_glsl_material(scene, ob, v3d, dt)) {
2407 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2409 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2410 draw_em_fancy__setGLSLFaceOpts, NULL);
2411 GPU_disable_material();
2413 glFrontFace(GL_CCW);
2416 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2420 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2421 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2423 glEnable(GL_LIGHTING);
2424 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2426 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material);
2428 glFrontFace(GL_CCW);
2429 glDisable(GL_LIGHTING);
2432 // Setup for drawing wire over, disable zbuffer
2433 // write to show selected edge wires better
2434 UI_ThemeColor(TH_WIRE);
2436 bglPolygonOffset(rv3d->dist, 1.0);
2440 if (cageDM!=finalDM) {
2441 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2442 finalDM->drawEdges(finalDM, 1, 0);
2446 if(me->drawflag & ME_DRAWFACES) { /* transp faces */
2447 unsigned char col1[4], col2[4], col3[4];
2449 UI_GetThemeColor4ubv(TH_FACE, col1);
2450 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2451 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2454 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2456 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2457 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2460 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2462 glDisable(GL_BLEND);
2463 glDepthMask(1); // restore write in zbuffer
2464 } else if (efa_act) {
2465 /* even if draw faces is off it would be nice to draw the stipple face
2466 * Make all other faces zero alpha except for the active
2468 unsigned char col1[4], col2[4], col3[4];
2469 col1[3] = col2[3] = 0; /* dont draw */
2470 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2473 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2475 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2477 glDisable(GL_BLEND);
2478 glDepthMask(1); // restore write in zbuffer
2482 /* here starts all fancy draw-extra over */
2483 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2484 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2486 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2487 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2490 if(me->drawflag & ME_DRAWSEAMS) {
2491 UI_ThemeColor(TH_EDGE_SEAM);
2494 draw_dm_edges_seams(cageDM);
2500 if(me->drawflag & ME_DRAWSHARP) {
2501 UI_ThemeColor(TH_EDGE_SHARP);
2504 draw_dm_edges_sharp(cageDM);
2510 if(me->drawflag & ME_DRAWCREASES) {
2511 draw_dm_creases(cageDM);
2513 if(me->drawflag & ME_DRAWBWEIGHTS) {
2514 draw_dm_bweights(scene, cageDM);
2517 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2520 // XXX retopo_matrix_update(v3d);
2522 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2524 if(me->drawflag & ME_DRAWNORMALS) {
2525 UI_ThemeColor(TH_NORMAL);
2526 draw_dm_face_normals(scene, cageDM);
2528 if(me->drawflag & ME_DRAW_VNORMALS) {
2529 UI_ThemeColor(TH_VNORMAL);
2530 draw_dm_vert_normals(scene, cageDM);
2533 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2534 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2539 bglPolygonOffset(rv3d->dist, 0.0);
2540 GPU_disable_material();
2543 EM_free_index_arrays();
2546 /* Mesh drawing routines */
2548 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2551 if(v3d->transp==0) { // not when we draw the transparent pass
2552 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2555 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2556 drawFacesSolid() doesn't draw the transparent faces */
2557 if(ob->dtx & OB_DRAWTRANSP) {
2558 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2559 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2560 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2561 GPU_disable_material();
2564 dm->drawEdges(dm, 0, 1);
2572 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2578 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2580 Object *ob= base->object;
2581 Mesh *me = ob->data;
2582 Material *ma= give_current_material(ob, 1);
2583 const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2584 const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2586 int /* totvert,*/ totedge, totface;
2588 DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2593 if (ob->dtx&OB_DRAWWIRE) {
2594 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2597 /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2598 totedge = dm->getNumEdges(dm);
2599 totface = dm->getNumFaces(dm);
2601 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2603 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2605 // Unwanted combination.
2606 if (is_paint_sel) draw_wire = 0;
2608 if(dt==OB_BOUNDBOX) {
2609 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2610 draw_bounding_volume(scene, ob);
2612 else if(hasHaloMat || (totface==0 && totedge==0)) {
2617 else if(dt==OB_WIRE || totface==0) {
2618 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2620 else if( (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2621 CHECK_OB_DRAWTEXTURE(v3d, dt))
2623 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2624 draw_mesh_object_outline(v3d, ob, dm);
2627 if(draw_glsl_material(scene, ob, v3d, dt)) {
2628 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2630 dm->drawFacesGLSL(dm, GPU_enable_material);
2631 // if(get_ob_property(ob, "Text"))
2632 // XXX draw_mesh_text(ob, 1);
2633 GPU_disable_material();
2635 glFrontFace(GL_CCW);
2638 draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2642 if(base->flag & SELECT)
2643 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2645 UI_ThemeColor(TH_WIRE);
2647 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2648 dm->drawLooseEdges(dm);
2651 else if(dt==OB_SOLID) {
2652 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2653 /* weight paint in solid mode, special case. focus on making the weights clear
2654 * rather then the shading, this is also forced in wire view */
2655 GPU_enable_material(0, NULL);
2656 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2658 bglPolygonOffset(rv3d->dist, 1.0);
2659 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2662 glColor4ub(255, 255, 255, 96);
2663 glEnable(GL_LINE_STIPPLE);
2664 glLineStipple(1, 0xAAAA);
2666 dm->drawEdges(dm, 1, 1);
2668 bglPolygonOffset(rv3d->dist, 0.0);
2670 glDisable(GL_LINE_STIPPLE);
2672 GPU_disable_material();
2674 /* since we already draw wire as wp guide, dont draw over the top */
2680 if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2681 draw_mesh_object_outline(v3d, ob, dm);
2683 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2685 glEnable(GL_LIGHTING);
2686 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2688 if(ob->sculpt && (p=paint_get_active(scene))) {
2690 float (*fpl)[4] = NULL;
2691 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2693 if(ob->sculpt->partial_redraw) {
2694 if(ar->do_draw & RGN_DRAW_PARTIAL) {
2695 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2697 ob->sculpt->partial_redraw = 0;
2701 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2704 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2706 GPU_disable_material();
2708 glFrontFace(GL_CCW);
2709 glDisable(GL_LIGHTING);
2711 if(base->flag & SELECT) {
2712 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2714 UI_ThemeColor(TH_WIRE);
2716 if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2717 dm->drawLooseEdges(dm);
2720 else if(dt==OB_SHADED) {
2721 int do_draw= 1; /* to resolve all G.f settings below... */
2725 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2726 /* enforce default material settings */
2727 GPU_enable_material(0, NULL);
2729 /* but set default spec */
2730 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2731 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2732 glColor3ub(120, 120, 120);
2733 glDisable(GL_COLOR_MATERIAL);
2735 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2736 glEnable(GL_LIGHTING);
2737 glEnable(GL_COLOR_MATERIAL);
2739 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2740 glDisable(GL_COLOR_MATERIAL);
2741 glDisable(GL_LIGHTING);
2743 GPU_disable_material();
2745 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2747 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
2749 glColor3f(1.0f, 1.0f, 1.0f);
2750 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
2756 dl = ob->disp.first;
2757 if (!dl || !dl->col1) {
2758 /* release and reload derivedmesh because it might be freed in
2759 shadeDispList due to a different datamask */
2761 shadeDispList(scene, base);
2762 dl = find_displist(&ob->disp, DL_VERTCOL);
2763 dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2766 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire) {
2767 draw_mesh_object_outline(v3d, ob, dm);
2770 /* False for dupliframe objects */
2772 unsigned int *obCol1 = dl->col1;
2773 unsigned int *obCol2 = dl->col2;
2775 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2778 if(base->flag & SELECT) {
2779 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2781 UI_ThemeColor(TH_WIRE);
2783 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2784 dm->drawLooseEdges(dm);
2788 /* set default draw color back for wire or for draw-extra later on */
2790 if(base->flag & SELECT) {
2791 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2792 UI_ThemeColor(TH_GROUP_ACTIVE);
2793 else if(ob->flag & OB_FROMGROUP)
2794 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2795 else if(flag!=DRAW_CONSTCOLOR)
2796 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2798 glColor3ub(80,80,80);
2800 if (ob->flag & OB_FROMGROUP)
2801 UI_ThemeColor(TH_GROUP);
2803 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2804 glColor3ub(80,80,80);
2806 UI_ThemeColor(TH_WIRE);
2812 /* When using wireframe object traw in particle edit mode
2813 * the mesh gets in the way of seeing the particles, fade the wire color
2814 * with the background. */
2815 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2816 float col_wire[4], col_bg[4], col[3];
2818 UI_GetThemeColor3fv(TH_BACK, col_bg);
2819 glGetFloatv(GL_CURRENT_COLOR, col_wire);
2820 interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2824 /* If drawing wire and drawtype is not OB_WIRE then we are
2825 * overlaying the wires.
2827 * UPDATE bug #10290 - With this wire-only objects can draw
2828 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2830 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2831 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2833 if (dt!=OB_WIRE && draw_wire==2) {
2834 bglPolygonOffset(rv3d->dist, 1.0);
2835 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2838 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2839 dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2841 if (dt!=OB_WIRE && draw_wire==2) {
2843 bglPolygonOffset(rv3d->dist, 0.0);
2850 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2851 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2853 Object *ob= base->object;
2854 Object *obedit= scene->obedit;
2856 EditMesh *em= me->edit_mesh;
2857 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2859 if(obedit && ob!=obedit && ob->data==obedit->data) {
2860 if(ob_get_key(ob) || ob_get_key(obedit));
2861 else if(ob->modifiers.first || obedit->modifiers.first);
2865 if(ob==obedit || drawlinked) {
2866 DerivedMesh *finalDM, *cageDM;
2869 finalDM = cageDM = editmesh_get_derived_base(ob, em);
2871 cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2872 scene->customdata_mask);
2875 // no transp in editmode, the fancy draw over goes bad then
2876 glsl = draw_glsl_material(scene, ob, v3d, dt);
2877 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2880 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2882 GPU_end_object_materials();
2884 if (obedit!=ob && finalDM)
2885 finalDM->release(finalDM);
2888 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2889 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2890 glsl = draw_glsl_material(scene, ob, v3d, dt);
2891 check_alpha = check_material_alpha(base, me, glsl);
2893 if(dt==OB_SOLID || glsl) {
2894 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2895 (check_alpha)? &do_alpha_pass: NULL);
2898 draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2900 GPU_end_object_materials();
2902 if(me->totvert==0) retval= 1;
2906 /* GPU_begin_object_materials checked if this is needed */
2908 if(ob->dtx & OB_DRAWXRAY) {
2909 add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2912 add_view3d_after(&v3d->afterdraw_transp, base, flag);
2915 else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2916 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2917 if(v3d->xray == 0 && v3d->transp == 0) {
2918 add_view3d_after(&v3d->afterdraw_xray, base, flag);
2925 /* ************** DRAW DISPLIST ****************** */
2927 static int draw_index_wire= 1;
2928 static int index3_nors_incr= 1;
2930 /* returns 1 when nothing was drawn */
2931 static int drawDispListwire(ListBase *dlbase)
2937 if(dlbase==NULL) return 1;
2939 glEnableClientState(GL_VERTEX_ARRAY);
2940 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2942 for(dl= dlbase->first; dl; dl= dl->next) {
2943 if(dl->parts==0 || dl->nr==0)
2951 glVertexPointer(3, GL_FLOAT, 0, data);
2953 for(parts=0; parts<dl->parts; parts++)
2954 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2959 glVertexPointer(3, GL_FLOAT, 0, data);
2961 for(parts=0; parts<dl->parts; parts++)
2962 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2967 glVertexPointer(3, GL_FLOAT, 0, data);
2969 for(parts=0; parts<dl->parts; parts++) {
2970 if(dl->flag & DL_CYCL_U)
2971 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2973 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2976 for(nr=0; nr<dl->nr; nr++) {
2979 data= ( dl->verts )+3*nr;
2982 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2983 else glBegin(GL_LINE_STRIP);
2991 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2992 // glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2993 // if(dl->flag & DL_CYCL_V)
2994 // glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2996 // glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
3001 if(draw_index_wire) {
3002 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3003 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
3008 if(draw_index_wire) {
3009 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3010 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
3016 glDisableClientState(GL_VERTEX_ARRAY);
3017 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3022 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
3025 GPUVertexAttribs gattribs;
3026 float *data, curcol[4];
3029 if(lb==NULL) return;
3031 /* for drawing wire */
3032 glGetFloatv(GL_CURRENT_COLOR, curcol);
3034 glEnable(GL_LIGHTING);
3035 glEnableClientState(GL_VERTEX_ARRAY);
3037 if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
3038 else glFrontFace(GL_CCW);
3040 if(ob->type==OB_MBALL) { // mball always smooth shaded
3041 glShadeModel(GL_SMOOTH);
3051 if(ob->type==OB_SURF) {
3054 glDisable(GL_LIGHTING);
3057 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3058 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
3060 glBegin(GL_LINE_STRIP);
3061 for(nr= dl->nr; nr; nr--, data+=3)
3065 glEnable(GL_LIGHTING);
3069 if(ob->type==OB_SURF) {
3072 glDisable(GL_LIGHTING);