4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation, full recode and added functions
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/editors/space_view3d/drawobject.c
36 #include "MEM_guardedalloc.h"
38 #include "DNA_camera_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_constraint_types.h" // for drawing constraint
41 #include "DNA_lamp_types.h"
42 #include "DNA_lattice_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_meta_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_smoke_types.h"
48 #include "DNA_speaker_types.h"
49 #include "DNA_world_types.h"
50 #include "DNA_armature_types.h"
52 #include "BLI_blenlib.h"
54 #include "BLI_editVert.h"
55 #include "BLI_edgehash.h"
57 #include "BLI_utildefines.h"
59 #include "BKE_anim.h" //for the where_on_path function
60 #include "BKE_constraint.h" // for the get_constraint_target function
61 #include "BKE_DerivedMesh.h"
62 #include "BKE_deform.h"
63 #include "BKE_displist.h"
65 #include "BKE_global.h"
66 #include "BKE_image.h"
68 #include "BKE_lattice.h"
70 #include "BKE_material.h"
71 #include "BKE_mball.h"
72 #include "BKE_modifier.h"
73 #include "BKE_object.h"
74 #include "BKE_paint.h"
75 #include "BKE_particle.h"
76 #include "BKE_pointcache.h"
79 #include "smoke_API.h"
81 #include "IMB_imbuf.h"
82 #include "IMB_imbuf_types.h"
85 #include "BIF_glutil.h"
88 #include "GPU_extensions.h"
91 #include "ED_particle.h"
92 #include "ED_screen.h"
93 #include "ED_sculpt.h"
95 #include "ED_curve.h" /* for ED_curve_editnurbs */
97 #include "UI_resources.h"
100 #include "wm_subwindow.h"
103 #include "view3d_intern.h" // own include
106 /* this condition has been made more complex since editmode can draw textures */
107 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
108 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
109 (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
111 static void draw_bounding_volume(Scene *scene, Object *ob);
113 static void drawcube_size(float size);
114 static void drawcircle_size(float size);
115 static void draw_empty_sphere(float size);
116 static void draw_empty_cone(float size);
118 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
120 if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
123 if(G.f & G_BACKBUFSEL)
126 if((vd->flag & V3D_ZBUF_SELECT) == 0)
129 /* if its drawing textures with zbuf sel, then dont draw dots */
130 if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
133 if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
139 /* ************* only use while object drawing **************
140 * or after running ED_view3d_init_mats_rv3d
142 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
144 RegionView3D *rv3d= ar->regiondata;
145 float fx, fy, vec4[4];
149 /* clipplanes in eye space */
150 if(rv3d->rflag & RV3D_CLIPPING) {
151 if(ED_view3d_test_clipping(rv3d, vec, local))
155 copy_v3_v3(vec4, vec);
158 mul_m4_v4(rv3d->persmatob, vec4);
160 /* clipplanes in window space */
161 if( vec4[3] > (float)BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
162 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
164 if( fx>0 && fx<ar->winx) {
166 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
168 if(fy > 0.0f && fy < (float)ar->winy) {
169 adr[0]= (short)floorf(fx);
170 adr[1]= (short)floorf(fy);
176 /* only use while object drawing */
177 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
179 RegionView3D *rv3d= ar->regiondata;
180 float fx, fy, vec4[4];
184 copy_v3_v3(vec4, vec);
187 mul_m4_v4(rv3d->persmatob, vec4);
189 if( vec4[3] > (float)BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
190 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
192 if( fx>-32700 && fx<32700) {
194 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
196 if(fy > -32700.0f && fy < 32700.0f) {
197 adr[0]= (short)floorf(fx);
198 adr[1]= (short)floorf(fy);
204 /* ************************ */
206 /* check for glsl drawing */
208 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
210 if(!GPU_glsl_support())
214 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
216 if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
219 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
222 static int check_material_alpha(Base *base, Mesh *me, int glsl)
224 if(base->flag & OB_FROMDUPLI)
233 return (glsl || (base->object->dtx & OB_DRAWTRANSP));
237 static unsigned int colortab[24]=
238 {0x0, 0xFF88FF, 0xFFBBFF,
239 0x403000, 0xFFFF88, 0xFFFFBB,
240 0x104040, 0x66CCCC, 0x77CCCC,
241 0x104010, 0x55BB55, 0x66FF66,
246 static float cube[8][3] = {
257 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
258 /* 32 values of sin function (still same result!) */
259 static float sinval[32] = {
294 /* 32 values of cos function (still same result!) */
295 static float cosval[32] ={
330 static void draw_xyz_wire(const float c[3], float size, int axis)
332 float v1[3]= {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
333 float dim = size * 0.1f;
334 float dx[3], dy[3], dz[3];
336 dx[0]=dim; dx[1]=0.f; dx[2]=0.f;
337 dy[0]=0.f; dy[1]=dim; dy[2]=0.f;
338 dz[0]=0.f; dz[1]=0.f; dz[2]=dim;
344 /* bottom left to top right */
345 sub_v3_v3v3(v1, c, dx);
347 add_v3_v3v3(v2, c, dx);
353 /* top left to bottom right */
366 /* bottom left to top right */
367 mul_v3_fl(dx, 0.75f);
368 sub_v3_v3v3(v1, c, dx);
370 add_v3_v3v3(v2, c, dx);
376 /* top left to center */
387 glBegin(GL_LINE_STRIP);
389 /* start at top left */
390 sub_v3_v3v3(v1, c, dx);
391 add_v3_v3v3(v1, c, dz);
416 void drawaxes(float size, char drawtype)
419 float v1[3]= {0.0, 0.0, 0.0};
420 float v2[3]= {0.0, 0.0, 0.0};
421 float v3[3]= {0.0, 0.0, 0.0};
426 for (axis=0; axis<3; axis++) {
434 /* reset v1 & v2 to zero */
435 v1[axis]= v2[axis]= 0.0f;
440 case OB_SINGLE_ARROW:
443 /* in positive z direction only */
450 glBegin(GL_TRIANGLES);
452 v2[0]= size * 0.035f; v2[1] = size * 0.035f;
453 v3[0]= size * -0.035f; v3[1] = size * 0.035f;
454 v2[2]= v3[2]= size * 0.75f;
456 for (axis=0; axis<4; axis++) {
478 drawcircle_size(size);
481 case OB_EMPTY_SPHERE:
482 draw_empty_sphere(size);
486 draw_empty_cone(size);
491 for (axis=0; axis<3; axis++) {
492 const int arrow_axis= (axis==0) ? 1:0;
500 v1[axis]= size*0.85f;
501 v1[arrow_axis]= -size*0.08f;
505 v1[arrow_axis]= size*0.08f;
511 v2[axis]+= size*0.125f;
513 draw_xyz_wire(v2, size, axis);
516 /* reset v1 & v2 to zero */
517 v1[arrow_axis]= v1[axis]= v2[axis]= 0.0f;
524 /* Function to draw an Image on a empty Object */
525 static void draw_empty_image(Object *ob)
527 Image *ima = (Image*)ob->data;
528 ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
530 float scale, ofs_x, ofs_y, sca_x, sca_y;
533 if(ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
534 IMB_rect_from_float(ibuf);
537 /* Get the buffer dimensions so we can fallback to fake ones */
538 if(ibuf && ibuf->rect) {
547 /* Get the image aspect even if the buffer is invalid */
549 if(ima->aspx > ima->aspy) {
551 sca_y= ima->aspy / ima->aspx;
553 else if(ima->aspx < ima->aspy) {
554 sca_x= ima->aspx / ima->aspy;
567 /* Calculate the scale center based on objects origin */
568 ofs_x= ob->ima_ofs[0] * ima_x;
569 ofs_y= ob->ima_ofs[1] * ima_y;
571 glMatrixMode(GL_MODELVIEW);
574 /* Make sure we are drawing at the origin */
575 glTranslatef(0.0f, 0.0f, 0.0f);
577 /* Calculate Image scale */
578 scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
580 /* Set the object scale */
581 glScalef(scale * sca_x, scale * sca_y, 1.0f);
583 if(ibuf && ibuf->rect) {
584 /* Setup GL params */
586 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
588 /* Use the object color and alpha */
591 /* Draw the Image on the screen */
592 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
593 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
598 UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
600 /* Calculate the outline vertex positions */
601 glBegin(GL_LINE_LOOP);
602 glVertex2f(ofs_x, ofs_y);
603 glVertex2f(ofs_x + ima_x, ofs_y);
604 glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
605 glVertex2f(ofs_x, ofs_y + ima_y);
608 /* Reset GL settings */
609 glMatrixMode(GL_MODELVIEW);
613 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
615 float vec[3], vx[3], vy[3];
618 mul_v3_v3fl(vx, tmat[0], rad);
619 mul_v3_v3fl(vy, tmat[1], rad);
622 for(a=0; a<tot; a++) {
623 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
624 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
625 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
631 /* circle for object centers, special_color is for library or ob users */
632 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
634 const float size= ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
636 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
637 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
641 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
643 else glColor4ub(0x55, 0xCC, 0xCC, 155);
646 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
647 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
648 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
650 drawcircball(GL_POLYGON, co, size, rv3d->viewinv);
652 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
653 drawcircball(GL_LINE_LOOP, co, size, rv3d->viewinv);
656 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
659 /* *********** text drawing for object/particles/armature ************* */
660 static ListBase CachedText[3];
661 static int CachedTextLevel= 0;
663 typedef struct ViewCachedString {
664 struct ViewCachedString *next, *prev;
674 /* str is allocated past the end */
677 void view3d_cached_text_draw_begin(void)
679 ListBase *strings= &CachedText[CachedTextLevel];
680 strings->first= strings->last= NULL;
684 void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4])
686 int alloc_len= strlen(str) + 1;
687 ListBase *strings= &CachedText[CachedTextLevel-1];
688 ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
690 BLI_addtail(strings, vos);
691 copy_v3_v3(vos->vec, co);
692 vos->col.pack= *((int *)col);
695 vos->str_len= alloc_len-1;
697 /* allocate past the end */
698 memcpy(++vos, str, alloc_len);
701 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
703 RegionView3D *rv3d= ar->regiondata;
704 ListBase *strings= &CachedText[CachedTextLevel-1];
705 ViewCachedString *vos;
708 /* project first and test */
709 for(vos= strings->first; vos; vos= vos->next) {
710 if(mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
711 mul_m4_v3(mat, vos->vec);
712 view3d_project_short_clip(ar, vos->vec, vos->sco, 0);
713 if(vos->sco[0]!=IS_CLIPPED)
718 int col_pack_prev= 0;
721 bglMats mats; /* ZBuffer depth vars */
728 if(rv3d->rflag & RV3D_CLIPPING)
730 glDisable(GL_CLIP_PLANE0+a);
732 glMatrixMode(GL_PROJECTION);
734 glMatrixMode(GL_MODELVIEW);
736 ED_region_pixelspace(ar);
739 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
743 for(vos= strings->first; vos; vos= vos->next) {
744 #if 0 // too slow, reading opengl info while drawing is very bad, better to see if we cn use the zbuffer while in pixel space - campbell
745 if(v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
746 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
747 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
753 if(vos->sco[0]!=IS_CLIPPED) {
754 const char *str= (char *)(vos+1);
756 if(col_pack_prev != vos->col.pack) {
757 glColor3ubv(vos->col.ub);
758 col_pack_prev= vos->col.pack;
760 if(vos->flag & V3D_CACHE_TEXT_ASCII) {
761 BLF_draw_default_ascii((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
764 BLF_draw_default((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
770 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
774 glMatrixMode(GL_PROJECTION);
776 glMatrixMode(GL_MODELVIEW);
779 if(rv3d->rflag & RV3D_CLIPPING)
781 glEnable(GL_CLIP_PLANE0+a);
785 BLI_freelistN(strings);
790 /* ******************** primitive drawing ******************* */
792 static void drawcube(void)
795 glBegin(GL_LINE_STRIP);
796 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
797 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
798 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
801 glBegin(GL_LINE_STRIP);
802 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
805 glBegin(GL_LINE_STRIP);
806 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
809 glBegin(GL_LINE_STRIP);
810 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
814 /* draws a cube on given the scaling of the cube, assuming that
815 * all required matrices have been set (used for drawing empties)
817 static void drawcube_size(float size)
819 glBegin(GL_LINE_STRIP);
820 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
821 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
822 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
825 glBegin(GL_LINE_STRIP);
826 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
829 glBegin(GL_LINE_STRIP);
830 glVertex3f(-size,size,size); glVertex3f(size,size,size);
833 glBegin(GL_LINE_STRIP);
834 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
838 /* this is an unused (old) cube-drawing function based on a given size */
840 static void drawcube_size(float *size)
844 glScalef(size[0], size[1], size[2]);
847 glBegin(GL_LINE_STRIP);
848 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
849 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
850 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
853 glBegin(GL_LINE_STRIP);
854 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
857 glBegin(GL_LINE_STRIP);
858 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
861 glBegin(GL_LINE_STRIP);
862 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
869 static void drawshadbuflimits(Lamp *la, float mat[][4])
871 float sta[3], end[3], lavec[3];
873 negate_v3_v3(lavec, mat[2]);
876 madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
877 madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
879 glBegin(GL_LINE_STRIP);
894 static void spotvolume(float *lvec, float *vvec, float inp)
896 /* camera is at 0,0,0 */
897 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
900 normalize_v3(vvec); /* is this the correct vector ? */
902 cross_v3_v3v3(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
903 cross_v3_v3v3(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
905 /* vectors are exactly aligned, use the X axis, this is arbitrary */
906 if(normalize_v3(plane) == 0.0f)
909 /* now we've got two equations: one of a cone and one of a plane, but we have
910 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
912 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
913 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
915 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
922 angle = saacos(plane[2])/2.0f;
931 quat_to_mat3(mat1,q);
933 /* rotate lamp vector now over acos(inp) degrees */
934 copy_v3_v3(vvec, lvec);
938 si = sqrt(1-inp*inp);
944 mul_m3_m3m3(mat3,mat2,mat1);
948 mul_m3_m3m3(mat4,mat2,mat1);
951 mul_m3_m3m3(mat2,mat1,mat3);
952 mul_m3_v3(mat2,lvec);
953 mul_m3_m3m3(mat2,mat1,mat4);
954 mul_m3_v3(mat2,vvec);
959 static void draw_spot_cone(Lamp *la, float x, float z)
963 glBegin(GL_TRIANGLE_FAN);
964 glVertex3f(0.0f, 0.0f, -x);
966 if(la->mode & LA_SQUARE) {
968 glVertex3f(-z, z, 0);
969 glVertex3f(-z, -z, 0);
970 glVertex3f(z, -z, 0);
977 for(a=0; a<33; a++) {
978 angle= a*M_PI*2/(33-1);
979 glVertex3f(z*cosf(angle), z*sinf(angle), 0);
986 static void draw_transp_spot_volume(Lamp *la, float x, float z)
988 glEnable(GL_CULL_FACE);
992 /* draw backside darkening */
993 glCullFace(GL_FRONT);
995 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
996 glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
998 draw_spot_cone(la, x, z);
1000 /* draw front side lighting */
1001 glCullFace(GL_BACK);
1003 glBlendFunc(GL_ONE, GL_ONE);
1004 glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1006 draw_spot_cone(la, x, z);
1009 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1010 glDisable(GL_BLEND);
1012 glDisable(GL_CULL_FACE);
1013 glCullFace(GL_BACK);
1016 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
1018 Object *ob= base->object;
1019 const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1021 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
1023 float imat[4][4], curcol[4];
1024 unsigned char col[4];
1025 /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1026 /* the moment of view3d_draw_transp() call */
1027 const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
1028 const short drawcone= (dt>OB_WIRE && !(G.f & G_PICKSEL) && (la->type == LA_SPOT) && (la->mode & LA_SHOW_CONE) && !(base->flag & OB_FROMDUPLI) && !is_view);
1030 if(drawcone && !v3d->transp) {
1031 /* in this case we need to draw delayed */
1032 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1036 /* we first draw only the screen aligned & fixed scale stuff */
1038 glLoadMatrixf(rv3d->viewmat);
1040 /* lets calculate the scale: */
1041 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
1043 /* and view aligned matrix: */
1044 copy_m4_m4(imat, rv3d->viewinv);
1045 normalize_v3(imat[0]);
1046 normalize_v3(imat[1]);
1049 copy_v3_v3(vec, ob->obmat[3]);
1051 /* for AA effects */
1052 glGetFloatv(GL_CURRENT_COLOR, curcol);
1056 if(lampsize > 0.0f) {
1059 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1060 else glColor4ub(0x77, 0xCC, 0xCC, 155);
1065 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1066 glDisable(GL_BLEND);
1067 drawcircball(GL_POLYGON, vec, lampsize, imat);
1074 circrad = 3.0f*lampsize;
1077 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1079 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1080 if(la->type!=LA_HEMI) {
1081 if( (la->mode & LA_SHAD_RAY) ||
1082 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
1084 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
1093 /* draw the pretty sun rays */
1094 if(la->type==LA_SUN) {
1095 float v1[3], v2[3], mat[3][3];
1098 /* setup a 45 degree rotation matrix */
1099 vec_rot_to_mat3(mat, imat[2], (float)M_PI/4.0f);
1102 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1103 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1106 glTranslatef(vec[0], vec[1], vec[2]);
1111 for (axis=0; axis<8; axis++) {
1119 glTranslatef(-vec[0], -vec[1], -vec[2]);
1123 if (la->type==LA_LOCAL) {
1124 if(la->mode & LA_SPHERE) {
1125 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1127 /* yafray: for photonlight also draw lightcone as for spot */
1130 glPopMatrix(); /* back in object space */
1134 /* skip drawing extra info */
1136 else if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
1137 lvec[0]=lvec[1]= 0.0;
1139 x = rv3d->persmat[0][2];
1140 y = rv3d->persmat[1][2];
1141 z = rv3d->persmat[2][2];
1142 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
1143 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
1144 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
1146 y = cosf(la->spotsize*(float)(M_PI/360.0));
1147 spotvolume(lvec, vvec, y);
1152 /* draw the angled sides of the cone */
1153 glBegin(GL_LINE_STRIP);
1159 z = x*sqrtf(1.0f - y*y);
1162 /* draw the circle/square at the end of the cone */
1163 glTranslatef(0.0, 0.0 , x);
1164 if(la->mode & LA_SQUARE) {
1166 float z_abs= fabs(z);
1168 tvec[0]= tvec[1]= z_abs;
1171 glBegin(GL_LINE_LOOP);
1173 tvec[1]= -z_abs; /* neg */
1175 tvec[0]= -z_abs; /* neg */
1177 tvec[1]= z_abs; /* pos */
1181 else circ(0.0, 0.0, fabsf(z));
1183 /* draw the circle/square representing spotbl */
1184 if(la->type==LA_SPOT) {
1185 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
1186 /* hide line if it is zero size or overlaps with outer border,
1187 previously it adjusted to always to show it but that seems
1188 confusing because it doesn't show the actual blend size */
1189 if (spotblcirc != 0 && spotblcirc != fabsf(z))
1190 circ(0.0, 0.0, spotblcirc);
1194 draw_transp_spot_volume(la, x, z);
1196 /* draw clip start, useful for wide cones where its not obvious where the start is */
1197 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
1198 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1201 float clipsta_fac= la->clipsta / -x;
1203 interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1204 interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1206 glBegin(GL_LINE_STRIP);
1207 glVertex3fv(lvec_clip);
1208 glVertex3fv(vvec_clip);
1212 else if ELEM(la->type, LA_HEMI, LA_SUN) {
1214 /* draw the line from the circle along the dist */
1215 glBegin(GL_LINE_STRIP);
1222 if(la->type==LA_HEMI) {
1223 /* draw the hemisphere curves */
1224 short axis, steps, dir;
1225 float outdist, zdist, mul;
1227 outdist = 0.14; mul = 1.4; dir = 1;
1230 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1231 for (axis=0; axis<4; axis++) {
1232 float v[3]= {0.0, 0.0, 0.0};
1235 glBegin(GL_LINE_STRIP);
1237 for (steps=0; steps<6; steps++) {
1238 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
1239 /* make the arcs start at the edge of the energy circle */
1240 if (steps == 0) v[0] = dir*circrad;
1241 else v[0] = v[0] + dir*(steps*outdist);
1242 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
1243 /* make the arcs start at the edge of the energy circle */
1244 if (steps == 0) v[1] = dir*circrad;
1245 else v[1] = v[1] + dir*(steps*outdist);
1248 v[2] = v[2] - steps*zdist;
1252 zdist = zdist * mul;
1256 /* flip the direction */
1260 } else if(la->type==LA_AREA) {
1262 if(la->area_shape==LA_AREA_SQUARE)
1263 fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
1264 else if(la->area_shape==LA_AREA_RECT)
1265 fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
1267 glBegin(GL_LINE_STRIP);
1268 glVertex3f(0.0,0.0,-circrad);
1269 glVertex3f(0.0,0.0,-la->dist);
1273 /* and back to viewspace */
1274 glLoadMatrixf(rv3d->viewmat);
1275 copy_v3_v3(vec, ob->obmat[3]);
1279 if((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1280 drawshadbuflimits(la, ob->obmat);
1283 UI_GetThemeColor4ubv(TH_LAMP, col);
1288 if (vec[2]>0) vec[2] -= circrad;
1289 else vec[2] += circrad;
1291 glBegin(GL_LINE_STRIP);
1303 glDisable(GL_BLEND);
1305 /* restore for drawing extra stuff */
1310 static void draw_limit_line(float sta, float end, unsigned int col)
1313 glVertex3f(0.0, 0.0, -sta);
1314 glVertex3f(0.0, 0.0, -end);
1320 glVertex3f(0.0, 0.0, -sta);
1321 glVertex3f(0.0, 0.0, -end);
1327 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1328 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1329 static void draw_focus_cross(float dist, float size)
1332 glVertex3f(-size, 0.f, -dist);
1333 glVertex3f(size, 0.f, -dist);
1334 glVertex3f(0.f, -size, -dist);
1335 glVertex3f(0.f, size, -dist);
1339 #ifdef VIEW3D_CAMERA_BORDER_HACK
1340 float view3d_camera_border_hack_col[4];
1341 short view3d_camera_border_hack_test= FALSE;
1344 /* flag similar to draw_object() */
1345 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1347 /* a standing up pyramid with (0,0,0) as top */
1349 float vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1352 const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1354 const float scax= 1.0f / len_v3(ob->obmat[0]);
1355 const float scay= 1.0f / len_v3(ob->obmat[1]);
1356 const float scaz= 1.0f / len_v3(ob->obmat[2]);
1358 #ifdef VIEW3D_CAMERA_BORDER_HACK
1359 if(is_view && !(G.f & G_PICKSEL)) {
1360 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1361 view3d_camera_border_hack_test= TRUE;
1367 aspx= (float) scene->r.xsch*scene->r.xasp;
1368 aspy= (float) scene->r.ysch*scene->r.yasp;
1379 glDisable(GL_LIGHTING);
1380 glDisable(GL_CULL_FACE);
1382 if(cam->type==CAM_ORTHO) {
1383 facx= 0.5f * cam->ortho_scale * caspx * scax;
1384 facy= 0.5f * cam->ortho_scale * caspy * scay;
1385 shx= cam->shiftx * cam->ortho_scale * scax;
1386 shy= cam->shifty * cam->ortho_scale * scay;
1387 depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
1389 drawsize= 0.5f * cam->ortho_scale;
1392 /* that way it's always visible - clipsta+0.1 */
1394 drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
1397 /* fixed depth, variable size (avoids exceeding clipping range) */
1398 depth = -(cam->clipsta + 0.1f);
1399 fac = depth / (cam->lens/-16.0f * scaz);
1402 /* fixed size, variable depth (stays a reasonable size in the 3D view) */
1403 depth= drawsize * cam->lens/-16.0f * scaz;
1407 facx= fac * caspx * scax;
1408 facy= fac * caspy * scay;
1409 shx= cam->shiftx*fac*2 * scax;
1410 shy= cam->shifty*fac*2 * scay;
1413 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
1414 vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1415 vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1416 vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1417 vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1420 glBegin(GL_LINE_LOOP);
1421 glVertex3fv(vec[1]);
1422 glVertex3fv(vec[2]);
1423 glVertex3fv(vec[3]);
1424 glVertex3fv(vec[4]);
1430 /* center point to camera frame */
1431 glBegin(GL_LINE_STRIP);
1432 glVertex3fv(vec[2]);
1433 glVertex3fv(vec[0]);
1434 glVertex3fv(vec[1]);
1435 glVertex3fv(vec[4]);
1436 glVertex3fv(vec[0]);
1437 glVertex3fv(vec[3]);
1445 /* draw an outline arrow for inactive cameras and filled
1446 * for active cameras. We actually draw both outline+filled
1447 * for active cameras so the wire can be seen side-on */
1449 if (i==0) glBegin(GL_LINE_LOOP);
1450 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1453 vec[0][0]= shx + ((-0.7f * drawsize) * scax);
1454 vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
1455 glVertex3fv(vec[0]); /* left */
1457 vec[0][0]= shx + ((0.7f * drawsize) * scax);
1458 glVertex3fv(vec[0]); /* right */
1461 vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
1462 glVertex3fv(vec[0]); /* top */
1468 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1472 /* draw in normalized object matrix space */
1473 copy_m4_m4(nobmat, ob->obmat);
1474 normalize_m4(nobmat);
1477 glLoadMatrixf(rv3d->viewmat);
1478 glMultMatrixf(nobmat);
1480 if(cam->flag & CAM_SHOWLIMITS) {
1481 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1482 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1483 draw_focus_cross(dof_camera(ob), cam->drawsize);
1487 if(cam->flag & CAM_SHOWMIST)
1488 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1495 /* flag similar to draw_object() */
1496 static void drawspeaker(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1498 //Speaker *spk = ob->data;
1505 for(j = 0; j < 3; j++)
1507 vec[2] = .25f * j -.125f;
1509 glBegin(GL_LINE_LOOP);
1510 for(i = 0; i < 16; i++)
1512 vec[0] = cos(M_PI * i / 8.0f) * (j == 0 ? .5f : .25f);
1513 vec[1] = sin(M_PI * i / 8.0f) * (j == 0 ? .5f : .25f);
1519 for(j = 0; j < 4; j++)
1521 vec[0] = (((j + 1) % 2) * (j - 1)) * .5f;
1522 vec[1] = ((j % 2) * (j - 2)) * .5f;
1523 glBegin(GL_LINE_STRIP);
1524 for(i = 0; i < 3; i++)
1532 vec[2] = .25f * i -.125f;
1538 glDisable(GL_BLEND);
1541 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1543 BPoint *bp = lt->def;
1544 float *co = dl?dl->verts:NULL;
1547 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1548 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1549 bglBegin(GL_POINTS);
1551 for(w=0; w<lt->pntsw; w++) {
1552 int wxt = (w==0 || w==lt->pntsw-1);
1553 for(v=0; v<lt->pntsv; v++) {
1554 int vxt = (v==0 || v==lt->pntsv-1);
1555 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1556 int uxt = (u==0 || u==lt->pntsu-1);
1557 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1559 if((bp->f1 & SELECT)==sel) {
1560 bglVertex3fv(dl?co:bp->vec);
1572 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1574 Object *obedit= vc->obedit;
1575 Lattice *lt= obedit->data;
1576 BPoint *bp = lt->editlatt->latt->def;
1577 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1578 float *co = dl?dl->verts:NULL;
1579 int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1580 short s[2] = {IS_CLIPPED, 0};
1582 ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1584 for (i=0; i<N; i++, bp++, co+=3) {
1586 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1587 if (s[0] != IS_CLIPPED)
1588 func(userData, bp, s[0], s[1]);
1593 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1595 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1599 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1601 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1607 glVertex3fv(&dl->verts[index*3]);
1609 glVertex3fv(lt->def[index].vec);
1613 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1614 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1616 Lattice *lt= ob->data;
1619 int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1621 /* now we default make displist, this will modifiers work for non animated case */
1622 if(ob->disp.first==NULL)
1623 lattice_calc_modifiers(scene, ob);
1624 dl= find_displist(&ob->disp, DL_VERTS);
1627 lt= lt->editlatt->latt;
1631 if(ob->defbase.first && lt->dvert) {
1632 use_wcol= ob->actdef;
1633 glShadeModel(GL_SMOOTH);
1638 for(w=0; w<lt->pntsw; w++) {
1639 int wxt = (w==0 || w==lt->pntsw-1);
1640 for(v=0; v<lt->pntsv; v++) {
1641 int vxt = (v==0 || v==lt->pntsv-1);
1642 for(u=0; u<lt->pntsu; u++) {
1643 int uxt = (u==0 || u==lt->pntsu-1);
1645 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1646 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1647 drawlattice__point(lt, dl, u, v, w, use_wcol);
1649 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1650 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1651 drawlattice__point(lt, dl, u, v, w, use_wcol);
1653 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1654 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1655 drawlattice__point(lt, dl, u, v, w, use_wcol);
1662 /* restoration for weight colors */
1664 glShadeModel(GL_FLAT);
1667 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1669 lattice_draw_verts(lt, dl, 0);
1670 lattice_draw_verts(lt, dl, 1);
1672 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1676 /* ***************** ******************** */
1678 /* Note! - foreach funcs should be called while drawing or directly after
1679 * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1680 * but would not give correct results with dupli's for eg. which dont
1681 * use the object matrix in the useual way */
1682 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1684 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1685 EditVert *eve = EM_get_vert_for_index(index);
1688 short s[2]= {IS_CLIPPED, 0};
1690 if (data->clipVerts) {
1691 view3d_project_short_clip(data->vc.ar, co, s, 1);
1693 view3d_project_short_noclip(data->vc.ar, co, s);
1696 if (s[0]!=IS_CLIPPED)
1697 data->func(data->userData, eve, s[0], s[1], index);
1701 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1703 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1704 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1708 data.userData = userData;
1709 data.clipVerts = clipVerts;
1712 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1714 EM_init_index_arrays(vc->em, 1, 0, 0);
1715 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1716 EM_free_index_arrays();
1721 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1723 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;
1724 EditEdge *eed = EM_get_edge_for_index(index);
1728 if (data->clipVerts==1) {
1729 view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1730 view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1732 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1733 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1735 if (data->clipVerts==2) {
1736 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1737 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1742 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1746 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)
1748 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1749 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1753 data.userData = userData;
1754 data.clipVerts = clipVerts;
1757 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1759 EM_init_index_arrays(vc->em, 0, 1, 0);
1760 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1761 EM_free_index_arrays();
1766 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1768 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1769 EditFace *efa = EM_get_face_for_index(index);
1772 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1773 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1775 data->func(data->userData, efa, s[0], s[1], index);
1779 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1781 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1782 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1786 data.userData = userData;
1789 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1791 EM_init_index_arrays(vc->em, 0, 0, 1);
1792 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1793 EM_free_index_arrays();
1798 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1800 Curve *cu= vc->obedit->data;
1801 short s[2] = {IS_CLIPPED, 0};
1804 ListBase *nurbs= ED_curve_editnurbs(cu);
1806 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1808 for (nu= nurbs->first; nu; nu=nu->next) {
1809 if(nu->type == CU_BEZIER) {
1810 for (i=0; i<nu->pntsu; i++) {
1811 BezTriple *bezt = &nu->bezt[i];
1815 if(cu->drawflag & CU_HIDE_HANDLES) {
1816 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1817 if (s[0] != IS_CLIPPED)
1818 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1820 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1821 if (s[0] != IS_CLIPPED)
1822 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1823 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1824 if (s[0] != IS_CLIPPED)
1825 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1826 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1827 if (s[0] != IS_CLIPPED)
1828 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1834 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1835 BPoint *bp = &nu->bp[i];
1838 view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1839 if (s[0] != IS_CLIPPED)
1840 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1847 /* ************** DRAW MESH ****************** */
1849 /* First section is all the "simple" draw routines,
1850 * ones that just pass some sort of primitive to GL,
1851 * with perhaps various options to control lighting,
1854 * These routines should not have user interface related
1858 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1860 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1861 EditFace *efa = EM_get_face_for_index(index);
1863 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1865 glVertex3f( cent[0] + no[0]*ts->normalsize,
1866 cent[1] + no[1]*ts->normalsize,
1867 cent[2] + no[2]*ts->normalsize);
1870 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1873 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1877 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1879 EditFace *efa = EM_get_face_for_index(index);
1880 int sel = *((int*) userData);
1882 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1886 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1888 bglBegin(GL_POINTS);
1889 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1893 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1895 Scene *scene= (Scene *)userData;
1896 ToolSettings *ts= scene->toolsettings;
1897 EditVert *eve = EM_get_vert_for_index(index);
1903 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1904 co[1] + no_f[1]*ts->normalsize,
1905 co[2] + no_f[2]*ts->normalsize);
1907 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1908 co[1] + no_s[1]*ts->normalsize/32767.0f,
1909 co[2] + no_s[2]*ts->normalsize/32767.0f);
1913 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1916 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1920 /* Draw verts with color set based on selection */
1921 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1923 struct { int sel; EditVert *eve_act; } * data = userData;
1924 EditVert *eve = EM_get_vert_for_index(index);
1926 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1927 /* draw active larger - need to stop/start point drawing for this :/ */
1928 if (eve==data->eve_act) {
1929 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1930 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1935 bglBegin(GL_POINTS);
1939 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1941 bglBegin(GL_POINTS);
1948 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1950 struct { int sel; EditVert *eve_act; } data;
1952 data.eve_act = eve_act;
1954 bglBegin(GL_POINTS);
1955 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1959 /* Draw edges with color set based on selection */
1960 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1962 EditEdge *eed = EM_get_edge_for_index(index);
1963 //unsigned char **cols = userData, *col;
1964 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1968 if (eed==data->eed_act) {
1969 glColor4ubv(data->actCol);
1971 if (eed->f&SELECT) {
1974 col = data->baseCol;
1976 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1977 if (col[3]==0) return 0;
1986 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1988 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1990 data.baseCol = baseCol;
1991 data.selCol = selCol;
1992 data.actCol = actCol;
1993 data.eed_act = eed_act;
1994 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1998 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
2000 return EM_get_edge_for_index(index)->h==0;
2002 static void draw_dm_edges(DerivedMesh *dm)
2004 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2007 /* Draw edges with color interpolated based on selection */
2008 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2010 return EM_get_edge_for_index(index)->h==0;
2012 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2014 EditEdge *eed = EM_get_edge_for_index(index);
2015 unsigned char **cols = userData;
2016 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2017 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2019 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
2020 col0[1] + (col1[1]-col0[1])*t,
2021 col0[2] + (col1[2]-col0[2])*t,
2022 col0[3] + (col1[3]-col0[3])*t);
2025 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2027 unsigned char *cols[2];
2030 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2033 /* Draw only seam edges */
2034 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2036 EditEdge *eed = EM_get_edge_for_index(index);
2038 return (eed->h==0 && eed->seam);
2040 static void draw_dm_edges_seams(DerivedMesh *dm)
2042 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2045 /* Draw only sharp edges */
2046 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2048 EditEdge *eed = EM_get_edge_for_index(index);
2050 return (eed->h==0 && eed->sharp);
2052 static void draw_dm_edges_sharp(DerivedMesh *dm)
2054 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2058 /* Draw faces with color set based on selection
2059 * return 2 for the active face so it renders with stipple enabled */
2060 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2062 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2063 EditFace *efa = EM_get_face_for_index(index);
2067 if (efa == data->efa_act) {
2068 glColor4ubv(data->cols[2]);
2069 return 2; /* stipple */
2071 col = data->cols[(efa->f&SELECT)?1:0];
2072 if (col[3]==0) return 0;
2080 /* also draws the active face */
2081 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
2083 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2084 data.cols[0] = baseCol;
2085 data.cols[1] = selCol;
2086 data.cols[2] = actCol;
2087 data.efa_act = efa_act;
2089 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
2092 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2094 EditEdge *eed = EM_get_edge_for_index(index);
2096 if (eed->h==0 && eed->crease != 0.0f) {
2097 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2103 static void draw_dm_creases(DerivedMesh *dm)
2106 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2110 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2112 EditEdge *eed = EM_get_edge_for_index(index);
2114 if (eed->h==0 && eed->bweight != 0.0f) {
2115 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2121 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2123 EditVert *eve = EM_get_vert_for_index(index);
2125 if (eve->h==0 && eve->bweight != 0.0f) {
2126 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2130 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2132 ToolSettings *ts= scene->toolsettings;
2134 if (ts->selectmode & SCE_SELECT_VERTEX) {
2135 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2136 bglBegin(GL_POINTS);
2137 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2142 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2147 /* Second section of routines: Combine first sets to form fancy
2148 * drawing routines (for example rendering twice to get overlays).
2150 * Also includes routines that are basic drawing but are too
2151 * specialized to be split out (like drawing creases or measurements).
2154 /* EditMesh drawing routines*/
2156 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2158 ToolSettings *ts= scene->toolsettings;
2161 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2163 for (sel=0; sel<2; sel++) {
2164 unsigned char col[4], fcol[4];
2167 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2168 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2170 for (pass=0; pass<2; pass++) {
2171 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2172 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2175 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2176 glDisable(GL_DEPTH_TEST);
2183 size = (size > 2.1f ? size/2.0f:size);
2184 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2185 col[3] = fcol[3] = 100;
2187 col[3] = fcol[3] = 255;
2190 if(ts->selectmode & SCE_SELECT_VERTEX) {
2193 draw_dm_verts(cageDM, sel, eve_act);
2196 if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2199 draw_dm_face_centers(cageDM, sel);
2203 glDisable(GL_BLEND);
2204 glEnable(GL_DEPTH_TEST);
2209 if(v3d->zbuf) glDepthMask(1);
2213 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2215 ToolSettings *ts= scene->toolsettings;
2217 unsigned char wireCol[4], selCol[4], actCol[4];
2219 /* since this function does transparant... */
2220 UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2221 UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2222 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2224 /* when sel only is used, dont render wire, only selected, this is used for
2225 * textured draw mode when the 'edges' option is disabled */
2229 for (pass=0; pass<2; pass++) {
2230 /* show wires in transparant when no zbuf clipping for select */
2232 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2234 glDisable(GL_DEPTH_TEST);
2236 if (!sel_only) wireCol[3] = 85;
2242 if (!sel_only) wireCol[3] = 255;
2245 if(ts->selectmode == SCE_SELECT_FACE) {
2246 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2248 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2249 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2250 glShadeModel(GL_SMOOTH);
2251 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2252 glShadeModel(GL_FLAT);
2254 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2259 glColor4ubv(wireCol);
2260 draw_dm_edges(cageDM);
2265 glDisable(GL_BLEND);
2266 glEnable(GL_DEPTH_TEST);
2271 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2276 float v1[3], v2[3], v3[3], v4[3], vmid[3];
2278 char val[32]; /* Stores the measurement display text here */
2279 const char *conv_float; /* Use a float conversion matching the grid size */
2280 unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2281 float area; /* area of the face */
2282 float grid= unit->system ? unit->scale_length : v3d->grid;
2283 const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2284 const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2285 const int do_moving= G.moving;
2287 /* make the precision of the pronted value proportionate to the gridsize */
2289 if (grid < 0.01f) conv_float= "%.6g";
2290 else if (grid < 0.1f) conv_float= "%.5g";
2291 else if (grid < 1.0f) conv_float= "%.4g";
2292 else if (grid < 10.0f) conv_float= "%.3g";
2293 else conv_float= "%.2g";
2295 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2296 glDisable(GL_DEPTH_TEST);
2298 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2300 if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2301 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2303 for(eed= em->edges.first; eed; eed= eed->next) {
2304 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2305 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2306 copy_v3_v3(v1, eed->v1->co);
2307 copy_v3_v3(v2, eed->v2->co);
2309 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2312 mul_mat3_m4_v3(ob->obmat, v1);
2313 mul_mat3_m4_v3(ob->obmat, v2);
2316 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2318 sprintf(val, conv_float, len_v3v3(v1, v2));
2320 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2325 if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2326 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2327 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2329 for(efa= em->faces.first; efa; efa= efa->next) {
2330 if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2331 copy_v3_v3(v1, efa->v1->co);
2332 copy_v3_v3(v2, efa->v2->co);
2333 copy_v3_v3(v3, efa->v3->co);
2335 copy_v3_v3(v4, efa->v4->co);
2338 mul_mat3_m4_v3(ob->obmat, v1);
2339 mul_mat3_m4_v3(ob->obmat, v2);
2340 mul_mat3_m4_v3(ob->obmat, v3);
2341 if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2345 area= area_quad_v3(v1, v2, v3, v4);
2347 area = area_tri_v3(v1, v2, v3);
2350 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2352 sprintf(val, conv_float, area);
2354 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2359 if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2360 EditEdge *e1, *e2, *e3, *e4;
2361 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2362 for(efa= em->faces.first; efa; efa= efa->next) {
2363 copy_v3_v3(v1, efa->v1->co);
2364 copy_v3_v3(v2, efa->v2->co);
2365 copy_v3_v3(v3, efa->v3->co);
2367 copy_v3_v3(v4, efa->v4->co);
2373 mul_mat3_m4_v3(ob->obmat, v1);
2374 mul_mat3_m4_v3(ob->obmat, v2);
2375 mul_mat3_m4_v3(ob->obmat, v3);
2376 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2382 if(efa->e4) e4= efa->e4; else e4= e3;
2384 /* Calculate the angles */
2386 if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2388 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2389 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2390 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2392 if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2394 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2395 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2396 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2398 if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2401 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2403 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2404 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2405 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2409 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2410 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2411 interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2412 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2418 /* useful for debugging index vs shape key index */
2423 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2424 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2425 sprintf(val, "%d:%d", j, eve->keyindex);
2426 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2432 glEnable(GL_DEPTH_TEST);
2433 bglPolygonOffset(rv3d->dist, 0.0f);
2437 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2439 EditFace *efa = EM_get_face_for_index(index);
2442 GPU_enable_material(efa->mat_nr+1, NULL);
2449 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2451 EditFace *efa = EM_get_face_for_index(index);
2456 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2458 Mesh *me = ob->data;
2459 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2460 EditEdge *eed_act = NULL;
2461 EditVert *eve_act = NULL;
2463 if (em->selected.last) {
2464 EditSelection *ese = em->selected.last;
2465 /* face is handeled above */
2466 /*if (ese->type == EDITFACE ) {
2467 efa_act = (EditFace *)ese->data;
2468 } else */ if ( ese->type == EDITEDGE ) {
2469 eed_act = (EditEdge *)ese->data;
2470 } else if ( ese->type == EDITVERT ) {
2471 eve_act = (EditVert *)ese->data;
2475 EM_init_index_arrays(em, 1, 1, 1);
2478 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2479 if(draw_glsl_material(scene, ob, v3d, dt)) {
2480 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2482 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2483 draw_em_fancy__setGLSLFaceOpts, NULL);
2484 GPU_disable_material();
2486 glFrontFace(GL_CCW);
2489 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2493 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2494 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2496 glEnable(GL_LIGHTING);
2497 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2499 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material);
2501 glFrontFace(GL_CCW);
2502 glDisable(GL_LIGHTING);
2505 // Setup for drawing wire over, disable zbuffer
2506 // write to show selected edge wires better
2507 UI_ThemeColor(TH_WIRE);
2509 bglPolygonOffset(rv3d->dist, 1.0);
2513 if (cageDM!=finalDM) {
2514 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2515 finalDM->drawEdges(finalDM, 1, 0);
2519 if(me->drawflag & ME_DRAWFACES) { /* transp faces */
2520 unsigned char col1[4], col2[4], col3[4];
2522 UI_GetThemeColor4ubv(TH_FACE, col1);
2523 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2524 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2527 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2529 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2530 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2533 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2535 glDisable(GL_BLEND);
2536 glDepthMask(1); // restore write in zbuffer
2537 } else if (efa_act) {
2538 /* even if draw faces is off it would be nice to draw the stipple face
2539 * Make all other faces zero alpha except for the active
2541 unsigned char col1[4], col2[4], col3[4];
2542 col1[3] = col2[3] = 0; /* dont draw */
2543 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2546 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2548 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2550 glDisable(GL_BLEND);
2551 glDepthMask(1); // restore write in zbuffer
2555 /* here starts all fancy draw-extra over */
2556 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2557 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2559 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2560 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2563 if(me->drawflag & ME_DRAWSEAMS) {
2564 UI_ThemeColor(TH_EDGE_SEAM);
2567 draw_dm_edges_seams(cageDM);
2573 if(me->drawflag & ME_DRAWSHARP) {
2574 UI_ThemeColor(TH_EDGE_SHARP);
2577 draw_dm_edges_sharp(cageDM);
2583 if(me->drawflag & ME_DRAWCREASES) {
2584 draw_dm_creases(cageDM);
2586 if(me->drawflag & ME_DRAWBWEIGHTS) {
2587 draw_dm_bweights(scene, cageDM);
2590 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2593 // XXX retopo_matrix_update(v3d);
2595 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2597 if(me->drawflag & ME_DRAWNORMALS) {
2598 UI_ThemeColor(TH_NORMAL);
2599 draw_dm_face_normals(scene, cageDM);
2601 if(me->drawflag & ME_DRAW_VNORMALS) {
2602 UI_ThemeColor(TH_VNORMAL);
2603 draw_dm_vert_normals(scene, cageDM);
2606 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2607 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2612 bglPolygonOffset(rv3d->dist, 0.0);
2613 GPU_disable_material();
2616 EM_free_index_arrays();
2619 /* Mesh drawing routines */
2621 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2624 if(v3d->transp==0) { // not when we draw the transparent pass
2625 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2628 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2629 drawFacesSolid() doesn't draw the transparent faces */
2630 if(ob->dtx & OB_DRAWTRANSP) {
2631 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2632 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2633 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2634 GPU_disable_material();
2637 dm->drawEdges(dm, 0, 1);
2645 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2651 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2653 Object *ob= base->object;
2654 Mesh *me = ob->data;
2655 Material *ma= give_current_material(ob, 1);
2656 const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2657 const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2659 int /* totvert,*/ totedge, totface;
2660 DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2665 if (ob->dtx&OB_DRAWWIRE) {
2666 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2669 /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2670 totedge = dm->getNumEdges(dm);
2671 totface = dm->getNumFaces(dm);
2673 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2675 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2677 // Unwanted combination.
2678 if (is_paint_sel) draw_wire = 0;
2680 if(dt==OB_BOUNDBOX) {
2681 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2682 draw_bounding_volume(scene, ob);
2684 else if(hasHaloMat || (totface==0 && totedge==0)) {
2689 else if(dt==OB_WIRE || totface==0) {
2690 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2692 else if( (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2693 CHECK_OB_DRAWTEXTURE(v3d, dt))
2695 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2696 draw_mesh_object_outline(v3d, ob, dm);
2699 if(draw_glsl_material(scene, ob, v3d, dt)) {
2700 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2702 dm->drawFacesGLSL(dm, GPU_enable_material);
2703 // if(get_ob_property(ob, "Text"))
2704 // XXX draw_mesh_text(ob, 1);
2705 GPU_disable_material();
2707 glFrontFace(GL_CCW);
2710 draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2714 if(base->flag & SELECT)
2715 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2717 UI_ThemeColor(TH_WIRE);
2719 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2720 dm->drawLooseEdges(dm);
2723 else if(dt==OB_SOLID) {
2724 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2725 /* weight paint in solid mode, special case. focus on making the weights clear
2726 * rather than the shading, this is also forced in wire view */
2727 GPU_enable_material(0, NULL);
2728 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2730 bglPolygonOffset(rv3d->dist, 1.0);
2731 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2734 glColor4ub(255, 255, 255, 96);
2735 glEnable(GL_LINE_STIPPLE);
2736 glLineStipple(1, 0xAAAA);
2738 dm->drawEdges(dm, 1, 1);
2740 bglPolygonOffset(rv3d->dist, 0.0);
2742 glDisable(GL_LINE_STIPPLE);
2744 GPU_disable_material();
2746 /* since we already draw wire as wp guide, dont draw over the top */
2752 if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2753 draw_mesh_object_outline(v3d, ob, dm);
2755 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2757 glEnable(GL_LIGHTING);
2758 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2760 if(ob->sculpt && (p=paint_get_active(scene))) {
2762 float (*fpl)[4] = NULL;
2763 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2765 if(ob->sculpt->partial_redraw) {
2766 if(ar->do_draw & RGN_DRAW_PARTIAL) {
2767 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2769 ob->sculpt->partial_redraw = 0;
2773 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2776 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2778 GPU_disable_material();
2780 glFrontFace(GL_CCW);
2781 glDisable(GL_LIGHTING);
2783 if(base->flag & SELECT) {
2784 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2786 UI_ThemeColor(TH_WIRE);
2788 if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2789 dm->drawLooseEdges(dm);
2792 else if(dt==OB_SHADED) {
2794 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2795 /* enforce default material settings */
2796 GPU_enable_material(0, NULL);
2798 /* but set default spec */
2799 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2800 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2801 glColor3ub(120, 120, 120);
2802 glDisable(GL_COLOR_MATERIAL);
2804 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2805 glEnable(GL_LIGHTING);
2806 glEnable(GL_COLOR_MATERIAL);
2808 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2809 glDisable(GL_COLOR_MATERIAL);
2810 glDisable(GL_LIGHTING);
2812 GPU_disable_material();
2814 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2816 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
2818 glColor3f(1.0f, 1.0f, 1.0f);
2819 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
2825 /* set default draw color back for wire or for draw-extra later on */
2827 if(base->flag & SELECT) {
2828 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2829 UI_ThemeColor(TH_GROUP_ACTIVE);
2830 else if(ob->flag & OB_FROMGROUP)
2831 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2832 else if(flag!=DRAW_CONSTCOLOR)
2833 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2835 glColor3ub(80,80,80);
2837 if (ob->flag & OB_FROMGROUP)
2838 UI_ThemeColor(TH_GROUP);
2840 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2841 glColor3ub(80,80,80);
2843 UI_ThemeColor(TH_WIRE);
2849 /* When using wireframe object traw in particle edit mode
2850 * the mesh gets in the way of seeing the particles, fade the wire color
2851 * with the background. */
2852 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2853 float col_wire[4], col_bg[4], col[3];
2855 UI_GetThemeColor3fv(TH_BACK, col_bg);
2856 glGetFloatv(GL_CURRENT_COLOR, col_wire);
2857 interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2861 /* If drawing wire and drawtype is not OB_WIRE then we are
2862 * overlaying the wires.
2864 * UPDATE bug #10290 - With this wire-only objects can draw
2865 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2867 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2868 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2870 if (dt!=OB_WIRE && draw_wire==2) {
2871 bglPolygonOffset(rv3d->dist, 1.0);
2872 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2875 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2876 dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2878 if (dt!=OB_WIRE && draw_wire==2) {
2880 bglPolygonOffset(rv3d->dist, 0.0);
2887 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2888 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2890 Object *ob= base->object;
2891 Object *obedit= scene->obedit;
2893 EditMesh *em= me->edit_mesh;
2894 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2896 if(obedit && ob!=obedit && ob->data==obedit->data) {
2897 if(ob_get_key(ob) || ob_get_key(obedit));
2898 else if(ob->modifiers.first || obedit->modifiers.first);
2902 if(ob==obedit || drawlinked) {
2903 DerivedMesh *finalDM, *cageDM;
2906 finalDM = cageDM = editmesh_get_derived_base(ob, em);
2908 cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2909 scene->customdata_mask);
2912 // no transp in editmode, the fancy draw over goes bad then
2913 glsl = draw_glsl_material(scene, ob, v3d, dt);
2914 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2917 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2919 GPU_end_object_materials();
2921 if (obedit!=ob && finalDM)
2922 finalDM->release(finalDM);
2925 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2926 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2927 glsl = draw_glsl_material(scene, ob, v3d, dt);
2928 check_alpha = check_material_alpha(base, me, glsl);
2930 if(dt==OB_SOLID || glsl) {
2931 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2932 (check_alpha)? &do_alpha_pass: NULL);
2935 draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2937 GPU_end_object_materials();
2939 if(me->totvert==0) retval= 1;
2943 /* GPU_begin_object_materials checked if this is needed */
2945 if(ob->dtx & OB_DRAWXRAY) {
2946 add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2949 add_view3d_after(&v3d->afterdraw_transp, base, flag);
2952 else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2953 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2954 if(v3d->xray == 0 && v3d->transp == 0) {
2955 add_view3d_after(&v3d->afterdraw_xray, base, flag);
2962 /* ************** DRAW DISPLIST ****************** */
2964 static int draw_index_wire= 1;
2965 static int index3_nors_incr= 1;
2967 /* returns 1 when nothing was drawn */
2968 static int drawDispListwire(ListBase *dlbase)
2974 if(dlbase==NULL) return 1;
2976 glEnableClientState(GL_VERTEX_ARRAY);
2977 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2979 for(dl= dlbase->first; dl; dl= dl->next) {
2980 if(dl->parts==0 || dl->nr==0)
2988 glVertexPointer(3, GL_FLOAT, 0, data);
2990 for(parts=0; parts<dl->parts; parts++)
2991 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2996 glVertexPointer(3, GL_FLOAT, 0, data);
2998 for(parts=0; parts<dl->parts; parts++)
2999 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3004 glVertexPointer(3, GL_FLOAT, 0, data);
3006 for(parts=0; parts<dl->parts; parts++) {
3007 if(dl->flag & DL_CYCL_U)
3008 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3010 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3013 for(nr=0; nr<dl->nr; nr++) {
3016 data= ( dl->verts )+3*nr;
3019 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
3020 else glBegin(GL_LINE_STRIP);
3028 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
3029 // glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
3030 // if(dl->flag & DL_CYCL_V)
3031 // glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
3033 // glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
3038 if(draw_index_wire) {
3039 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3040 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
3045 if(draw_index_wire) {
3046 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3047 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
3053 glDisableClientState(GL_VERTEX_ARRAY);
3054 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3059 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
3062 GPUVertexAttribs gattribs;
3063 float *data, curcol[4];
3066 if(lb==NULL) return;
3068 /* for drawing wire */
3069 glGetFloatv(GL_CURRENT_COLOR, curcol);
3071 glEnable(GL_LIGHTING);
3072 glEnableClientState(GL_VERTEX_ARRAY);
3074 if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
3075 else glFrontFace(GL_CCW);
3077 if(ob->type==OB_MBALL) { // mball always smooth shaded
3078 glShadeModel(GL_SMOOTH);