2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation, full recode and added functions
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/space_view3d/drawobject.c
30 #include "MEM_guardedalloc.h"
32 #include "DNA_camera_types.h"
33 #include "DNA_curve_types.h"
34 #include "DNA_constraint_types.h" /* for drawing constraint */
35 #include "DNA_lamp_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meta_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_smoke_types.h"
42 #include "DNA_world_types.h"
43 #include "DNA_object_types.h"
45 #include "BLI_blenlib.h"
48 #include "BKE_anim.h" /* for the where_on_path function */
49 #include "BKE_armature.h"
50 #include "BKE_camera.h"
51 #include "BKE_constraint.h" /* for the get_constraint_target function */
52 #include "BKE_curve.h"
53 #include "BKE_DerivedMesh.h"
54 #include "BKE_deform.h"
55 #include "BKE_displist.h"
57 #include "BKE_global.h"
58 #include "BKE_image.h"
60 #include "BKE_lattice.h"
62 #include "BKE_material.h"
63 #include "BKE_mball.h"
64 #include "BKE_modifier.h"
65 #include "BKE_object.h"
66 #include "BKE_paint.h"
67 #include "BKE_particle.h"
68 #include "BKE_pointcache.h"
69 #include "BKE_scene.h"
71 #include "BKE_tracking.h"
73 #include "BKE_tessmesh.h"
75 #include "IMB_imbuf.h"
76 #include "IMB_imbuf_types.h"
79 #include "BIF_glutil.h"
82 #include "GPU_extensions.h"
85 #include "ED_particle.h"
86 #include "ED_screen.h"
87 #include "ED_sculpt.h"
90 #include "UI_resources.h"
95 #include "view3d_intern.h" /* bad level include */
97 typedef enum eWireDrawMode {
100 OBDRAW_WIRE_ON_DEPTH = 2
103 typedef struct drawDMVerts_userData {
104 BMEditMesh *em; /* BMESH BRANCH ONLY */
109 /* cached theme values */
110 unsigned char th_editmesh_active[4];
111 unsigned char th_vertex_select[4];
112 unsigned char th_vertex[4];
113 unsigned char th_skin_root[4];
114 float th_vertex_size;
116 /* for skin node drawing */
119 } drawDMVerts_userData;
121 typedef struct drawDMEdgesSel_userData {
122 BMEditMesh *em; /* BMESH BRANCH ONLY */
124 unsigned char *baseCol, *selCol, *actCol;
126 } drawDMEdgesSel_userData;
128 typedef struct drawDMFacesSel_userData {
129 unsigned char *cols[4];
131 DerivedMesh *dm; /* BMESH BRANCH ONLY */
132 BMEditMesh *em; /* BMESH BRANCH ONLY */
135 int *orig_index_mf_to_mpoly;
136 int *orig_index_mp_to_orig;
137 } drawDMFacesSel_userData;
139 typedef struct drawDMNormal_userData {
145 } drawDMNormal_userData;
147 typedef struct bbsObmodeMeshVerts_userData {
150 } bbsObmodeMeshVerts_userData;
152 static void draw_bounding_volume(Scene *scene, Object *ob, char type);
154 static void drawcube_size(float size);
155 static void drawcircle_size(float size);
156 static void draw_empty_sphere(float size);
157 static void draw_empty_cone(float size);
159 static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
161 float col_wire[3], col_bg[3], col[3];
163 rgb_uchar_to_float(col_wire, ob_wire_col);
165 UI_GetThemeColor3fv(theme_id, col_bg);
166 interp_v3_v3v3(col, col_bg, col_wire, fac);
170 /* this condition has been made more complex since editmode can draw textures */
171 static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype)
173 /* texture and material draw modes */
174 if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID)
178 if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene))
184 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
186 if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
189 if (G.f & G_BACKBUFSEL)
192 if ((vd->flag & V3D_ZBUF_SELECT) == 0)
195 /* if its drawing textures with zbuf sel, then don't draw dots */
196 if (dt == OB_TEXTURE && vd->drawtype == OB_TEXTURE)
199 if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
205 /* ************************ */
207 /* check for glsl drawing */
209 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt)
211 if (!GPU_glsl_support())
215 if (!check_object_draw_texture(scene, v3d, dt))
217 if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
219 if (BKE_scene_use_new_shading_nodes(scene))
222 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
225 static int check_alpha_pass(Base *base)
227 if (base->flag & OB_FROMDUPLI)
233 return (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 Optimized Drawing Speed ------------------ */
258 /* 32 values of sin function (still same result!) */
259 #define CIRCLE_RESOL 32
261 static const float sinval[CIRCLE_RESOL] = {
296 /* 32 values of cos function (still same result!) */
297 static const float cosval[CIRCLE_RESOL] = {
332 static void draw_xyz_wire(const float c[3], float size, int axis)
334 float v1[3] = {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
335 float dim = size * 0.1f;
336 float dx[3], dy[3], dz[3];
338 dx[0] = dim; dx[1] = 0.f; dx[2] = 0.f;
339 dy[0] = 0.f; dy[1] = dim; dy[2] = 0.f;
340 dz[0] = 0.f; dz[1] = 0.f; dz[2] = dim;
346 /* bottom left to top right */
347 sub_v3_v3v3(v1, c, dx);
349 add_v3_v3v3(v2, c, dx);
355 /* top left to bottom right */
368 /* bottom left to top right */
369 mul_v3_fl(dx, 0.75f);
370 sub_v3_v3v3(v1, c, dx);
372 add_v3_v3v3(v2, c, dx);
378 /* top left to center */
389 glBegin(GL_LINE_STRIP);
391 /* start at top left */
392 sub_v3_v3v3(v1, c, dx);
393 add_v3_v3v3(v1, c, dz);
418 void drawaxes(float size, char drawtype)
421 float v1[3] = {0.0, 0.0, 0.0};
422 float v2[3] = {0.0, 0.0, 0.0};
423 float v3[3] = {0.0, 0.0, 0.0};
428 for (axis = 0; axis < 3; axis++) {
436 /* reset v1 & v2 to zero */
437 v1[axis] = v2[axis] = 0.0f;
442 case OB_SINGLE_ARROW:
445 /* in positive z direction only */
452 glBegin(GL_TRIANGLES);
454 v2[0] = size * 0.035f; v2[1] = size * 0.035f;
455 v3[0] = size * -0.035f; v3[1] = size * 0.035f;
456 v2[2] = v3[2] = size * 0.75f;
458 for (axis = 0; axis < 4; axis++) {
481 drawcircle_size(size);
484 case OB_EMPTY_SPHERE:
485 draw_empty_sphere(size);
489 draw_empty_cone(size);
495 for (axis = 0; axis < 3; axis++) {
496 const int arrow_axis = (axis == 0) ? 1 : 0;
504 v1[axis] = size * 0.85f;
505 v1[arrow_axis] = -size * 0.08f;
509 v1[arrow_axis] = size * 0.08f;
515 v2[axis] += size * 0.125f;
517 draw_xyz_wire(v2, size, axis);
520 /* reset v1 & v2 to zero */
521 v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
529 /* Function to draw an Image on a empty Object */
530 static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
532 Image *ima = (Image *)ob->data;
533 ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
535 float scale, ofs_x, ofs_y, sca_x, sca_y;
538 if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
539 IMB_rect_from_float(ibuf);
542 /* Get the buffer dimensions so we can fallback to fake ones */
543 if (ibuf && ibuf->rect) {
552 /* Get the image aspect even if the buffer is invalid */
554 if (ima->aspx > ima->aspy) {
556 sca_y = ima->aspy / ima->aspx;
558 else if (ima->aspx < ima->aspy) {
559 sca_x = ima->aspx / ima->aspy;
572 /* Calculate the scale center based on objects origin */
573 ofs_x = ob->ima_ofs[0] * ima_x;
574 ofs_y = ob->ima_ofs[1] * ima_y;
576 glMatrixMode(GL_MODELVIEW);
579 /* Make sure we are drawing at the origin */
580 glTranslatef(0.0f, 0.0f, 0.0f);
582 /* Calculate Image scale */
583 scale = (ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y));
585 /* Set the object scale */
586 glScalef(scale * sca_x, scale * sca_y, 1.0f);
588 if (ibuf && ibuf->rect) {
589 /* Setup GL params */
591 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
593 /* Use the object color and alpha */
596 /* Draw the Image on the screen */
597 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
598 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
603 if ((dflag & DRAW_CONSTCOLOR) == 0) {
604 glColor3ubv(ob_wire_col);
606 /* Calculate the outline vertex positions */
607 glBegin(GL_LINE_LOOP);
608 glVertex2f(ofs_x, ofs_y);
609 glVertex2f(ofs_x + ima_x, ofs_y);
610 glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
611 glVertex2f(ofs_x, ofs_y + ima_y);
615 /* Reset GL settings */
616 glMatrixMode(GL_MODELVIEW);
620 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4])
623 float *viter = (float *)verts;
626 mul_v3_v3fl(vx, tmat[0], rad);
627 mul_v3_v3fl(vy, tmat[1], rad);
629 for (a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
630 viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
631 viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
632 viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
636 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
638 float verts[CIRCLE_RESOL][3];
640 circball_array_fill(verts, cent, rad, tmat);
642 glEnableClientState(GL_VERTEX_ARRAY);
643 glVertexPointer(3, GL_FLOAT, 0, verts);
644 glDrawArrays(mode, 0, CIRCLE_RESOL);
645 glDisableClientState(GL_VERTEX_ARRAY);
648 /* circle for object centers, special_color is for library or ob users */
649 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
651 const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
652 float verts[CIRCLE_RESOL][3];
654 /* using gldepthfunc guarantees that it does write z values,
655 * but not checks for it, so centers remain visible independent order of drawing */
656 if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
660 if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
662 else glColor4ub(0x55, 0xCC, 0xCC, 155);
665 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
666 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
667 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
670 circball_array_fill(verts, co, size, rv3d->viewinv);
672 /* enable vertex array */
673 glEnableClientState(GL_VERTEX_ARRAY);
674 glVertexPointer(3, GL_FLOAT, 0, verts);
676 /* 1. draw filled, blended polygon */
677 glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
679 /* 2. draw outline */
680 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
681 glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
684 glDisableClientState(GL_VERTEX_ARRAY);
688 if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
691 /* *********** text drawing for object/particles/armature ************* */
692 static ListBase CachedText[3];
693 static int CachedTextLevel = 0;
695 typedef struct ViewCachedString {
696 struct ViewCachedString *next, *prev;
706 /* str is allocated past the end */
709 void view3d_cached_text_draw_begin(void)
711 ListBase *strings = &CachedText[CachedTextLevel];
712 strings->first = strings->last = NULL;
716 void view3d_cached_text_draw_add(const float co[3],
718 short xoffs, short flag,
719 const unsigned char col[4])
721 int alloc_len = strlen(str) + 1;
722 ListBase *strings = &CachedText[CachedTextLevel - 1];
723 /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
724 ViewCachedString *vos = MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
726 BLI_addtail(strings, vos);
727 copy_v3_v3(vos->vec, co);
728 copy_v4_v4_char((char *)vos->col.ub, (const char *)col);
731 vos->str_len = alloc_len - 1;
733 /* allocate past the end */
734 memcpy(++vos, str, alloc_len);
737 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
739 RegionView3D *rv3d = ar->regiondata;
740 ListBase *strings = &CachedText[CachedTextLevel - 1];
741 ViewCachedString *vos;
744 /* project first and test */
745 for (vos = strings->first; vos; vos = vos->next) {
746 if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
747 mul_m4_v3(mat, vos->vec);
749 if (ED_view3d_project_short_ex(ar,
750 (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
751 (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0,
753 V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK)
758 vos->sco[0] = IS_CLIPPED;
763 int col_pack_prev = 0;
766 bglMats mats; /* ZBuffer depth vars */
773 if (rv3d->rflag & RV3D_CLIPPING) {
774 ED_view3d_clipping_disable();
777 glMatrixMode(GL_PROJECTION);
779 glMatrixMode(GL_MODELVIEW);
781 ED_region_pixelspace(ar);
784 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
790 for (vos = strings->first; vos; vos = vos->next) {
791 /* too slow, reading opengl info while drawing is very bad,
792 * better to see if we can use the zbuffer while in pixel space - campbell */
794 if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
795 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
796 glReadPixels(ar->winrct.xmin + vos->mval[0] + vos->xoffs, ar->winrct.ymin + vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
802 if (vos->sco[0] != IS_CLIPPED) {
803 const char *str = (char *)(vos + 1);
805 if (col_pack_prev != vos->col.pack) {
806 glColor3ubv(vos->col.ub);
807 col_pack_prev = vos->col.pack;
810 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
811 BLF_draw_default_ascii :
813 )( (float)vos->sco[0] + vos->xoffs,
815 (depth_write) ? 0.0f : 2.0f,
822 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
828 glMatrixMode(GL_PROJECTION);
830 glMatrixMode(GL_MODELVIEW);
833 if (rv3d->rflag & RV3D_CLIPPING) {
834 ED_view3d_clipping_enable();
839 BLI_freelistN(strings);
844 /* ******************** primitive drawing ******************* */
846 static void drawcube(void)
849 glBegin(GL_LINE_STRIP);
850 glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
851 glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
852 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
855 glBegin(GL_LINE_STRIP);
856 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
859 glBegin(GL_LINE_STRIP);
860 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
863 glBegin(GL_LINE_STRIP);
864 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
868 /* draws a cube on given the scaling of the cube, assuming that
869 * all required matrices have been set (used for drawing empties)
871 static void drawcube_size(float size)
873 glBegin(GL_LINE_STRIP);
874 glVertex3f(-size, -size, -size); glVertex3f(-size, -size, size);
875 glVertex3f(-size, size, size); glVertex3f(-size, size, -size);
877 glVertex3f(-size, -size, -size); glVertex3f(size, -size, -size);
878 glVertex3f(size, -size, size); glVertex3f(size, size, size);
880 glVertex3f(size, size, -size); glVertex3f(size, -size, -size);
883 glBegin(GL_LINE_STRIP);
884 glVertex3f(-size, -size, size); glVertex3f(size, -size, size);
887 glBegin(GL_LINE_STRIP);
888 glVertex3f(-size, size, size); glVertex3f(size, size, size);
891 glBegin(GL_LINE_STRIP);
892 glVertex3f(-size, size, -size); glVertex3f(size, size, -size);
896 /* this is an unused (old) cube-drawing function based on a given size */
898 static void drawcube_size(const float size[3])
902 glScalef(size[0], size[1], size[2]);
905 glBegin(GL_LINE_STRIP);
906 glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
907 glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
908 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
911 glBegin(GL_LINE_STRIP);
912 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
915 glBegin(GL_LINE_STRIP);
916 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
919 glBegin(GL_LINE_STRIP);
920 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
927 static void drawshadbuflimits(Lamp *la, float mat[][4])
929 float sta[3], end[3], lavec[3];
931 negate_v3_v3(lavec, mat[2]);
934 madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
935 madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
937 glBegin(GL_LINE_STRIP);
952 static void spotvolume(float lvec[3], float vvec[3], const float inp)
954 /* camera is at 0,0,0 */
955 float temp[3], plane[3], mat1[3][3], mat2[3][3], mat3[3][3], mat4[3][3], q[4], co, si, angle;
958 normalize_v3(vvec); /* is this the correct vector ? */
960 cross_v3_v3v3(temp, vvec, lvec); /* equation for a plane through vvec en lvec */
961 cross_v3_v3v3(plane, lvec, temp); /* a plane perpendicular to this, parrallel with lvec */
963 /* vectors are exactly aligned, use the X axis, this is arbitrary */
964 if (normalize_v3(plane) == 0.0f)
967 /* now we've got two equations: one of a cone and one of a plane, but we have
968 * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
970 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
971 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
973 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
980 angle = saacos(plane[2]) / 2.0f;
982 si = sqrtf(1 - co * co);
989 quat_to_mat3(mat1, q);
991 /* rotate lamp vector now over acos(inp) degrees */
992 copy_v3_v3(vvec, lvec);
996 si = sqrtf(1.0f - inp * inp);
1002 mul_m3_m3m3(mat3, mat2, mat1);
1006 mul_m3_m3m3(mat4, mat2, mat1);
1009 mul_m3_m3m3(mat2, mat1, mat3);
1010 mul_m3_v3(mat2, lvec);
1011 mul_m3_m3m3(mat2, mat1, mat4);
1012 mul_m3_v3(mat2, vvec);
1017 static void draw_spot_cone(Lamp *la, float x, float z)
1021 glBegin(GL_TRIANGLE_FAN);
1022 glVertex3f(0.0f, 0.0f, -x);
1024 if (la->mode & LA_SQUARE) {
1025 glVertex3f(z, z, 0);
1026 glVertex3f(-z, z, 0);
1027 glVertex3f(-z, -z, 0);
1028 glVertex3f(z, -z, 0);
1029 glVertex3f(z, z, 0);
1035 for (a = 0; a < 33; a++) {
1036 angle = a * M_PI * 2 / (33 - 1);
1037 glVertex3f(z * cosf(angle), z * sinf(angle), 0);
1044 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1046 glEnable(GL_CULL_FACE);
1050 /* draw backside darkening */
1051 glCullFace(GL_FRONT);
1053 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1054 glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1056 draw_spot_cone(la, x, z);
1058 /* draw front side lighting */
1059 glCullFace(GL_BACK);
1061 glBlendFunc(GL_ONE, GL_ONE);
1062 glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1064 draw_spot_cone(la, x, z);
1067 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1068 glDisable(GL_BLEND);
1070 glDisable(GL_CULL_FACE);
1071 glCullFace(GL_BACK);
1074 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1075 const short dt, const short dflag, const unsigned char ob_wire_col[4])
1077 Object *ob = base->object;
1078 const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1079 Lamp *la = ob->data;
1080 float vec[3], lvec[3], vvec[3], circrad, x, y, z;
1084 unsigned char curcol[4];
1085 unsigned char col[4];
1086 /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1087 /* the moment of view3d_draw_transp() call */
1088 const short is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
1089 const short drawcone = ((dt > OB_WIRE) &&
1090 !(G.f & G_PICKSEL) &&
1091 (la->type == LA_SPOT) &&
1092 (la->mode & LA_SHOW_CONE) &&
1093 !(base->flag & OB_FROMDUPLI) &&
1096 if (drawcone && !v3d->transp) {
1097 /* in this case we need to draw delayed */
1098 ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
1102 /* we first draw only the screen aligned & fixed scale stuff */
1104 glLoadMatrixf(rv3d->viewmat);
1106 /* lets calculate the scale: */
1107 lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
1109 /* and view aligned matrix: */
1110 copy_m4_m4(imat, rv3d->viewinv);
1111 normalize_v3(imat[0]);
1112 normalize_v3(imat[1]);
1115 copy_v3_v3(vec, ob->obmat[3]);
1117 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1118 /* for AA effects */
1119 curcol[0] = ob_wire_col[0];
1120 curcol[1] = ob_wire_col[1];
1121 curcol[2] = ob_wire_col[2];
1123 glColor4ubv(curcol);
1126 if (lampsize > 0.0f) {
1128 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1129 if (ob->id.us > 1) {
1130 if (ob == OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1131 else glColor4ub(0x77, 0xCC, 0xCC, 155);
1137 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1138 glDisable(GL_BLEND);
1139 drawcircball(GL_POLYGON, vec, lampsize, imat);
1142 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1144 glColor4ubv(curcol);
1148 circrad = 3.0f * lampsize;
1151 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1153 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1154 if (la->type != LA_HEMI) {
1155 if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
1156 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat);
1165 /* draw the pretty sun rays */
1166 if (la->type == LA_SUN) {
1167 float v1[3], v2[3], mat[3][3];
1170 /* setup a 45 degree rotation matrix */
1171 vec_rot_to_mat3(mat, imat[2], (float)M_PI / 4.0f);
1174 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1175 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1178 glTranslatef(vec[0], vec[1], vec[2]);
1183 for (axis = 0; axis < 8; axis++) {
1191 glTranslatef(-vec[0], -vec[1], -vec[2]);
1195 if (la->type == LA_LOCAL) {
1196 if (la->mode & LA_SPHERE) {
1197 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1201 glPopMatrix(); /* back in object space */
1205 /* skip drawing extra info */
1207 else if ((la->type == LA_SPOT) || (la->type == LA_YF_PHOTON)) {
1208 lvec[0] = lvec[1] = 0.0;
1210 x = rv3d->persmat[0][2];
1211 y = rv3d->persmat[1][2];
1212 z = rv3d->persmat[2][2];
1213 vvec[0] = x * ob->obmat[0][0] + y * ob->obmat[0][1] + z * ob->obmat[0][2];
1214 vvec[1] = x * ob->obmat[1][0] + y * ob->obmat[1][1] + z * ob->obmat[1][2];
1215 vvec[2] = x * ob->obmat[2][0] + y * ob->obmat[2][1] + z * ob->obmat[2][2];
1217 y = cosf(la->spotsize * (float)(M_PI / 360.0));
1218 spotvolume(lvec, vvec, y);
1223 /* draw the angled sides of the cone */
1224 glBegin(GL_LINE_STRIP);
1230 z = x * sqrtf(1.0f - y * y);
1233 /* draw the circle/square at the end of the cone */
1234 glTranslatef(0.0, 0.0, x);
1235 if (la->mode & LA_SQUARE) {
1237 float z_abs = fabs(z);
1239 tvec[0] = tvec[1] = z_abs;
1242 glBegin(GL_LINE_LOOP);
1244 tvec[1] = -z_abs; /* neg */
1246 tvec[0] = -z_abs; /* neg */
1248 tvec[1] = z_abs; /* pos */
1253 circ(0.0, 0.0, fabsf(z));
1256 /* draw the circle/square representing spotbl */
1257 if (la->type == LA_SPOT) {
1258 float spotblcirc = fabs(z) * (1 - pow(la->spotblend, 2));
1259 /* hide line if it is zero size or overlaps with outer border,
1260 * previously it adjusted to always to show it but that seems
1261 * confusing because it doesn't show the actual blend size */
1262 if (spotblcirc != 0 && spotblcirc != fabsf(z))
1263 circ(0.0, 0.0, spotblcirc);
1267 draw_transp_spot_volume(la, x, z);
1269 /* draw clip start, useful for wide cones where its not obvious where the start is */
1270 glTranslatef(0.0, 0.0, -x); /* reverse translation above */
1271 if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1274 float clipsta_fac = la->clipsta / -x;
1276 interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1277 interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1279 glBegin(GL_LINE_STRIP);
1280 glVertex3fv(lvec_clip);
1281 glVertex3fv(vvec_clip);
1285 else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
1287 /* draw the line from the circle along the dist */
1288 glBegin(GL_LINE_STRIP);
1295 if (la->type == LA_HEMI) {
1296 /* draw the hemisphere curves */
1297 short axis, steps, dir;
1298 float outdist, zdist, mul;
1300 outdist = 0.14; mul = 1.4; dir = 1;
1303 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1304 for (axis = 0; axis < 4; axis++) {
1305 float v[3] = {0.0, 0.0, 0.0};
1308 glBegin(GL_LINE_STRIP);
1310 for (steps = 0; steps < 6; steps++) {
1311 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
1312 /* make the arcs start at the edge of the energy circle */
1313 if (steps == 0) v[0] = dir * circrad;
1314 else v[0] = v[0] + dir * (steps * outdist);
1316 else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
1317 /* make the arcs start at the edge of the energy circle */
1318 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1321 v[2] = v[2] - steps * zdist;
1325 zdist = zdist * mul;
1329 /* flip the direction */
1334 else if (la->type == LA_AREA) {
1336 if (la->area_shape == LA_AREA_SQUARE)
1337 fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
1338 else if (la->area_shape == LA_AREA_RECT)
1339 fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
1341 glBegin(GL_LINE_STRIP);
1342 glVertex3f(0.0, 0.0, -circrad);
1343 glVertex3f(0.0, 0.0, -la->dist);
1347 /* and back to viewspace */
1348 glLoadMatrixf(rv3d->viewmat);
1349 copy_v3_v3(vec, ob->obmat[3]);
1353 if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1354 drawshadbuflimits(la, ob->obmat);
1357 UI_GetThemeColor4ubv(TH_LAMP, col);
1362 if (vec[2] > 0) vec[2] -= circrad;
1363 else vec[2] += circrad;
1365 glBegin(GL_LINE_STRIP);
1377 glDisable(GL_BLEND);
1379 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1380 /* restore for drawing extra stuff */
1381 glColor3ubv(ob_wire_col);
1385 static void draw_limit_line(float sta, float end, unsigned int col)
1388 glVertex3f(0.0, 0.0, -sta);
1389 glVertex3f(0.0, 0.0, -end);
1395 glVertex3f(0.0, 0.0, -sta);
1396 glVertex3f(0.0, 0.0, -end);
1402 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1403 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1404 static void draw_focus_cross(float dist, float size)
1407 glVertex3f(-size, 0.f, -dist);
1408 glVertex3f(size, 0.f, -dist);
1409 glVertex3f(0.f, -size, -dist);
1410 glVertex3f(0.f, size, -dist);
1414 #ifdef VIEW3D_CAMERA_BORDER_HACK
1415 unsigned char view3d_camera_border_hack_col[3];
1416 short view3d_camera_border_hack_test = FALSE;
1419 /* ****************** draw clip data *************** */
1421 static void draw_bundle_sphere(void)
1423 static GLuint displist = 0;
1425 if (displist == 0) {
1426 GLUquadricObj *qobj;
1428 displist = glGenLists(1);
1429 glNewList(displist, GL_COMPILE);
1431 qobj = gluNewQuadric();
1432 gluQuadricDrawStyle(qobj, GLU_FILL);
1433 glShadeModel(GL_SMOOTH);
1434 gluSphere(qobj, 0.05, 8, 8);
1435 glShadeModel(GL_FLAT);
1436 gluDeleteQuadric(qobj);
1441 glCallList(displist);
1444 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1445 MovieClip *clip, MovieTrackingObject *tracking_object,
1446 const short dflag, const unsigned char ob_wire_col[4],
1447 int *global_track_index, int draw_selected)
1449 MovieTracking *tracking = &clip->tracking;
1450 MovieTrackingTrack *track;
1451 float mat[4][4], imat[4][4];
1452 unsigned char col_unsel[4], col_sel[4];
1453 int tracknr = *global_track_index;
1454 ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
1456 UI_GetThemeColor4ubv(TH_TEXT, col_unsel);
1457 UI_GetThemeColor4ubv(TH_SELECT, col_sel);
1459 BKE_tracking_get_camera_object_matrix(scene, base->object, mat);
1463 if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1464 /* current ogl matrix is translated in camera space, bundles should
1465 * be rendered in world space, so camera matrix should be "removed"
1466 * from current ogl matrix */
1467 invert_m4_m4(imat, base->object->obmat);
1469 glMultMatrixf(imat);
1475 BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, scene->r.cfra, obmat);
1477 invert_m4_m4(imat, obmat);
1478 glMultMatrixf(imat);
1481 for (track = tracksbase->first; track; track = track->next) {
1482 int selected = TRACK_SELECTED(track);
1484 if (draw_selected && !selected)
1487 if ((track->flag & TRACK_HAS_BUNDLE) == 0)
1490 if (dflag & DRAW_PICKING)
1491 glLoadName(base->selcol + (tracknr << 16));
1494 glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1495 glScalef(v3d->bundle_size / 0.05f, v3d->bundle_size / 0.05f, v3d->bundle_size / 0.05f);
1497 if (v3d->drawtype == OB_WIRE) {
1498 glDisable(GL_LIGHTING);
1500 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1501 if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
1502 glColor3ubv(ob_wire_col);
1505 glColor3fv(track->color);
1509 drawaxes(0.05f, v3d->bundle_drawtype);
1511 glEnable(GL_LIGHTING);
1513 else if (v3d->drawtype > OB_WIRE) {
1514 if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
1515 /* selection outline */
1517 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1518 glColor3ubv(ob_wire_col);
1522 glDisable(GL_LIGHTING);
1523 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1525 draw_bundle_sphere();
1527 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1528 glEnable(GL_LIGHTING);
1532 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1533 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1534 else UI_ThemeColor(TH_BUNDLE_SOLID);
1537 draw_bundle_sphere();
1540 glDisable(GL_LIGHTING);
1542 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1544 glColor3ubv(ob_wire_col);
1547 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1548 else UI_ThemeColor(TH_WIRE);
1552 drawaxes(0.05f, v3d->bundle_drawtype);
1554 glEnable(GL_LIGHTING);
1560 if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
1563 mul_v3_m4v3(pos, mat, track->bundle_pos);
1564 view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, selected ? col_sel : col_unsel);
1570 if ((dflag & DRAW_PICKING) == 0) {
1571 if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) {
1572 MovieTrackingReconstruction *reconstruction;
1573 reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object);
1575 if (reconstruction->camnr) {
1576 MovieReconstructedCamera *camera = reconstruction->cameras;
1579 glDisable(GL_LIGHTING);
1580 UI_ThemeColor(TH_CAMERA_PATH);
1583 glBegin(GL_LINE_STRIP);
1584 for (a = 0; a < reconstruction->camnr; a++, camera++) {
1585 glVertex3fv(camera->mat[3]);
1590 glEnable(GL_LIGHTING);
1597 *global_track_index = tracknr;
1600 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
1601 const short dflag, const unsigned char ob_wire_col[4],
1604 MovieTracking *tracking = &clip->tracking;
1605 MovieTrackingObject *tracking_object;
1606 int global_track_index = 1;
1608 if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0)
1611 if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1614 glEnable(GL_LIGHTING);
1615 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1616 glEnable(GL_COLOR_MATERIAL);
1617 glShadeModel(GL_SMOOTH);
1619 tracking_object = tracking->objects.first;
1620 while (tracking_object) {
1621 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1622 dflag, ob_wire_col, &global_track_index, draw_selected);
1624 tracking_object = tracking_object->next;
1628 glShadeModel(GL_FLAT);
1629 glDisable(GL_COLOR_MATERIAL);
1630 glDisable(GL_LIGHTING);
1632 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1633 glColor3ubv(ob_wire_col);
1636 if (dflag & DRAW_PICKING)
1637 glLoadName(base->selcol);
1640 /* flag similar to draw_object() */
1641 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1642 const short dflag, const unsigned char ob_wire_col[4])
1644 /* a standing up pyramid with (0,0,0) as top */
1646 Object *ob = base->object;
1648 float vec[4][3], asp[2], shift[2], scale[3];
1651 const short is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
1652 MovieClip *clip = BKE_object_movieclip_get(scene, base->object, 0);
1654 /* draw data for movie clip set as active for scene */
1656 draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, FALSE);
1657 draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, TRUE);
1660 #ifdef VIEW3D_CAMERA_BORDER_HACK
1661 if (is_view && !(G.f & G_PICKSEL)) {
1662 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1663 view3d_camera_border_hack_col[0] = ob_wire_col[0];
1664 view3d_camera_border_hack_col[1] = ob_wire_col[1];
1665 view3d_camera_border_hack_col[2] = ob_wire_col[2];
1669 glGetFloatv(GL_CURRENT_COLOR, col);
1670 rgb_float_to_uchar(view3d_camera_border_hack_col, col);
1672 view3d_camera_border_hack_test = TRUE;
1679 scale[0] = 1.0f / len_v3(ob->obmat[0]);
1680 scale[1] = 1.0f / len_v3(ob->obmat[1]);
1681 scale[2] = 1.0f / len_v3(ob->obmat[2]);
1683 BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1684 asp, shift, &drawsize, vec);
1686 glDisable(GL_LIGHTING);
1687 glDisable(GL_CULL_FACE);
1690 glBegin(GL_LINE_LOOP);
1691 glVertex3fv(vec[0]);
1692 glVertex3fv(vec[1]);
1693 glVertex3fv(vec[2]);
1694 glVertex3fv(vec[3]);
1702 /* center point to camera frame */
1703 glBegin(GL_LINE_STRIP);
1704 glVertex3fv(vec[1]);
1706 glVertex3fv(vec[0]);
1707 glVertex3fv(vec[3]);
1709 glVertex3fv(vec[2]);
1714 tvec[2] = vec[1][2]; /* copy the depth */
1717 /* draw an outline arrow for inactive cameras and filled
1718 * for active cameras. We actually draw both outline+filled
1719 * for active cameras so the wire can be seen side-on */
1720 for (i = 0; i < 2; i++) {
1721 if (i == 0) glBegin(GL_LINE_LOOP);
1722 else if (i == 1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1725 tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
1726 tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1727 glVertex3fv(tvec); /* left */
1729 tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
1730 glVertex3fv(tvec); /* right */
1733 tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1734 glVertex3fv(tvec); /* top */
1740 if (cam->flag & (CAM_SHOWLIMITS + CAM_SHOWMIST)) {
1744 /* draw in normalized object matrix space */
1745 copy_m4_m4(nobmat, ob->obmat);
1746 normalize_m4(nobmat);
1749 glLoadMatrixf(rv3d->viewmat);
1750 glMultMatrixf(nobmat);
1752 if (cam->flag & CAM_SHOWLIMITS) {
1753 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1754 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
1755 draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
1758 wrld = scene->world;
1759 if (cam->flag & CAM_SHOWMIST)
1760 if (wrld) draw_limit_line(wrld->miststa, wrld->miststa + wrld->mistdist, 0xFFFFFF);
1767 /* flag similar to draw_object() */
1768 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1769 Object *UNUSED(ob), int UNUSED(flag))
1771 //Speaker *spk = ob->data;
1778 for (j = 0; j < 3; j++) {
1779 vec[2] = 0.25f * j - 0.125f;
1781 glBegin(GL_LINE_LOOP);
1782 for (i = 0; i < 16; i++) {
1783 vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1784 vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1790 for (j = 0; j < 4; j++) {
1791 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1792 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1793 glBegin(GL_LINE_STRIP);
1794 for (i = 0; i < 3; i++) {
1800 vec[2] = 0.25f * i - 0.125f;
1806 glDisable(GL_BLEND);
1809 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1811 BPoint *bp = lt->def;
1812 float *co = dl ? dl->verts : NULL;
1815 UI_ThemeColor(sel ? TH_VERTEX_SELECT : TH_VERTEX);
1816 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1817 bglBegin(GL_POINTS);
1819 for (w = 0; w < lt->pntsw; w++) {
1820 int wxt = (w == 0 || w == lt->pntsw - 1);
1821 for (v = 0; v < lt->pntsv; v++) {
1822 int vxt = (v == 0 || v == lt->pntsv - 1);
1823 for (u = 0; u < lt->pntsu; u++, bp++, co += 3) {
1824 int uxt = (u == 0 || u == lt->pntsu - 1);
1825 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1826 if (bp->hide == 0) {
1827 if ((bp->f1 & SELECT) == sel) {
1828 bglVertex3fv(dl ? co : bp->vec);
1840 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1842 int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
1846 MDeformWeight *mdw = defvert_find_index(lt->dvert + index, use_wcol - 1);
1848 weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
1854 glVertex3fv(&dl->verts[index * 3]);
1857 glVertex3fv(lt->def[index].vec);
1861 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1862 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1864 Lattice *lt = ob->data;
1867 int use_wcol = FALSE, is_edit = (lt->editlatt != NULL);
1869 /* now we default make displist, this will modifiers work for non animated case */
1870 if (ob->disp.first == NULL)
1871 BKE_lattice_modifiers_calc(scene, ob);
1872 dl = BKE_displist_find(&ob->disp, DL_VERTS);
1875 lt = lt->editlatt->latt;
1879 if (ob->defbase.first && lt->dvert) {
1880 use_wcol = ob->actdef;
1881 glShadeModel(GL_SMOOTH);
1886 for (w = 0; w < lt->pntsw; w++) {
1887 int wxt = (w == 0 || w == lt->pntsw - 1);
1888 for (v = 0; v < lt->pntsv; v++) {
1889 int vxt = (v == 0 || v == lt->pntsv - 1);
1890 for (u = 0; u < lt->pntsu; u++) {
1891 int uxt = (u == 0 || u == lt->pntsu - 1);
1893 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1894 drawlattice__point(lt, dl, u, v, w - 1, use_wcol);
1895 drawlattice__point(lt, dl, u, v, w, use_wcol);
1897 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1898 drawlattice__point(lt, dl, u, v - 1, w, use_wcol);
1899 drawlattice__point(lt, dl, u, v, w, use_wcol);
1901 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1902 drawlattice__point(lt, dl, u - 1, v, w, use_wcol);
1903 drawlattice__point(lt, dl, u, v, w, use_wcol);
1910 /* restoration for weight colors */
1912 glShadeModel(GL_FLAT);
1915 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1917 lattice_draw_verts(lt, dl, 0);
1918 lattice_draw_verts(lt, dl, 1);
1920 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
1924 /* ***************** ******************** */
1927 static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
1928 const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
1930 MVert *mv = &((MVert *)userData)[index];
1932 if (!(mv->flag & ME_HIDE)) {
1933 const char sel = mv->flag & SELECT;
1935 /* TODO define selected color */
1937 glColor3f(1.0f, 1.0f, 0.0f);
1940 glColor3f(0.0f, 0.0f, 0.0f);
1947 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
1950 dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
1954 /* ************** DRAW MESH ****************** */
1956 /* First section is all the "simple" draw routines,
1957 * ones that just pass some sort of primitive to GL,
1958 * with perhaps various options to control lighting,
1961 * These routines should not have user interface related
1965 static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
1969 copy_m3_m4(obmat, ob->obmat);
1971 data->uniform_scale = is_uniform_scaled_m3(obmat);
1973 if (!data->uniform_scale) {
1974 /* inverted matrix */
1975 invert_m3_m3(data->imat, obmat);
1977 /* transposed inverted matrix */
1978 copy_m3_m3(data->tmat, data->imat);
1979 transpose_m3(data->tmat);
1983 static void draw_dm_face_normals__mapFunc(void *userData, int index, const float cent[3], const float no[3])
1985 drawDMNormal_userData *data = userData;
1986 BMFace *efa = EDBM_face_at_index(data->em, index);
1989 if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
1990 if (!data->uniform_scale) {
1991 mul_v3_m3v3(n, data->tmat, (float *) no);
1993 mul_m3_v3(data->imat, n);
2000 glVertex3f(cent[0] + n[0] * data->normalsize,
2001 cent[1] + n[1] * data->normalsize,
2002 cent[2] + n[2] * data->normalsize);
2006 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2008 drawDMNormal_userData data;
2011 data.normalsize = scene->toolsettings->normalsize;
2013 calcDrawDMNormalScale(ob, &data);
2016 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data);
2020 static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2022 BMFace *efa = EDBM_face_at_index(((void **)userData)[0], index);
2023 int sel = *(((int **)userData)[1]);
2025 if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT) == sel) {
2029 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
2031 void *ptrs[2] = {em, &sel};
2033 bglBegin(GL_POINTS);
2034 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
2038 static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
2040 drawDMNormal_userData *data = userData;
2041 BMVert *eve = EDBM_vert_at_index(data->em, index);
2043 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2047 copy_v3_v3(no, no_f);
2050 no[0] = no_s[0] / 32767.0f;
2051 no[1] = no_s[1] / 32767.0f;
2052 no[2] = no_s[2] / 32767.0f;
2055 if (!data->uniform_scale) {
2056 mul_v3_m3v3(n, data->tmat, (float *) no);
2058 mul_m3_v3(data->imat, n);
2065 glVertex3f(co[0] + n[0] * data->normalsize,
2066 co[1] + n[1] * data->normalsize,
2067 co[2] + n[2] * data->normalsize);
2071 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2073 drawDMNormal_userData data;
2076 data.normalsize = scene->toolsettings->normalsize;
2078 calcDrawDMNormalScale(ob, &data);
2081 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data);
2085 /* Draw verts with color set based on selection */
2086 static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
2087 const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2089 drawDMVerts_userData *data = userData;
2090 BMVert *eve = EDBM_vert_at_index(data->em, index);
2092 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
2093 /* skin nodes: draw a red circle around the root
2095 if (data->has_vskin) {
2096 const MVertSkin *vs = CustomData_bmesh_get(&data->em->bm->vdata,
2099 if (vs->flag & MVERT_SKIN_ROOT) {
2100 float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
2103 glColor4ubv(data->th_skin_root);
2104 drawcircball(GL_LINES, co, radius, data->imat);
2106 glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2107 bglBegin(GL_POINTS);
2111 /* draw active larger - need to stop/start point drawing for this :/ */
2112 if (eve == data->eve_act) {
2113 glColor4ubv(data->th_editmesh_active);
2117 glPointSize(data->th_vertex_size);
2118 bglBegin(GL_POINTS);
2122 glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2123 glPointSize(data->th_vertex_size);
2124 bglBegin(GL_POINTS);
2132 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act,
2135 drawDMVerts_userData data;
2137 data.eve_act = eve_act;
2140 /* Cache theme values */
2141 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
2142 UI_GetThemeColor4ubv(TH_VERTEX_SELECT, data.th_vertex_select);
2143 UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
2144 UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
2145 data.th_vertex_size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2147 /* For skin root drawing */
2148 data.has_vskin = CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN);
2149 /* view-aligned matrix */
2150 mult_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
2151 invert_m4(data.imat);
2153 bglBegin(GL_POINTS);
2154 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2158 /* Draw edges with color set based on selection */
2159 static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2162 //unsigned char **cols = userData, *col;
2163 drawDMEdgesSel_userData *data = userData;
2166 eed = EDBM_edge_at_index(data->em, index);
2168 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2169 if (eed == data->eed_act) {
2170 glColor4ubv(data->actCol);
2173 if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2177 col = data->baseCol;
2179 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
2181 return DM_DRAW_OPTION_SKIP;
2185 return DM_DRAW_OPTION_NORMAL;
2188 return DM_DRAW_OPTION_SKIP;
2191 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2192 unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
2194 drawDMEdgesSel_userData data;
2196 data.baseCol = baseCol;
2197 data.selCol = selCol;
2198 data.actCol = actCol;
2200 data.eed_act = eed_act;
2201 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2205 static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
2207 if (BM_elem_flag_test(EDBM_edge_at_index(userData, index), BM_ELEM_HIDDEN))
2208 return DM_DRAW_OPTION_SKIP;
2210 return DM_DRAW_OPTION_NORMAL;
2213 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
2215 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
2218 /* Draw edges with color interpolated based on selection */
2219 static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2221 if (BM_elem_flag_test(EDBM_edge_at_index(((void **)userData)[0], index), BM_ELEM_HIDDEN))
2222 return DM_DRAW_OPTION_SKIP;
2224 return DM_DRAW_OPTION_NORMAL;
2226 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2228 BMEdge *eed = EDBM_edge_at_index(((void **)userData)[0], index);
2229 unsigned char **cols = userData;
2230 unsigned char *col0 = cols[(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT)) ? 2 : 1];
2231 unsigned char *col1 = cols[(BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) ? 2 : 1];
2233 glColor4ub(col0[0] + (col1[0] - col0[0]) * t,
2234 col0[1] + (col1[1] - col0[1]) * t,
2235 col0[2] + (col1[2] - col0[2]) * t,
2236 col0[3] + (col1[3] - col0[3]) * t);
2239 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2241 void *cols[3] = {em, baseCol, selCol};
2243 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2246 /* Draw only seam edges */
2247 static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2249 BMEdge *eed = EDBM_edge_at_index(userData, index);
2251 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
2252 return DM_DRAW_OPTION_NORMAL;
2254 return DM_DRAW_OPTION_SKIP;
2257 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2259 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2262 /* Draw only sharp edges */
2263 static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2265 BMEdge *eed = EDBM_edge_at_index(userData, index);
2267 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
2268 return DM_DRAW_OPTION_NORMAL;
2270 return DM_DRAW_OPTION_SKIP;
2273 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2275 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2278 /* Draw only Freestyle feature edges */
2279 static DMDrawOption draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
2281 BMEdge *eed = EDBM_edge_at_index(userData, index);
2283 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_FREESTYLE))
2284 return DM_DRAW_OPTION_NORMAL;
2286 return DM_DRAW_OPTION_SKIP;
2289 static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
2291 dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em);
2294 /* Draw faces with color set based on selection
2295 * return 2 for the active face so it renders with stipple enabled */
2296 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2298 drawDMFacesSel_userData *data = userData;
2299 BMFace *efa = EDBM_face_at_index(data->em, index);
2303 return DM_DRAW_OPTION_SKIP;
2305 if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2306 if (efa == data->efa_act) {
2307 glColor4ubv(data->cols[3]);
2308 return DM_DRAW_OPTION_STIPPLE;
2311 col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(efa, BM_ELEM_FREESTYLE) ? 2 : 0];
2313 return DM_DRAW_OPTION_SKIP;
2315 return DM_DRAW_OPTION_NORMAL;
2318 return DM_DRAW_OPTION_SKIP;
2321 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2324 drawDMFacesSel_userData *data = userData;
2328 unsigned char *col, *next_col;
2330 if (!data->orig_index_mf_to_mpoly)
2333 efa = EDBM_face_at_index(data->em, DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, index));
2334 next_efa = EDBM_face_at_index(data->em, DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, next_index));
2336 if (efa == next_efa)
2339 if (efa == data->efa_act || next_efa == data->efa_act)
2342 col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(efa, BM_ELEM_FREESTYLE) ? 2 : 0];
2343 next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : BM_elem_flag_test(next_efa, BM_ELEM_FREESTYLE) ? 2 : 0];
2345 if (col[3] == 0 || next_col[3] == 0)
2348 return col == next_col;
2351 /* also draws the active face */
2352 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2353 unsigned char *selCol, unsigned char *markCol, unsigned char *actCol, BMFace *efa_act)
2355 drawDMFacesSel_userData data;
2357 data.cols[0] = baseCol;
2359 data.cols[1] = selCol;
2360 data.cols[2] = markCol;
2361 data.cols[3] = actCol;
2362 data.efa_act = efa_act;
2364 data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2365 data.orig_index_mp_to_orig = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
2366 if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == FALSE) {
2367 data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL;
2370 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2373 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2375 BMEditMesh *em = userData;
2376 BMEdge *eed = EDBM_edge_at_index(userData, index);
2377 float *crease = eed ? (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2380 return DM_DRAW_OPTION_SKIP;
2382 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *crease != 0.0f) {
2383 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2384 return DM_DRAW_OPTION_NORMAL;
2387 return DM_DRAW_OPTION_SKIP;
2390 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2393 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2397 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2399 BMEditMesh *em = userData;
2400 BMEdge *eed = EDBM_edge_at_index(userData, index);
2401 float *bweight = (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2404 return DM_DRAW_OPTION_SKIP;
2406 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2407 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2408 return DM_DRAW_OPTION_NORMAL;
2411 return DM_DRAW_OPTION_SKIP;
2414 static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
2415 const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2417 BMEditMesh *em = userData;
2418 BMVert *eve = EDBM_vert_at_index(userData, index);
2419 float *bweight = (float *)CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2424 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2425 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2429 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2431 ToolSettings *ts = scene->toolsettings;
2433 if (ts->selectmode & SCE_SELECT_VERTEX) {
2434 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2435 bglBegin(GL_POINTS);
2436 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2441 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2446 /* Second section of routines: Combine first sets to form fancy
2447 * drawing routines (for example rendering twice to get overlays).
2449 * Also includes routines that are basic drawing but are too
2450 * specialized to be split out (like drawing creases or measurements).
2453 /* EditMesh drawing routines*/
2455 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2456 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
2459 ToolSettings *ts = scene->toolsettings;
2462 if (v3d->zbuf) glDepthMask(0); /* disable write in zbuffer, zbuf select */
2464 for (sel = 0; sel < 2; sel++) {
2465 unsigned char col[4], fcol[4];
2468 UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
2469 UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE, fcol);
2471 for (pass = 0; pass < 2; pass++) {
2472 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2473 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2476 if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
2477 glDisable(GL_DEPTH_TEST);
2485 size = (size > 2.1f ? size / 2.0f : size);
2486 fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
2487 col[3] = fcol[3] = 100;
2490 col[3] = fcol[3] = 255;
2493 if (ts->selectmode & SCE_SELECT_VERTEX) {
2496 draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
2499 if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2502 draw_dm_face_centers(em, cageDM, sel);
2506 glDisable(GL_BLEND);
2507 glEnable(GL_DEPTH_TEST);
2512 if (v3d->zbuf) glDepthMask(1);
2516 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2517 Mesh *me, DerivedMesh *cageDM, short sel_only,
2520 ToolSettings *ts = scene->toolsettings;
2522 unsigned char wireCol[4], selCol[4], actCol[4];
2524 /* since this function does transparent... */
2525 UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2526 UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2527 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2529 /* when sel only is used, don't render wire, only selected, this is used for
2530 * textured draw mode when the 'edges' option is disabled */
2534 for (pass = 0; pass < 2; pass++) {
2535 /* show wires in transparent when no zbuf clipping for select */
2537 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT) == 0) {
2539 glDisable(GL_DEPTH_TEST);
2541 if (!sel_only) wireCol[3] = 85;
2549 if (!sel_only) wireCol[3] = 255;
2552 if (ts->selectmode == SCE_SELECT_FACE) {
2553 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2555 else if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
2556 if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2557 glShadeModel(GL_SMOOTH);
2558 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2559 glShadeModel(GL_FLAT);
2562 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2567 glColor4ubv(wireCol);
2568 draw_dm_edges(em, cageDM);
2573 glDisable(GL_BLEND);
2574 glEnable(GL_DEPTH_TEST);
2579 static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2581 const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2582 Mesh *me = ob->data;
2583 float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2584 char numstr[32]; /* Stores the measurement display text here */
2585 const char *conv_float; /* Use a float conversion matching the grid size */
2586 unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
2587 float area; /* area of the face */
2588 float grid = unit->system ? unit->scale_length : v3d->grid;
2589 const int do_split = unit->flag & USER_UNIT_OPT_SPLIT;
2590 const int do_global = v3d->flag & V3D_GLOBAL_STATS;
2591 const int do_moving = G.moving;
2596 /* make the precision of the pronted value proportionate to the gridsize */
2598 if (grid < 0.01f) conv_float = "%.6g";
2599 else if (grid < 0.1f) conv_float = "%.5g";
2600 else if (grid < 1.0f) conv_float = "%.4g";
2601 else if (grid < 10.0f) conv_float = "%.3g";
2602 else conv_float = "%.2g";
2604 if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2607 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2609 eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2610 for (; eed; eed = BM_iter_step(&iter)) {
2611 /* draw selected edges, or edges next to selected verts while draging */
2612 if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2613 (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2614 BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2617 copy_v3_v3(v1, eed->v1->co);
2618 copy_v3_v3(v2, eed->v2->co);
2620 mid_v3_v3v3(vmid, v1, v2);
2623 mul_mat3_m4_v3(ob->obmat, v1);
2624 mul_mat3_m4_v3(ob->obmat, v2);
2628 bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2629 unit->system, B_UNIT_LENGTH, do_split, FALSE);
2632 sprintf(numstr, conv_float, len_v3v3(v1, v2));
2635 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2640 if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2641 /* would be nice to use BM_face_calc_area, but that is for 2d faces
2642 * so instead add up tessellation triangle areas */
2646 #define DRAW_EM_MEASURE_STATS_FACEAREA() \
2647 if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \
2648 mul_v3_fl(vmid, 1.0f / (float)n); \
2650 bUnit_AsString(numstr, sizeof(numstr), \
2651 (double)(area * unit->scale_length), \
2652 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); \
2654 BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \
2655 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \
2658 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2664 for (i = 0; i < em->tottri; i++) {
2665 BMLoop **l = em->looptris[i];
2666 if (f && l[0]->f != f) {
2667 DRAW_EM_MEASURE_STATS_FACEAREA();
2674 copy_v3_v3(v1, l[0]->v->co);
2675 copy_v3_v3(v2, l[1]->v->co);
2676 copy_v3_v3(v3, l[2]->v->co);
2677 add_v3_v3(vmid, v1);
2678 add_v3_v3(vmid, v2);
2679 add_v3_v3(vmid, v3);
2682 mul_mat3_m4_v3(ob->obmat, v1);
2683 mul_mat3_m4_v3(ob->obmat, v2);
2684 mul_mat3_m4_v3(ob->obmat, v3);
2686 area += area_tri_v3(v1, v2, v3);
2690 DRAW_EM_MEASURE_STATS_FACEAREA();
2692 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2695 if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
2697 int is_rad = unit->system_rotation == USER_UNIT_ROT_RADIANS;
2699 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2702 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2703 const int is_face_sel = BM_elem_flag_test(efa, BM_ELEM_SELECT);
2705 if (is_face_sel || do_moving) {
2708 int is_first = TRUE;
2710 BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
2711 if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
2714 /* lazy init center calc */
2716 BM_face_calc_center_bounds(efa, vmid);
2717 /* Avoid triple matrix multiply every vertex for 'global' */
2719 copy_v3_v3(v1, loop->prev->v->co);
2720 copy_v3_v3(v2, loop->v->co);
2721 mul_mat3_m4_v3(ob->obmat, v1);
2722 mul_mat3_m4_v3(ob->obmat, v2);
2728 copy_v3_v3(v3, loop->next->v->co);
2730 mul_mat3_m4_v3(ob->obmat, v3);
2732 angle = angle_v3v3v3(v1, v2, v3);
2737 angle = angle_v3v3v3(loop->prev->v->co, loop->v->co, loop->next->v->co);
2740 BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
2741 interp_v3_v3v3(fvec, vmid, loop->v->co, 0.8f);
2742 view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
2750 static void draw_em_indices(BMEditMesh *em)
2752 const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2759 unsigned char col[4];
2764 /* For now, reuse appropriate theme colors from stats text colors */
2766 if (em->selectmode & SCE_SELECT_VERTEX) {
2767 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2768 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
2769 if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
2770 sprintf(numstr, "%d", i);
2771 view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
2777 if (em->selectmode & SCE_SELECT_EDGE) {
2779 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2780 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2781 if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
2782 sprintf(numstr, "%d", i);
2783 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
2784 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2790 if (em->selectmode & SCE_SELECT_FACE) {
2792 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2793 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
2794 if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
2795 BM_face_calc_center_mean(f, pos);
2796 sprintf(numstr, "%d", i);
2797 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2804 static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
2806 BMFace *efa = EDBM_face_at_index(userData, index);
2808 if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2809 GPU_enable_material(efa->mat_nr + 1, NULL);
2810 return DM_DRAW_OPTION_NORMAL;
2813 return DM_DRAW_OPTION_SKIP;
2816 static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2818 BMFace *efa = EDBM_face_at_index(userData, index);
2820 if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
2821 return DM_DRAW_OPTION_SKIP;
2823 return DM_DRAW_OPTION_NORMAL;
2826 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
2827 Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const short dt)
2830 Mesh *me = ob->data;
2831 BMFace *efa_act = BM_active_face_get(em->bm, FALSE, FALSE); /* annoying but active faces is stored differently */
2832 BMEdge *eed_act = NULL;
2833 BMVert *eve_act = NULL;
2835 if (em->bm->selected.last) {
2836 BMEditSelection *ese = em->bm->selected.last;
2837 /* face is handeled above */
2839 if (ese->type == BM_FACE) {
2840 efa_act = (BMFace *)ese->data;
2844 if (ese->htype == BM_EDGE) {
2845 eed_act = (BMEdge *)ese->ele;
2847 else if (ese->htype == BM_VERT) {
2848 eve_act = (BMVert *)ese->ele;
2852 EDBM_index_arrays_init(em, 1, 1, 1);
2855 if (check_object_draw_texture(scene, v3d, dt)) {
2856 if (draw_glsl_material(scene, ob, v3d, dt)) {
2857 glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
2859 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2860 draw_em_fancy__setGLSLFaceOpts, em);
2861 GPU_disable_material();
2863 glFrontFace(GL_CCW);
2866 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2870 /* 3 floats for position,
2871 * 3 for normal and times two because the faces may actually be quads instead of triangles */
2872 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
2874 glEnable(GL_LIGHTING);
2875 glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
2876 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, 0);
2878 glFrontFace(GL_CCW);
2879 glDisable(GL_LIGHTING);
2880 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
2883 /* Setup for drawing wire over, disable zbuffer
2884 * write to show selected edge wires better */
2885 UI_ThemeColor(TH_WIRE);
2887 bglPolygonOffset(rv3d->dist, 1.0);
2891 if (cageDM != finalDM) {
2892 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2893 finalDM->drawEdges(finalDM, 1, 0);
2897 if (me->drawflag & ME_DRAWFACES) { /* transp faces */
2898 unsigned char col1[4], col2[4], col3[4], col4[4];
2900 UI_GetThemeColor4ubv(TH_FACE, col1);
2901 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2902 UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col3);
2903 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
2906 glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
2908 /* don't draw unselected faces, only selected, this is MUCH nicer when texturing */
2909 if (check_object_draw_texture(scene, v3d, dt))
2912 if (!(me->drawflag & ME_DRAW_FREESTYLE_FACE))
2915 draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
2917 glDisable(GL_BLEND);
2918 glDepthMask(1); /* restore write in zbuffer */
2921 /* even if draw faces is off it would be nice to draw the stipple face
2922 * Make all other faces zero alpha except for the active
2924 unsigned char col1[4], col2[4], col3[4], col4[4];
2925 col1[3] = col2[3] = col3[3] = 0; /* don't draw */
2926 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
2929 glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
2931 draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
2933 glDisable(GL_BLEND);
2934 glDepthMask(1); /* restore write in zbuffer */
2938 /* here starts all fancy draw-extra over */
2939 if ((me->drawflag & ME_DRAWEDGES) == 0 && check_object_draw_texture(scene, v3d, dt)) {
2940 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, don't draw any edges */
2942 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2943 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
2947 if (me->drawflag & ME_DRAWSEAMS) {
2948 UI_ThemeColor(TH_EDGE_SEAM);
2951 draw_dm_edges_seams(em, cageDM);
2953 glColor3ub(0, 0, 0);
2957 if (me->drawflag & ME_DRAWSHARP) {
2958 UI_ThemeColor(TH_EDGE_SHARP);
2961 draw_dm_edges_sharp(em, cageDM);
2963 glColor3ub(0, 0, 0);
2967 if(me->drawflag & ME_DRAW_FREESTYLE_EDGE) {
2968 UI_ThemeColor(TH_FREESTYLE_EDGE_MARK);
2971 draw_dm_edges_freestyle(em, cageDM);
2977 if (me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
2978 draw_dm_creases(em, cageDM);
2980 if (me->drawflag & ME_DRAWBWEIGHTS) {
2981 draw_dm_bweights(em, scene, cageDM);
2984 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
2988 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d);
2990 if (me->drawflag & ME_DRAWNORMALS) {
2991 UI_ThemeColor(TH_NORMAL);
2992 draw_dm_face_normals(em, scene, ob, cageDM);
2994 if (me->drawflag & ME_DRAW_VNORMALS) {
2995 UI_ThemeColor(TH_VNORMAL);
2996 draw_dm_vert_normals(em, scene, ob, cageDM);
2999 if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_FACEAREA | ME_DRAWEXTRA_FACEANG)) &&
3000 !(v3d->flag2 & V3D_RENDER_OVERRIDE))
3002 draw_em_measure_stats(v3d, ob, em, &scene->unit);
3005 if ((G.debug & G_DEBUG) && (me->drawflag & ME_DRAWEXTRA_INDICES) &&
3006 !(v3d->flag2 & V3D_RENDER_OVERRIDE))
3008 draw_em_indices(em);
3014 bglPolygonOffset(rv3d->dist, 0.0);
3015 GPU_disable_material();
3018 EDBM_index_arrays_free(em);
3021 /* Mesh drawing routines */
3023 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
3025 if ((v3d->transp == FALSE) && /* not when we draw the transparent pass */
3026 (ob->mode & OB_MODE_ALL_PAINT) == FALSE) /* not when painting (its distracting) - campbell */
3028 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
3031 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
3032 * drawFacesSolid() doesn't draw the transparent faces */
3033 if (ob->dtx & OB_DRAWTRANSP) {
3034 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
3035 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3036 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3037 GPU_disable_material();
3040 dm->drawEdges(dm, 0, 1);
3048 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
3049 const short dt, const unsigned char ob_wire_col[4], const short dflag)
3051 Object *ob = base->object;
3052 Mesh *me = ob->data;
3053 Material *ma = give_current_material(ob, 1);
3054 const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
3055 eWireDrawMode draw_wire = OBDRAW_WIRE_OFF;
3056 int /* totvert,*/ totedge, totface;
3057 DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
3058 const short is_obact = (ob == OBACT);
3059 int draw_flags = (is_obact && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
3064 /* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
3065 * Note: Last "preview-active" modifier in stack will win! */
3066 if (DM_get_tessface_data_layer(dm, CD_PREVIEW_MCOL) && modifiers_isPreview(ob))
3067 draw_flags |= DRAW_MODIFIERS_PREVIEW;
3069 /* Unwanted combination */
3070 if (draw_flags & DRAW_FACE_SELECT) {
3071 draw_wire = OBDRAW_WIRE_OFF;
3073 else if (ob->dtx & OB_DRAWWIRE) {
3074 draw_wire = OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
3077 /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
3078 totedge = dm->getNumEdges(dm);
3079 totface = dm->getNumTessFaces(dm);
3081 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
3082 glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
3084 if (dt == OB_BOUNDBOX) {
3085 if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
3086 draw_bounding_volume(scene, ob, ob->boundtype);
3088 else if (hasHaloMat || (totface == 0 && totedge == 0)) {
3093 else if (dt == OB_WIRE || totface == 0) {
3094 draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */
3096 else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
3097 check_object_draw_texture(scene, v3d, dt))
3099 if ((v3d->flag & V3D_SELECT_OUTLINE) &&
3100 ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
3101 (base->flag & SELECT) &&
3102 !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
3103 (draw_wire == OBDRAW_WIRE_OFF))
3105 draw_mesh_object_outline(v3d, ob, dm);
3108 if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
3109 glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
3111 dm->drawFacesGLSL(dm, GPU_enable_material);
3112 // if (BKE_bproperty_object_get(ob, "Text"))
3113 // XXX draw_mesh_text(ob, 1);
3114 GPU_disable_material();
3116 glFrontFace(GL_CCW);
3119 draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
3122 if (!(draw_flags & DRAW_FACE_SELECT)) {
3123 if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
3124 if ((dflag & DRAW_CONSTCOLOR) == 0) {
3125 glColor3ubv(ob_wire_col);
3127 dm->drawLooseEdges(dm);
3131 else if (dt == OB_SOLID) {
3132 if (draw_flags & DRAW_MODIFIERS_PREVIEW) {
3133 /* for object selection draws no shade */