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"
39 #include "IMB_imbuf.h"
42 #include "MTC_matrixops.h"
44 #include "DNA_armature_types.h"
45 #include "DNA_camera_types.h"
46 #include "DNA_curve_types.h"
47 #include "DNA_constraint_types.h" // for drawing constraint
48 #include "DNA_effect_types.h"
49 #include "DNA_ipo_types.h"
50 #include "DNA_lamp_types.h"
51 #include "DNA_lattice_types.h"
52 #include "DNA_material_types.h"
53 #include "DNA_mesh_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_meta_types.h"
56 #include "DNA_modifier_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_object_force.h"
59 #include "DNA_particle_types.h"
60 #include "DNA_space_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_screen_types.h"
63 #include "DNA_userdef_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_world_types.h"
67 #include "DNA_object_fluidsim.h"
69 #include "BLI_blenlib.h"
70 #include "BLI_arithb.h"
71 #include "BLI_editVert.h"
72 #include "BLI_edgehash.h"
75 #include "BKE_anim.h" //for the where_on_path function
76 #include "BKE_curve.h"
77 #include "BKE_constraint.h" // for the get_constraint_target function
78 #include "BKE_DerivedMesh.h"
79 #include "BKE_deform.h"
80 #include "BKE_displist.h"
81 #include "BKE_effect.h"
83 #include "BKE_global.h"
84 #include "BKE_image.h"
87 #include "BKE_lattice.h"
89 #include "BKE_material.h"
90 #include "BKE_mball.h"
91 #include "BKE_modifier.h"
92 #include "BKE_object.h"
93 #include "BKE_particle.h"
94 #include "BKE_property.h"
95 #include "BKE_utildefines.h"
98 #include "BIF_glutil.h"
100 #include "GPU_draw.h"
101 #include "GPU_material.h"
102 #include "GPU_extensions.h"
104 #include "ED_types.h"
107 #include "UI_resources.h"
108 #include "UI_interface_icons.h"
112 #include "view3d_intern.h" // own include
116 /* extern Lattice *editLatt; already in BKE_lattice.h */
118 extern ListBase editNurb;
120 extern ListBase editelems;
122 static void draw_bounding_volume(Object *ob);
124 static void drawcube_size(float size);
125 static void drawcircle_size(float size);
126 static void draw_empty_sphere(float size);
127 static void draw_empty_cone(float size);
129 EditVert *EM_get_vert_for_index(int x) {return 0;} // XXX
130 EditEdge *EM_get_edge_for_index(int x) {return 0;} // XXX
131 EditFace *EM_get_face_for_index(int x) {return 0;} // XXX
132 void EM_init_index_arrays(int x, int y, int z) {} // XXX
133 void EM_free_index_arrays(void) {} // XXX
135 EditFace *EM_get_actFace(int x) {return NULL;} // XXX
136 int em_solidoffs; // XXX
140 /* check for glsl drawing */
142 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
144 if(!GPU_extensions_minimum_support())
148 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
150 if(ob==OBACT && (G.f & G_WEIGHTPAINT))
153 return ((G.fileflags & G_FILE_GAME_MAT) &&
154 (G.fileflags & G_FILE_GAME_MAT_GLSL) && (dt >= OB_SHADED));
157 static int check_material_alpha(Base *base, Object *ob, int glsl)
159 if(base->flag & OB_FROMDUPLI)
165 if(G.obedit && G.obedit->data==ob->data)
168 return (glsl || (ob->dtx & OB_DRAWTRANSP));
172 static unsigned int colortab[24]=
173 {0x0, 0xFF88FF, 0xFFBBFF,
174 0x403000, 0xFFFF88, 0xFFFFBB,
175 0x104040, 0x66CCCC, 0x77CCCC,
176 0x104010, 0x55BB55, 0x66FF66,
181 static float cube[8][3] = {
192 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
193 /* 32 values of sin function (still same result!) */
194 static float sinval[32] = {
229 /* 32 values of cos function (still same result!) */
230 static float cosval[32] ={
265 /* flag is same as for draw_object */
266 void drawaxes(float size, int flag, char drawtype)
269 float v1[3]= {0.0, 0.0, 0.0};
270 float v2[3]= {0.0, 0.0, 0.0};
271 float v3[3]= {0.0, 0.0, 0.0};
273 if(G.f & G_RENDER_SHADOW)
279 for (axis=0; axis<3; axis++) {
280 float v1[3]= {0.0, 0.0, 0.0};
281 float v2[3]= {0.0, 0.0, 0.0};
293 case OB_SINGLE_ARROW:
296 /* in positive z direction only */
303 glBegin(GL_TRIANGLES);
305 v2[0]= size*0.035; v2[1] = size*0.035;
306 v3[0]= size*-0.035; v3[1] = size*0.035;
307 v2[2]= v3[2]= size*0.75;
309 for (axis=0; axis<4; axis++) {
331 drawcircle_size(size);
334 case OB_EMPTY_SPHERE:
335 draw_empty_sphere(size);
339 draw_empty_cone(size);
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};
347 int arrow_axis= (axis==0)?1:0;
356 v1[arrow_axis]= -size*0.125;
360 v1[arrow_axis]= size*0.125;
366 v2[axis]+= size*0.125;
369 // patch for 3d cards crashing on glSelect for text drawing (IBM)
370 if((flag & DRAW_PICKING) == 0) {
372 BMF_DrawString(G.font, "x");
374 BMF_DrawString(G.font, "y");
376 BMF_DrawString(G.font, "z");
383 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
385 float vec[3], vx[3], vy[3];
388 VECCOPY(vx, tmat[0]);
389 VECCOPY(vy, tmat[1]);
394 for(a=0; a<tot; a++) {
395 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
396 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
397 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
403 /* circle for object centers, special_color is for library or ob users */
404 static void drawcentercircle(View3D *v3d, float *vec, int selstate, int special_color)
408 size= v3d->persmat[0][3]*vec[0]+ v3d->persmat[1][3]*vec[1]+ v3d->persmat[2][3]*vec[2]+ v3d->persmat[3][3];
409 size*= v3d->pixsize*((float)U.obcenter_dia*0.5f);
411 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
412 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
416 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
418 else glColor4ub(0x55, 0xCC, 0xCC, 155);
421 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
422 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
423 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
425 drawcircball(GL_POLYGON, vec, size, v3d->viewinv);
427 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
428 drawcircball(GL_LINE_LOOP, vec, size, v3d->viewinv);
431 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
435 void drawsolidcube(float size)
440 glScalef(size, size, size);
442 n[0]=0; n[1]=0; n[2]=0;
446 glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
453 glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
460 glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
467 glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
474 glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
481 glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
487 static void drawcube(void)
490 glBegin(GL_LINE_STRIP);
491 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
492 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
493 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
496 glBegin(GL_LINE_STRIP);
497 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
500 glBegin(GL_LINE_STRIP);
501 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
504 glBegin(GL_LINE_STRIP);
505 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
509 /* draws a cube on given the scaling of the cube, assuming that
510 * all required matrices have been set (used for drawing empties)
512 static void drawcube_size(float size)
514 glBegin(GL_LINE_STRIP);
515 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
516 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
517 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
520 glBegin(GL_LINE_STRIP);
521 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
524 glBegin(GL_LINE_STRIP);
525 glVertex3f(-size,size,size); glVertex3f(size,size,size);
528 glBegin(GL_LINE_STRIP);
529 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
533 /* this is an unused (old) cube-drawing function based on a given size */
535 static void drawcube_size(float *size)
539 glScalef(size[0], size[1], size[2]);
542 glBegin(GL_LINE_STRIP);
543 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
544 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
545 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
548 glBegin(GL_LINE_STRIP);
549 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
552 glBegin(GL_LINE_STRIP);
553 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
556 glBegin(GL_LINE_STRIP);
557 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
564 static void drawshadbuflimits(Lamp *la, float mat[][4])
566 float sta[3], end[3], lavec[3];
568 lavec[0]= -mat[2][0];
569 lavec[1]= -mat[2][1];
570 lavec[2]= -mat[2][2];
573 sta[0]= mat[3][0]+ la->clipsta*lavec[0];
574 sta[1]= mat[3][1]+ la->clipsta*lavec[1];
575 sta[2]= mat[3][2]+ la->clipsta*lavec[2];
577 end[0]= mat[3][0]+ la->clipend*lavec[0];
578 end[1]= mat[3][1]+ la->clipend*lavec[1];
579 end[2]= mat[3][2]+ la->clipend*lavec[2];
582 glBegin(GL_LINE_STRIP);
597 static void spotvolume(float *lvec, float *vvec, float inp)
599 /* camera is at 0,0,0 */
600 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
603 Normalize(vvec); /* is this the correct vector ? */
605 Crossf(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
606 Crossf(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
610 /* now we've got two equations: one of a cone and one of a plane, but we have
611 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
613 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
614 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
616 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
623 angle = saacos(plane[2])/2.0;
634 /* rotate lamp vector now over acos(inp) degrees */
642 si = sqrt(1-inp*inp);
648 Mat3MulMat3(mat3,mat2,mat1);
652 Mat3MulMat3(mat4,mat2,mat1);
655 Mat3MulMat3(mat2,mat1,mat3);
656 Mat3MulVecfl(mat2,lvec);
657 Mat3MulMat3(mat2,mat1,mat4);
658 Mat3MulVecfl(mat2,vvec);
663 static void drawlamp(Scene *scene, View3D *v3d, Object *ob)
666 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
667 float pixsize, lampsize;
668 float imat[4][4], curcol[4];
671 if(G.f & G_RENDER_SHADOW)
676 /* we first draw only the screen aligned & fixed scale stuff */
678 wmLoadMatrix(v3d->viewmat);
680 /* lets calculate the scale: */
681 pixsize= v3d->persmat[0][3]*ob->obmat[3][0]+ v3d->persmat[1][3]*ob->obmat[3][1]+ v3d->persmat[2][3]*ob->obmat[3][2]+ v3d->persmat[3][3];
682 pixsize*= v3d->pixsize;
683 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
685 /* and view aligned matrix: */
686 Mat4CpyMat4(imat, v3d->viewinv);
691 glGetFloatv(GL_CURRENT_COLOR, curcol);
696 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
697 else glColor4ub(0x77, 0xCC, 0xCC, 155);
701 VECCOPY(vec, ob->obmat[3]);
703 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
705 drawcircball(GL_POLYGON, vec, lampsize, imat);
712 circrad = 3.0f*lampsize;
713 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
717 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
718 if (la->type!=LA_HEMI) {
719 if ((la->mode & LA_SHAD_RAY) ||
720 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
722 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
726 /* draw the pretty sun rays */
727 if(la->type==LA_SUN) {
728 float v1[3], v2[3], mat[3][3];
731 /* setup a 45 degree rotation matrix */
732 VecRotToMat3(imat[2], M_PI/4.0f, mat);
735 VECCOPY(v1, imat[0]);
736 VecMulf(v1, circrad*1.2f);
737 VECCOPY(v2, imat[0]);
738 VecMulf(v2, circrad*2.5f);
741 glTranslatef(vec[0], vec[1], vec[2]);
746 for (axis=0; axis<8; axis++) {
749 Mat3MulVecfl(mat, v1);
750 Mat3MulVecfl(mat, v2);
754 glTranslatef(-vec[0], -vec[1], -vec[2]);
758 if (la->type==LA_LOCAL) {
759 if(la->mode & LA_SPHERE) {
760 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
762 /* yafray: for photonlight also draw lightcone as for spot */
765 glPopMatrix(); /* back in object space */
766 vec[0]= vec[1]= vec[2]= 0.0f;
768 if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
769 lvec[0]=lvec[1]= 0.0;
771 x = v3d->persmat[0][2];
772 y = v3d->persmat[1][2];
773 z = v3d->persmat[2][2];
774 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
775 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
776 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
778 y = cos( M_PI*la->spotsize/360.0 );
779 spotvolume(lvec, vvec, y);
788 /* draw the angled sides of the cone */
789 glBegin(GL_LINE_STRIP);
795 z = x*sqrt(1.0 - y*y);
798 /* draw the circle/square at the end of the cone */
799 glTranslatef(0.0, 0.0 , x);
800 if(la->mode & LA_SQUARE) {
804 glBegin(GL_LINE_LOOP);
814 else circ(0.0, 0.0, fabs(z));
816 /* draw the circle/square representing spotbl */
817 if(la->type==LA_SPOT) {
818 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
819 /* make sure the line is always visible - prevent it from reaching the outer border (or 0)
820 * values are kinda arbitrary - just what seemed to work well */
821 if (spotblcirc == 0) spotblcirc = 0.15;
822 else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
823 circ(0.0, 0.0, spotblcirc);
827 else if ELEM(la->type, LA_HEMI, LA_SUN) {
829 /* draw the line from the circle along the dist */
830 glBegin(GL_LINE_STRIP);
837 if(la->type==LA_HEMI) {
838 /* draw the hemisphere curves */
839 short axis, steps, dir;
840 float outdist, zdist, mul;
841 vec[0]=vec[1]=vec[2]= 0.0;
842 outdist = 0.14; mul = 1.4; dir = 1;
845 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
846 for (axis=0; axis<4; axis++) {
847 float v[3]= {0.0, 0.0, 0.0};
850 glBegin(GL_LINE_STRIP);
852 for (steps=0; steps<6; steps++) {
853 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
854 /* make the arcs start at the edge of the energy circle */
855 if (steps == 0) v[0] = dir*circrad;
856 else v[0] = v[0] + dir*(steps*outdist);
857 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
858 /* make the arcs start at the edge of the energy circle */
859 if (steps == 0) v[1] = dir*circrad;
860 else v[1] = v[1] + dir*(steps*outdist);
863 v[2] = v[2] - steps*zdist;
871 /* flip the direction */
875 } else if(la->type==LA_AREA) {
877 if(la->area_shape==LA_AREA_SQUARE)
878 fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
879 else if(la->area_shape==LA_AREA_RECT)
880 fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
882 glBegin(GL_LINE_STRIP);
883 glVertex3f(0.0,0.0,-circrad);
884 glVertex3f(0.0,0.0,-la->dist);
888 /* and back to viewspace */
889 wmLoadMatrix(v3d->viewmat);
890 VECCOPY(vec, ob->obmat[3]);
894 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
895 drawshadbuflimits(la, ob->obmat);
898 UI_GetThemeColor4ubv(TH_LAMP, col);
899 glColor4ub(col[0], col[1], col[2], col[3]);
903 if (vec[2]>0) vec[2] -= circrad;
904 else vec[2] += circrad;
906 glBegin(GL_LINE_STRIP);
920 /* restore for drawing extra stuff */
925 static void draw_limit_line(float sta, float end, unsigned int col)
928 glVertex3f(0.0, 0.0, -sta);
929 glVertex3f(0.0, 0.0, -end);
935 glVertex3f(0.0, 0.0, -sta);
936 glVertex3f(0.0, 0.0, -end);
942 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
943 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
944 static void draw_focus_cross(float dist, float size)
947 glVertex3f(-size, 0.f, -dist);
948 glVertex3f(size, 0.f, -dist);
949 glVertex3f(0.f, -size, -dist);
950 glVertex3f(0.f, size, -dist);
954 /* flag similar to draw_object() */
955 static void drawcamera(Scene *scene, View3D *v3d, Object *ob, int flag)
957 /* a standing up pyramid with (0,0,0) as top */
960 float vec[8][4], tmat[4][4], fac, facx, facy, depth;
963 if(G.f & G_RENDER_SHADOW)
968 glDisable(GL_LIGHTING);
969 glDisable(GL_CULL_FACE);
971 if(v3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
972 facx= 0.5*cam->ortho_scale*1.28;
973 facy= 0.5*cam->ortho_scale*1.024;
974 depth= -cam->clipsta-0.1;
978 if(v3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
980 depth= - fac*cam->lens/16.0;
985 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */
986 vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
987 vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
988 vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
989 vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
991 glBegin(GL_LINE_LOOP);
999 if(v3d->persp>=2 && ob==v3d->camera) return;
1001 glBegin(GL_LINE_STRIP);
1002 glVertex3fv(vec[2]);
1003 glVertex3fv(vec[0]);
1004 glVertex3fv(vec[1]);
1005 glVertex3fv(vec[4]);
1006 glVertex3fv(vec[0]);
1007 glVertex3fv(vec[3]);
1015 /* draw an outline arrow for inactive cameras and filled
1016 * for active cameras. We actually draw both outline+filled
1017 * for active cameras so the wire can be seen side-on */
1019 if (i==0) glBegin(GL_LINE_LOOP);
1020 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1023 vec[0][0]= -0.7*cam->drawsize;
1024 vec[0][1]= 1.1*cam->drawsize;
1025 glVertex3fv(vec[0]);
1028 vec[0][1]= 1.8*cam->drawsize;
1029 glVertex3fv(vec[0]);
1031 vec[0][0]= 0.7*cam->drawsize;
1032 vec[0][1]= 1.1*cam->drawsize;
1033 glVertex3fv(vec[0]);
1039 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1040 wmLoadMatrix(v3d->viewmat);
1041 Mat4CpyMat4(vec, ob->obmat);
1045 MTC_Mat4SwapMat4(v3d->persmat, tmat);
1046 wmGetSingleMatrix(v3d->persmat);
1048 if(cam->flag & CAM_SHOWLIMITS) {
1049 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1050 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1051 draw_focus_cross(dof_camera(ob), cam->drawsize);
1055 if(cam->flag & CAM_SHOWMIST)
1056 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1058 MTC_Mat4SwapMat4(v3d->persmat, tmat);
1063 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1065 BPoint *bp = lt->def;
1066 float *co = dl?dl->verts:NULL;
1069 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1070 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1071 bglBegin(GL_POINTS);
1073 for(w=0; w<lt->pntsw; w++) {
1074 int wxt = (w==0 || w==lt->pntsw-1);
1075 for(v=0; v<lt->pntsv; v++) {
1076 int vxt = (v==0 || v==lt->pntsv-1);
1077 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1078 int uxt = (u==0 || u==lt->pntsu-1);
1079 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1081 if((bp->f1 & SELECT)==sel) {
1082 bglVertex3fv(dl?co:bp->vec);
1094 void lattice_foreachScreenVert(void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1096 ARegion *ar= NULL; // XXX
1097 View3D *v3d= NULL; // XXX
1098 BPoint *bp = editLatt->def;
1099 DispList *dl = find_displist(&G.obedit->disp, DL_VERTS);
1100 float *co = dl?dl->verts:NULL;
1101 float pmat[4][4], vmat[4][4];
1102 int i, N = editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1105 view3d_get_object_project_mat(v3d, G.obedit, pmat, vmat);
1107 for (i=0; i<N; i++, bp++, co+=3) {
1109 view3d_project_short_clip(ar, v3d, dl?co:bp->vec, s, pmat, vmat);
1110 func(userData, bp, s[0], s[1]);
1115 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1117 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1123 MDeformWeight *mdw= get_defweight (lt->dvert+index, use_wcol-1);
1125 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1131 glVertex3fv(&dl->verts[index*3]);
1133 glVertex3fv(lt->def[index].vec);
1137 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1138 static void drawlattice(View3D *v3d, Object *ob)
1145 lt= (ob==G.obedit)?editLatt:ob->data;
1147 /* now we default make displist, this will modifiers work for non animated case */
1148 if(ob->disp.first==NULL)
1149 lattice_calc_modifiers(ob);
1150 dl= find_displist(&ob->disp, DL_VERTS);
1155 if(ob->defbase.first && lt->dvert) {
1156 use_wcol= ob->actdef;
1157 glShadeModel(GL_SMOOTH);
1162 for(w=0; w<lt->pntsw; w++) {
1163 int wxt = (w==0 || w==lt->pntsw-1);
1164 for(v=0; v<lt->pntsv; v++) {
1165 int vxt = (v==0 || v==lt->pntsv-1);
1166 for(u=0; u<lt->pntsu; u++) {
1167 int uxt = (u==0 || u==lt->pntsu-1);
1169 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1170 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1171 drawlattice__point(lt, dl, u, v, w, use_wcol);
1173 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1174 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1175 drawlattice__point(lt, dl, u, v, w, use_wcol);
1177 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1178 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1179 drawlattice__point(lt, dl, u, v, w, use_wcol);
1186 /* restoration for weight colors */
1188 glShadeModel(GL_FLAT);
1191 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1193 lattice_draw_verts(lt, dl, 0);
1194 lattice_draw_verts(lt, dl, 1);
1196 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1200 /* ***************** ******************** */
1202 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1204 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1205 EditVert *eve = EM_get_vert_for_index(index);
1209 if (data->clipVerts) {
1210 view3d_project_short_clip(data->ar, data->v3d, co, s, data->pmat, data->vmat);
1212 view3d_project_short_noclip(data->ar, co, s, data->pmat);
1215 data->func(data->userData, eve, s[0], s[1], index);
1219 void mesh_foreachScreenVert(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1221 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
1222 DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1225 data.userData = userData;
1228 data.clipVerts = clipVerts;
1230 view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
1232 EM_init_index_arrays(1, 0, 0);
1233 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1234 EM_free_index_arrays();
1239 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1241 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1242 EditEdge *eed = EM_get_edge_for_index(index);
1246 if (data->clipVerts==1) {
1247 view3d_project_short_clip(data->ar, data->v3d, v0co, s[0], data->pmat, data->vmat);
1248 view3d_project_short_clip(data->ar, data->v3d, v1co, s[1], data->pmat, data->vmat);
1250 view3d_project_short_noclip(data->ar, v0co, s[0], data->pmat);
1251 view3d_project_short_noclip(data->ar, v1co, s[1], data->pmat);
1253 if (data->clipVerts==2) {
1254 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->ar->winx && s[0][1]<data->ar->winy))
1255 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->ar->winx && s[1][1]<data->ar->winy))
1260 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1263 void mesh_foreachScreenEdge(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
1265 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
1266 DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1271 data.userData = userData;
1272 data.clipVerts = clipVerts;
1274 view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
1276 EM_init_index_arrays(0, 1, 0);
1277 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1278 EM_free_index_arrays();
1283 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1285 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; float pmat[4][4], vmat[4][4]; } *data = userData;
1286 EditFace *efa = EM_get_face_for_index(index);
1289 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1290 view3d_project_short_clip(data->ar, data->v3d, cent, s, data->pmat, data->vmat);
1292 data->func(data->userData, efa, s[0], s[1], index);
1295 void mesh_foreachScreenFace(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1297 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; float pmat[4][4], vmat[4][4]; } data;
1298 DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1303 data.userData = userData;
1305 view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
1307 EM_init_index_arrays(0, 0, 1);
1308 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1309 EM_free_index_arrays();
1314 void nurbs_foreachScreenVert(ARegion *ar, View3D *v3d, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1316 float pmat[4][4], vmat[4][4];
1321 view3d_get_object_project_mat(v3d, G.obedit, pmat, vmat);
1323 for (nu= editNurb.first; nu; nu=nu->next) {
1324 if((nu->type & 7)==CU_BEZIER) {
1325 for (i=0; i<nu->pntsu; i++) {
1326 BezTriple *bezt = &nu->bezt[i];
1329 if (G.f & G_HIDDENHANDLES) {
1330 view3d_project_short_clip(ar, v3d, bezt->vec[1], s, pmat, vmat);
1331 if (s[0] != IS_CLIPPED)
1332 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1334 view3d_project_short_clip(ar, v3d, bezt->vec[0], s, pmat, vmat);
1335 if (s[0] != IS_CLIPPED)
1336 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1337 view3d_project_short_clip(ar, v3d, bezt->vec[1], s, pmat, vmat);
1338 if (s[0] != IS_CLIPPED)
1339 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1340 view3d_project_short_clip(ar, v3d, bezt->vec[2], s, pmat, vmat);
1341 if (s[0] != IS_CLIPPED)
1342 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1348 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1349 BPoint *bp = &nu->bp[i];
1352 view3d_project_short_clip(ar, v3d, bp->vec, s, pmat, vmat);
1353 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1360 /* ************** DRAW MESH ****************** */
1362 /* First section is all the "simple" draw routines,
1363 * ones that just pass some sort of primitive to GL,
1364 * with perhaps various options to control lighting,
1367 * These routines should not have user interface related
1371 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1373 Scene *scene= (Scene *)userData;
1374 EditFace *efa = EM_get_face_for_index(index);
1376 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1378 glVertex3f( cent[0] + no[0]*scene->editbutsize,
1379 cent[1] + no[1]*scene->editbutsize,
1380 cent[2] + no[2]*scene->editbutsize);
1383 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1386 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1390 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1392 EditFace *efa = EM_get_face_for_index(index);
1393 int sel = *((int*) userData);
1395 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1399 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1401 bglBegin(GL_POINTS);
1402 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1406 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1408 Scene *scene= (Scene *)userData;
1409 EditVert *eve = EM_get_vert_for_index(index);
1415 glVertex3f( co[0] + no_f[0]*scene->editbutsize,
1416 co[1] + no_f[1]*scene->editbutsize,
1417 co[2] + no_f[2]*scene->editbutsize);
1419 glVertex3f( co[0] + no_s[0]*scene->editbutsize/32767.0f,
1420 co[1] + no_s[1]*scene->editbutsize/32767.0f,
1421 co[2] + no_s[2]*scene->editbutsize/32767.0f);
1425 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1428 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1432 /* Draw verts with color set based on selection */
1433 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1435 struct { int sel; EditVert *eve_act; } * data = userData;
1436 EditVert *eve = EM_get_vert_for_index(index);
1438 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1439 /* draw active larger - need to stop/start point drawing for this :/ */
1440 if (eve==data->eve_act) {
1441 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1442 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1447 bglBegin(GL_POINTS);
1451 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1453 bglBegin(GL_POINTS);
1459 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1461 struct { int sel; EditVert *eve_act; } data;
1463 data.eve_act = eve_act;
1465 bglBegin(GL_POINTS);
1466 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1470 /* Draw edges with color set based on selection */
1471 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1473 EditEdge *eed = EM_get_edge_for_index(index);
1474 //unsigned char **cols = userData, *col;
1475 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1479 if (eed==data->eed_act) {
1480 glColor4ubv(data->actCol);
1482 if (eed->f&SELECT) {
1485 col = data->baseCol;
1487 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1488 if (col[3]==0) return 0;
1497 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1499 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1501 data.baseCol = baseCol;
1502 data.selCol = selCol;
1503 data.actCol = actCol;
1504 data.eed_act = eed_act;
1505 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1509 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1511 return EM_get_edge_for_index(index)->h==0;
1513 static void draw_dm_edges(DerivedMesh *dm)
1515 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1518 /* Draw edges with color interpolated based on selection */
1519 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1521 return EM_get_edge_for_index(index)->h==0;
1523 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1525 EditEdge *eed = EM_get_edge_for_index(index);
1526 unsigned char **cols = userData;
1527 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1528 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1530 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
1531 col0[1] + (col1[1]-col0[1])*t,
1532 col0[2] + (col1[2]-col0[2])*t,
1533 col0[3] + (col1[3]-col0[3])*t);
1535 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1537 unsigned char *cols[2];
1540 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1543 /* Draw only seam edges */
1544 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1546 EditEdge *eed = EM_get_edge_for_index(index);
1548 return (eed->h==0 && eed->seam);
1550 static void draw_dm_edges_seams(DerivedMesh *dm)
1552 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1555 /* Draw only sharp edges */
1556 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1558 EditEdge *eed = EM_get_edge_for_index(index);
1560 return (eed->h==0 && eed->sharp);
1562 static void draw_dm_edges_sharp(DerivedMesh *dm)
1564 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1568 /* Draw faces with color set based on selection
1569 * return 2 for the active face so it renders with stipple enabled */
1570 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1572 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1573 EditFace *efa = EM_get_face_for_index(index);
1577 if (efa == data->efa_act) {
1578 glColor4ubv(data->cols[2]);
1579 return 2; /* stipple */
1581 col = data->cols[(efa->f&SELECT)?1:0];
1582 if (col[3]==0) return 0;
1590 /* also draws the active face */
1591 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
1593 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1594 data.cols[0] = baseCol;
1595 data.cols[1] = selCol;
1596 data.cols[2] = actCol;
1597 data.efa_act = efa_act;
1599 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
1602 static int draw_dm_creases__setDrawOptions(void *userData, int index)
1604 EditEdge *eed = EM_get_edge_for_index(index);
1606 if (eed->h==0 && eed->crease!=0.0) {
1607 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
1613 static void draw_dm_creases(DerivedMesh *dm)
1616 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1620 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
1622 EditEdge *eed = EM_get_edge_for_index(index);
1624 if (eed->h==0 && eed->bweight!=0.0) {
1625 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1631 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1633 EditVert *eve = EM_get_vert_for_index(index);
1635 if (eve->h==0 && eve->bweight!=0.0) {
1636 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1640 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1642 if (scene->selectmode & SCE_SELECT_VERTEX) {
1643 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1644 bglBegin(GL_POINTS);
1645 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1650 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1655 /* Second section of routines: Combine first sets to form fancy
1656 * drawing routines (for example rendering twice to get overlays).
1658 * Also includes routines that are basic drawing but are too
1659 * specialized to be split out (like drawing creases or measurements).
1662 /* EditMesh drawing routines*/
1664 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
1668 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
1670 for (sel=0; sel<2; sel++) {
1671 char col[4], fcol[4];
1674 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1675 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1677 for (pass=0; pass<2; pass++) {
1678 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1679 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1682 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1683 glDisable(GL_DEPTH_TEST);
1690 size = (size>2.1?size/2.0:size);
1691 fsize = (fsize>2.1?fsize/2.0:fsize);
1692 col[3] = fcol[3] = 100;
1694 col[3] = fcol[3] = 255;
1697 if(scene->selectmode & SCE_SELECT_VERTEX) {
1699 glColor4ubv((GLubyte *)col);
1700 draw_dm_verts(cageDM, sel, eve_act);
1703 if( CHECK_OB_DRAWFACEDOT(scene, v3d, G.obedit->dt) ) {
1705 glColor4ubv((GLubyte *)fcol);
1706 draw_dm_face_centers(cageDM, sel);
1710 glDisable(GL_BLEND);
1711 glEnable(GL_DEPTH_TEST);
1716 if(v3d->zbuf) glDepthMask(1);
1720 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1723 unsigned char wireCol[4], selCol[4], actCol[4];
1725 /* since this function does transparant... */
1726 UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
1727 UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
1728 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
1730 /* when sel only is used, dont render wire, only selected, this is used for
1731 * textured draw mode when the 'edges' option is disabled */
1735 for (pass=0; pass<2; pass++) {
1736 /* show wires in transparant when no zbuf clipping for select */
1738 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
1740 glDisable(GL_DEPTH_TEST);
1742 if (!sel_only) wireCol[3] = 85;
1748 if (!sel_only) wireCol[3] = 255;
1751 if(scene->selectmode == SCE_SELECT_FACE) {
1752 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1754 else if( (G.f & G_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {
1755 if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
1756 glShadeModel(GL_SMOOTH);
1757 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
1758 glShadeModel(GL_FLAT);
1760 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1765 glColor4ubv(wireCol);
1766 draw_dm_edges(cageDM);
1771 glDisable(GL_BLEND);
1772 glEnable(GL_DEPTH_TEST);
1777 static void draw_em_measure_stats(View3D *v3d, Object *ob, EditMesh *em)
1781 float v1[3], v2[3], v3[3], v4[3];
1783 char val[32]; /* Stores the measurement display text here */
1784 char conv_float[5]; /* Use a float conversion matching the grid size */
1785 float area, col[3]; /* area of the face, color of the text to draw */
1787 if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
1790 /* make the precission of the pronted value proportionate to the gridsize */
1791 if ((v3d->grid) < 0.01)
1792 strcpy(conv_float, "%.6f");
1793 else if ((v3d->grid) < 0.1)
1794 strcpy(conv_float, "%.5f");
1795 else if ((v3d->grid) < 1.0)
1796 strcpy(conv_float, "%.4f");
1797 else if ((v3d->grid) < 10.0)
1798 strcpy(conv_float, "%.3f");
1800 strcpy(conv_float, "%.2f");
1803 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
1804 glDisable(GL_DEPTH_TEST);
1806 if(v3d->zbuf) bglPolygonOffset(v3d->dist, 5.0);
1808 if(G.f & G_DRAW_EDGELEN) {
1809 UI_GetThemeColor3fv(TH_TEXT, col);
1810 /* make color a bit more red */
1811 if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1812 else col[0]= col[0]*0.7 + 0.3;
1815 for(eed= em->edges.first; eed; eed= eed->next) {
1816 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1817 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1818 VECCOPY(v1, eed->v1->co);
1819 VECCOPY(v2, eed->v2->co);
1821 glRasterPos3f( 0.5*(v1[0]+v2[0]), 0.5*(v1[1]+v2[1]), 0.5*(v1[2]+v2[2]));
1823 if(v3d->flag & V3D_GLOBAL_STATS) {
1824 Mat4MulVecfl(ob->obmat, v1);
1825 Mat4MulVecfl(ob->obmat, v2);
1828 sprintf(val, conv_float, VecLenf(v1, v2));
1829 BMF_DrawString( G.fonts, val);
1834 if(G.f & G_DRAW_FACEAREA) {
1835 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
1837 UI_GetThemeColor3fv(TH_TEXT, col);
1838 /* make color a bit more green */
1839 if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
1840 else col[1]= col[1]*0.7 + 0.3;
1843 for(efa= em->faces.first; efa; efa= efa->next) {
1844 if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
1845 VECCOPY(v1, efa->v1->co);
1846 VECCOPY(v2, efa->v2->co);
1847 VECCOPY(v3, efa->v3->co);
1849 VECCOPY(v4, efa->v4->co);
1851 if(v3d->flag & V3D_GLOBAL_STATS) {
1852 Mat4MulVecfl(ob->obmat, v1);
1853 Mat4MulVecfl(ob->obmat, v2);
1854 Mat4MulVecfl(ob->obmat, v3);
1855 if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1859 area= AreaQ3Dfl(v1, v2, v3, v4);
1861 area = AreaT3Dfl(v1, v2, v3);
1863 sprintf(val, conv_float, area);
1864 glRasterPos3fv(efa->cent);
1865 BMF_DrawString( G.fonts, val);
1870 if(G.f & G_DRAW_EDGEANG) {
1871 EditEdge *e1, *e2, *e3, *e4;
1873 UI_GetThemeColor3fv(TH_TEXT, col);
1874 /* make color a bit more blue */
1875 if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
1876 else col[2]= col[2]*0.7 + 0.3;
1879 for(efa= em->faces.first; efa; efa= efa->next) {
1880 VECCOPY(v1, efa->v1->co);
1881 VECCOPY(v2, efa->v2->co);
1882 VECCOPY(v3, efa->v3->co);
1884 VECCOPY(v4, efa->v4->co);
1889 if(v3d->flag & V3D_GLOBAL_STATS) {
1890 Mat4MulVecfl(ob->obmat, v1);
1891 Mat4MulVecfl(ob->obmat, v2);
1892 Mat4MulVecfl(ob->obmat, v3);
1893 Mat4MulVecfl(ob->obmat, v4);
1899 if(efa->e4) e4= efa->e4; else e4= e3;
1901 /* Calculate the angles */
1903 if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
1905 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
1906 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
1907 glRasterPos3fv(fvec);
1908 BMF_DrawString( G.fonts, val);
1910 if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
1912 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
1913 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
1914 glRasterPos3fv(fvec);
1915 BMF_DrawString( G.fonts, val);
1917 if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
1920 sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
1922 sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
1923 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
1924 glRasterPos3fv(fvec);
1925 BMF_DrawString( G.fonts, val);
1929 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
1930 sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
1931 VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
1932 glRasterPos3fv(fvec);
1933 BMF_DrawString( G.fonts, val);
1940 glEnable(GL_DEPTH_TEST);
1941 bglPolygonOffset(v3d->dist, 0.0);
1945 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
1947 EditFace *efa = EM_get_face_for_index(index);
1950 GPU_enable_material(efa->mat_nr+1, NULL);
1957 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
1959 EditFace *efa = EM_get_face_for_index(index);
1964 static void draw_em_fancy(Scene *scene, View3D *v3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
1966 Mesh *me = ob->data;
1967 EditFace *efa_act = EM_get_actFace(0); /* annoying but active faces is stored differently */
1968 EditEdge *eed_act = NULL;
1969 EditVert *eve_act = NULL;
1971 if (G.editMesh->selected.last) {
1972 EditSelection *ese = G.editMesh->selected.last;
1973 /* face is handeled above */
1974 /*if (ese->type == EDITFACE ) {
1975 efa_act = (EditFace *)ese->data;
1976 } else */ if ( ese->type == EDITEDGE ) {
1977 eed_act = (EditEdge *)ese->data;
1978 } else if ( ese->type == EDITVERT ) {
1979 eve_act = (EditVert *)ese->data;
1983 EM_init_index_arrays(1, 1, 1);
1986 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
1987 if(draw_glsl_material(scene, ob, v3d, dt)) {
1988 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
1990 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
1991 draw_em_fancy__setGLSLFaceOpts, NULL);
1992 GPU_disable_material();
1994 glFrontFace(GL_CCW);
1997 draw_mesh_textured(scene, v3d, ob, finalDM, 0);
2001 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2003 glEnable(GL_LIGHTING);
2004 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2006 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2008 glFrontFace(GL_CCW);
2009 glDisable(GL_LIGHTING);
2012 // Setup for drawing wire over, disable zbuffer
2013 // write to show selected edge wires better
2014 UI_ThemeColor(TH_WIRE);
2016 bglPolygonOffset(v3d->dist, 1.0);
2020 if (cageDM!=finalDM) {
2021 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2022 finalDM->drawEdges(finalDM, 1);
2026 if((G.f & (G_DRAWFACES)) || FACESEL_PAINT_TEST) { /* transp faces */
2027 unsigned char col1[4], col2[4], col3[4];
2029 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2030 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2031 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2034 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2036 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2037 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2040 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2042 glDisable(GL_BLEND);
2043 glDepthMask(1); // restore write in zbuffer
2044 } else if (efa_act) {
2045 /* even if draw faces is off it would be nice to draw the stipple face
2046 * Make all other faces zero alpha except for the active
2048 unsigned char col1[4], col2[4], col3[4];
2049 col1[3] = col2[3] = 0; /* dont draw */
2050 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2053 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2055 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2057 glDisable(GL_BLEND);
2058 glDepthMask(1); // restore write in zbuffer
2062 /* here starts all fancy draw-extra over */
2063 if((G.f & G_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2064 /* we are drawing textures and 'G_DRAWEDGES' is disabled, dont draw any edges */
2066 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2067 draw_em_fancy_edges(scene, v3d, cageDM, 1, eed_act);
2070 if(G.f & G_DRAWSEAMS) {
2071 UI_ThemeColor(TH_EDGE_SEAM);
2074 draw_dm_edges_seams(cageDM);
2080 if(G.f & G_DRAWSHARP) {
2081 UI_ThemeColor(TH_EDGE_SHARP);
2084 draw_dm_edges_sharp(cageDM);
2090 if(G.f & G_DRAWCREASES) {
2091 draw_dm_creases(cageDM);
2093 if(G.f & G_DRAWBWEIGHTS) {
2094 draw_dm_bweights(scene, cageDM);
2097 draw_em_fancy_edges(scene, v3d, cageDM, 0, eed_act);
2100 // XXX retopo_matrix_update(v3d);
2102 draw_em_fancy_verts(scene, v3d, em, cageDM, eve_act);
2104 if(G.f & G_DRAWNORMALS) {
2105 UI_ThemeColor(TH_NORMAL);
2106 draw_dm_face_normals(scene, cageDM);
2108 if(G.f & G_DRAW_VNORMALS) {
2109 UI_ThemeColor(TH_NORMAL);
2110 draw_dm_vert_normals(scene, cageDM);
2113 if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
2114 draw_em_measure_stats(v3d, ob, em);
2119 bglPolygonOffset(v3d->dist, 0.0);
2120 GPU_disable_material();
2123 EM_free_index_arrays();
2126 /* Mesh drawing routines */
2128 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2131 if(v3d->transp==0) { // not when we draw the transparent pass
2135 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2136 drawFacesSolid() doesn't draw the transparent faces */
2137 if(ob->dtx & OB_DRAWTRANSP) {
2138 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2139 dm->drawFacesSolid(dm, GPU_enable_material);
2140 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2141 GPU_disable_material();
2144 dm->drawEdges(dm, 0);
2152 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2158 static void draw_mesh_fancy(Scene *scene, View3D *v3d, Base *base, int dt, int flag)
2160 Object *ob= base->object;
2161 Mesh *me = ob->data;
2162 Material *ma= give_current_material(ob, 1);
2163 int hasHaloMat = (ma && (ma->mode&MA_HALO));
2165 int totvert, totedge, totface;
2167 DerivedMesh *dm= mesh_get_derived_final(ob, get_viewedit_datamask());
2172 if (ob->dtx&OB_DRAWWIRE) {
2173 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2176 totvert = dm->getNumVerts(dm);
2177 totedge = dm->getNumEdges(dm);
2178 totface = dm->getNumFaces(dm);
2180 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2182 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2184 // Unwanted combination.
2185 if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
2187 if(dt==OB_BOUNDBOX) {
2188 draw_bounding_volume(ob);
2190 else if(hasHaloMat || (totface==0 && totedge==0)) {
2195 else if(dt==OB_WIRE || totface==0) {
2196 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2198 else if( (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
2199 CHECK_OB_DRAWTEXTURE(v3d, dt))
2201 int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
2203 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
2204 draw_mesh_object_outline(v3d, ob, dm);
2207 if(draw_glsl_material(scene, ob, v3d, dt)) {
2208 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2210 dm->drawFacesGLSL(dm, GPU_enable_material);
2211 // if(get_ob_property(ob, "Text"))
2212 // XXX draw_mesh_text(ob, 1);
2213 GPU_disable_material();
2215 glFrontFace(GL_CCW);
2218 draw_mesh_textured(scene, v3d, ob, dm, faceselect);
2222 if(base->flag & SELECT)
2223 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2225 UI_ThemeColor(TH_WIRE);
2227 dm->drawLooseEdges(dm);
2230 else if(dt==OB_SOLID) {
2231 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2232 draw_mesh_object_outline(v3d, ob, dm);
2234 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2236 glEnable(GL_LIGHTING);
2237 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2239 dm->drawFacesSolid(dm, GPU_enable_material);
2240 GPU_disable_material();
2242 glFrontFace(GL_CCW);
2243 glDisable(GL_LIGHTING);
2245 if(base->flag & SELECT) {
2246 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2248 UI_ThemeColor(TH_WIRE);
2250 dm->drawLooseEdges(dm);
2252 else if(dt==OB_SHADED) {
2253 int do_draw= 1; /* to resolve all G.f settings below... */
2257 if( (G.f & G_WEIGHTPAINT)) {
2258 /* enforce default material settings */
2259 GPU_enable_material(0, NULL);
2261 /* but set default spec */
2262 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2263 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2264 glColor3ub(120, 120, 120);
2265 glDisable(GL_COLOR_MATERIAL);
2267 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2268 glEnable(GL_LIGHTING);
2269 glEnable(GL_COLOR_MATERIAL);
2271 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2272 glDisable(GL_COLOR_MATERIAL);
2273 glDisable(GL_LIGHTING);
2275 GPU_disable_material();
2277 else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
2278 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2280 else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
2281 glColor3f(1.0f, 1.0f, 1.0f);
2282 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2287 dl = ob->disp.first;
2288 if (!dl || !dl->col1) {
2289 /* release and reload derivedmesh because it might be freed in
2290 shadeDispList due to a different datamask */
2292 shadeDispList(base);
2293 dl = find_displist(&ob->disp, DL_VERTCOL);
2294 dm= mesh_get_derived_final(ob, get_viewedit_datamask());
2297 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2298 draw_mesh_object_outline(v3d, ob, dm);
2301 /* False for dupliframe objects */
2303 unsigned int *obCol1 = dl->col1;
2304 unsigned int *obCol2 = dl->col2;
2306 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2309 if(base->flag & SELECT) {
2310 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2312 UI_ThemeColor(TH_WIRE);
2314 dm->drawLooseEdges(dm);
2318 /* set default draw color back for wire or for draw-extra later on */
2320 if(base->flag & SELECT) {
2321 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2322 UI_ThemeColor(TH_GROUP_ACTIVE);
2323 else if(ob->flag & OB_FROMGROUP)
2324 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2325 else if(flag!=DRAW_CONSTCOLOR)
2326 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2328 glColor3ub(80,80,80);
2330 if (ob->flag & OB_FROMGROUP)
2331 UI_ThemeColor(TH_GROUP);
2333 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2334 glColor3ub(80,80,80);
2336 UI_ThemeColor(TH_WIRE);
2341 /* If drawing wire and drawtype is not OB_WIRE then we are
2342 * overlaying the wires.
2344 * UPDATE bug #10290 - With this wire-only objects can draw
2345 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2347 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2348 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2350 if (dt!=OB_WIRE && draw_wire==2) {
2351 bglPolygonOffset(v3d->dist, 1.0);
2352 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2355 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2357 if (dt!=OB_WIRE && draw_wire==2) {
2359 bglPolygonOffset(v3d->dist, 0.0);
2366 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2367 static int draw_mesh_object(Scene *scene, View3D *v3d, Base *base, int dt, int flag)
2369 Object *ob= base->object;
2371 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2373 if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) {
2378 if(ob==G.obedit || drawlinked) {
2379 DerivedMesh *finalDM, *cageDM;
2382 finalDM = cageDM = editmesh_get_derived_base();
2384 cageDM = editmesh_get_derived_cage_and_final(&finalDM,
2385 get_viewedit_datamask());
2388 // no transp in editmode, the fancy draw over goes bad then
2389 glsl = draw_glsl_material(scene, ob, v3d, dt);
2390 GPU_set_object_materials(v3d, scene, ob, glsl, NULL);
2393 draw_em_fancy(scene, v3d, ob, G.editMesh, cageDM, finalDM, dt);
2395 if (G.obedit!=ob && finalDM)
2396 finalDM->release(finalDM);
2398 // else if(!G.obedit && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2399 // OBACT==ob && !sculpt_modifiers_active(ob)) {
2400 // XXX sculptmode_draw_mesh(0);
2403 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2404 if(me->totface<=4 || boundbox_clip(v3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2405 glsl = draw_glsl_material(scene, ob, v3d, dt);
2406 check_alpha = check_material_alpha(base, ob, glsl);
2408 if(dt==OB_SOLID || glsl) {
2409 GPU_set_object_materials(v3d, scene, ob, glsl,
2410 (check_alpha)? &do_alpha_pass: NULL);
2413 draw_mesh_fancy(scene, v3d, base, dt, flag);
2415 if(me->totvert==0) retval= 1;
2419 /* GPU_set_object_materials checked if this is needed */
2420 if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
2425 /* ************** DRAW DISPLIST ****************** */
2427 static int draw_index_wire= 1;
2428 static int index3_nors_incr= 1;
2430 /* returns 1 when nothing was drawn */
2431 static int drawDispListwire(ListBase *dlbase)
2437 if(dlbase==NULL) return 1;
2439 glDisableClientState(GL_NORMAL_ARRAY);
2440 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2442 for(dl= dlbase->first; dl; dl= dl->next) {
2443 if(dl->parts==0 || dl->nr==0)
2451 glVertexPointer(3, GL_FLOAT, 0, data);
2453 for(parts=0; parts<dl->parts; parts++)
2454 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2459 glVertexPointer(3, GL_FLOAT, 0, data);
2461 for(parts=0; parts<dl->parts; parts++)
2462 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2467 glVertexPointer(3, GL_FLOAT, 0, data);
2469 for(parts=0; parts<dl->parts; parts++) {
2470 if(dl->flag & DL_CYCL_U)
2471 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2473 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2476 for(nr=0; nr<dl->nr; nr++) {
2479 data= ( dl->verts )+3*nr;
2482 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2483 else glBegin(GL_LINE_STRIP);
2491 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2492 // glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2493 // if(dl->flag & DL_CYCL_V)
2494 // glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2496 // glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2501 if(draw_index_wire) {
2502 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2503 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2508 if(draw_index_wire) {
2509 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2510 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2516 glEnableClientState(GL_NORMAL_ARRAY);
2517 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2522 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2525 GPUVertexAttribs gattribs;
2526 float *data, curcol[4];
2529 if(lb==NULL) return;
2531 /* for drawing wire */
2532 glGetFloatv(GL_CURRENT_COLOR, curcol);
2534 glEnable(GL_LIGHTING);
2536 if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2537 else glFrontFace(GL_CCW);
2539 if(ob->type==OB_MBALL) { // mball always smooth shaded
2540 glShadeModel(GL_SMOOTH);
2550 if(ob->type==OB_SURF) {
2553 glDisable(GL_LIGHTING);
2556 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2557 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2559 glBegin(GL_LINE_STRIP);
2560 for(nr= dl->nr; nr; nr--, data+=3)
2564 glEnable(GL_LIGHTING);
2568 if(ob->type==OB_SURF) {
2571 UI_ThemeColor(TH_WIRE);
2572 glDisable(GL_LIGHTING);
2574 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2575 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2576 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2578 glBegin(GL_LINE_LOOP);
2579 for(nr= dl->nr; nr; nr--, data+=3)
2583 glEnable(GL_LIGHTING);
2589 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2591 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2592 else glShadeModel(GL_FLAT);
2594 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2595 glNormalPointer(GL_FLOAT, 0, dl->nors);
2596 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2597 GPU_disable_material();
2602 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2604 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2606 /* voor polys only one normal needed */
2607 if(index3_nors_incr==0) {
2608 glDisableClientState(GL_NORMAL_ARRAY);
2612 glNormalPointer(GL_FLOAT, 0, dl->nors);
2614 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2615 GPU_disable_material();
2617 if(index3_nors_incr==0)
2618 glEnableClientState(GL_NORMAL_ARRAY);
2623 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2625 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2626 glNormalPointer(GL_FLOAT, 0, dl->nors);
2627 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2629 GPU_disable_material();
2636 glShadeModel(GL_FLAT);
2637 glDisable(GL_LIGHTING);
2638 glFrontFace(GL_CCW);
2641 static void drawDispListshaded(ListBase *lb, Object *ob)
2643 DispList *dl, *dlob;
2644 unsigned int *cdata;
2646 if(lb==NULL) return;
2648 glShadeModel(GL_SMOOTH);
2649 glDisableClientState(GL_NORMAL_ARRAY);
2650 glEnableClientState(GL_COLOR_ARRAY);
2653 dlob= ob->disp.first;
2657 if(cdata==NULL) break;
2662 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2663 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2664 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2670 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2671 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2672 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2677 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2678 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2679 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2687 glShadeModel(GL_FLAT);
2688 glEnableClientState(GL_NORMAL_ARRAY);
2689 glDisableClientState(GL_COLOR_ARRAY);
2692 /* returns 1 when nothing was drawn */
2693 static int drawDispList(Scene *scene, View3D *v3d, Base *base, int dt)
2695 Object *ob= base->object;
2699 int solid, retval= 0;
2701 solid= (dt > OB_WIRE);
2712 if(dl==NULL) return 1;
2714 if(dl->nors==0) addnormalsDispList(ob, lb);
2715 index3_nors_incr= 0;
2717 if( displist_has_faces(lb)==0) {
2719 drawDispListwire(lb);
2723 if(draw_glsl_material(scene, ob, v3d, dt)) {
2724 GPU_set_object_materials(v3d, scene, ob, 1, NULL);
2725 drawDispListsolid(lb, ob, 1);
2727 else if(dt == OB_SHADED) {
2728 if(ob->disp.first==0) shadeDispList(base);
2729 drawDispListshaded(lb, ob);
2732 GPU_set_object_materials(v3d, scene, ob, 0, NULL);
2733 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2734 drawDispListsolid(lb, ob, 0);
2736 if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
2739 drawDispListwire(lb);
2743 index3_nors_incr= 1;
2747 retval= drawDispListwire(lb);
2753 lb= &((Curve *)ob->data)->disp;
2757 if(dl==NULL) return 1;
2759 if(dl->nors==NULL) addnormalsDispList(ob, lb);
2761 if(draw_glsl_material(scene, ob, v3d, dt)) {
2762 GPU_set_object_materials(v3d, scene, ob, 1, NULL);
2763 drawDispListsolid(lb, ob, 1);
2765 else if(dt==OB_SHADED) {
2766 if(ob->disp.first==NULL) shadeDispList(base);
2767 drawDispListshaded(lb, ob);
2770 GPU_set_object_materials(v3d, scene, ob, 0, NULL);
2771 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2773 drawDispListsolid(lb, ob, 0);
2777 retval= drawDispListwire(lb);
2782 if( is_basis_mball(ob)) {
2784 if(lb->first==NULL) makeDispListMBall(ob);
2785 if(lb->first==NULL) return 1;
2789 if(draw_glsl_material(scene, ob, v3d, dt)) {
2790 GPU_set_object_materials(v3d, scene, ob, 1, NULL);
2791 drawDispListsolid(lb, ob, 1);
2793 else if(dt == OB_SHADED) {
2795 if(dl && dl->col1==0) shadeDispList(base);
2796 drawDispListshaded(lb, ob);
2799 GPU_set_object_materials(v3d, scene, ob, 0, NULL);
2800 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2802 drawDispListsolid(lb, ob, 0);
2806 /* MetaBalls use DL_INDEX4 type of DispList */
2807 retval= drawDispListwire(lb);
2816 /* unified drawing of all new particle systems draw types except dupli ob & group */
2817 /* mostly tries to use vertex arrays for speed */
2819 /* 1. check that everything is ok & updated */
2820 /* 2. start initialising things */
2821 /* 3. initialize according to draw type */
2822 /* 4. allocate drawing data arrays */
2823 /* 5. start filling the arrays */
2824 /* 6. draw the arrays */
2826 static void draw_new_particle_system(View3D *v3d, Base *base, ParticleSystem *psys, int dt)
2828 Object *ob=base->object;
2829 ParticleSystemModifierData *psmd;
2830 ParticleSettings *part;
2831 ParticleData *pars, *pa;
2832 ParticleKey state, *states=0;
2833 ParticleCacheKey *cache=0;
2836 float vel[3], vec[3], vec2[3], imat[4][4], onevec[3]={0.0f,0.0f,0.0f}, bb_center[3];
2837 float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
2838 float cfra=bsystem_time(ob,(float)CFRA,0.0);
2839 float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
2840 float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
2841 int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
2842 int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
2843 int select=ob->flag&SELECT, create_cdata=0;
2844 GLint polygonmode[2];
2852 pars=psys->particles;
2854 if(part==0 || !psys_check_enabled(ob, psys))
2859 if(!G.obedit && psys_in_edit_mode(psys)
2860 && psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
2863 if(part->draw_as==PART_DRAW_NOT) return;
2866 if(part->phystype==PART_PHYS_KEYED){
2867 if(psys->flag & PSYS_FIRST_KEYED){
2868 if(psys->flag&PSYS_KEYED){
2869 select=psys_count_keyed_targets(ob,psys);
2870 if(psys->totkeyed==0)
2880 if(psys_get_current(ob)==psys)
2884 psys->flag|=PSYS_DRAWING;
2886 if(part->type==PART_HAIR && !psys->childcache)
2889 totchild=psys->totchild*part->disp/100;
2891 ma= give_current_material(ob,part->omat);
2899 if(v3d->zbuf) glDepthMask(1);
2903 else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
2904 glColor3f(ma->r,ma->g,ma->b);
2910 psmd= psys_get_modifier(ob,psys);
2912 timestep= psys_get_timestep(part);
2914 wmLoadMatrix(v3d->viewmat);
2916 if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
2918 Mat4MulMat4(mat, psys->imat, ob->obmat);
2922 totpart=psys->totpart;
2923 draw_as=part->draw_as;
2925 if(part->flag&PART_GLOB_TIME)
2926 cfra=bsystem_time(0,(float)CFRA,0.0);
2928 if(psys->pathcache){
2932 if(draw_as==PART_DRAW_PATH && path_possible==0)
2933 draw_as=PART_DRAW_DOT;
2935 if(draw_as!=PART_DRAW_PATH && keys_possible && part->draw&PART_DRAW_KEYS){
2936 path_nbr=part->keys_step;
2944 glPointSize(part->draw_size);
2946 glPointSize(2.0); /* default dot size */
2948 case PART_DRAW_CIRC:
2949 /* calculate view aligned matrix: */
2950 Mat4CpyMat4(imat, v3d->viewinv);
2954 case PART_DRAW_CROSS:
2955 case PART_DRAW_AXIS:
2956 /* lets calculate the scale: */
2957 pixsize= v3d->persmat[0][3]*ob->obmat[3][0]+ v3d->persmat[1][3]*ob->obmat[3][1]+ v3d->persmat[2][3]*ob->obmat[3][2]+ v3d->persmat[3][3];
2958 pixsize*= v3d->pixsize;
2959 if(part->draw_size==0.0)
2962 pixsize*=part->draw_size;
2966 draw_as=PART_DRAW_DOT;
2971 if(part->dup_group==0)
2972 draw_as=PART_DRAW_DOT;
2977 if(v3d->camera==0 && part->bb_ob==0){
2978 printf("Billboards need an active camera or a target object!\n");
2980 draw_as=part->draw_as=PART_DRAW_DOT;
2983 glPointSize(part->draw_size);
2985 glPointSize(2.0); /* default dot size */
2987 else if(part->bb_ob)
2992 if(part->bb_align<PART_BB_VIEW)
2993 onevec[part->bb_align]=1.0f;
2995 case PART_DRAW_PATH:
2998 if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
2999 Mat4CpyMat4(imat, v3d->viewinv);
3005 if(draw_as && draw_as!=PART_DRAW_PATH){
3006 if(draw_as!=PART_DRAW_CIRC){
3008 case PART_DRAW_AXIS:
3009 case PART_DRAW_CROSS:
3010 if(draw_as!=PART_DRAW_CROSS || create_cdata)
3011 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
3012 vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
3014 case PART_DRAW_LINE:
3016 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata");
3017 vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
3021 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata");
3022 vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
3023 ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
3027 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata");
3028 vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
3032 if(part->draw&PART_DRAW_VEL && draw_as!=PART_DRAW_LINE)
3033 vedata=MEM_callocN((totpart+totchild)*2*3*(path_nbr+1)*sizeof(float), "particle_vedata");
3040 psys->lattice=psys_get_lattice(ob,psys);
3045 for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
3047 if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
3048 if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
3050 pa_time=(cfra-pa->time)/pa->lifetime;