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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 *****
35 #include "MEM_guardedalloc.h"
37 #include "IMB_imbuf.h"
40 #include "MTC_matrixops.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_camera_types.h"
44 #include "DNA_curve_types.h"
45 #include "DNA_constraint_types.h" // for drawing constraint
46 #include "DNA_effect_types.h"
47 #include "DNA_lamp_types.h"
48 #include "DNA_lattice_types.h"
49 #include "DNA_material_types.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_meta_types.h"
53 #include "DNA_modifier_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_object_force.h"
56 #include "DNA_object_fluidsim.h"
57 #include "DNA_particle_types.h"
58 #include "DNA_space_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_userdef_types.h"
62 #include "DNA_view3d_types.h"
63 #include "DNA_world_types.h"
65 #include "BLI_blenlib.h"
66 #include "BLI_arithb.h"
67 #include "BLI_editVert.h"
68 #include "BLI_edgehash.h"
71 #include "BKE_anim.h" //for the where_on_path function
72 #include "BKE_curve.h"
73 #include "BKE_constraint.h" // for the get_constraint_target function
74 #include "BKE_DerivedMesh.h"
75 #include "BKE_deform.h"
76 #include "BKE_displist.h"
77 #include "BKE_effect.h"
79 #include "BKE_global.h"
80 #include "BKE_image.h"
82 #include "BKE_lattice.h"
84 #include "BKE_material.h"
85 #include "BKE_mball.h"
86 #include "BKE_modifier.h"
87 #include "BKE_object.h"
88 #include "BKE_particle.h"
89 #include "BKE_property.h"
90 #include "BKE_utildefines.h"
93 #include "BIF_glutil.h"
96 #include "GPU_material.h"
97 #include "GPU_extensions.h"
100 #include "ED_particle.h"
101 #include "ED_screen.h"
102 #include "ED_types.h"
105 #include "UI_resources.h"
106 #include "UI_interface_icons.h"
111 #include "view3d_intern.h" // own include
114 /* this condition has been made more complex since editmode can draw textures */
115 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
116 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
117 (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
119 #define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \
120 ( (sce->selectmode & SCE_SELECT_FACE) && \
121 (vd->drawtype<=OB_SOLID) && \
122 (((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \
128 extern ListBase editelems;
130 static void draw_bounding_volume(Scene *scene, Object *ob);
132 static void drawcube_size(float size);
133 static void drawcircle_size(float size);
134 static void draw_empty_sphere(float size);
135 static void draw_empty_cone(float size);
138 /* ************* only use while object drawing ************** */
139 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
141 RegionView3D *rv3d= ar->regiondata;
142 float fx, fy, vec4[4];
146 /* clipplanes in eye space */
147 if(rv3d->rflag & RV3D_CLIPPING) {
149 Mat4MulVecfl(rv3d->viewmatob, vec4);
150 if(view3d_test_clipping(rv3d, vec4))
157 Mat4MulVec4fl(rv3d->persmatob, vec4);
159 /* clipplanes in window space */
160 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
161 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
163 if( fx>0 && fx<ar->winx) {
165 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
167 if(fy>0.0 && fy< (float)ar->winy) {
168 adr[0]= (short)floor(fx);
169 adr[1]= (short)floor(fy);
175 /* only use while object drawing */
176 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
178 RegionView3D *rv3d= ar->regiondata;
179 float fx, fy, vec4[4];
186 Mat4MulVec4fl(rv3d->persmatob, vec4);
188 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
189 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
191 if( fx>-32700 && fx<32700) {
193 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
195 if(fy>-32700.0 && fy<32700.0) {
196 adr[0]= (short)floor(fx);
197 adr[1]= (short)floor(fy);
203 /* ************************ */
205 /* check for glsl drawing */
207 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
209 if(!GPU_extensions_minimum_support())
213 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
215 if(ob==OBACT && (G.f & G_WEIGHTPAINT))
218 return ((G.fileflags & G_FILE_GAME_MAT) &&
219 (G.fileflags & G_FILE_GAME_MAT_GLSL) && (dt >= OB_SHADED));
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 /* flag is same as for draw_object */
331 void drawaxes(float size, int flag, char drawtype)
334 float v1[3]= {0.0, 0.0, 0.0};
335 float v2[3]= {0.0, 0.0, 0.0};
336 float v3[3]= {0.0, 0.0, 0.0};
338 if(G.f & G_RENDER_SHADOW)
344 for (axis=0; axis<3; axis++) {
345 float v1[3]= {0.0, 0.0, 0.0};
346 float v2[3]= {0.0, 0.0, 0.0};
358 case OB_SINGLE_ARROW:
361 /* in positive z direction only */
368 glBegin(GL_TRIANGLES);
370 v2[0]= size*0.035; v2[1] = size*0.035;
371 v3[0]= size*-0.035; v3[1] = size*0.035;
372 v2[2]= v3[2]= size*0.75;
374 for (axis=0; axis<4; axis++) {
396 drawcircle_size(size);
399 case OB_EMPTY_SPHERE:
400 draw_empty_sphere(size);
404 draw_empty_cone(size);
409 for (axis=0; axis<3; axis++) {
410 float v1[3]= {0.0, 0.0, 0.0};
411 float v2[3]= {0.0, 0.0, 0.0};
412 int arrow_axis= (axis==0)?1:0;
421 v1[arrow_axis]= -size*0.125;
425 v1[arrow_axis]= size*0.125;
431 v2[axis]+= size*0.125;
433 // patch for 3d cards crashing on glSelect for text drawing (IBM)
434 if((flag & DRAW_PICKING) == 0) {
436 view3d_object_text_draw_add(v2[0], v2[1], v2[2], "x", 0);
438 view3d_object_text_draw_add(v2[0], v2[1], v2[2], "y", 0);
440 view3d_object_text_draw_add(v2[0], v2[1], v2[2], "z", 0);
447 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
449 float vec[3], vx[3], vy[3];
452 VECCOPY(vx, tmat[0]);
453 VECCOPY(vy, tmat[1]);
458 for(a=0; a<tot; a++) {
459 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
460 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
461 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
467 /* circle for object centers, special_color is for library or ob users */
468 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, float *vec, int selstate, int special_color)
472 size= rv3d->persmat[0][3]*vec[0]+ rv3d->persmat[1][3]*vec[1]+ rv3d->persmat[2][3]*vec[2]+ rv3d->persmat[3][3];
473 size*= rv3d->pixsize*((float)U.obcenter_dia*0.5f);
475 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
476 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
480 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
482 else glColor4ub(0x55, 0xCC, 0xCC, 155);
485 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
486 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
487 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
489 drawcircball(GL_POLYGON, vec, size, rv3d->viewinv);
491 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
492 drawcircball(GL_LINE_LOOP, vec, size, rv3d->viewinv);
495 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
498 /* *********** text drawing for object ************* */
499 static ListBase strings= {NULL, NULL};
501 typedef struct ViewObjectString {
502 struct ViewObjectString *next, *prev;
503 float vec[3], col[4];
510 void view3d_object_text_draw_add(float x, float y, float z, char *str, short xoffs)
512 ViewObjectString *vos= MEM_callocN(sizeof(ViewObjectString), "ViewObjectString");
514 BLI_addtail(&strings, vos);
515 BLI_strncpy(vos->str, str, 128);
519 glGetFloatv(GL_CURRENT_COLOR, vos->col);
523 static void view3d_object_text_draw(View3D *v3d, ARegion *ar)
525 ViewObjectString *vos;
528 /* project first and test */
529 for(vos= strings.first; vos; vos= vos->next) {
530 view3d_project_short_clip(ar, vos->vec, vos->mval);
531 if(vos->mval[0]!=IS_CLIPPED)
536 RegionView3D *rv3d= ar->regiondata;
539 if(rv3d->rflag & RV3D_CLIPPING)
541 glDisable(GL_CLIP_PLANE0+a);
544 ED_region_pixelspace(ar);
546 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
548 for(vos= strings.first; vos; vos= vos->next) {
549 if(vos->mval[0]!=IS_CLIPPED) {
550 glColor3fv(vos->col);
551 BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], 0.0, vos->str);
555 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
559 if(rv3d->rflag & RV3D_CLIPPING)
561 glEnable(GL_CLIP_PLANE0+a);
565 BLI_freelistN(&strings);
568 void drawsolidcube(float size)
573 glScalef(size, size, size);
575 n[0]=0; n[1]=0; n[2]=0;
579 glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
586 glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
593 glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
600 glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
607 glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
614 glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
620 static void drawcube(void)
623 glBegin(GL_LINE_STRIP);
624 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
625 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
626 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
629 glBegin(GL_LINE_STRIP);
630 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
633 glBegin(GL_LINE_STRIP);
634 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
637 glBegin(GL_LINE_STRIP);
638 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
642 /* draws a cube on given the scaling of the cube, assuming that
643 * all required matrices have been set (used for drawing empties)
645 static void drawcube_size(float size)
647 glBegin(GL_LINE_STRIP);
648 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
649 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
650 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
653 glBegin(GL_LINE_STRIP);
654 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
657 glBegin(GL_LINE_STRIP);
658 glVertex3f(-size,size,size); glVertex3f(size,size,size);
661 glBegin(GL_LINE_STRIP);
662 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
666 /* this is an unused (old) cube-drawing function based on a given size */
668 static void drawcube_size(float *size)
672 glScalef(size[0], size[1], size[2]);
675 glBegin(GL_LINE_STRIP);
676 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
677 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
678 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
681 glBegin(GL_LINE_STRIP);
682 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
685 glBegin(GL_LINE_STRIP);
686 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
689 glBegin(GL_LINE_STRIP);
690 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
697 static void drawshadbuflimits(Lamp *la, float mat[][4])
699 float sta[3], end[3], lavec[3];
701 lavec[0]= -mat[2][0];
702 lavec[1]= -mat[2][1];
703 lavec[2]= -mat[2][2];
706 sta[0]= mat[3][0]+ la->clipsta*lavec[0];
707 sta[1]= mat[3][1]+ la->clipsta*lavec[1];
708 sta[2]= mat[3][2]+ la->clipsta*lavec[2];
710 end[0]= mat[3][0]+ la->clipend*lavec[0];
711 end[1]= mat[3][1]+ la->clipend*lavec[1];
712 end[2]= mat[3][2]+ la->clipend*lavec[2];
715 glBegin(GL_LINE_STRIP);
730 static void spotvolume(float *lvec, float *vvec, float inp)
732 /* camera is at 0,0,0 */
733 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
736 Normalize(vvec); /* is this the correct vector ? */
738 Crossf(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
739 Crossf(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
743 /* now we've got two equations: one of a cone and one of a plane, but we have
744 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
746 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
747 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
749 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
756 angle = saacos(plane[2])/2.0;
767 /* rotate lamp vector now over acos(inp) degrees */
775 si = sqrt(1-inp*inp);
781 Mat3MulMat3(mat3,mat2,mat1);
785 Mat3MulMat3(mat4,mat2,mat1);
788 Mat3MulMat3(mat2,mat1,mat3);
789 Mat3MulVecfl(mat2,lvec);
790 Mat3MulMat3(mat2,mat1,mat4);
791 Mat3MulVecfl(mat2,vvec);
796 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
799 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
800 float pixsize, lampsize;
801 float imat[4][4], curcol[4];
804 if(G.f & G_RENDER_SHADOW)
809 /* we first draw only the screen aligned & fixed scale stuff */
811 wmLoadMatrix(rv3d->viewmat);
813 /* lets calculate the scale: */
814 pixsize= rv3d->persmat[0][3]*ob->obmat[3][0]+ rv3d->persmat[1][3]*ob->obmat[3][1]+ rv3d->persmat[2][3]*ob->obmat[3][2]+ rv3d->persmat[3][3];
815 pixsize*= rv3d->pixsize;
816 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
818 /* and view aligned matrix: */
819 Mat4CpyMat4(imat, rv3d->viewinv);
824 glGetFloatv(GL_CURRENT_COLOR, curcol);
829 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
830 else glColor4ub(0x77, 0xCC, 0xCC, 155);
834 VECCOPY(vec, ob->obmat[3]);
836 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
838 drawcircball(GL_POLYGON, vec, lampsize, imat);
845 circrad = 3.0f*lampsize;
846 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
850 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
851 if (la->type!=LA_HEMI) {
852 if ((la->mode & LA_SHAD_RAY) ||
853 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
855 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
859 /* draw the pretty sun rays */
860 if(la->type==LA_SUN) {
861 float v1[3], v2[3], mat[3][3];
864 /* setup a 45 degree rotation matrix */
865 VecRotToMat3(imat[2], M_PI/4.0f, mat);
868 VECCOPY(v1, imat[0]);
869 VecMulf(v1, circrad*1.2f);
870 VECCOPY(v2, imat[0]);
871 VecMulf(v2, circrad*2.5f);
874 glTranslatef(vec[0], vec[1], vec[2]);
879 for (axis=0; axis<8; axis++) {
882 Mat3MulVecfl(mat, v1);
883 Mat3MulVecfl(mat, v2);
887 glTranslatef(-vec[0], -vec[1], -vec[2]);
891 if (la->type==LA_LOCAL) {
892 if(la->mode & LA_SPHERE) {
893 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
895 /* yafray: for photonlight also draw lightcone as for spot */
898 glPopMatrix(); /* back in object space */
899 vec[0]= vec[1]= vec[2]= 0.0f;
901 if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
902 lvec[0]=lvec[1]= 0.0;
904 x = rv3d->persmat[0][2];
905 y = rv3d->persmat[1][2];
906 z = rv3d->persmat[2][2];
907 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
908 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
909 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
911 y = cos( M_PI*la->spotsize/360.0 );
912 spotvolume(lvec, vvec, y);
921 /* draw the angled sides of the cone */
922 glBegin(GL_LINE_STRIP);
928 z = x*sqrt(1.0 - y*y);
931 /* draw the circle/square at the end of the cone */
932 glTranslatef(0.0, 0.0 , x);
933 if(la->mode & LA_SQUARE) {
937 glBegin(GL_LINE_LOOP);
947 else circ(0.0, 0.0, fabs(z));
949 /* draw the circle/square representing spotbl */
950 if(la->type==LA_SPOT) {
951 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
952 /* make sure the line is always visible - prevent it from reaching the outer border (or 0)
953 * values are kinda arbitrary - just what seemed to work well */
954 if (spotblcirc == 0) spotblcirc = 0.15;
955 else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
956 circ(0.0, 0.0, spotblcirc);
960 else if ELEM(la->type, LA_HEMI, LA_SUN) {
962 /* draw the line from the circle along the dist */
963 glBegin(GL_LINE_STRIP);
970 if(la->type==LA_HEMI) {
971 /* draw the hemisphere curves */
972 short axis, steps, dir;
973 float outdist, zdist, mul;
974 vec[0]=vec[1]=vec[2]= 0.0;
975 outdist = 0.14; mul = 1.4; dir = 1;
978 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
979 for (axis=0; axis<4; axis++) {
980 float v[3]= {0.0, 0.0, 0.0};
983 glBegin(GL_LINE_STRIP);
985 for (steps=0; steps<6; steps++) {
986 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
987 /* make the arcs start at the edge of the energy circle */
988 if (steps == 0) v[0] = dir*circrad;
989 else v[0] = v[0] + dir*(steps*outdist);
990 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
991 /* make the arcs start at the edge of the energy circle */
992 if (steps == 0) v[1] = dir*circrad;
993 else v[1] = v[1] + dir*(steps*outdist);
996 v[2] = v[2] - steps*zdist;
1000 zdist = zdist * mul;
1004 /* flip the direction */
1008 } else if(la->type==LA_AREA) {
1010 if(la->area_shape==LA_AREA_SQUARE)
1011 fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
1012 else if(la->area_shape==LA_AREA_RECT)
1013 fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
1015 glBegin(GL_LINE_STRIP);
1016 glVertex3f(0.0,0.0,-circrad);
1017 glVertex3f(0.0,0.0,-la->dist);
1021 /* and back to viewspace */
1022 wmLoadMatrix(rv3d->viewmat);
1023 VECCOPY(vec, ob->obmat[3]);
1027 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1028 drawshadbuflimits(la, ob->obmat);
1031 UI_GetThemeColor4ubv(TH_LAMP, col);
1032 glColor4ub(col[0], col[1], col[2], col[3]);
1036 if (vec[2]>0) vec[2] -= circrad;
1037 else vec[2] += circrad;
1039 glBegin(GL_LINE_STRIP);
1051 glDisable(GL_BLEND);
1053 /* restore for drawing extra stuff */
1058 static void draw_limit_line(float sta, float end, unsigned int col)
1061 glVertex3f(0.0, 0.0, -sta);
1062 glVertex3f(0.0, 0.0, -end);
1068 glVertex3f(0.0, 0.0, -sta);
1069 glVertex3f(0.0, 0.0, -end);
1075 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1076 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1077 static void draw_focus_cross(float dist, float size)
1080 glVertex3f(-size, 0.f, -dist);
1081 glVertex3f(size, 0.f, -dist);
1082 glVertex3f(0.f, -size, -dist);
1083 glVertex3f(0.f, size, -dist);
1087 /* flag similar to draw_object() */
1088 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1090 /* a standing up pyramid with (0,0,0) as top */
1093 float vec[8][4], tmat[4][4], fac, facx, facy, depth;
1096 if(G.f & G_RENDER_SHADOW)
1101 glDisable(GL_LIGHTING);
1102 glDisable(GL_CULL_FACE);
1104 if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
1105 facx= 0.5*cam->ortho_scale*1.28;
1106 facy= 0.5*cam->ortho_scale*1.024;
1107 depth= -cam->clipsta-0.1;
1111 if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1113 depth= - fac*cam->lens/16.0;
1118 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */
1119 vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
1120 vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
1121 vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
1122 vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
1124 glBegin(GL_LINE_LOOP);
1125 glVertex3fv(vec[1]);
1126 glVertex3fv(vec[2]);
1127 glVertex3fv(vec[3]);
1128 glVertex3fv(vec[4]);
1132 if(rv3d->persp>=2 && ob==v3d->camera) return;
1134 glBegin(GL_LINE_STRIP);
1135 glVertex3fv(vec[2]);
1136 glVertex3fv(vec[0]);
1137 glVertex3fv(vec[1]);
1138 glVertex3fv(vec[4]);
1139 glVertex3fv(vec[0]);
1140 glVertex3fv(vec[3]);
1148 /* draw an outline arrow for inactive cameras and filled
1149 * for active cameras. We actually draw both outline+filled
1150 * for active cameras so the wire can be seen side-on */
1152 if (i==0) glBegin(GL_LINE_LOOP);
1153 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1156 vec[0][0]= -0.7*cam->drawsize;
1157 vec[0][1]= 1.1*cam->drawsize;
1158 glVertex3fv(vec[0]);
1161 vec[0][1]= 1.8*cam->drawsize;
1162 glVertex3fv(vec[0]);
1164 vec[0][0]= 0.7*cam->drawsize;
1165 vec[0][1]= 1.1*cam->drawsize;
1166 glVertex3fv(vec[0]);
1172 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1173 wmLoadMatrix(rv3d->viewmat);
1174 Mat4CpyMat4(vec, ob->obmat);
1178 MTC_Mat4SwapMat4(rv3d->persmat, tmat);
1179 wmGetSingleMatrix(rv3d->persmat);
1181 if(cam->flag & CAM_SHOWLIMITS) {
1182 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1183 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1184 draw_focus_cross(dof_camera(ob), cam->drawsize);
1188 if(cam->flag & CAM_SHOWMIST)
1189 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1191 MTC_Mat4SwapMat4(rv3d->persmat, tmat);
1196 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1198 BPoint *bp = lt->def;
1199 float *co = dl?dl->verts:NULL;
1202 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1203 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1204 bglBegin(GL_POINTS);
1206 for(w=0; w<lt->pntsw; w++) {
1207 int wxt = (w==0 || w==lt->pntsw-1);
1208 for(v=0; v<lt->pntsv; v++) {
1209 int vxt = (v==0 || v==lt->pntsv-1);
1210 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1211 int uxt = (u==0 || u==lt->pntsu-1);
1212 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1214 if((bp->f1 & SELECT)==sel) {
1215 bglVertex3fv(dl?co:bp->vec);
1227 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1229 Object *obedit= vc->obedit;
1230 Lattice *lt= obedit->data;
1231 BPoint *bp = lt->editlatt->def;
1232 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1233 float *co = dl?dl->verts:NULL;
1234 int i, N = lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
1235 short s[2] = {IS_CLIPPED, 0};
1237 for (i=0; i<N; i++, bp++, co+=3) {
1239 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s);
1240 if (s[0] != IS_CLIPPED)
1241 func(userData, bp, s[0], s[1]);
1246 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1248 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1252 MDeformWeight *mdw= get_defweight (lt->dvert+index, use_wcol-1);
1254 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1260 glVertex3fv(&dl->verts[index*3]);
1262 glVertex3fv(lt->def[index].vec);
1266 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1267 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1269 Lattice *lt= ob->data;
1274 /* now we default make displist, this will modifiers work for non animated case */
1275 if(ob->disp.first==NULL)
1276 lattice_calc_modifiers(scene, ob);
1277 dl= find_displist(&ob->disp, DL_VERTS);
1282 if(ob->defbase.first && lt->dvert) {
1283 use_wcol= ob->actdef;
1284 glShadeModel(GL_SMOOTH);
1288 if(lt->editlatt) lt= lt->editlatt;
1291 for(w=0; w<lt->pntsw; w++) {
1292 int wxt = (w==0 || w==lt->pntsw-1);
1293 for(v=0; v<lt->pntsv; v++) {
1294 int vxt = (v==0 || v==lt->pntsv-1);
1295 for(u=0; u<lt->pntsu; u++) {
1296 int uxt = (u==0 || u==lt->pntsu-1);
1298 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1299 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1300 drawlattice__point(lt, dl, u, v, w, use_wcol);
1302 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1303 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1304 drawlattice__point(lt, dl, u, v, w, use_wcol);
1306 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1307 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1308 drawlattice__point(lt, dl, u, v, w, use_wcol);
1315 /* restoration for weight colors */
1317 glShadeModel(GL_FLAT);
1319 if( ((Lattice *)ob->data)->editlatt ) {
1320 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1322 lattice_draw_verts(lt, dl, 0);
1323 lattice_draw_verts(lt, dl, 1);
1325 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1329 /* ***************** ******************** */
1331 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1333 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1334 EditVert *eve = EM_get_vert_for_index(index);
1337 short s[2]= {IS_CLIPPED, 0};
1339 if (data->clipVerts) {
1340 view3d_project_short_clip(data->vc.ar, co, s);
1342 view3d_project_short_noclip(data->vc.ar, co, s);
1345 if (s[0]!=IS_CLIPPED)
1346 data->func(data->userData, eve, s[0], s[1], index);
1350 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1352 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1353 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1357 data.userData = userData;
1358 data.clipVerts = clipVerts;
1360 EM_init_index_arrays(vc->em, 1, 0, 0);
1361 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1362 EM_free_index_arrays();
1367 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1369 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;
1370 EditEdge *eed = EM_get_edge_for_index(index);
1374 if (data->clipVerts==1) {
1375 view3d_project_short_clip(data->vc.ar, v0co, s[0]);
1376 view3d_project_short_clip(data->vc.ar, v1co, s[1]);
1378 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1379 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1381 if (data->clipVerts==2) {
1382 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1383 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1388 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1392 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)
1394 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1395 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1399 data.userData = userData;
1400 data.clipVerts = clipVerts;
1402 EM_init_index_arrays(vc->em, 0, 1, 0);
1403 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1404 EM_free_index_arrays();
1409 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1411 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1412 EditFace *efa = EM_get_face_for_index(index);
1415 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1416 view3d_project_short_clip(data->vc.ar, cent, s);
1418 data->func(data->userData, efa, s[0], s[1], index);
1422 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1424 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1425 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1429 data.userData = userData;
1431 EM_init_index_arrays(vc->em, 0, 0, 1);
1432 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1433 EM_free_index_arrays();
1438 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1440 Curve *cu= vc->obedit->data;
1441 short s[2] = {IS_CLIPPED, 0};
1445 for (nu= cu->editnurb->first; nu; nu=nu->next) {
1446 if((nu->type & 7)==CU_BEZIER) {
1447 for (i=0; i<nu->pntsu; i++) {
1448 BezTriple *bezt = &nu->bezt[i];
1451 if (G.f & G_HIDDENHANDLES) {
1452 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1453 if (s[0] != IS_CLIPPED)
1454 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1456 view3d_project_short_clip(vc->ar, bezt->vec[0], s);
1457 if (s[0] != IS_CLIPPED)
1458 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1459 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1460 if (s[0] != IS_CLIPPED)
1461 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1462 view3d_project_short_clip(vc->ar, bezt->vec[2], s);
1463 if (s[0] != IS_CLIPPED)
1464 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1470 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1471 BPoint *bp = &nu->bp[i];
1474 view3d_project_short_clip(vc->ar, bp->vec, s);
1475 if (s[0] != IS_CLIPPED)
1476 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1483 /* ************** DRAW MESH ****************** */
1485 /* First section is all the "simple" draw routines,
1486 * ones that just pass some sort of primitive to GL,
1487 * with perhaps various options to control lighting,
1490 * These routines should not have user interface related
1494 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1496 Scene *scene= (Scene *)userData;
1497 EditFace *efa = EM_get_face_for_index(index);
1499 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1501 glVertex3f( cent[0] + no[0]*scene->editbutsize,
1502 cent[1] + no[1]*scene->editbutsize,
1503 cent[2] + no[2]*scene->editbutsize);
1506 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1509 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1513 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1515 EditFace *efa = EM_get_face_for_index(index);
1516 int sel = *((int*) userData);
1518 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1522 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1524 bglBegin(GL_POINTS);
1525 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1529 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1531 Scene *scene= (Scene *)userData;
1532 EditVert *eve = EM_get_vert_for_index(index);
1538 glVertex3f( co[0] + no_f[0]*scene->editbutsize,
1539 co[1] + no_f[1]*scene->editbutsize,
1540 co[2] + no_f[2]*scene->editbutsize);
1542 glVertex3f( co[0] + no_s[0]*scene->editbutsize/32767.0f,
1543 co[1] + no_s[1]*scene->editbutsize/32767.0f,
1544 co[2] + no_s[2]*scene->editbutsize/32767.0f);
1548 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1551 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1555 /* Draw verts with color set based on selection */
1556 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1558 struct { int sel; EditVert *eve_act; } * data = userData;
1559 EditVert *eve = EM_get_vert_for_index(index);
1561 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1562 /* draw active larger - need to stop/start point drawing for this :/ */
1563 if (eve==data->eve_act) {
1564 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1565 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1570 bglBegin(GL_POINTS);
1574 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1576 bglBegin(GL_POINTS);
1582 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1584 struct { int sel; EditVert *eve_act; } data;
1586 data.eve_act = eve_act;
1588 bglBegin(GL_POINTS);
1589 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1593 /* Draw edges with color set based on selection */
1594 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1596 EditEdge *eed = EM_get_edge_for_index(index);
1597 //unsigned char **cols = userData, *col;
1598 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1602 if (eed==data->eed_act) {
1603 glColor4ubv(data->actCol);
1605 if (eed->f&SELECT) {
1608 col = data->baseCol;
1610 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1611 if (col[3]==0) return 0;
1620 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1622 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1624 data.baseCol = baseCol;
1625 data.selCol = selCol;
1626 data.actCol = actCol;
1627 data.eed_act = eed_act;
1628 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1632 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1634 return EM_get_edge_for_index(index)->h==0;
1636 static void draw_dm_edges(DerivedMesh *dm)
1638 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1641 /* Draw edges with color interpolated based on selection */
1642 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1644 return EM_get_edge_for_index(index)->h==0;
1646 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1648 EditEdge *eed = EM_get_edge_for_index(index);
1649 unsigned char **cols = userData;
1650 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1651 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1653 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
1654 col0[1] + (col1[1]-col0[1])*t,
1655 col0[2] + (col1[2]-col0[2])*t,
1656 col0[3] + (col1[3]-col0[3])*t);
1658 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1660 unsigned char *cols[2];
1663 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1666 /* Draw only seam edges */
1667 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1669 EditEdge *eed = EM_get_edge_for_index(index);
1671 return (eed->h==0 && eed->seam);
1673 static void draw_dm_edges_seams(DerivedMesh *dm)
1675 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1678 /* Draw only sharp edges */
1679 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1681 EditEdge *eed = EM_get_edge_for_index(index);
1683 return (eed->h==0 && eed->sharp);
1685 static void draw_dm_edges_sharp(DerivedMesh *dm)
1687 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1691 /* Draw faces with color set based on selection
1692 * return 2 for the active face so it renders with stipple enabled */
1693 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1695 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1696 EditFace *efa = EM_get_face_for_index(index);
1700 if (efa == data->efa_act) {
1701 glColor4ubv(data->cols[2]);
1702 return 2; /* stipple */
1704 col = data->cols[(efa->f&SELECT)?1:0];
1705 if (col[3]==0) return 0;
1713 /* also draws the active face */
1714 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
1716 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1717 data.cols[0] = baseCol;
1718 data.cols[1] = selCol;
1719 data.cols[2] = actCol;
1720 data.efa_act = efa_act;
1722 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
1725 static int draw_dm_creases__setDrawOptions(void *userData, int index)
1727 EditEdge *eed = EM_get_edge_for_index(index);
1729 if (eed->h==0 && eed->crease!=0.0) {
1730 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
1736 static void draw_dm_creases(DerivedMesh *dm)
1739 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1743 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
1745 EditEdge *eed = EM_get_edge_for_index(index);
1747 if (eed->h==0 && eed->bweight!=0.0) {
1748 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1754 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1756 EditVert *eve = EM_get_vert_for_index(index);
1758 if (eve->h==0 && eve->bweight!=0.0) {
1759 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1763 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1765 if (scene->selectmode & SCE_SELECT_VERTEX) {
1766 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1767 bglBegin(GL_POINTS);
1768 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1773 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1778 /* Second section of routines: Combine first sets to form fancy
1779 * drawing routines (for example rendering twice to get overlays).
1781 * Also includes routines that are basic drawing but are too
1782 * specialized to be split out (like drawing creases or measurements).
1785 /* EditMesh drawing routines*/
1787 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
1791 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
1793 for (sel=0; sel<2; sel++) {
1794 char col[4], fcol[4];
1797 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1798 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1800 for (pass=0; pass<2; pass++) {
1801 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1802 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1805 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1806 glDisable(GL_DEPTH_TEST);
1813 size = (size>2.1?size/2.0:size);
1814 fsize = (fsize>2.1?fsize/2.0:fsize);
1815 col[3] = fcol[3] = 100;
1817 col[3] = fcol[3] = 255;
1820 if(scene->selectmode & SCE_SELECT_VERTEX) {
1822 glColor4ubv((GLubyte *)col);
1823 draw_dm_verts(cageDM, sel, eve_act);
1826 if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
1828 glColor4ubv((GLubyte *)fcol);
1829 draw_dm_face_centers(cageDM, sel);
1833 glDisable(GL_BLEND);
1834 glEnable(GL_DEPTH_TEST);
1839 if(v3d->zbuf) glDepthMask(1);
1843 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1846 unsigned char wireCol[4], selCol[4], actCol[4];
1848 /* since this function does transparant... */
1849 UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
1850 UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
1851 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
1853 /* when sel only is used, dont render wire, only selected, this is used for
1854 * textured draw mode when the 'edges' option is disabled */
1858 for (pass=0; pass<2; pass++) {
1859 /* show wires in transparant when no zbuf clipping for select */
1861 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
1863 glDisable(GL_DEPTH_TEST);
1865 if (!sel_only) wireCol[3] = 85;
1871 if (!sel_only) wireCol[3] = 255;
1874 if(scene->selectmode == SCE_SELECT_FACE) {
1875 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1877 else if( (me->drawflag & ME_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {
1878 if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
1879 glShadeModel(GL_SMOOTH);
1880 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
1881 glShadeModel(GL_FLAT);
1883 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1888 glColor4ubv(wireCol);
1889 draw_dm_edges(cageDM);
1894 glDisable(GL_BLEND);
1895 glEnable(GL_DEPTH_TEST);
1900 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em)
1905 float v1[3], v2[3], v3[3], v4[3], x, y, z;
1907 char val[32]; /* Stores the measurement display text here */
1908 char conv_float[5]; /* Use a float conversion matching the grid size */
1909 float area, col[3]; /* area of the face, color of the text to draw */
1911 if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
1914 /* make the precission of the pronted value proportionate to the gridsize */
1915 if ((v3d->grid) < 0.01)
1916 strcpy(conv_float, "%.6f");
1917 else if ((v3d->grid) < 0.1)
1918 strcpy(conv_float, "%.5f");
1919 else if ((v3d->grid) < 1.0)
1920 strcpy(conv_float, "%.4f");
1921 else if ((v3d->grid) < 10.0)
1922 strcpy(conv_float, "%.3f");
1924 strcpy(conv_float, "%.2f");
1927 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
1928 glDisable(GL_DEPTH_TEST);
1930 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0);
1932 if(me->drawflag & ME_DRAW_EDGELEN) {
1933 UI_GetThemeColor3fv(TH_TEXT, col);
1934 /* make color a bit more red */
1935 if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1936 else col[0]= col[0]*0.7 + 0.3;
1939 for(eed= em->edges.first; eed; eed= eed->next) {
1940 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1941 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1942 VECCOPY(v1, eed->v1->co);
1943 VECCOPY(v2, eed->v2->co);
1945 x= 0.5*(v1[0]+v2[0]);
1946 y= 0.5*(v1[1]+v2[1]);
1947 z= 0.5*(v1[2]+v2[2]);
1949 if(v3d->flag & V3D_GLOBAL_STATS) {
1950 Mat4MulVecfl(ob->obmat, v1);
1951 Mat4MulVecfl(ob->obmat, v2);
1954 sprintf(val, conv_float, VecLenf(v1, v2));
1955 view3d_object_text_draw_add(x, y, z, val, 0);
1960 if(me->drawflag & ME_DRAW_FACEAREA) {
1961 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
1963 UI_GetThemeColor3fv(TH_TEXT, col);
1964 /* make color a bit more green */
1965 if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
1966 else col[1]= col[1]*0.7 + 0.3;
1969 for(efa= em->faces.first; efa; efa= efa->next) {
1970 if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
1971 VECCOPY(v1, efa->v1->co);
1972 VECCOPY(v2, efa->v2->co);
1973 VECCOPY(v3, efa->v3->co);
1975 VECCOPY(v4, efa->v4->co);
1977 if(v3d->flag & V3D_GLOBAL_STATS) {
1978 Mat4MulVecfl(ob->obmat, v1);
1979 Mat4MulVecfl(ob->obmat, v2);
1980 Mat4MulVecfl(ob->obmat, v3);
1981 if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1985 area= AreaQ3Dfl(v1, v2, v3, v4);
1987 area = AreaT3Dfl(v1, v2, v3);
1989 sprintf(val, conv_float, area);
1990 view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
1995 if(me->drawflag & ME_DRAW_EDGEANG) {
1996 EditEdge *e1, *e2, *e3, *e4;
1998 UI_GetThemeColor3fv(TH_TEXT, col);
1999 /* make color a bit more blue */
2000 if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
2001 else col[2]= col[2]*0.7 + 0.3;
2004 for(efa= em->faces.first; efa; efa= efa->next) {
2005 VECCOPY(v1, efa->v1->co);
2006 VECCOPY(v2, efa->v2->co);
2007 VECCOPY(v3, efa->v3->co);
2009 VECCOPY(v4, efa->v4->co);
2014 if(v3d->flag & V3D_GLOBAL_STATS) {
2015 Mat4MulVecfl(ob->obmat, v1);
2016 Mat4MulVecfl(ob->obmat, v2);
2017 Mat4MulVecfl(ob->obmat, v3);
2018 Mat4MulVecfl(ob->obmat, v4);
2024 if(efa->e4) e4= efa->e4; else e4= e3;
2026 /* Calculate the angles */
2028 if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
2030 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
2031 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
2032 view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2034 if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
2036 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
2037 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
2038 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2040 if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2043 sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
2045 sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
2046 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
2047 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2051 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2052 sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
2053 VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
2054 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2061 glEnable(GL_DEPTH_TEST);
2062 bglPolygonOffset(rv3d->dist, 0.0);
2066 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2068 EditFace *efa = EM_get_face_for_index(index);
2071 GPU_enable_material(efa->mat_nr+1, NULL);
2078 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2080 EditFace *efa = EM_get_face_for_index(index);
2085 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2087 Mesh *me = ob->data;
2088 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2089 EditEdge *eed_act = NULL;
2090 EditVert *eve_act = NULL;
2092 if (em->selected.last) {
2093 EditSelection *ese = em->selected.last;
2094 /* face is handeled above */
2095 /*if (ese->type == EDITFACE ) {
2096 efa_act = (EditFace *)ese->data;
2097 } else */ if ( ese->type == EDITEDGE ) {
2098 eed_act = (EditEdge *)ese->data;
2099 } else if ( ese->type == EDITVERT ) {
2100 eve_act = (EditVert *)ese->data;
2104 EM_init_index_arrays(em, 1, 1, 1);
2107 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2108 if(draw_glsl_material(scene, ob, v3d, dt)) {
2109 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2111 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2112 draw_em_fancy__setGLSLFaceOpts, NULL);
2113 GPU_disable_material();
2115 glFrontFace(GL_CCW);
2118 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2122 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2124 glEnable(GL_LIGHTING);
2125 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2127 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2129 glFrontFace(GL_CCW);
2130 glDisable(GL_LIGHTING);
2133 // Setup for drawing wire over, disable zbuffer
2134 // write to show selected edge wires better
2135 UI_ThemeColor(TH_WIRE);
2137 bglPolygonOffset(rv3d->dist, 1.0);
2141 if (cageDM!=finalDM) {
2142 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2143 finalDM->drawEdges(finalDM, 1);
2147 if((me->drawflag & (ME_DRAWFACES)) || FACESEL_PAINT_TEST) { /* transp faces */
2148 unsigned char col1[4], col2[4], col3[4];
2150 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2151 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2152 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2155 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2157 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2158 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2161 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2163 glDisable(GL_BLEND);
2164 glDepthMask(1); // restore write in zbuffer
2165 } else if (efa_act) {
2166 /* even if draw faces is off it would be nice to draw the stipple face
2167 * Make all other faces zero alpha except for the active
2169 unsigned char col1[4], col2[4], col3[4];
2170 col1[3] = col2[3] = 0; /* dont draw */
2171 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2174 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2176 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2178 glDisable(GL_BLEND);
2179 glDepthMask(1); // restore write in zbuffer
2183 /* here starts all fancy draw-extra over */
2184 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2185 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2187 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2188 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2191 if(me->drawflag & ME_DRAWSEAMS) {
2192 UI_ThemeColor(TH_EDGE_SEAM);
2195 draw_dm_edges_seams(cageDM);
2201 if(me->drawflag & ME_DRAWSHARP) {
2202 UI_ThemeColor(TH_EDGE_SHARP);
2205 draw_dm_edges_sharp(cageDM);
2211 if(me->drawflag & ME_DRAWCREASES) {
2212 draw_dm_creases(cageDM);
2214 if(me->drawflag & ME_DRAWBWEIGHTS) {
2215 draw_dm_bweights(scene, cageDM);
2218 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2221 // XXX retopo_matrix_update(v3d);
2223 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2225 if(me->drawflag & ME_DRAWNORMALS) {
2226 UI_ThemeColor(TH_NORMAL);
2227 draw_dm_face_normals(scene, cageDM);
2229 if(me->drawflag & ME_DRAW_VNORMALS) {
2230 UI_ThemeColor(TH_NORMAL);
2231 draw_dm_vert_normals(scene, cageDM);
2234 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2235 draw_em_measure_stats(v3d, rv3d, ob, em);
2240 bglPolygonOffset(rv3d->dist, 0.0);
2241 GPU_disable_material();
2244 EM_free_index_arrays();
2247 /* Mesh drawing routines */
2249 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2252 if(v3d->transp==0) { // not when we draw the transparent pass
2256 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2257 drawFacesSolid() doesn't draw the transparent faces */
2258 if(ob->dtx & OB_DRAWTRANSP) {
2259 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2260 dm->drawFacesSolid(dm, GPU_enable_material);
2261 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2262 GPU_disable_material();
2265 dm->drawEdges(dm, 0);
2273 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2279 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2281 Object *ob= base->object;
2282 Mesh *me = ob->data;
2283 Material *ma= give_current_material(ob, 1);
2284 int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2286 int totvert, totedge, totface;
2288 DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2293 if (ob->dtx&OB_DRAWWIRE) {
2294 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2297 totvert = dm->getNumVerts(dm);
2298 totedge = dm->getNumEdges(dm);
2299 totface = dm->getNumFaces(dm);
2301 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2303 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2305 // Unwanted combination.
2306 if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
2308 if(dt==OB_BOUNDBOX) {
2309 draw_bounding_volume(scene, ob);
2311 else if(hasHaloMat || (totface==0 && totedge==0)) {
2316 else if(dt==OB_WIRE || totface==0) {
2317 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2319 else if( (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
2320 CHECK_OB_DRAWTEXTURE(v3d, dt))
2322 int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
2324 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
2325 draw_mesh_object_outline(v3d, ob, dm);
2328 if(draw_glsl_material(scene, ob, v3d, dt)) {
2329 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2331 dm->drawFacesGLSL(dm, GPU_enable_material);
2332 // if(get_ob_property(ob, "Text"))
2333 // XXX draw_mesh_text(ob, 1);
2334 GPU_disable_material();
2336 glFrontFace(GL_CCW);
2339 draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2343 if(base->flag & SELECT)
2344 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2346 UI_ThemeColor(TH_WIRE);
2348 dm->drawLooseEdges(dm);
2351 else if(dt==OB_SOLID) {
2352 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2353 draw_mesh_object_outline(v3d, ob, dm);
2355 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2357 glEnable(GL_LIGHTING);
2358 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2360 dm->drawFacesSolid(dm, GPU_enable_material);
2361 GPU_disable_material();
2363 glFrontFace(GL_CCW);
2364 glDisable(GL_LIGHTING);
2366 if(base->flag & SELECT) {
2367 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2369 UI_ThemeColor(TH_WIRE);
2371 dm->drawLooseEdges(dm);
2373 else if(dt==OB_SHADED) {
2374 int do_draw= 1; /* to resolve all G.f settings below... */
2378 if( (G.f & G_WEIGHTPAINT)) {
2379 /* enforce default material settings */
2380 GPU_enable_material(0, NULL);
2382 /* but set default spec */
2383 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2384 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2385 glColor3ub(120, 120, 120);
2386 glDisable(GL_COLOR_MATERIAL);
2388 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2389 glEnable(GL_LIGHTING);
2390 glEnable(GL_COLOR_MATERIAL);
2392 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2393 glDisable(GL_COLOR_MATERIAL);
2394 glDisable(GL_LIGHTING);
2396 GPU_disable_material();
2398 else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
2399 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2401 else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
2402 glColor3f(1.0f, 1.0f, 1.0f);
2403 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2408 dl = ob->disp.first;
2409 if (!dl || !dl->col1) {
2410 /* release and reload derivedmesh because it might be freed in
2411 shadeDispList due to a different datamask */
2413 shadeDispList(scene, base);
2414 dl = find_displist(&ob->disp, DL_VERTCOL);
2415 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2418 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2419 draw_mesh_object_outline(v3d, ob, dm);
2422 /* False for dupliframe objects */
2424 unsigned int *obCol1 = dl->col1;
2425 unsigned int *obCol2 = dl->col2;
2427 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2430 if(base->flag & SELECT) {
2431 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2433 UI_ThemeColor(TH_WIRE);
2435 dm->drawLooseEdges(dm);
2439 /* set default draw color back for wire or for draw-extra later on */
2441 if(base->flag & SELECT) {
2442 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2443 UI_ThemeColor(TH_GROUP_ACTIVE);
2444 else if(ob->flag & OB_FROMGROUP)
2445 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2446 else if(flag!=DRAW_CONSTCOLOR)
2447 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2449 glColor3ub(80,80,80);
2451 if (ob->flag & OB_FROMGROUP)
2452 UI_ThemeColor(TH_GROUP);
2454 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2455 glColor3ub(80,80,80);
2457 UI_ThemeColor(TH_WIRE);
2462 /* If drawing wire and drawtype is not OB_WIRE then we are
2463 * overlaying the wires.
2465 * UPDATE bug #10290 - With this wire-only objects can draw
2466 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2468 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2469 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2471 if (dt!=OB_WIRE && draw_wire==2) {
2472 bglPolygonOffset(rv3d->dist, 1.0);
2473 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2476 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2478 if (dt!=OB_WIRE && draw_wire==2) {
2480 bglPolygonOffset(rv3d->dist, 0.0);
2487 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2488 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2490 Object *ob= base->object;
2491 Object *obedit= scene->obedit;
2493 EditMesh *em= me->edit_mesh;
2494 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2496 if(obedit && ob!=obedit && ob->data==obedit->data) {
2501 if(ob==obedit || drawlinked) {
2502 DerivedMesh *finalDM, *cageDM;
2505 finalDM = cageDM = editmesh_get_derived_base(ob, em);
2507 cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2508 v3d->customdata_mask);
2511 // no transp in editmode, the fancy draw over goes bad then
2512 glsl = draw_glsl_material(scene, ob, v3d, dt);
2513 GPU_set_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2516 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2518 if (obedit!=ob && finalDM)
2519 finalDM->release(finalDM);
2521 // else if(!em && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2522 // OBACT==ob && !sculpt_modifiers_active(ob)) {
2523 // XXX sculptmode_draw_mesh(0);
2526 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2527 if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2528 glsl = draw_glsl_material(scene, ob, v3d, dt);
2529 check_alpha = check_material_alpha(base, me, glsl);
2531 if(dt==OB_SOLID || glsl) {
2532 GPU_set_object_materials(v3d, rv3d, scene, ob, glsl,
2533 (check_alpha)? &do_alpha_pass: NULL);
2536 draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag);
2538 if(me->totvert==0) retval= 1;
2542 /* GPU_set_object_materials checked if this is needed */
2543 if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
2548 /* ************** DRAW DISPLIST ****************** */
2550 static int draw_index_wire= 1;
2551 static int index3_nors_incr= 1;
2553 /* returns 1 when nothing was drawn */
2554 static int drawDispListwire(ListBase *dlbase)
2560 if(dlbase==NULL) return 1;
2562 glDisableClientState(GL_NORMAL_ARRAY);
2563 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2565 for(dl= dlbase->first; dl; dl= dl->next) {
2566 if(dl->parts==0 || dl->nr==0)
2574 glVertexPointer(3, GL_FLOAT, 0, data);
2576 for(parts=0; parts<dl->parts; parts++)
2577 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2582 glVertexPointer(3, GL_FLOAT, 0, data);
2584 for(parts=0; parts<dl->parts; parts++)
2585 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2590 glVertexPointer(3, GL_FLOAT, 0, data);
2592 for(parts=0; parts<dl->parts; parts++) {
2593 if(dl->flag & DL_CYCL_U)
2594 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2596 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2599 for(nr=0; nr<dl->nr; nr++) {
2602 data= ( dl->verts )+3*nr;
2605 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2606 else glBegin(GL_LINE_STRIP);
2614 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2615 // glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2616 // if(dl->flag & DL_CYCL_V)
2617 // glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2619 // glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2624 if(draw_index_wire) {
2625 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2626 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2631 if(draw_index_wire) {
2632 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2633 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2639 glEnableClientState(GL_NORMAL_ARRAY);
2640 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2645 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2648 GPUVertexAttribs gattribs;
2649 float *data, curcol[4];
2652 if(lb==NULL) return;
2654 /* for drawing wire */
2655 glGetFloatv(GL_CURRENT_COLOR, curcol);
2657 glEnable(GL_LIGHTING);
2659 if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2660 else glFrontFace(GL_CCW);
2662 if(ob->type==OB_MBALL) { // mball always smooth shaded
2663 glShadeModel(GL_SMOOTH);
2673 if(ob->type==OB_SURF) {
2676 glDisable(GL_LIGHTING);
2679 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2680 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2682 glBegin(GL_LINE_STRIP);
2683 for(nr= dl->nr; nr; nr--, data+=3)
2687 glEnable(GL_LIGHTING);
2691 if(ob->type==OB_SURF) {
2694 UI_ThemeColor(TH_WIRE);
2695 glDisable(GL_LIGHTING);
2697 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2698 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2699 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2701 glBegin(GL_LINE_LOOP);
2702 for(nr= dl->nr; nr; nr--, data+=3)
2706 glEnable(GL_LIGHTING);
2712 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2714 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2715 else glShadeModel(GL_FLAT);
2717 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2718 glNormalPointer(GL_FLOAT, 0, dl->nors);
2719 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2720 GPU_disable_material();
2725 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2727 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2729 /* voor polys only one normal needed */
2730 if(index3_nors_incr==0) {
2731 glDisableClientState(GL_NORMAL_ARRAY);
2735 glNormalPointer(GL_FLOAT, 0, dl->nors);
2737 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2738 GPU_disable_material();
2740 if(index3_nors_incr==0)
2741 glEnableClientState(GL_NORMAL_ARRAY);
2746 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2748 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2749 glNormalPointer(GL_FLOAT, 0, dl->nors);
2750 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2752 GPU_disable_material();
2759 glShadeModel(GL_FLAT);
2760 glDisable(GL_LIGHTING);
2761 glFrontFace(GL_CCW);
2764 static void drawDispListshaded(ListBase *lb, Object *ob)
2766 DispList *dl, *dlob;
2767 unsigned int *cdata;
2769 if(lb==NULL) return;
2771 glShadeModel(GL_SMOOTH);
2772 glDisableClientState(GL_NORMAL_ARRAY);
2773 glEnableClientState(GL_COLOR_ARRAY);
2776 dlob= ob->disp.first;
2780 if(cdata==NULL) break;
2785 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2786 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2787 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2793 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2794 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2795 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2800 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2801 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2802 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2810 glShadeModel(GL_FLAT);
2811 glEnableClientState(GL_NORMAL_ARRAY);
2812 glDisableClientState(GL_COLOR_ARRAY);
2815 /* returns 1 when nothing was drawn */
2816 static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
2818 Object *ob= base->object;
2822 int solid, retval= 0;
2824 solid= (dt > OB_WIRE);
2835 if(dl==NULL) return 1;
2837 if(dl->nors==0) addnormalsDispList(ob, lb);
2838 index3_nors_incr= 0;
2840 if( displist_has_faces(lb)==0) {
2842 drawDispListwire(lb);
2846 if(draw_glsl_material(scene, ob, v3d, dt)) {
2847 GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2848 drawDispListsolid(lb, ob, 1);
2850 else if(dt == OB_SHADED) {
2851 if(ob->disp.first==0) shadeDispList(scene, base);
2852 drawDispListshaded(lb, ob);
2855 GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2856 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2857 drawDispListsolid(lb, ob, 0);
2859 if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
2862 drawDispListwire(lb);
2866 index3_nors_incr= 1;
2870 retval= drawDispListwire(lb);
2876 lb= &((Curve *)ob->data)->disp;
2880 if(dl==NULL) return 1;
2882 if(dl->nors==NULL) addnormalsDispList(ob, lb);
2884 if(draw_glsl_material(scene, ob, v3d, dt)) {
2885 GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2886 drawDispListsolid(lb, ob, 1);
2888 else if(dt==OB_SHADED) {
2889 if(ob->disp.first==NULL) shadeDispList(scene, base);
2890 drawDispListshaded(lb, ob);
2893 GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2894 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2896 drawDispListsolid(lb, ob, 0);
2900 retval= drawDispListwire(lb);
2905 if( is_basis_mball(ob)) {
2907 if(lb->first==NULL) makeDispListMBall(scene, ob);
2908 if(lb->first==NULL) return 1;
2912 if(draw_glsl_material(scene, ob, v3d, dt)) {
2913 GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2914 drawDispListsolid(lb, ob, 1);
2916 else if(dt == OB_SHADED) {
2918 if(dl && dl->col1==0) shadeDispList(scene, base);
2919 drawDispListshaded(lb, ob);
2922 GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2923 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2925 drawDispListsolid(lb, ob, 0);
2929 /* MetaBalls use DL_INDEX4 type of DispList */
2930 retval= drawDispListwire(lb);
2939 /* unified drawing of all new particle systems draw types except dupli ob & group */
2940 /* mostly tries to use vertex arrays for speed */
2942 /* 1. check that everything is ok & updated */
2943 /* 2. start initialising things */
2944 /* 3. initialize according to draw type */
2945 /* 4. allocate drawing data arrays */
2946 /* 5. start filling the arrays */
2947 /* 6. draw the arrays */
2949 static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, int dt)
2951 Object *ob=base->object;
2952 ParticleSystemModifierData *psmd;
2953 ParticleSettings *part;
2954 ParticleData *pars, *pa;
2955 ParticleKey state, *states=0;
2956 ParticleBillboardData bb;
2958 float vel[3], vec[3], vec2[3], imat[4][4], bb_center[3];
2959 float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
2960 float cfra= bsystem_time(scene, ob,(float)CFRA,0.0);
2961 float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
2962 float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
2963 int a, totpart, totpoint=0, draw_as, totchild=0;
2964 int select=ob->flag&SELECT, create_cdata=0;
2965 GLint polygonmode[2];
2973 pars=psys->particles;
2975 if(part==0 || !psys_check_enabled(ob, psys))
2980 // XXX what logic is this?
2981 if(!scene->obedit && psys_in_edit_mode(scene, psys)
2982 && psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
2985 if(part->draw_as==PART_DRAW_NOT) return;
2988 if(part->phystype==PART_PHYS_KEYED){
2989 if(psys->flag & PSYS_FIRST_KEYED){
2990 if(psys->flag&PSYS_KEYED){
2991 select=psys_count_keyed_targets(ob,psys);
2992 if(psys->totkeyed==0)