Blender  V2.59
drawobject.c
Go to the documentation of this file.
00001 /*
00002  * $Id: drawobject.c 39259 2011-08-10 15:53:46Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * Contributor(s): Blender Foundation, full recode and added functions
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <string.h>
00034 #include <math.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "DNA_camera_types.h"
00039 #include "DNA_curve_types.h"
00040 #include "DNA_constraint_types.h" // for drawing constraint
00041 #include "DNA_lamp_types.h"
00042 #include "DNA_lattice_types.h"
00043 #include "DNA_material_types.h"
00044 #include "DNA_meshdata_types.h"
00045 #include "DNA_meta_types.h"
00046 #include "DNA_scene_types.h"
00047 #include "DNA_smoke_types.h"
00048 #include "DNA_world_types.h"
00049 #include "DNA_armature_types.h"
00050 
00051 #include "BLI_blenlib.h"
00052 #include "BLI_math.h"
00053 #include "BLI_editVert.h"
00054 #include "BLI_edgehash.h"
00055 #include "BLI_rand.h"
00056 #include "BLI_utildefines.h"
00057 
00058 #include "BKE_anim.h"                   //for the where_on_path function
00059 #include "BKE_constraint.h" // for the get_constraint_target function
00060 #include "BKE_DerivedMesh.h"
00061 #include "BKE_deform.h"
00062 #include "BKE_displist.h"
00063 #include "BKE_font.h"
00064 #include "BKE_global.h"
00065 #include "BKE_image.h"
00066 #include "BKE_key.h"
00067 #include "BKE_lattice.h"
00068 #include "BKE_mesh.h"
00069 #include "BKE_material.h"
00070 #include "BKE_mball.h"
00071 #include "BKE_modifier.h"
00072 #include "BKE_object.h"
00073 #include "BKE_paint.h"
00074 #include "BKE_particle.h"
00075 #include "BKE_pointcache.h"
00076 #include "BKE_unit.h"
00077 
00078 #include "smoke_API.h"
00079 
00080 #include "IMB_imbuf.h"
00081 #include "IMB_imbuf_types.h"
00082 
00083 #include "BIF_gl.h"
00084 #include "BIF_glutil.h"
00085 
00086 #include "GPU_draw.h"
00087 #include "GPU_extensions.h"
00088 
00089 #include "ED_mesh.h"
00090 #include "ED_particle.h"
00091 #include "ED_screen.h"
00092 #include "ED_sculpt.h"
00093 #include "ED_types.h"
00094 #include "ED_curve.h" /* for ED_curve_editnurbs */
00095 
00096 #include "UI_resources.h"
00097 
00098 #include "WM_api.h"
00099 #include "wm_subwindow.h"
00100 #include "BLF_api.h"
00101 
00102 #include "view3d_intern.h"      // own include
00103 
00104 
00105 /* this condition has been made more complex since editmode can draw textures */
00106 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
00107 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
00108         (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
00109 
00110 static void draw_bounding_volume(Scene *scene, Object *ob);
00111 
00112 static void drawcube_size(float size);
00113 static void drawcircle_size(float size);
00114 static void draw_empty_sphere(float size);
00115 static void draw_empty_cone(float size);
00116 
00117 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
00118 {
00119         if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
00120                 return 0;
00121 
00122         if(G.f & G_BACKBUFSEL)
00123                 return 0;
00124 
00125         if((vd->flag & V3D_ZBUF_SELECT) == 0)
00126                 return 1;
00127 
00128         /* if its drawing textures with zbuf sel, then dont draw dots */
00129         if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
00130                 return 0;
00131 
00132         if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
00133                 return 0;
00134 
00135         return 1;
00136 }
00137 
00138 /* ************* only use while object drawing **************
00139  * or after running ED_view3d_init_mats_rv3d
00140  * */
00141 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
00142 {
00143         RegionView3D *rv3d= ar->regiondata;
00144         float fx, fy, vec4[4];
00145         
00146         adr[0]= IS_CLIPPED;
00147         
00148         /* clipplanes in eye space */
00149         if(rv3d->rflag & RV3D_CLIPPING) {
00150                 if(ED_view3d_test_clipping(rv3d, vec, local))
00151                         return;
00152         }
00153         
00154         copy_v3_v3(vec4, vec);
00155         vec4[3]= 1.0;
00156         
00157         mul_m4_v4(rv3d->persmatob, vec4);
00158         
00159         /* clipplanes in window space */
00160         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
00161                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
00162                 
00163                 if( fx>0 && fx<ar->winx) {
00164                         
00165                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
00166                         
00167                         if(fy > 0.0f && fy < (float)ar->winy) {
00168                                 adr[0]= (short)floorf(fx);
00169                                 adr[1]= (short)floorf(fy);
00170                         }
00171                 }
00172         }
00173 }
00174 
00175 /* only use while object drawing */
00176 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
00177 {
00178         RegionView3D *rv3d= ar->regiondata;
00179         float fx, fy, vec4[4];
00180         
00181         adr[0]= IS_CLIPPED;
00182         
00183         copy_v3_v3(vec4, vec);
00184         vec4[3]= 1.0;
00185         
00186         mul_m4_v4(rv3d->persmatob, vec4);
00187         
00188         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
00189                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
00190                 
00191                 if( fx>-32700 && fx<32700) {
00192                         
00193                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
00194                         
00195                         if(fy > -32700.0f && fy < 32700.0f) {
00196                                 adr[0]= (short)floorf(fx);
00197                                 adr[1]= (short)floorf(fy);
00198                         }
00199                 }
00200         }
00201 }
00202 
00203 /* ************************ */
00204 
00205 /* check for glsl drawing */
00206 
00207 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
00208 {
00209         if(!GPU_glsl_support())
00210                 return 0;
00211         if(G.f & G_PICKSEL)
00212                 return 0;
00213         if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
00214                 return 0;
00215         if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
00216                 return 0;
00217         
00218         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
00219 }
00220 
00221 static int check_material_alpha(Base *base, Mesh *me, int glsl)
00222 {
00223         if(base->flag & OB_FROMDUPLI)
00224                 return 0;
00225 
00226         if(G.f & G_PICKSEL)
00227                 return 0;
00228                         
00229         if(me->edit_mesh)
00230                 return 0;
00231         
00232         return (glsl || (base->object->dtx & OB_DRAWTRANSP));
00233 }
00234 
00235         /***/
00236 static unsigned int colortab[24]=
00237         {0x0,           0xFF88FF, 0xFFBBFF, 
00238          0x403000,      0xFFFF88, 0xFFFFBB, 
00239          0x104040,      0x66CCCC, 0x77CCCC, 
00240          0x104010,      0x55BB55, 0x66FF66, 
00241          0xFFFFFF
00242 };
00243 
00244 
00245 static float cube[8][3] = {
00246         {-1.0, -1.0, -1.0},
00247         {-1.0, -1.0,  1.0},
00248         {-1.0,  1.0,  1.0},
00249         {-1.0,  1.0, -1.0},
00250         { 1.0, -1.0, -1.0},
00251         { 1.0, -1.0,  1.0},
00252         { 1.0,  1.0,  1.0},
00253         { 1.0,  1.0, -1.0},
00254 };
00255 
00256 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
00257 /* 32 values of sin function (still same result!) */
00258 static float sinval[32] = {
00259         0.00000000,
00260         0.20129852,
00261         0.39435585,
00262         0.57126821,
00263         0.72479278,
00264         0.84864425,
00265         0.93775213,
00266         0.98846832,
00267         0.99871650,
00268         0.96807711,
00269         0.89780453,
00270         0.79077573,
00271         0.65137248,
00272         0.48530196,
00273         0.29936312,
00274         0.10116832,
00275         -0.10116832,
00276         -0.29936312,
00277         -0.48530196,
00278         -0.65137248,
00279         -0.79077573,
00280         -0.89780453,
00281         -0.96807711,
00282         -0.99871650,
00283         -0.98846832,
00284         -0.93775213,
00285         -0.84864425,
00286         -0.72479278,
00287         -0.57126821,
00288         -0.39435585,
00289         -0.20129852,
00290         0.00000000
00291 };
00292 
00293 /* 32 values of cos function (still same result!) */
00294 static float cosval[32] ={
00295         1.00000000,
00296         0.97952994,
00297         0.91895781,
00298         0.82076344,
00299         0.68896691,
00300         0.52896401,
00301         0.34730525,
00302         0.15142777,
00303         -0.05064916,
00304         -0.25065253,
00305         -0.44039415,
00306         -0.61210598,
00307         -0.75875812,
00308         -0.87434661,
00309         -0.95413925,
00310         -0.99486932,
00311         -0.99486932,
00312         -0.95413925,
00313         -0.87434661,
00314         -0.75875812,
00315         -0.61210598,
00316         -0.44039415,
00317         -0.25065253,
00318         -0.05064916,
00319         0.15142777,
00320         0.34730525,
00321         0.52896401,
00322         0.68896691,
00323         0.82076344,
00324         0.91895781,
00325         0.97952994,
00326         1.00000000
00327 };
00328 
00329 static void draw_xyz_wire(const float c[3], float size, int axis)
00330 {
00331         float v1[3]= {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
00332         float dim = size * 0.1f;
00333         float dx[3], dy[3], dz[3];
00334 
00335         dx[0]=dim; dx[1]=0.f; dx[2]=0.f;
00336         dy[0]=0.f; dy[1]=dim; dy[2]=0.f;
00337         dz[0]=0.f; dz[1]=0.f; dz[2]=dim;
00338 
00339         switch(axis) {
00340                 case 0:         /* x axis */
00341                         glBegin(GL_LINES);
00342                         
00343                         /* bottom left to top right */
00344                         sub_v3_v3v3(v1, c, dx);
00345                         sub_v3_v3(v1, dy);
00346                         add_v3_v3v3(v2, c, dx);
00347                         add_v3_v3(v2, dy);
00348                         
00349                         glVertex3fv(v1);
00350                         glVertex3fv(v2);
00351                         
00352                         /* top left to bottom right */
00353                         mul_v3_fl(dy, 2.f);
00354                         add_v3_v3(v1, dy);
00355                         sub_v3_v3(v2, dy);
00356                         
00357                         glVertex3fv(v1);
00358                         glVertex3fv(v2);
00359                         
00360                         glEnd();
00361                         break;
00362                 case 1:         /* y axis */
00363                         glBegin(GL_LINES);
00364                         
00365                         /* bottom left to top right */
00366                         mul_v3_fl(dx, 0.75f);
00367                         sub_v3_v3v3(v1, c, dx);
00368                         sub_v3_v3(v1, dy);
00369                         add_v3_v3v3(v2, c, dx);
00370                         add_v3_v3(v2, dy);
00371                         
00372                         glVertex3fv(v1);
00373                         glVertex3fv(v2);
00374                         
00375                         /* top left to center */
00376                         mul_v3_fl(dy, 2.f);
00377                         add_v3_v3(v1, dy);
00378                         copy_v3_v3(v2, c);
00379                         
00380                         glVertex3fv(v1);
00381                         glVertex3fv(v2);
00382                         
00383                         glEnd();
00384                         break;
00385                 case 2:         /* z axis */
00386                         glBegin(GL_LINE_STRIP);
00387                         
00388                         /* start at top left */
00389                         sub_v3_v3v3(v1, c, dx);
00390                         add_v3_v3v3(v1, c, dz);
00391                         
00392                         glVertex3fv(v1);
00393                         
00394                         mul_v3_fl(dx, 2.f);
00395                         add_v3_v3(v1, dx);
00396 
00397                         glVertex3fv(v1);
00398                         
00399                         mul_v3_fl(dz, 2.f);
00400                         sub_v3_v3(v1, dx);
00401                         sub_v3_v3(v1, dz);
00402                         
00403                         glVertex3fv(v1);
00404                         
00405                         add_v3_v3(v1, dx);
00406                 
00407                         glVertex3fv(v1);
00408                         
00409                         glEnd();
00410                         break;
00411         }
00412         
00413 }
00414 
00415 void drawaxes(float size, char drawtype)
00416 {
00417         int axis;
00418         float v1[3]= {0.0, 0.0, 0.0};
00419         float v2[3]= {0.0, 0.0, 0.0};
00420         float v3[3]= {0.0, 0.0, 0.0};
00421         
00422         switch(drawtype) {
00423         
00424         case OB_PLAINAXES:
00425                 for (axis=0; axis<3; axis++) {
00426                         glBegin(GL_LINES);
00427                         
00428                         v1[axis]= size;
00429                         v2[axis]= -size;
00430                         glVertex3fv(v1);
00431                         glVertex3fv(v2);
00432 
00433                         /* reset v1 & v2 to zero */
00434                         v1[axis]= v2[axis]= 0.0f;
00435 
00436                         glEnd();
00437                 }
00438                 break;
00439         case OB_SINGLE_ARROW:
00440         
00441                 glBegin(GL_LINES);
00442                 /* in positive z direction only */
00443                 v1[2]= size;
00444                 glVertex3fv(v1);
00445                 glVertex3fv(v2);
00446                 glEnd();
00447                 
00448                 /* square pyramid */
00449                 glBegin(GL_TRIANGLES);
00450                 
00451                 v2[0]= size * 0.035f; v2[1] = size * 0.035f;
00452                 v3[0]= size * -0.035f; v3[1] = size * 0.035f;
00453                 v2[2]= v3[2]= size * 0.75f;
00454                 
00455                 for (axis=0; axis<4; axis++) {
00456                         if (axis % 2 == 1) {
00457                                 v2[0] = -v2[0];
00458                                 v3[1] = -v3[1];
00459                         } else {
00460                                 v2[1] = -v2[1];
00461                                 v3[0] = -v3[0];
00462                         }
00463                         
00464                         glVertex3fv(v1);
00465                         glVertex3fv(v2);
00466                         glVertex3fv(v3);
00467                         
00468                 }
00469                 glEnd();
00470                 
00471                 break;
00472         case OB_CUBE:
00473                 drawcube_size(size);
00474                 break;
00475                 
00476         case OB_CIRCLE:
00477                 drawcircle_size(size);
00478                 break;
00479         
00480         case OB_EMPTY_SPHERE:
00481                 draw_empty_sphere(size);
00482                 break;
00483 
00484         case OB_EMPTY_CONE:
00485                 draw_empty_cone(size);
00486                 break;
00487 
00488         case OB_ARROWS:
00489         default:
00490                 for (axis=0; axis<3; axis++) {
00491                         const int arrow_axis= (axis==0) ? 1:0;
00492 
00493                         glBegin(GL_LINES);
00494                         
00495                         v2[axis]= size;
00496                         glVertex3fv(v1);
00497                         glVertex3fv(v2);
00498                                 
00499                         v1[axis]= size*0.85f;
00500                         v1[arrow_axis]= -size*0.08f;
00501                         glVertex3fv(v1);
00502                         glVertex3fv(v2);
00503                                 
00504                         v1[arrow_axis]= size*0.08f;
00505                         glVertex3fv(v1);
00506                         glVertex3fv(v2);
00507                         
00508                         glEnd();
00509                                 
00510                         v2[axis]+= size*0.125f;
00511                         
00512                         draw_xyz_wire(v2, size, axis);
00513                         
00514                         
00515                         /* reset v1 & v2 to zero */
00516                         v1[arrow_axis]= v1[axis]= v2[axis]= 0.0f;
00517                 }
00518                 break;
00519         }
00520 }
00521 
00522 
00523 /* Function to draw an Image on a empty Object */
00524 static void draw_empty_image(Object *ob)
00525 {
00526         Image *ima = (Image*)ob->data;
00527         ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
00528 
00529         float scale, ofs_x, ofs_y, sca_x, sca_y;
00530         int ima_x, ima_y;
00531 
00532         if(ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
00533                 IMB_rect_from_float(ibuf);
00534         }
00535 
00536         /* Get the buffer dimensions so we can fallback to fake ones */
00537         if(ibuf && ibuf->rect) {
00538                 ima_x= ibuf->x;
00539                 ima_y= ibuf->y;
00540         }
00541         else {
00542                 ima_x= 1;
00543                 ima_y= 1;
00544         }
00545 
00546         /* Get the image aspect even if the buffer is invalid */
00547         if(ima) {
00548                 if(ima->aspx > ima->aspy) {
00549                         sca_x= 1.0f;
00550                         sca_y= ima->aspy / ima->aspx;
00551                 }
00552                 else if(ima->aspx < ima->aspy) {
00553                         sca_x= ima->aspx / ima->aspy;
00554                         sca_y= 1.0f;
00555                 }
00556                 else {
00557                         sca_x= 1.0f;
00558                         sca_y= 1.0f;
00559                 }
00560         }
00561         else {
00562                 sca_x= 1.0f;
00563                 sca_y= 1.0f;
00564         }
00565 
00566         /* Calculate the scale center based on objects origin */
00567         ofs_x= ob->ima_ofs[0] * ima_x;
00568         ofs_y= ob->ima_ofs[1] * ima_y;
00569 
00570         glMatrixMode(GL_MODELVIEW);
00571         glPushMatrix();
00572 
00573         /* Make sure we are drawing at the origin */
00574         glTranslatef(0.0f,  0.0f,  0.0f);
00575 
00576         /* Calculate Image scale */
00577         scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
00578 
00579         /* Set the object scale */
00580         glScalef(scale * sca_x, scale * sca_y, 1.0f);
00581 
00582         if(ibuf && ibuf->rect) {
00583                 /* Setup GL params */
00584                 glEnable(GL_BLEND);
00585                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
00586 
00587                 /* Use the object color and alpha */
00588                 glColor4fv(ob->col);
00589 
00590                 /* Draw the Image on the screen */
00591                 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
00592                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
00593 
00594                 glDisable(GL_BLEND);
00595         }
00596 
00597         UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
00598 
00599         /* Calculate the outline vertex positions */
00600         glBegin(GL_LINE_LOOP);
00601         glVertex2f(ofs_x, ofs_y);
00602         glVertex2f(ofs_x + ima_x, ofs_y);
00603         glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
00604         glVertex2f(ofs_x, ofs_y + ima_y);
00605         glEnd();
00606 
00607         /* Reset GL settings */
00608         glMatrixMode(GL_MODELVIEW);
00609         glPopMatrix();
00610 }
00611 
00612 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
00613 {
00614         float vec[3], vx[3], vy[3];
00615         int a, tot=32;
00616 
00617         mul_v3_v3fl(vx, tmat[0], rad);
00618         mul_v3_v3fl(vy, tmat[1], rad);
00619 
00620         glBegin(mode);
00621         for(a=0; a<tot; a++) {
00622                 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
00623                 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
00624                 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
00625                 glVertex3fv(vec);
00626         }
00627         glEnd();
00628 }
00629 
00630 /* circle for object centers, special_color is for library or ob users */
00631 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
00632 {
00633         const float size= ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
00634 
00635         /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
00636         if(v3d->zbuf)  glDepthFunc(GL_ALWAYS);
00637         glEnable(GL_BLEND);
00638         
00639         if(special_color) {
00640                 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
00641 
00642                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
00643         }
00644         else {
00645                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
00646                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
00647                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
00648         }
00649         drawcircball(GL_POLYGON, co, size, rv3d->viewinv);
00650         
00651         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
00652         drawcircball(GL_LINE_LOOP, co, size, rv3d->viewinv);
00653         
00654         glDisable(GL_BLEND);
00655         if(v3d->zbuf)  glDepthFunc(GL_LEQUAL);
00656 }
00657 
00658 /* *********** text drawing for object/particles/armature ************* */
00659 static ListBase CachedText[3];
00660 static int CachedTextLevel= 0;
00661 
00662 typedef struct ViewCachedString {
00663         struct ViewCachedString *next, *prev;
00664         float vec[3];
00665         union {
00666                 unsigned char ub[4];
00667                 int pack;
00668         } col;
00669         short sco[2];
00670         short xoffs;
00671         short flag;
00672         int str_len, pad;
00673         /* str is allocated past the end */
00674 } ViewCachedString;
00675 
00676 void view3d_cached_text_draw_begin(void)
00677 {
00678         ListBase *strings= &CachedText[CachedTextLevel];
00679         strings->first= strings->last= NULL;
00680         CachedTextLevel++;
00681 }
00682 
00683 void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4])
00684 {
00685         int alloc_len= strlen(str) + 1;
00686         ListBase *strings= &CachedText[CachedTextLevel-1];
00687         ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
00688 
00689         BLI_addtail(strings, vos);
00690         copy_v3_v3(vos->vec, co);
00691         vos->col.pack= *((int *)col);
00692         vos->xoffs= xoffs;
00693         vos->flag= flag;
00694         vos->str_len= alloc_len-1;
00695 
00696         /* allocate past the end */
00697         memcpy(++vos, str, alloc_len);
00698 }
00699 
00700 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
00701 {
00702         RegionView3D *rv3d= ar->regiondata;
00703         ListBase *strings= &CachedText[CachedTextLevel-1];
00704         ViewCachedString *vos;
00705         int a, tot= 0;
00706         
00707         /* project first and test */
00708         for(vos= strings->first; vos; vos= vos->next) {
00709                 if(mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
00710                         mul_m4_v3(mat, vos->vec);
00711                 view3d_project_short_clip(ar, vos->vec, vos->sco, 0);
00712                 if(vos->sco[0]!=IS_CLIPPED)
00713                         tot++;
00714         }
00715 
00716         if(tot) {
00717                 int col_pack_prev= 0;
00718 
00719 #if 0
00720                 bglMats mats; /* ZBuffer depth vars */
00721                 double ux, uy, uz;
00722                 float depth;
00723 
00724                 if(v3d->zbuf)
00725                         bgl_get_mats(&mats);
00726 #endif
00727                 if(rv3d->rflag & RV3D_CLIPPING)
00728                         for(a=0; a<6; a++)
00729                                 glDisable(GL_CLIP_PLANE0+a);
00730                 
00731                 glMatrixMode(GL_PROJECTION);
00732                 glPushMatrix();
00733                 glMatrixMode(GL_MODELVIEW);
00734                 glPushMatrix();
00735                 ED_region_pixelspace(ar);
00736                 
00737                 if(depth_write) {
00738                         if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
00739                 }
00740                 else glDepthMask(0);
00741                 
00742                 for(vos= strings->first; vos; vos= vos->next) {
00743 #if 0       // too slow, reading opengl info while drawing is very bad, better to see if we cn use the zbuffer while in pixel space - campbell
00744                         if(v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
00745                                 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
00746                                 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
00747 
00748                                 if(uz > depth)
00749                                         continue;
00750                         }
00751 #endif
00752                         if(vos->sco[0]!=IS_CLIPPED) {
00753                                 const char *str= (char *)(vos+1);
00754 
00755                                 if(col_pack_prev != vos->col.pack) {
00756                                         glColor3ubv(vos->col.ub);
00757                                         col_pack_prev= vos->col.pack;
00758                                 }
00759                                 if(vos->flag & V3D_CACHE_TEXT_ASCII) {
00760                                         BLF_draw_default_ascii((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
00761                                 }
00762                                 else {
00763                                         BLF_draw_default((float)vos->sco[0]+vos->xoffs, (float)vos->sco[1], (depth_write)? 0.0f: 2.0f, str, vos->str_len);
00764                                 }
00765                         }
00766                 }
00767                 
00768                 if(depth_write) {
00769                         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
00770                 }
00771                 else glDepthMask(1);
00772                 
00773                 glMatrixMode(GL_PROJECTION);
00774                 glPopMatrix();
00775                 glMatrixMode(GL_MODELVIEW);
00776                 glPopMatrix();
00777 
00778                 if(rv3d->rflag & RV3D_CLIPPING)
00779                         for(a=0; a<6; a++)
00780                                 glEnable(GL_CLIP_PLANE0+a);
00781         }
00782         
00783         if(strings->first) 
00784                 BLI_freelistN(strings);
00785         
00786         CachedTextLevel--;
00787 }
00788 
00789 /* ******************** primitive drawing ******************* */
00790 
00791 static void drawcube(void)
00792 {
00793 
00794         glBegin(GL_LINE_STRIP);
00795                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
00796                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
00797                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
00798         glEnd();
00799 
00800         glBegin(GL_LINE_STRIP);
00801                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
00802         glEnd();
00803 
00804         glBegin(GL_LINE_STRIP);
00805                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
00806         glEnd();
00807 
00808         glBegin(GL_LINE_STRIP);
00809                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
00810         glEnd();
00811 }
00812 
00813 /* draws a cube on given the scaling of the cube, assuming that 
00814  * all required matrices have been set (used for drawing empties)
00815  */
00816 static void drawcube_size(float size)
00817 {
00818         glBegin(GL_LINE_STRIP);
00819                 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
00820                 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
00821                 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
00822         glEnd();
00823 
00824         glBegin(GL_LINE_STRIP);
00825                 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
00826         glEnd();
00827 
00828         glBegin(GL_LINE_STRIP);
00829                 glVertex3f(-size,size,size); glVertex3f(size,size,size);
00830         glEnd();
00831 
00832         glBegin(GL_LINE_STRIP);
00833                 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
00834         glEnd();
00835 }
00836 
00837 /* this is an unused (old) cube-drawing function based on a given size */
00838 #if 0
00839 static void drawcube_size(float *size)
00840 {
00841 
00842         glPushMatrix();
00843         glScalef(size[0],  size[1],  size[2]);
00844         
00845 
00846         glBegin(GL_LINE_STRIP);
00847                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
00848                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
00849                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
00850         glEnd();
00851 
00852         glBegin(GL_LINE_STRIP);
00853                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
00854         glEnd();
00855 
00856         glBegin(GL_LINE_STRIP);
00857                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
00858         glEnd();
00859 
00860         glBegin(GL_LINE_STRIP);
00861                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
00862         glEnd();
00863         
00864         glPopMatrix();
00865 }
00866 #endif
00867 
00868 static void drawshadbuflimits(Lamp *la, float mat[][4])
00869 {
00870         float sta[3], end[3], lavec[3];
00871 
00872         negate_v3_v3(lavec, mat[2]);
00873         normalize_v3(lavec);
00874 
00875         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
00876         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
00877 
00878         glBegin(GL_LINE_STRIP);
00879                 glVertex3fv(sta);
00880                 glVertex3fv(end);
00881         glEnd();
00882 
00883         glPointSize(3.0);
00884         bglBegin(GL_POINTS);
00885         bglVertex3fv(sta);
00886         bglVertex3fv(end);
00887         bglEnd();
00888         glPointSize(1.0);
00889 }
00890 
00891 
00892 
00893 static void spotvolume(float *lvec, float *vvec, float inp)
00894 {
00895         /* camera is at 0,0,0 */
00896         float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
00897 
00898         normalize_v3(lvec);
00899         normalize_v3(vvec);                             /* is this the correct vector ? */
00900 
00901         cross_v3_v3v3(temp,vvec,lvec);          /* equation for a plane through vvec en lvec */
00902         cross_v3_v3v3(plane,lvec,temp);         /* a plane perpendicular to this, parrallel with lvec */
00903 
00904         /* vectors are exactly aligned, use the X axis, this is arbitrary */
00905         if(normalize_v3(plane) == 0.0f)
00906                 plane[1]= 1.0f;
00907 
00908         /* now we've got two equations: one of a cone and one of a plane, but we have
00909         three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
00910 
00911         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
00912         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
00913 
00914         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
00915         
00916         q[1] = plane[1] ; 
00917         q[2] = -plane[0] ; 
00918         q[3] = 0 ;
00919         normalize_v3(&q[1]);
00920 
00921         angle = saacos(plane[2])/2.0f;
00922         co = cos(angle);
00923         si = sqrt(1-co*co);
00924 
00925         q[0] =  co;
00926         q[1] *= si;
00927         q[2] *= si;
00928         q[3] =  0;
00929 
00930         quat_to_mat3(mat1,q);
00931 
00932         /* rotate lamp vector now over acos(inp) degrees */
00933         copy_v3_v3(vvec, lvec);
00934 
00935         unit_m3(mat2);
00936         co = inp;
00937         si = sqrt(1-inp*inp);
00938 
00939         mat2[0][0] =  co;
00940         mat2[1][0] = -si;
00941         mat2[0][1] =  si;
00942         mat2[1][1] =  co;
00943         mul_m3_m3m3(mat3,mat2,mat1);
00944 
00945         mat2[1][0] =  si;
00946         mat2[0][1] = -si;
00947         mul_m3_m3m3(mat4,mat2,mat1);
00948         transpose_m3(mat1);
00949 
00950         mul_m3_m3m3(mat2,mat1,mat3);
00951         mul_m3_v3(mat2,lvec);
00952         mul_m3_m3m3(mat2,mat1,mat4);
00953         mul_m3_v3(mat2,vvec);
00954 
00955         return;
00956 }
00957 
00958 static void draw_spot_cone(Lamp *la, float x, float z)
00959 {
00960         z= fabs(z);
00961 
00962         glBegin(GL_TRIANGLE_FAN);
00963         glVertex3f(0.0f, 0.0f, -x);
00964 
00965         if(la->mode & LA_SQUARE) {
00966                 glVertex3f(z, z, 0);
00967                 glVertex3f(-z, z, 0);
00968                 glVertex3f(-z, -z, 0);
00969                 glVertex3f(z, -z, 0);
00970                 glVertex3f(z, z, 0);
00971         }
00972         else {
00973                 float angle;
00974                 int a;
00975 
00976                 for(a=0; a<33; a++) {
00977                         angle= a*M_PI*2/(33-1);
00978                         glVertex3f(z*cosf(angle), z*sinf(angle), 0);
00979                 }
00980         }
00981 
00982         glEnd();
00983 }
00984 
00985 static void draw_transp_spot_volume(Lamp *la, float x, float z)
00986 {
00987         glEnable(GL_CULL_FACE);
00988         glEnable(GL_BLEND);
00989         glDepthMask(0);
00990 
00991         /* draw backside darkening */
00992         glCullFace(GL_FRONT);
00993 
00994         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
00995         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
00996 
00997         draw_spot_cone(la, x, z);
00998 
00999         /* draw front side lighting */
01000         glCullFace(GL_BACK);
01001 
01002         glBlendFunc(GL_ONE,  GL_ONE); 
01003         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
01004 
01005         draw_spot_cone(la, x, z);
01006 
01007         /* restore state */
01008         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01009         glDisable(GL_BLEND);
01010         glDepthMask(1);
01011         glDisable(GL_CULL_FACE);
01012         glCullFace(GL_BACK);
01013 }
01014 
01015 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
01016 {
01017         Object *ob= base->object;
01018         const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
01019         Lamp *la= ob->data;
01020         float vec[3], lvec[3], vvec[3], circrad, x,y,z;
01021         float lampsize;
01022         float imat[4][4], curcol[4];
01023         unsigned char col[4];
01024         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
01025         /* the moment of view3d_draw_transp() call */
01026         const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
01027         const short drawcone= (dt>OB_WIRE && !(G.f & G_PICKSEL) && (la->type == LA_SPOT) && (la->mode & LA_SHOW_CONE) && !(base->flag & OB_FROMDUPLI) && !is_view);
01028 
01029         if(drawcone && !v3d->transp) {
01030                 /* in this case we need to draw delayed */
01031                 add_view3d_after(&v3d->afterdraw_transp, base, flag);
01032                 return;
01033         }
01034         
01035         /* we first draw only the screen aligned & fixed scale stuff */
01036         glPushMatrix();
01037         glLoadMatrixf(rv3d->viewmat);
01038 
01039         /* lets calculate the scale: */
01040         lampsize= pixsize*((float)U.obcenter_dia*0.5f);
01041 
01042         /* and view aligned matrix: */
01043         copy_m4_m4(imat, rv3d->viewinv);
01044         normalize_v3(imat[0]);
01045         normalize_v3(imat[1]);
01046 
01047         /* lamp center */
01048         copy_v3_v3(vec, ob->obmat[3]);
01049         
01050         /* for AA effects */
01051         glGetFloatv(GL_CURRENT_COLOR, curcol);
01052         curcol[3]= 0.6;
01053         glColor4fv(curcol);
01054         
01055         if(lampsize > 0.0f) {
01056 
01057                 if(ob->id.us>1) {
01058                         if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
01059                         else glColor4ub(0x77, 0xCC, 0xCC, 155);
01060                 }
01061                 
01062                 /* Inner Circle */
01063                 glEnable(GL_BLEND);
01064                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
01065                 glDisable(GL_BLEND);
01066                 drawcircball(GL_POLYGON, vec, lampsize, imat);
01067                 
01068                 /* restore */
01069                 if(ob->id.us>1)
01070                         glColor4fv(curcol);
01071                         
01072                 /* Outer circle */
01073                 circrad = 3.0f*lampsize;
01074                 setlinestyle(3);
01075 
01076                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
01077 
01078                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
01079                 if(la->type!=LA_HEMI) {
01080                         if(     (la->mode & LA_SHAD_RAY) ||
01081                                 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
01082                         ) {
01083                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
01084                         }
01085                 }
01086         }
01087         else {
01088                 setlinestyle(3);
01089                 circrad = 0.0f;
01090         }
01091         
01092         /* draw the pretty sun rays */
01093         if(la->type==LA_SUN) {
01094                 float v1[3], v2[3], mat[3][3];
01095                 short axis;
01096                 
01097                 /* setup a 45 degree rotation matrix */
01098                 vec_rot_to_mat3(mat, imat[2], (float)M_PI/4.0f);
01099                 
01100                 /* vectors */
01101                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
01102                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
01103                 
01104                 /* center */
01105                 glTranslatef(vec[0], vec[1], vec[2]);
01106                 
01107                 setlinestyle(3);
01108                 
01109                 glBegin(GL_LINES);
01110                 for (axis=0; axis<8; axis++) {
01111                         glVertex3fv(v1);
01112                         glVertex3fv(v2);
01113                         mul_m3_v3(mat, v1);
01114                         mul_m3_v3(mat, v2);
01115                 }
01116                 glEnd();
01117                 
01118                 glTranslatef(-vec[0], -vec[1], -vec[2]);
01119 
01120         }               
01121         
01122         if (la->type==LA_LOCAL) {
01123                 if(la->mode & LA_SPHERE) {
01124                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
01125                 }
01126                 /* yafray: for photonlight also draw lightcone as for spot */
01127         }
01128         
01129         glPopMatrix();  /* back in object space */
01130         zero_v3(vec);
01131         
01132         if(is_view) {
01133                 /* skip drawing extra info */
01134         }
01135         else if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
01136                 lvec[0]=lvec[1]= 0.0; 
01137                 lvec[2] = 1.0;
01138                 x = rv3d->persmat[0][2];
01139                 y = rv3d->persmat[1][2];
01140                 z = rv3d->persmat[2][2];
01141                 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
01142                 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
01143                 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
01144 
01145                 y = cosf(la->spotsize*(float)(M_PI/360.0));
01146                 spotvolume(lvec, vvec, y);
01147                 x = -la->dist;
01148                 mul_v3_fl(lvec, x);
01149                 mul_v3_fl(vvec, x);
01150 
01151                 /* draw the angled sides of the cone */
01152                 glBegin(GL_LINE_STRIP);
01153                         glVertex3fv(vvec);
01154                         glVertex3fv(vec);
01155                         glVertex3fv(lvec);
01156                 glEnd();
01157                 
01158                 z = x*sqrtf(1.0f - y*y);
01159                 x *= y;
01160 
01161                 /* draw the circle/square at the end of the cone */
01162                 glTranslatef(0.0, 0.0 ,  x);
01163                 if(la->mode & LA_SQUARE) {
01164                         float tvec[3];
01165                         float z_abs= fabs(z);
01166 
01167                         tvec[0]= tvec[1]= z_abs;
01168                         tvec[2]= 0.0;
01169 
01170                         glBegin(GL_LINE_LOOP);
01171                                 glVertex3fv(tvec);
01172                                 tvec[1]= -z_abs; /* neg */
01173                                 glVertex3fv(tvec);
01174                                 tvec[0]= -z_abs; /* neg */
01175                                 glVertex3fv(tvec);
01176                                 tvec[1]= z_abs; /* pos */
01177                                 glVertex3fv(tvec);
01178                         glEnd();
01179                 }
01180                 else circ(0.0, 0.0, fabsf(z));
01181                 
01182                 /* draw the circle/square representing spotbl */
01183                 if(la->type==LA_SPOT) {
01184                         float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
01185                         /* hide line if it is zero size or overlaps with outer border,
01186                            previously it adjusted to always to show it but that seems
01187                            confusing because it doesn't show the actual blend size */
01188                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
01189                                 circ(0.0, 0.0, spotblcirc);
01190                 }
01191 
01192                 if(drawcone)
01193                         draw_transp_spot_volume(la, x, z);
01194 
01195                 /* draw clip start, useful for wide cones where its not obvious where the start is */
01196                 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
01197                 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
01198                         float lvec_clip[3];
01199                         float vvec_clip[3];
01200                         float clipsta_fac= la->clipsta / -x;
01201 
01202                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
01203                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
01204 
01205                         glBegin(GL_LINE_STRIP);
01206                                 glVertex3fv(lvec_clip);
01207                                 glVertex3fv(vvec_clip);
01208                         glEnd();
01209                 }
01210         }
01211         else if ELEM(la->type, LA_HEMI, LA_SUN) {
01212                 
01213                 /* draw the line from the circle along the dist */
01214                 glBegin(GL_LINE_STRIP);
01215                         vec[2] = -circrad;
01216                         glVertex3fv(vec); 
01217                         vec[2]= -la->dist; 
01218                         glVertex3fv(vec);
01219                 glEnd();
01220                 
01221                 if(la->type==LA_HEMI) {
01222                         /* draw the hemisphere curves */
01223                         short axis, steps, dir;
01224                         float outdist, zdist, mul;
01225                         zero_v3(vec);
01226                         outdist = 0.14; mul = 1.4; dir = 1;
01227                         
01228                         setlinestyle(4);
01229                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
01230                         for (axis=0; axis<4; axis++) {
01231                                 float v[3]= {0.0, 0.0, 0.0};
01232                                 zdist = 0.02;
01233                                 
01234                                 glBegin(GL_LINE_STRIP);
01235                                 
01236                                 for (steps=0; steps<6; steps++) {
01237                                         if (axis == 0 || axis == 1) {           /* x axis up, x axis down */    
01238                                                 /* make the arcs start at the edge of the energy circle */
01239                                                 if (steps == 0) v[0] = dir*circrad;
01240                                                 else v[0] = v[0] + dir*(steps*outdist);
01241                                         } else if (axis == 2 || axis == 3) {            /* y axis up, y axis down */
01242                                                 /* make the arcs start at the edge of the energy circle */
01243                                                 if (steps == 0) v[1] = dir*circrad;
01244                                                 else v[1] = v[1] + dir*(steps*outdist); 
01245                                         }
01246                 
01247                                         v[2] = v[2] - steps*zdist;
01248                                         
01249                                         glVertex3fv(v);
01250                                         
01251                                         zdist = zdist * mul;
01252                                 }
01253                                 
01254                                 glEnd();
01255                                 /* flip the direction */
01256                                 dir = -dir;
01257                         }
01258                 }
01259         } else if(la->type==LA_AREA) {
01260                 setlinestyle(3);
01261                 if(la->area_shape==LA_AREA_SQUARE) 
01262                         fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
01263                 else if(la->area_shape==LA_AREA_RECT) 
01264                         fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
01265 
01266                 glBegin(GL_LINE_STRIP); 
01267                 glVertex3f(0.0,0.0,-circrad);
01268                 glVertex3f(0.0,0.0,-la->dist);
01269                 glEnd();
01270         }
01271         
01272         /* and back to viewspace */
01273         glLoadMatrixf(rv3d->viewmat);
01274         copy_v3_v3(vec, ob->obmat[3]);
01275 
01276         setlinestyle(0);
01277         
01278         if((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
01279                 drawshadbuflimits(la, ob->obmat);
01280         }
01281         
01282         UI_GetThemeColor4ubv(TH_LAMP, col);
01283         glColor4ubv(col);
01284          
01285         glEnable(GL_BLEND);
01286         
01287         if (vec[2]>0) vec[2] -= circrad;
01288         else vec[2] += circrad;
01289         
01290         glBegin(GL_LINE_STRIP);
01291                 glVertex3fv(vec); 
01292                 vec[2]= 0; 
01293                 glVertex3fv(vec);
01294         glEnd();
01295         
01296         glPointSize(2.0);
01297         glBegin(GL_POINTS);
01298                 glVertex3fv(vec);
01299         glEnd();
01300         glPointSize(1.0);
01301         
01302         glDisable(GL_BLEND);
01303         
01304         /* restore for drawing extra stuff */
01305         glColor3fv(curcol);
01306 
01307 }
01308 
01309 static void draw_limit_line(float sta, float end, unsigned int col)
01310 {
01311         glBegin(GL_LINES);
01312         glVertex3f(0.0, 0.0, -sta);
01313         glVertex3f(0.0, 0.0, -end);
01314         glEnd();
01315 
01316         glPointSize(3.0);
01317         glBegin(GL_POINTS);
01318         cpack(col);
01319         glVertex3f(0.0, 0.0, -sta);
01320         glVertex3f(0.0, 0.0, -end);
01321         glEnd();
01322         glPointSize(1.0);
01323 }               
01324 
01325 
01326 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
01327 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
01328 static void draw_focus_cross(float dist, float size)
01329 {
01330         glBegin(GL_LINES);
01331         glVertex3f(-size, 0.f, -dist);
01332         glVertex3f(size, 0.f, -dist);
01333         glVertex3f(0.f, -size, -dist);
01334         glVertex3f(0.f, size, -dist);
01335         glEnd();
01336 }
01337 
01338 #ifdef VIEW3D_CAMERA_BORDER_HACK
01339 float view3d_camera_border_hack_col[4];
01340 short view3d_camera_border_hack_test= FALSE;
01341 #endif
01342 
01343 /* flag similar to draw_object() */
01344 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
01345 {
01346         /* a standing up pyramid with (0,0,0) as top */
01347         Camera *cam;
01348         float vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
01349         int i;
01350         float drawsize;
01351         const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
01352 
01353         const float scax= 1.0f / len_v3(ob->obmat[0]);
01354         const float scay= 1.0f / len_v3(ob->obmat[1]);
01355         const float scaz= 1.0f / len_v3(ob->obmat[2]);
01356 
01357 #ifdef VIEW3D_CAMERA_BORDER_HACK
01358         if(is_view && !(G.f & G_PICKSEL)) {
01359                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
01360                 view3d_camera_border_hack_test= TRUE;
01361                 return;
01362         }
01363 #endif
01364 
01365         cam= ob->data;
01366         aspx= (float) scene->r.xsch*scene->r.xasp;
01367         aspy= (float) scene->r.ysch*scene->r.yasp;
01368 
01369         if(aspx < aspy) {
01370                 caspx= aspx / aspy;
01371                 caspy= 1.0;
01372         }
01373         else {
01374                 caspx= 1.0;
01375                 caspy= aspy / aspx;
01376         }
01377         
01378         glDisable(GL_LIGHTING);
01379         glDisable(GL_CULL_FACE);
01380         
01381         if(cam->type==CAM_ORTHO) {
01382                 facx= 0.5f * cam->ortho_scale * caspx * scax;
01383                 facy= 0.5f * cam->ortho_scale * caspy * scay;
01384                 shx= cam->shiftx * cam->ortho_scale * scax;
01385                 shy= cam->shifty * cam->ortho_scale * scay;
01386                 depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
01387                 
01388                 drawsize= 0.5f * cam->ortho_scale;
01389         }
01390         else {
01391                 /* that way it's always visible - clipsta+0.1 */
01392                 float fac;
01393                 drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
01394 
01395                 if(is_view) {
01396                         /* fixed depth, variable size (avoids exceeding clipping range) */
01397                         depth = -(cam->clipsta + 0.1f);
01398                         fac = depth / (cam->lens/-16.0f * scaz);
01399                 }
01400                 else {
01401                         /* fixed size, variable depth (stays a reasonable size in the 3D view) */
01402                         depth= drawsize * cam->lens/-16.0f * scaz;
01403                         fac= drawsize;
01404                 }
01405 
01406                 facx= fac * caspx * scax;
01407                 facy= fac * caspy * scay;
01408                 shx= cam->shiftx*fac*2 * scax;
01409                 shy= cam->shifty*fac*2 * scay;
01410         }
01411         
01412         vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
01413         vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
01414         vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
01415         vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
01416         vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
01417 
01418         /* camera frame */
01419         glBegin(GL_LINE_LOOP);
01420                 glVertex3fv(vec[1]); 
01421                 glVertex3fv(vec[2]); 
01422                 glVertex3fv(vec[3]); 
01423                 glVertex3fv(vec[4]);
01424         glEnd();
01425 
01426         if(is_view)
01427                 return;
01428 
01429         /* center point to camera frame */
01430         glBegin(GL_LINE_STRIP);
01431                 glVertex3fv(vec[2]); 
01432                 glVertex3fv(vec[0]);
01433                 glVertex3fv(vec[1]);
01434                 glVertex3fv(vec[4]);
01435                 glVertex3fv(vec[0]);
01436                 glVertex3fv(vec[3]); 
01437         glEnd();
01438 
01439 
01440         /* arrow on top */
01441         vec[0][2]= depth;
01442 
01443 
01444         /* draw an outline arrow for inactive cameras and filled
01445          * for active cameras. We actually draw both outline+filled
01446          * for active cameras so the wire can be seen side-on */        
01447         for (i=0;i<2;i++) {
01448                 if (i==0) glBegin(GL_LINE_LOOP);
01449                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
01450                 else break;
01451 
01452                 vec[0][0]= shx + ((-0.7f * drawsize) * scax);
01453                 vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
01454                 glVertex3fv(vec[0]); /* left */
01455                 
01456                 vec[0][0]= shx + ((0.7f * drawsize) * scax);
01457                 glVertex3fv(vec[0]); /* right */
01458                 
01459                 vec[0][0]= shx;
01460                 vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
01461                 glVertex3fv(vec[0]); /* top */
01462         
01463                 glEnd();
01464         }
01465 
01466         if(flag==0) {
01467                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
01468                         float nobmat[4][4];
01469                         World *wrld;
01470         
01471                         /* draw in normalized object matrix space */
01472                         copy_m4_m4(nobmat, ob->obmat);
01473                         normalize_m4(nobmat);
01474 
01475                         glPushMatrix();
01476                         glLoadMatrixf(rv3d->viewmat);
01477                         glMultMatrixf(nobmat);
01478 
01479                         if(cam->flag & CAM_SHOWLIMITS) {
01480                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
01481                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
01482                                 draw_focus_cross(dof_camera(ob), cam->drawsize);
01483                         }
01484 
01485                         wrld= scene->world;
01486                         if(cam->flag & CAM_SHOWMIST) 
01487                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
01488                                 
01489                         glPopMatrix();
01490                 }
01491         }
01492 }
01493 
01494 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
01495 {
01496         BPoint *bp = lt->def;
01497         float *co = dl?dl->verts:NULL;
01498         int u, v, w;
01499 
01500         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
01501         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
01502         bglBegin(GL_POINTS);
01503 
01504         for(w=0; w<lt->pntsw; w++) {
01505                 int wxt = (w==0 || w==lt->pntsw-1);
01506                 for(v=0; v<lt->pntsv; v++) {
01507                         int vxt = (v==0 || v==lt->pntsv-1);
01508                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
01509                                 int uxt = (u==0 || u==lt->pntsu-1);
01510                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
01511                                         if(bp->hide==0) {
01512                                                 if((bp->f1 & SELECT)==sel) {
01513                                                         bglVertex3fv(dl?co:bp->vec);
01514                                                 }
01515                                         }
01516                                 }
01517                         }
01518                 }
01519         }
01520         
01521         glPointSize(1.0);
01522         bglEnd();       
01523 }
01524 
01525 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
01526 {
01527         Object *obedit= vc->obedit;
01528         Lattice *lt= obedit->data;
01529         BPoint *bp = lt->editlatt->latt->def;
01530         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
01531         float *co = dl?dl->verts:NULL;
01532         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
01533         short s[2] = {IS_CLIPPED, 0};
01534 
01535         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
01536 
01537         for (i=0; i<N; i++, bp++, co+=3) {
01538                 if (bp->hide==0) {
01539                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
01540                         if (s[0] != IS_CLIPPED)
01541                                 func(userData, bp, s[0], s[1]);
01542                 }
01543         }
01544 }
01545 
01546 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
01547 {
01548         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
01549 
01550         if(use_wcol) {
01551                 float col[3];
01552                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
01553                 
01554                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
01555                 glColor3fv(col);
01556 
01557         }
01558         
01559         if (dl) {
01560                 glVertex3fv(&dl->verts[index*3]);
01561         } else {
01562                 glVertex3fv(lt->def[index].vec);
01563         }
01564 }
01565 
01566 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
01567 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
01568 {
01569         Lattice *lt= ob->data;
01570         DispList *dl;
01571         int u, v, w;
01572         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
01573 
01574         /* now we default make displist, this will modifiers work for non animated case */
01575         if(ob->disp.first==NULL)
01576                 lattice_calc_modifiers(scene, ob);
01577         dl= find_displist(&ob->disp, DL_VERTS);
01578         
01579         if(is_edit) {
01580                 lt= lt->editlatt->latt;
01581 
01582                 cpack(0x004000);
01583                 
01584                 if(ob->defbase.first && lt->dvert) {
01585                         use_wcol= ob->actdef;
01586                         glShadeModel(GL_SMOOTH);
01587                 }
01588         }
01589         
01590         glBegin(GL_LINES);
01591         for(w=0; w<lt->pntsw; w++) {
01592                 int wxt = (w==0 || w==lt->pntsw-1);
01593                 for(v=0; v<lt->pntsv; v++) {
01594                         int vxt = (v==0 || v==lt->pntsv-1);
01595                         for(u=0; u<lt->pntsu; u++) {
01596                                 int uxt = (u==0 || u==lt->pntsu-1);
01597 
01598                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
01599                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
01600                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
01601                                 }
01602                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
01603                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
01604                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
01605                                 }
01606                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
01607                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
01608                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
01609                                 }
01610                         }
01611                 }
01612         }               
01613         glEnd();
01614         
01615         /* restoration for weight colors */
01616         if(use_wcol)
01617                 glShadeModel(GL_FLAT);
01618 
01619         if(is_edit) {
01620                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
01621                 
01622                 lattice_draw_verts(lt, dl, 0);
01623                 lattice_draw_verts(lt, dl, 1);
01624                 
01625                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
01626         }
01627 }
01628 
01629 /* ***************** ******************** */
01630 
01631 /* Note! - foreach funcs should be called while drawing or directly after
01632  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
01633  * but would not give correct results with dupli's for eg. which dont
01634  * use the object matrix in the useual way */
01635 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
01636 {
01637         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
01638         EditVert *eve = EM_get_vert_for_index(index);
01639 
01640         if (eve->h==0) {
01641                 short s[2]= {IS_CLIPPED, 0};
01642 
01643                 if (data->clipVerts) {
01644                         view3d_project_short_clip(data->vc.ar, co, s, 1);
01645                 } else {
01646                         view3d_project_short_noclip(data->vc.ar, co, s);
01647                 }
01648 
01649                 if (s[0]!=IS_CLIPPED)
01650                         data->func(data->userData, eve, s[0], s[1], index);
01651         }
01652 }
01653 
01654 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
01655 {
01656         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
01657         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
01658         
01659         data.vc= *vc;
01660         data.func = func;
01661         data.userData = userData;
01662         data.clipVerts = clipVerts;
01663 
01664         if(clipVerts)
01665                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
01666 
01667         EM_init_index_arrays(vc->em, 1, 0, 0);
01668         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
01669         EM_free_index_arrays();
01670 
01671         dm->release(dm);
01672 }
01673 
01674 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
01675 {
01676         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;
01677         EditEdge *eed = EM_get_edge_for_index(index);
01678         short s[2][2];
01679 
01680         if (eed->h==0) {
01681                 if (data->clipVerts==1) {
01682                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
01683                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
01684                 } else {
01685                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
01686                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
01687 
01688                         if (data->clipVerts==2) {
01689                                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
01690                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
01691                                                 return;
01692                         }
01693                 }
01694 
01695                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
01696         }
01697 }
01698 
01699 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)
01700 {
01701         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
01702         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
01703 
01704         data.vc= *vc;
01705         data.func = func;
01706         data.userData = userData;
01707         data.clipVerts = clipVerts;
01708 
01709         if(clipVerts)
01710                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
01711 
01712         EM_init_index_arrays(vc->em, 0, 1, 0);
01713         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
01714         EM_free_index_arrays();
01715 
01716         dm->release(dm);
01717 }
01718 
01719 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
01720 {
01721         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
01722         EditFace *efa = EM_get_face_for_index(index);
01723         short s[2];
01724 
01725         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
01726                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
01727 
01728                 data->func(data->userData, efa, s[0], s[1], index);
01729         }
01730 }
01731 
01732 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
01733 {
01734         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
01735         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
01736 
01737         data.vc= *vc;
01738         data.func = func;
01739         data.userData = userData;
01740 
01741         //if(clipVerts)
01742         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
01743 
01744         EM_init_index_arrays(vc->em, 0, 0, 1);
01745         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
01746         EM_free_index_arrays();
01747 
01748         dm->release(dm);
01749 }
01750 
01751 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
01752 {
01753         Curve *cu= vc->obedit->data;
01754         short s[2] = {IS_CLIPPED, 0};
01755         Nurb *nu;
01756         int i;
01757         ListBase *nurbs= ED_curve_editnurbs(cu);
01758 
01759         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
01760 
01761         for (nu= nurbs->first; nu; nu=nu->next) {
01762                 if(nu->type == CU_BEZIER) {
01763                         for (i=0; i<nu->pntsu; i++) {
01764                                 BezTriple *bezt = &nu->bezt[i];
01765 
01766                                 if(bezt->hide==0) {
01767                                         
01768                                         if(cu->drawflag & CU_HIDE_HANDLES) {
01769                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
01770                                                 if (s[0] != IS_CLIPPED)
01771                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
01772                                         } else {
01773                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
01774                                                 if (s[0] != IS_CLIPPED)
01775                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
01776                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
01777                                                 if (s[0] != IS_CLIPPED)
01778                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
01779                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
01780                                                 if (s[0] != IS_CLIPPED)
01781                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
01782                                         }
01783                                 }
01784                         }
01785                 }
01786                 else {
01787                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
01788                                 BPoint *bp = &nu->bp[i];
01789 
01790                                 if(bp->hide==0) {
01791                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
01792                                         if (s[0] != IS_CLIPPED)
01793                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
01794                                 }
01795                         }
01796                 }
01797         }
01798 }
01799 
01800 /* ************** DRAW MESH ****************** */
01801 
01802 /* First section is all the "simple" draw routines, 
01803  * ones that just pass some sort of primitive to GL,
01804  * with perhaps various options to control lighting,
01805  * color, etc.
01806  *
01807  * These routines should not have user interface related
01808  * logic!!!
01809  */
01810 
01811 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
01812 {
01813         ToolSettings *ts= ((Scene *)userData)->toolsettings;
01814         EditFace *efa = EM_get_face_for_index(index);
01815 
01816         if (efa->h==0 && efa->fgonf!=EM_FGON) {
01817                 glVertex3fv(cent);
01818                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
01819                                         cent[1] + no[1]*ts->normalsize,
01820                                         cent[2] + no[2]*ts->normalsize);
01821         }
01822 }
01823 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
01824 {
01825         glBegin(GL_LINES);
01826         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
01827         glEnd();
01828 }
01829 
01830 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
01831 {
01832         EditFace *efa = EM_get_face_for_index(index);
01833         int sel = *((int*) userData);
01834 
01835         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
01836                 bglVertex3fv(cent);
01837         }
01838 }
01839 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
01840 {
01841         bglBegin(GL_POINTS);
01842         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
01843         bglEnd();
01844 }
01845 
01846 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
01847 {
01848         Scene *scene= (Scene *)userData;
01849         ToolSettings *ts= scene->toolsettings;
01850         EditVert *eve = EM_get_vert_for_index(index);
01851 
01852         if (eve->h==0) {
01853                 glVertex3fv(co);
01854 
01855                 if (no_f) {
01856                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
01857                                                 co[1] + no_f[1]*ts->normalsize,
01858                                                 co[2] + no_f[2]*ts->normalsize);
01859                 } else {
01860                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
01861                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
01862                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
01863                 }
01864         }
01865 }
01866 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
01867 {
01868         glBegin(GL_LINES);
01869         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
01870         glEnd();
01871 }
01872 
01873         /* Draw verts with color set based on selection */
01874 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
01875 {
01876         struct { int sel; EditVert *eve_act; } * data = userData;
01877         EditVert *eve = EM_get_vert_for_index(index);
01878 
01879         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
01880                 /* draw active larger - need to stop/start point drawing for this :/ */
01881                 if (eve==data->eve_act) {
01882                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
01883                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
01884                         
01885                         bglEnd();
01886                         
01887                         glPointSize(size);
01888                         bglBegin(GL_POINTS);
01889                         bglVertex3fv(co);
01890                         bglEnd();
01891                         
01892                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
01893                         glPointSize(size);
01894                         bglBegin(GL_POINTS);
01895                 } else {
01896                         bglVertex3fv(co);
01897                 }
01898         }
01899 }
01900 
01901 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
01902 {
01903         struct { int sel; EditVert *eve_act; } data;
01904         data.sel = sel;
01905         data.eve_act = eve_act;
01906 
01907         bglBegin(GL_POINTS);
01908         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
01909         bglEnd();
01910 }
01911 
01912         /* Draw edges with color set based on selection */
01913 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
01914 {
01915         EditEdge *eed = EM_get_edge_for_index(index);
01916         //unsigned char **cols = userData, *col;
01917         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
01918         unsigned char *col;
01919 
01920         if (eed->h==0) {
01921                 if (eed==data->eed_act) {
01922                         glColor4ubv(data->actCol);
01923                 } else {
01924                         if (eed->f&SELECT) {
01925                                 col = data->selCol;
01926                         } else {
01927                                 col = data->baseCol;
01928                         }
01929                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
01930                         if (col[3]==0) return 0;
01931                         
01932                         glColor4ubv(col);
01933                 }
01934                 return 1;
01935         } else {
01936                 return 0;
01937         }
01938 }
01939 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
01940 {
01941         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
01942         
01943         data.baseCol = baseCol;
01944         data.selCol = selCol;
01945         data.actCol = actCol;
01946         data.eed_act = eed_act;
01947         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
01948 }
01949 
01950         /* Draw edges */
01951 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
01952 {
01953         return EM_get_edge_for_index(index)->h==0;
01954 }
01955 static void draw_dm_edges(DerivedMesh *dm) 
01956 {
01957         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
01958 }
01959 
01960         /* Draw edges with color interpolated based on selection */
01961 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
01962 {
01963         return EM_get_edge_for_index(index)->h==0;
01964 }
01965 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
01966 {
01967         EditEdge *eed = EM_get_edge_for_index(index);
01968         unsigned char **cols = userData;
01969         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
01970         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
01971 
01972         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
01973                                 col0[1] + (col1[1]-col0[1])*t,
01974                                 col0[2] + (col1[2]-col0[2])*t,
01975                                 col0[3] + (col1[3]-col0[3])*t);
01976 }
01977 
01978 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
01979 {
01980         unsigned char *cols[2];
01981         cols[0]= baseCol;
01982         cols[1]= selCol;
01983         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
01984 }
01985 
01986         /* Draw only seam edges */
01987 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
01988 {
01989         EditEdge *eed = EM_get_edge_for_index(index);
01990 
01991         return (eed->h==0 && eed->seam);
01992 }
01993 static void draw_dm_edges_seams(DerivedMesh *dm)
01994 {
01995         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
01996 }
01997 
01998         /* Draw only sharp edges */
01999 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
02000 {
02001         EditEdge *eed = EM_get_edge_for_index(index);
02002 
02003         return (eed->h==0 && eed->sharp);
02004 }
02005 static void draw_dm_edges_sharp(DerivedMesh *dm)
02006 {
02007         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
02008 }
02009 
02010 
02011         /* Draw faces with color set based on selection
02012          * return 2 for the active face so it renders with stipple enabled */
02013 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
02014 {
02015         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
02016         EditFace *efa = EM_get_face_for_index(index);
02017         unsigned char *col;
02018         
02019         if (efa->h==0) {
02020                 if (efa == data->efa_act) {
02021                         glColor4ubv(data->cols[2]);
02022                         return 2; /* stipple */
02023                 } else {
02024                         col = data->cols[(efa->f&SELECT)?1:0];
02025                         if (col[3]==0) return 0;
02026                         glColor4ubv(col);
02027                         return 1;
02028                 }
02029         }
02030         return 0;
02031 }
02032 
02033 /* also draws the active face */
02034 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
02035 {
02036         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
02037         data.cols[0] = baseCol;
02038         data.cols[1] = selCol;
02039         data.cols[2] = actCol;
02040         data.efa_act = efa_act;
02041 
02042         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
02043 }
02044 
02045 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
02046 {
02047         EditEdge *eed = EM_get_edge_for_index(index);
02048 
02049         if (eed->h==0 && eed->crease != 0.0f) {
02050                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
02051                 return 1;
02052         } else {
02053                 return 0;
02054         }
02055 }
02056 static void draw_dm_creases(DerivedMesh *dm)
02057 {
02058         glLineWidth(3.0);
02059         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
02060         glLineWidth(1.0);
02061 }
02062 
02063 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
02064 {
02065         EditEdge *eed = EM_get_edge_for_index(index);
02066 
02067         if (eed->h==0 && eed->bweight != 0.0f) {
02068                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
02069                 return 1;
02070         } else {
02071                 return 0;
02072         }
02073 }
02074 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
02075 {
02076         EditVert *eve = EM_get_vert_for_index(index);
02077 
02078         if (eve->h==0 && eve->bweight != 0.0f) {
02079                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
02080                 bglVertex3fv(co);
02081         }
02082 }
02083 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
02084 {
02085         ToolSettings *ts= scene->toolsettings;
02086 
02087         if (ts->selectmode & SCE_SELECT_VERTEX) {
02088                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
02089                 bglBegin(GL_POINTS);
02090                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
02091                 bglEnd();
02092         }
02093         else {
02094                 glLineWidth(3.0);
02095                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
02096                 glLineWidth(1.0);
02097         }
02098 }
02099 
02100 /* Second section of routines: Combine first sets to form fancy
02101  * drawing routines (for example rendering twice to get overlays).
02102  *
02103  * Also includes routines that are basic drawing but are too
02104  * specialized to be split out (like drawing creases or measurements).
02105  */
02106 
02107 /* EditMesh drawing routines*/
02108 
02109 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
02110 {
02111         ToolSettings *ts= scene->toolsettings;
02112         int sel;
02113 
02114         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
02115 
02116         for (sel=0; sel<2; sel++) {
02117                 unsigned char col[4], fcol[4];
02118                 int pass;
02119 
02120                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
02121                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
02122 
02123                 for (pass=0; pass<2; pass++) {
02124                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
02125                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
02126 
02127                         if (pass==0) {
02128                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
02129                                         glDisable(GL_DEPTH_TEST);
02130                                                 
02131                                         glEnable(GL_BLEND);
02132                                 } else {
02133                                         continue;
02134                                 }
02135 
02136                                 size = (size > 2.1f ? size/2.0f:size);
02137                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
02138                                 col[3] = fcol[3] = 100;
02139                         } else {
02140                                 col[3] = fcol[3] = 255;
02141                         }
02142                                 
02143                         if(ts->selectmode & SCE_SELECT_VERTEX) {
02144                                 glPointSize(size);
02145                                 glColor4ubv(col);
02146                                 draw_dm_verts(cageDM, sel, eve_act);
02147                         }
02148                         
02149                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
02150                                 glPointSize(fsize);
02151                                 glColor4ubv(fcol);
02152                                 draw_dm_face_centers(cageDM, sel);
02153                         }
02154                         
02155                         if (pass==0) {
02156                                 glDisable(GL_BLEND);
02157                                 glEnable(GL_DEPTH_TEST);
02158                         }
02159                 }
02160         }
02161 
02162         if(v3d->zbuf) glDepthMask(1);
02163         glPointSize(1.0);
02164 }
02165 
02166 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
02167 {
02168         ToolSettings *ts= scene->toolsettings;
02169         int pass;
02170         unsigned char wireCol[4], selCol[4], actCol[4];
02171 
02172         /* since this function does transparant... */
02173         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
02174         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
02175         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
02176         
02177         /* when sel only is used, dont render wire, only selected, this is used for
02178          * textured draw mode when the 'edges' option is disabled */
02179         if (sel_only)
02180                 wireCol[3] = 0;
02181 
02182         for (pass=0; pass<2; pass++) {
02183                         /* show wires in transparant when no zbuf clipping for select */
02184                 if (pass==0) {
02185                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
02186                                 glEnable(GL_BLEND);
02187                                 glDisable(GL_DEPTH_TEST);
02188                                 selCol[3] = 85;
02189                                 if (!sel_only) wireCol[3] = 85;
02190                         } else {
02191                                 continue;
02192                         }
02193                 } else {
02194                         selCol[3] = 255;
02195                         if (!sel_only) wireCol[3] = 255;
02196                 }
02197 
02198                 if(ts->selectmode == SCE_SELECT_FACE) {
02199                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
02200                 }       
02201                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
02202                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
02203                                 glShadeModel(GL_SMOOTH);
02204                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
02205                                 glShadeModel(GL_FLAT);
02206                         } else {
02207                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
02208                         }
02209                 }
02210                 else {
02211                         if (!sel_only) {
02212                                 glColor4ubv(wireCol);
02213                                 draw_dm_edges(cageDM);
02214                         }
02215                 }
02216 
02217                 if (pass==0) {
02218                         glDisable(GL_BLEND);
02219                         glEnable(GL_DEPTH_TEST);
02220                 }
02221         }
02222 }       
02223 
02224 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
02225 {
02226         Mesh *me= ob->data;
02227         EditEdge *eed;
02228         EditFace *efa;
02229         float v1[3], v2[3], v3[3], v4[3], vmid[3];
02230         float fvec[3];
02231         char val[32]; /* Stores the measurement display text here */
02232         const char *conv_float; /* Use a float conversion matching the grid size */
02233         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
02234         float area; /* area of the face */
02235         float grid= unit->system ? unit->scale_length : v3d->grid;
02236         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
02237         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
02238         const int do_moving= G.moving;
02239 
02240         /* make the precision of the pronted value proportionate to the gridsize */
02241 
02242         if (grid < 0.01f)               conv_float= "%.6g";
02243         else if (grid < 0.1f)   conv_float= "%.5g";
02244         else if (grid < 1.0f)   conv_float= "%.4g";
02245         else if (grid < 10.0f)  conv_float= "%.3g";
02246         else                                    conv_float= "%.2g";
02247 
02248         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
02249                 glDisable(GL_DEPTH_TEST);
02250 
02251         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
02252         
02253         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
02254                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
02255 
02256                 for(eed= em->edges.first; eed; eed= eed->next) {
02257                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
02258                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
02259                                 copy_v3_v3(v1, eed->v1->co);
02260                                 copy_v3_v3(v2, eed->v2->co);
02261 
02262                                 interp_v3_v3v3(vmid, v1, v2, 0.5f);
02263 
02264                                 if(do_global) {
02265                                         mul_mat3_m4_v3(ob->obmat, v1);
02266                                         mul_mat3_m4_v3(ob->obmat, v2);
02267                                 }
02268                                 if(unit->system)
02269                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
02270                                 else
02271                                         sprintf(val, conv_float, len_v3v3(v1, v2));
02272 
02273                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
02274                         }
02275                 }
02276         }
02277 
02278         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
02279 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
02280                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
02281                 
02282                 for(efa= em->faces.first; efa; efa= efa->next) {
02283                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
02284                                 copy_v3_v3(v1, efa->v1->co);
02285                                 copy_v3_v3(v2, efa->v2->co);
02286                                 copy_v3_v3(v3, efa->v3->co);
02287                                 if (efa->v4) {
02288                                         copy_v3_v3(v4, efa->v4->co);
02289                                 }
02290                                 if(do_global) {
02291                                         mul_mat3_m4_v3(ob->obmat, v1);
02292                                         mul_mat3_m4_v3(ob->obmat, v2);
02293                                         mul_mat3_m4_v3(ob->obmat, v3);
02294                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
02295                                 }
02296                                 
02297                                 if (efa->v4)
02298                                         area=  area_quad_v3(v1, v2, v3, v4);
02299                                 else
02300                                         area = area_tri_v3(v1, v2, v3);
02301 
02302                                 if(unit->system)
02303                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
02304                                 else
02305                                         sprintf(val, conv_float, area);
02306 
02307                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
02308                         }
02309                 }
02310         }
02311 
02312         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
02313                 EditEdge *e1, *e2, *e3, *e4;
02314                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
02315                 for(efa= em->faces.first; efa; efa= efa->next) {
02316                         copy_v3_v3(v1, efa->v1->co);
02317                         copy_v3_v3(v2, efa->v2->co);
02318                         copy_v3_v3(v3, efa->v3->co);
02319                         if(efa->v4) {
02320                                 copy_v3_v3(v4, efa->v4->co); 
02321                         }
02322                         else {
02323                                 copy_v3_v3(v4, v3);
02324                         }
02325                         if(do_global) {
02326                                 mul_mat3_m4_v3(ob->obmat, v1);
02327                                 mul_mat3_m4_v3(ob->obmat, v2);
02328                                 mul_mat3_m4_v3(ob->obmat, v3);
02329                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
02330                         }
02331                         
02332                         e1= efa->e1;
02333                         e2= efa->e2;
02334                         e3= efa->e3;
02335                         if(efa->e4) e4= efa->e4; else e4= e3;
02336                         
02337                         /* Calculate the angles */
02338                                 
02339                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
02340                                 /* Vec 1 */
02341                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
02342                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
02343                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
02344                         }
02345                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
02346                                 /* Vec 2 */
02347                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
02348                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
02349                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
02350                         }
02351                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
02352                                 /* Vec 3 */
02353                                 if(efa->v4) 
02354                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
02355                                 else
02356                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
02357                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
02358                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
02359                         }
02360                                 /* Vec 4 */
02361                         if(efa->v4) {
02362                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
02363                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
02364                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
02365                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
02366                                 }
02367                         }
02368                 }
02369         }
02370         
02371         if(v3d->zbuf) {
02372                 glEnable(GL_DEPTH_TEST);
02373                 bglPolygonOffset(rv3d->dist, 0.0f);
02374         }
02375 }
02376 
02377 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
02378 {
02379         EditFace *efa = EM_get_face_for_index(index);
02380 
02381         if (efa->h==0) {
02382                 GPU_enable_material(efa->mat_nr+1, NULL);
02383                 return 1;
02384         }
02385         else
02386                 return 0;
02387 }
02388 
02389 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
02390 {
02391         EditFace *efa = EM_get_face_for_index(index);
02392 
02393         return (efa->h==0);
02394 }
02395 
02396 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
02397 {
02398         Mesh *me = ob->data;
02399         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
02400         EditEdge *eed_act = NULL;
02401         EditVert *eve_act = NULL;
02402         
02403         if (em->selected.last) {
02404                 EditSelection *ese = em->selected.last;
02405                 /* face is handeled above */
02406                 /*if (ese->type == EDITFACE ) {
02407                         efa_act = (EditFace *)ese->data;
02408                 } else */ if ( ese->type == EDITEDGE ) {
02409                         eed_act = (EditEdge *)ese->data;
02410                 } else if ( ese->type == EDITVERT ) {
02411                         eve_act = (EditVert *)ese->data;
02412                 }
02413         }
02414         
02415         EM_init_index_arrays(em, 1, 1, 1);
02416 
02417         if(dt>OB_WIRE) {
02418                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
02419                         if(draw_glsl_material(scene, ob, v3d, dt)) {
02420                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
02421 
02422                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
02423                                         draw_em_fancy__setGLSLFaceOpts, NULL);
02424                                 GPU_disable_material();
02425 
02426                                 glFrontFace(GL_CCW);
02427                         }
02428                         else {
02429                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
02430                         }
02431                 }
02432                 else {
02433                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
02434                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
02435 
02436                         glEnable(GL_LIGHTING);
02437                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
02438 
02439                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material);
02440 
02441                         glFrontFace(GL_CCW);
02442                         glDisable(GL_LIGHTING);
02443                 }
02444                         
02445                 // Setup for drawing wire over, disable zbuffer
02446                 // write to show selected edge wires better
02447                 UI_ThemeColor(TH_WIRE);
02448 
02449                 bglPolygonOffset(rv3d->dist, 1.0);
02450                 glDepthMask(0);
02451         } 
02452         else {
02453                 if (cageDM!=finalDM) {
02454                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
02455                         finalDM->drawEdges(finalDM, 1, 0);
02456                 }
02457         }
02458         
02459         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
02460                 unsigned char col1[4], col2[4], col3[4];
02461                         
02462                 UI_GetThemeColor4ubv(TH_FACE, col1);
02463                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
02464                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
02465                 
02466                 glEnable(GL_BLEND);
02467                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
02468                 
02469                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
02470                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
02471                         col1[3] = 0;
02472                 
02473                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
02474 
02475                 glDisable(GL_BLEND);
02476                 glDepthMask(1);         // restore write in zbuffer
02477         } else if (efa_act) {
02478                 /* even if draw faces is off it would be nice to draw the stipple face
02479                  * Make all other faces zero alpha except for the active
02480                  * */
02481                 unsigned char col1[4], col2[4], col3[4];
02482                 col1[3] = col2[3] = 0; /* dont draw */
02483                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
02484                 
02485                 glEnable(GL_BLEND);
02486                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
02487                 
02488                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
02489 
02490                 glDisable(GL_BLEND);
02491                 glDepthMask(1);         // restore write in zbuffer
02492                 
02493         }
02494 
02495         /* here starts all fancy draw-extra over */
02496         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
02497                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
02498                 
02499                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
02500                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
02501                 
02502         } else {
02503                 if(me->drawflag & ME_DRAWSEAMS) {
02504                         UI_ThemeColor(TH_EDGE_SEAM);
02505                         glLineWidth(2);
02506         
02507                         draw_dm_edges_seams(cageDM);
02508         
02509                         glColor3ub(0,0,0);
02510                         glLineWidth(1);
02511                 }
02512                 
02513                 if(me->drawflag & ME_DRAWSHARP) {
02514                         UI_ThemeColor(TH_EDGE_SHARP);
02515                         glLineWidth(2);
02516         
02517                         draw_dm_edges_sharp(cageDM);
02518         
02519                         glColor3ub(0,0,0);
02520                         glLineWidth(1);
02521                 }
02522         
02523                 if(me->drawflag & ME_DRAWCREASES) {
02524                         draw_dm_creases(cageDM);
02525                 }
02526                 if(me->drawflag & ME_DRAWBWEIGHTS) {
02527                         draw_dm_bweights(scene, cageDM);
02528                 }
02529         
02530                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
02531         }
02532         if(em) {
02533 // XXX          retopo_matrix_update(v3d);
02534 
02535                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
02536 
02537                 if(me->drawflag & ME_DRAWNORMALS) {
02538                         UI_ThemeColor(TH_NORMAL);
02539                         draw_dm_face_normals(scene, cageDM);
02540                 }
02541                 if(me->drawflag & ME_DRAW_VNORMALS) {
02542                         UI_ThemeColor(TH_VNORMAL);
02543                         draw_dm_vert_normals(scene, cageDM);
02544                 }
02545 
02546                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
02547                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
02548         }
02549 
02550         if(dt>OB_WIRE) {
02551                 glDepthMask(1);
02552                 bglPolygonOffset(rv3d->dist, 0.0);
02553                 GPU_disable_material();
02554         }
02555 
02556         EM_free_index_arrays();
02557 }
02558 
02559 /* Mesh drawing routines */
02560 
02561 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
02562 {
02563         
02564         if(v3d->transp==0) {    // not when we draw the transparent pass
02565                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
02566                 glDepthMask(0);
02567                 
02568                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
02569                    drawFacesSolid() doesn't draw the transparent faces */
02570                 if(ob->dtx & OB_DRAWTRANSP) {
02571                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
02572                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
02573                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
02574                         GPU_disable_material();
02575                 }
02576                 else {
02577                         dm->drawEdges(dm, 0, 1);
02578                 }
02579                                         
02580                 glLineWidth(1.0);
02581                 glDepthMask(1);
02582         }
02583 }
02584 
02585 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
02586 {
02587         *drawSmooth_r = 1;
02588         return 1;
02589 }
02590 
02591 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
02592 {
02593         Object *ob= base->object;
02594         Mesh *me = ob->data;
02595         Material *ma= give_current_material(ob, 1);
02596         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
02597         const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
02598         int draw_wire = 0;
02599         int /* totvert,*/ totedge, totface;
02600         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
02601 
02602         if(!dm)
02603                 return;
02604         
02605         if (ob->dtx&OB_DRAWWIRE) {
02606                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
02607         }
02608         
02609         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
02610         totedge = dm->getNumEdges(dm);
02611         totface = dm->getNumFaces(dm);
02612         
02613         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
02614         if(dt!=OB_SHADED)
02615                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
02616 
02617                 // Unwanted combination.
02618         if (is_paint_sel) draw_wire = 0;
02619 
02620         if(dt==OB_BOUNDBOX) {
02621                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
02622                         draw_bounding_volume(scene, ob);
02623         }
02624         else if(hasHaloMat || (totface==0 && totedge==0)) {
02625                 glPointSize(1.5);
02626                 dm->drawVerts(dm);
02627                 glPointSize(1.0);
02628         }
02629         else if(dt==OB_WIRE || totface==0) {
02630                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
02631         }
02632         else if(        (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
02633                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
02634         {
02635                 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
02636                         draw_mesh_object_outline(v3d, ob, dm);
02637                 }
02638 
02639                 if(draw_glsl_material(scene, ob, v3d, dt)) {
02640                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
02641 
02642                         dm->drawFacesGLSL(dm, GPU_enable_material);
02643 //                      if(get_ob_property(ob, "Text"))
02644 // XXX                          draw_mesh_text(ob, 1);
02645                         GPU_disable_material();
02646 
02647                         glFrontFace(GL_CCW);
02648                 }
02649                 else {
02650                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
02651                 }
02652 
02653                 if(!is_paint_sel) {
02654                         if(base->flag & SELECT)
02655                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
02656                         else
02657                                 UI_ThemeColor(TH_WIRE);
02658 
02659                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
02660                                 dm->drawLooseEdges(dm);
02661                 }
02662         }
02663         else if(dt==OB_SOLID) {
02664                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
02665                         /* weight paint in solid mode, special case. focus on making the weights clear
02666                          * rather than the shading, this is also forced in wire view */
02667                         GPU_enable_material(0, NULL);
02668                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
02669                 
02670                         bglPolygonOffset(rv3d->dist, 1.0);
02671                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
02672 
02673                         glEnable(GL_BLEND);
02674                         glColor4ub(255, 255, 255, 96);
02675                         glEnable(GL_LINE_STIPPLE);
02676                         glLineStipple(1, 0xAAAA);
02677 
02678                         dm->drawEdges(dm, 1, 1);
02679 
02680                         bglPolygonOffset(rv3d->dist, 0.0);
02681                         glDepthMask(1);
02682                         glDisable(GL_LINE_STIPPLE);
02683 
02684                         GPU_disable_material();
02685                         
02686                         /* since we already draw wire as wp guide, dont draw over the top */
02687                         draw_wire= 0;
02688                 }
02689                 else {
02690                         Paint *p;
02691 
02692                         if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
02693                                 draw_mesh_object_outline(v3d, ob, dm);
02694 
02695                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
02696 
02697                         glEnable(GL_LIGHTING);
02698                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
02699 
02700                         if(ob->sculpt && (p=paint_get_active(scene))) {
02701                                 float planes[4][4];
02702                                 float (*fpl)[4] = NULL;
02703                                 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
02704 
02705                                 if(ob->sculpt->partial_redraw) {
02706                                         if(ar->do_draw & RGN_DRAW_PARTIAL) {
02707                                                 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
02708                                                 fpl = planes;
02709                                                 ob->sculpt->partial_redraw = 0;
02710                                         }
02711                                 }
02712 
02713                                 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
02714                         }
02715                         else
02716                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
02717 
02718                         GPU_disable_material();
02719 
02720                         glFrontFace(GL_CCW);
02721                         glDisable(GL_LIGHTING);
02722 
02723                         if(base->flag & SELECT) {
02724                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
02725                         } else {
02726                                 UI_ThemeColor(TH_WIRE);
02727                         }
02728                         if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
02729                                 dm->drawLooseEdges(dm);
02730                 }
02731         }
02732         else if(dt==OB_SHADED) {
02733                 if(ob==OBACT) {
02734                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
02735                                 /* enforce default material settings */
02736                                 GPU_enable_material(0, NULL);
02737                                 
02738                                 /* but set default spec */
02739                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
02740                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
02741                                 glColor3ub(120, 120, 120);
02742                                 glDisable(GL_COLOR_MATERIAL);
02743                                 /* diffuse */
02744                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
02745                                 glEnable(GL_LIGHTING);
02746                                 glEnable(GL_COLOR_MATERIAL);
02747 
02748                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
02749                                 glDisable(GL_COLOR_MATERIAL);
02750                                 glDisable(GL_LIGHTING);
02751 
02752                                 GPU_disable_material();
02753                         }
02754                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
02755                                 if(me->mcol)
02756                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
02757                                 else {
02758                                         glColor3f(1.0f, 1.0f, 1.0f);
02759                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
02760                                 }
02761                         }
02762                 }
02763         }
02764         
02765         /* set default draw color back for wire or for draw-extra later on */
02766         if (dt!=OB_WIRE) {
02767                 if(base->flag & SELECT) {
02768                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
02769                                 UI_ThemeColor(TH_GROUP_ACTIVE);
02770                         else if(ob->flag & OB_FROMGROUP) 
02771                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
02772                         else if(flag!=DRAW_CONSTCOLOR)
02773                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
02774                         else
02775                                 glColor3ub(80,80,80);
02776                 } else {
02777                         if (ob->flag & OB_FROMGROUP) 
02778                                 UI_ThemeColor(TH_GROUP);
02779                         else {
02780                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
02781                                         glColor3ub(80,80,80);
02782                                 else
02783                                         UI_ThemeColor(TH_WIRE);
02784                         }
02785                 }
02786         }
02787         if (draw_wire) {
02788 
02789                 /* When using wireframe object traw in particle edit mode
02790                  * the mesh gets in the way of seeing the particles, fade the wire color
02791                  * with the background. */
02792                 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
02793                         float col_wire[4], col_bg[4], col[3];
02794 
02795                         UI_GetThemeColor3fv(TH_BACK, col_bg);
02796                         glGetFloatv(GL_CURRENT_COLOR, col_wire);
02797                         interp_v3_v3v3(col, col_bg, col_wire, 0.15);
02798                         glColor3fv(col);
02799                 }
02800 
02801                 /* If drawing wire and drawtype is not OB_WIRE then we are
02802                  * overlaying the wires.
02803                  *
02804                  * UPDATE bug #10290 - With this wire-only objects can draw
02805                  * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
02806                  *
02807                  * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
02808                  * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
02809                  */
02810                 if (dt!=OB_WIRE && draw_wire==2) {
02811                         bglPolygonOffset(rv3d->dist, 1.0);
02812                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
02813                 }
02814                 
02815                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
02816                         dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
02817 
02818                 if (dt!=OB_WIRE && draw_wire==2) {
02819                         glDepthMask(1);
02820                         bglPolygonOffset(rv3d->dist, 0.0);
02821                 }
02822         }
02823 
02824         dm->release(dm);
02825 }
02826 
02827 /* returns 1 if nothing was drawn, for detecting to draw an object center */
02828 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
02829 {
02830         Object *ob= base->object;
02831         Object *obedit= scene->obedit;
02832         Mesh *me= ob->data;
02833         EditMesh *em= me->edit_mesh;
02834         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
02835         
02836         if(obedit && ob!=obedit && ob->data==obedit->data) {
02837                 if(ob_get_key(ob) || ob_get_key(obedit));
02838                 else if(ob->modifiers.first || obedit->modifiers.first);
02839                 else drawlinked= 1;
02840         }
02841         
02842         if(ob==obedit || drawlinked) {
02843                 DerivedMesh *finalDM, *cageDM;
02844                 
02845                 if (obedit!=ob)
02846                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
02847                 else
02848                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
02849                                                                                         scene->customdata_mask);
02850 
02851                 if(dt>OB_WIRE) {
02852                         // no transp in editmode, the fancy draw over goes bad then
02853                         glsl = draw_glsl_material(scene, ob, v3d, dt);
02854                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
02855                 }
02856 
02857                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
02858 
02859                 GPU_end_object_materials();
02860 
02861                 if (obedit!=ob && finalDM)
02862                         finalDM->release(finalDM);
02863         }
02864         else {
02865                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
02866                 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
02867                         glsl = draw_glsl_material(scene, ob, v3d, dt);
02868                         check_alpha = check_material_alpha(base, me, glsl);
02869 
02870                         if(dt==OB_SOLID || glsl) {
02871                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
02872                                         (check_alpha)? &do_alpha_pass: NULL);
02873                         }
02874 
02875                         draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
02876 
02877                         GPU_end_object_materials();
02878                         
02879                         if(me->totvert==0) retval= 1;
02880                 }
02881         }
02882         
02883         /* GPU_begin_object_materials checked if this is needed */
02884         if(do_alpha_pass) {
02885                 if(ob->dtx & OB_DRAWXRAY) {
02886                         add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
02887                 }
02888                 else {
02889                         add_view3d_after(&v3d->afterdraw_transp, base, flag);
02890                 }
02891         }
02892         else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
02893                 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
02894                 if(v3d->xray == 0 && v3d->transp == 0) {
02895                         add_view3d_after(&v3d->afterdraw_xray, base, flag);
02896                 }
02897         }
02898         
02899         return retval;
02900 }
02901 
02902 /* ************** DRAW DISPLIST ****************** */
02903 
02904 static int draw_index_wire= 1;
02905 static int index3_nors_incr= 1;
02906 
02907 /* returns 1 when nothing was drawn */
02908 static int drawDispListwire(ListBase *dlbase)
02909 {
02910         DispList *dl;
02911         int parts, nr;
02912         float *data;
02913 
02914         if(dlbase==NULL) return 1;
02915         
02916         glEnableClientState(GL_VERTEX_ARRAY);
02917         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
02918 
02919         for(dl= dlbase->first; dl; dl= dl->next) {
02920                 if(dl->parts==0 || dl->nr==0)
02921                         continue;
02922                 
02923                 data= dl->verts;
02924         
02925                 switch(dl->type) {
02926                 case DL_SEGM:
02927                         
02928                         glVertexPointer(3, GL_FLOAT, 0, data);
02929                         
02930                         for(parts=0; parts<dl->parts; parts++)
02931                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
02932                                 
02933                         break;
02934                 case DL_POLY:
02935                         
02936                         glVertexPointer(3, GL_FLOAT, 0, data);
02937                         
02938                         for(parts=0; parts<dl->parts; parts++)
02939                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
02940                         
02941                         break;
02942                 case DL_SURF:
02943                         
02944                         glVertexPointer(3, GL_FLOAT, 0, data);
02945                         
02946                         for(parts=0; parts<dl->parts; parts++) {
02947                                 if(dl->flag & DL_CYCL_U) 
02948                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
02949                                 else
02950                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
02951                         }
02952                         
02953                         for(nr=0; nr<dl->nr; nr++) {
02954                                 int ofs= 3*dl->nr;
02955                                 
02956                                 data= (  dl->verts )+3*nr;
02957                                 parts= dl->parts;
02958 
02959                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
02960                                 else glBegin(GL_LINE_STRIP);
02961                                 
02962                                 while(parts--) {
02963                                         glVertex3fv(data);
02964                                         data+=ofs;
02965                                 }
02966                                 glEnd();
02967                                 
02968                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
02969 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
02970 //                              if(dl->flag & DL_CYCL_V) 
02971 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
02972 //                              else
02973 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
02974                         }
02975                         break;
02976                         
02977                 case DL_INDEX3:
02978                         if(draw_index_wire) {
02979                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
02980                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
02981                         }
02982                         break;
02983                         
02984                 case DL_INDEX4:
02985                         if(draw_index_wire) {
02986                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
02987                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
02988                         }
02989                         break;
02990                 }
02991         }
02992         
02993         glDisableClientState(GL_VERTEX_ARRAY);
02994         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
02995         
02996         return 0;
02997 }
02998 
02999 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
03000 {
03001         DispList *dl;
03002         GPUVertexAttribs gattribs;
03003         float *data, curcol[4];
03004         float *ndata;
03005         
03006         if(lb==NULL) return;
03007         
03008         /* for drawing wire */
03009         glGetFloatv(GL_CURRENT_COLOR, curcol);
03010 
03011         glEnable(GL_LIGHTING);
03012         glEnableClientState(GL_VERTEX_ARRAY);
03013         
03014         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
03015         else glFrontFace(GL_CCW);
03016         
03017         if(ob->type==OB_MBALL) {        // mball always smooth shaded
03018                 glShadeModel(GL_SMOOTH);
03019         }
03020         
03021         dl= lb->first;
03022         while(dl) {
03023                 data= dl->verts;
03024                 ndata= dl->nors;
03025 
03026                 switch(dl->type) {
03027                 case DL_SEGM:
03028                         if(ob->type==OB_SURF) {
03029                                 int nr;
03030 
03031                                 glDisable(GL_LIGHTING);
03032                                 glColor3fv(curcol);
03033                                 
03034                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
03035                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
03036 
03037                                 glBegin(GL_LINE_STRIP);
03038                                 for(nr= dl->nr; nr; nr--, data+=3)
03039                                         glVertex3fv(data);
03040                                 glEnd();
03041 
03042                                 glEnable(GL_LIGHTING);
03043                         }
03044                         break;
03045                 case DL_POLY:
03046                         if(ob->type==OB_SURF) {
03047                                 int nr;
03048 
03049                                 glDisable(GL_LIGHTING);
03050                                 
03051                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
03052                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
03053                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
03054                                 
03055                                 glBegin(GL_LINE_LOOP);
03056                                 for(nr= dl->nr; nr; nr--, data+=3)
03057                                         glVertex3fv(data);
03058                                 glEnd();
03059                                 
03060                                 glEnable(GL_LIGHTING);
03061                                 break;
03062                         }
03063                 case DL_SURF:
03064                         
03065                         if(dl->index) {
03066                                 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
03067                                 
03068                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
03069                                 else glShadeModel(GL_FLAT);
03070 
03071                                 glEnableClientState(GL_NORMAL_ARRAY);
03072                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
03073                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
03074                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
03075                                 glDisableClientState(GL_NORMAL_ARRAY);
03076                         }                       
03077                         break;
03078 
03079                 case DL_INDEX3:
03080                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
03081                         
03082                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
03083                         
03084                         /* voor polys only one normal needed */
03085                         if(index3_nors_incr) {
03086                                 glEnableClientState(GL_NORMAL_ARRAY);
03087                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
03088                         }
03089                         else
03090                                 glNormal3fv(ndata);
03091                         
03092                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
03093                         
03094                         if(index3_nors_incr)
03095                                 glDisableClientState(GL_NORMAL_ARRAY);
03096 
03097                         break;
03098 
03099                 case DL_INDEX4:
03100                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
03101                         
03102                         glEnableClientState(GL_NORMAL_ARRAY);
03103                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
03104                         glNormalPointer(GL_FLOAT, 0, dl->nors);
03105                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
03106                         glDisableClientState(GL_NORMAL_ARRAY);
03107 
03108                         break;
03109                 }
03110                 dl= dl->next;
03111         }
03112 
03113         glDisableClientState(GL_VERTEX_ARRAY);
03114         glShadeModel(GL_FLAT);
03115         glDisable(GL_LIGHTING);
03116         glFrontFace(GL_CCW);
03117 }
03118 
03119 static void drawCurveDMWired(Object *ob)
03120 {
03121         DerivedMesh *dm = ob->derivedFinal;
03122         dm->drawEdges (dm, 1, 0);
03123 }
03124 
03125 /* return 1 when nothing was drawn */
03126 static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
03127 {
03128         Object *ob= base->object;
03129         DerivedMesh *dm = ob->derivedFinal;
03130 
03131         if (!dm) {
03132                 return 1;
03133         }
03134 
03135         if(dt>OB_WIRE && dm->getNumFaces(dm)) {
03136                 int glsl = draw_glsl_material(scene, ob, v3d, dt);
03137                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
03138 
03139                 if(!glsl) {
03140                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
03141                         glEnable(GL_LIGHTING);
03142                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
03143                         glDisable(GL_LIGHTING);
03144                 }
03145                 else
03146                         dm->drawFacesGLSL(dm, GPU_enable_material);
03147 
03148                 GPU_end_object_materials();
03149         } else {
03150                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
03151                         drawCurveDMWired (ob);
03152         }
03153 
03154         return 0;
03155 }
03156 
03157 /* returns 1 when nothing was drawn */
03158 static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
03159 {
03160         Object *ob= base->object;
03161         ListBase *lb=NULL;
03162         DispList *dl;
03163         Curve *cu;
03164         const short render_only= (v3d->flag2 & V3D_RENDER_OVERRIDE);
03165         const short solid= (dt > OB_WIRE);
03166         int retval= 0;
03167 
03168         if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == 0) {
03169                 return 0;
03170         }
03171 
03172         switch(ob->type) {
03173         case OB_FONT:
03174         case OB_CURVE:
03175                 cu= ob->data;
03176                 
03177                 lb= &ob->disp;
03178                 
03179                 if(solid) {
03180                         dl= lb->first;
03181                         if(dl==NULL) return 1;
03182 
03183                         if(dl->nors==NULL) addnormalsDispList(lb);
03184                         index3_nors_incr= 0;
03185                         
03186                         if( displist_has_faces(lb)==0) {
03187                                 if(!render_only) {
03188                                         draw_index_wire= 0;
03189                                         drawDispListwire(lb);
03190                                         draw_index_wire= 1;
03191                                 }
03192                         }
03193                         else {
03194                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
03195                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
03196                                         drawDispListsolid(lb, ob, 1);
03197                                         GPU_end_object_materials();
03198                                 }
03199                                 else {
03200                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
03201                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
03202                                         drawDispListsolid(lb, ob, 0);
03203                                         GPU_end_object_materials();
03204                                 }
03205                                 if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) {
03206                                         cpack(0);
03207                                         draw_index_wire= 0;
03208                                         drawDispListwire(lb);
03209                                         draw_index_wire= 1;
03210                                 }
03211                         }
03212                         index3_nors_incr= 1;
03213                 }
03214                 else {
03215                         if(!render_only || (render_only && displist_has_faces(lb))) {
03216                                 draw_index_wire= 0;
03217                                 retval= drawDispListwire(lb);
03218                                 draw_index_wire= 1;
03219                         }
03220                 }
03221                 break;
03222         case OB_SURF:
03223 
03224                 lb= &ob->disp;
03225                 
03226                 if(solid) {
03227                         dl= lb->first;
03228                         if(dl==NULL) return 1;
03229                         
03230                         if(dl->nors==NULL) addnormalsDispList(lb);
03231                         
03232                         if(draw_glsl_material(scene, ob, v3d, dt)) {
03233                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
03234                                 drawDispListsolid(lb, ob, 1);
03235                                 GPU_end_object_materials();
03236                         }
03237                         else {
03238                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
03239                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
03240                                 drawDispListsolid(lb, ob, 0);
03241                                 GPU_end_object_materials();
03242                         }
03243                 }
03244                 else {
03245                         retval= drawDispListwire(lb);
03246                 }
03247                 break;
03248         case OB_MBALL:
03249                 
03250                 if( is_basis_mball(ob)) {
03251                         lb= &ob->disp;
03252                         if(lb->first==NULL) makeDispListMBall(scene, ob);
03253                         if(lb->first==NULL) return 1;
03254                         
03255                         if(solid) {
03256                                 
03257                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
03258                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
03259                                         drawDispListsolid(lb, ob, 1);
03260                                         GPU_end_object_materials();
03261                                 }
03262                                 else {
03263                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
03264                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
03265                                         drawDispListsolid(lb, ob, 0);
03266                                         GPU_end_object_materials();
03267                                 }
03268                         }
03269                         else{
03270                                 /* MetaBalls use DL_INDEX4 type of DispList */
03271                                 retval= drawDispListwire(lb);
03272                         }
03273                 }
03274                 break;
03275         }
03276         
03277         return retval;
03278 }
03279 
03280 /* *********** drawing for particles ************* */
03281 static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select)
03282 {
03283         /* draw created data arrays */
03284         switch(draw_as){
03285                 case PART_DRAW_AXIS:
03286                 case PART_DRAW_CROSS:
03287                         glDrawArrays(GL_LINES, 0, 6*totpoint);
03288                         break;
03289                 case PART_DRAW_LINE:
03290                         glDrawArrays(GL_LINES, 0, 2*totpoint);
03291                         break;
03292                 case PART_DRAW_BB:
03293                         if(ob_dt<=OB_WIRE || select)
03294                                 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
03295                         else
03296                                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
03297 
03298                         glDrawArrays(GL_QUADS, 0, 4*totpoint);
03299                         break;
03300                 default:
03301                         glDrawArrays(GL_POINTS, 0, totpoint);
03302                         break;
03303         }
03304 }
03305 static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd)
03306 {
03307         float vec[3], vec2[3];
03308         float *vd = NULL;
03309         float *cd = NULL;
03310         float ma_r=0.0f;
03311         float ma_g=0.0f;
03312         float ma_b=0.0f;
03313 
03314         /* null only for PART_DRAW_CIRC */
03315         if(pdd) {
03316                 vd = pdd->vd;
03317                 cd = pdd->cd;
03318 
03319                 if(pdd->ma_r) {
03320                         ma_r = *pdd->ma_r;
03321                         ma_g = *pdd->ma_g;
03322                         ma_b = *pdd->ma_b;
03323                 }
03324         }
03325 
03326         switch(draw_as){
03327                 case PART_DRAW_DOT:
03328                 {
03329                         if(vd) {
03330                                 copy_v3_v3(vd,state->co); pdd->vd+=3;
03331                         }
03332                         if(cd) {
03333                                 cd[0]=ma_r;
03334                                 cd[1]=ma_g;
03335                                 cd[2]=ma_b;
03336                                 pdd->cd+=3;
03337                         }
03338                         break;
03339                 }
03340                 case PART_DRAW_CROSS:
03341                 case PART_DRAW_AXIS:
03342                 {
03343                         vec[0]=2.0f*pixsize;
03344                         vec[1]=vec[2]=0.0;
03345                         mul_qt_v3(state->rot,vec);
03346                         if(draw_as==PART_DRAW_AXIS) {
03347                                 if(cd) {
03348                                         cd[1]=cd[2]=cd[4]=cd[5]=0.0;
03349                                         cd[0]=cd[3]=1.0;
03350                                         cd[6]=cd[8]=cd[9]=cd[11]=0.0;
03351                                         cd[7]=cd[10]=1.0;
03352                                         cd[13]=cd[12]=cd[15]=cd[16]=0.0;
03353                                         cd[14]=cd[17]=1.0;
03354                                         pdd->cd+=18;
03355                                 }
03356 
03357                                 copy_v3_v3(vec2,state->co);
03358                         }
03359                         else {
03360                                 if(cd) {
03361                                         cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r;
03362                                         cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g;
03363                                         cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b;
03364                                         pdd->cd+=18;
03365                                 }
03366                                 sub_v3_v3v3(vec2, state->co, vec);
03367                         }
03368 
03369                         add_v3_v3(vec, state->co);
03370                         copy_v3_v3(pdd->vd,vec); pdd->vd+=3;
03371                         copy_v3_v3(pdd->vd,vec2); pdd->vd+=3;
03372                                 
03373                         vec[1]=2.0f*pixsize;
03374                         vec[0]=vec[2]=0.0;
03375                         mul_qt_v3(state->rot,vec);
03376                         if(draw_as==PART_DRAW_AXIS){
03377                                 copy_v3_v3(vec2,state->co);
03378                         }               
03379                         else sub_v3_v3v3(vec2, state->co, vec);
03380 
03381                         add_v3_v3(vec, state->co);
03382                         copy_v3_v3(pdd->vd,vec); pdd->vd+=3;
03383                         copy_v3_v3(pdd->vd,vec2); pdd->vd+=3;
03384 
03385                         vec[2]=2.0f*pixsize;
03386                         vec[0]=vec[1]=0.0;
03387                         mul_qt_v3(state->rot,vec);
03388                         if(draw_as==PART_DRAW_AXIS){
03389                                 copy_v3_v3(vec2,state->co);
03390                         }
03391                         else sub_v3_v3v3(vec2, state->co, vec);
03392 
03393                         add_v3_v3(vec, state->co);
03394 
03395                         copy_v3_v3(pdd->vd,vec); pdd->vd+=3;
03396                         copy_v3_v3(pdd->vd,vec2); pdd->vd+=3;
03397                         break;
03398                 }
03399                 case PART_DRAW_LINE:
03400                 {
03401                         copy_v3_v3(vec,state->vel);
03402                         normalize_v3(vec);
03403                         if(draw & PART_DRAW_VEL_LENGTH)
03404                                 mul_v3_fl(vec,len_v3(state->vel));
03405                         madd_v3_v3v3fl(pdd->vd, state->co, vec, -draw_line[0]); pdd->vd+=3;
03406                         madd_v3_v3v3fl(pdd->vd, state->co, vec,  draw_line[1]); pdd->vd+=3;
03407                         if(cd) {
03408                                 cd[0]=cd[3]=ma_r;
03409                                 cd[1]=cd[4]=ma_g;
03410                                 cd[2]=cd[5]=ma_b;
03411                                 pdd->cd+=6;
03412                         }
03413                         break;
03414                 }
03415                 case PART_DRAW_CIRC:
03416                 {
03417                         drawcircball(GL_LINE_LOOP, state->co, pixsize, imat);
03418                         break;
03419                 }
03420                 case PART_DRAW_BB:
03421                 {
03422                         float xvec[3], yvec[3], zvec[3], bb_center[3];
03423                         if(cd) {
03424                                 cd[0]=cd[3]=cd[6]=cd[9]=ma_r;
03425                                 cd[1]=cd[4]=cd[7]=cd[10]=ma_g;
03426                                 cd[2]=cd[5]=cd[8]=cd[11]=ma_b;
03427                                 pdd->cd+=12;
03428                         }
03429 
03430 
03431                         copy_v3_v3(bb->vec, state->co);
03432                         copy_v3_v3(bb->vel, state->vel);
03433 
03434                         psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
03435                         
03436                         add_v3_v3v3(pdd->vd, bb_center, xvec);
03437                         add_v3_v3(pdd->vd, yvec); pdd->vd+=3;
03438 
03439                         sub_v3_v3v3(pdd->vd, bb_center, xvec);
03440                         add_v3_v3(pdd->vd, yvec); pdd->vd+=3;
03441 
03442                         sub_v3_v3v3(pdd->vd, bb_center, xvec);
03443                         sub_v3_v3v3(pdd->vd, pdd->vd,yvec); pdd->vd+=3;
03444 
03445                         add_v3_v3v3(pdd->vd, bb_center, xvec);
03446                         sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd+=3;
03447 
03448                         copy_v3_v3(pdd->nd, zvec); pdd->nd+=3;
03449                         copy_v3_v3(pdd->nd, zvec); pdd->nd+=3;
03450                         copy_v3_v3(pdd->nd, zvec); pdd->nd+=3;
03451                         copy_v3_v3(pdd->nd, zvec); pdd->nd+=3;
03452                         break;
03453                 }
03454         }
03455 }
03456 /* unified drawing of all new particle systems draw types except dupli ob & group       */
03457 /* mostly tries to use vertex arrays for speed                                                                          */
03458 
03459 /* 1. check that everything is ok & updated */
03460 /* 2. start initialising things                         */
03461 /* 3. initialize according to draw type         */
03462 /* 4. allocate drawing data arrays                      */
03463 /* 5. start filling the arrays                          */
03464 /* 6. draw the arrays                                           */
03465 /* 7. clean up                                                          */
03466 static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, int ob_dt)
03467 {
03468         Object *ob=base->object;
03469         ParticleEditSettings *pset = PE_settings(scene);
03470         ParticleSettings *part;
03471         ParticleData *pars, *pa;
03472         ParticleKey state, *states=NULL;
03473         ParticleBillboardData bb;
03474         ParticleSimulationData sim= {NULL};
03475         ParticleDrawData *pdd = psys->pdd;
03476         Material *ma;
03477         float vel[3], imat[4][4];
03478         float timestep, pixsize=1.0, pa_size, r_tilt, r_length;
03479         float pa_time, pa_birthtime, pa_dietime, pa_health, intensity;
03480         float cfra;
03481         float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
03482         int a, totpart, totpoint=0, totve=0, drawn, draw_as, totchild=0;
03483         int select=ob->flag&SELECT, create_cdata=0, need_v=0;
03484         GLint polygonmode[2];
03485         char val[32];
03486         unsigned char tcol[4]= {0, 0, 0, 255};
03487 
03488 /* 1. */
03489         if(psys==NULL)
03490                 return;
03491 
03492         part=psys->part;
03493         pars=psys->particles;
03494 
03495         if(part==NULL || !psys_check_enabled(ob, psys))
03496                 return;
03497 
03498         if(pars==NULL) return;
03499 
03500         /* don't draw normal paths in edit mode */
03501         if(psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART)==0)
03502                 return;
03503                 
03504         if(part->draw_as == PART_DRAW_REND)
03505                 draw_as = part->ren_as;
03506         else
03507                 draw_as = part->draw_as;
03508 
03509         if(draw_as == PART_DRAW_NOT)
03510                 return;
03511 
03512 /* 2. */
03513         sim.scene= scene;
03514         sim.ob= ob;
03515         sim.psys= psys;
03516         sim.psmd = psys_get_modifier(ob,psys);
03517 
03518         if(part->phystype==PART_PHYS_KEYED){
03519                 if(psys->flag&PSYS_KEYED){
03520                         psys_count_keyed_targets(&sim);
03521                         if(psys->totkeyed==0)
03522                                 return;
03523                 }
03524         }
03525 
03526         if(select){
03527                 select=0;
03528                 if(psys_get_current(ob)==psys)
03529                         select=1;
03530         }
03531 
03532         psys->flag|=PSYS_DRAWING;
03533 
03534         if(part->type==PART_HAIR && !psys->childcache)
03535                 totchild=0;
03536         else
03537                 totchild=psys->totchild*part->disp/100;
03538 
03539         ma= give_current_material(ob,part->omat);
03540 
03541         if(v3d->zbuf) glDepthMask(1);
03542 
03543         if((ma) && (part->draw_col == PART_DRAW_COL_MAT)) {
03544                 rgb_float_to_byte(&(ma->r), tcol);
03545 
03546                 ma_r = ma->r;
03547                 ma_g = ma->g;
03548                 ma_b = ma->b;
03549         }
03550 
03551         glColor3ubv(tcol);
03552 
03553         timestep= psys_get_timestep(&sim);
03554 
03555         if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
03556                 float mat[4][4];
03557                 mul_m4_m4m4(mat, psys->imat, ob->obmat);
03558                 glMultMatrixf(mat);
03559         }
03560 
03561         /* needed for text display */
03562         invert_m4_m4(ob->imat, ob->obmat);
03563 
03564         totpart=psys->totpart;
03565 
03566         cfra= bsystem_time(scene, NULL, (float)CFRA, 0.0f);
03567 
03568         if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL && psys->childcache==NULL)
03569                 draw_as=PART_DRAW_DOT;
03570 
03571 /* 3. */
03572         switch(draw_as){
03573                 case PART_DRAW_DOT:
03574                         if(part->draw_size)
03575                                 glPointSize(part->draw_size);
03576                         else
03577                                 glPointSize(2.0); /* default dot size */
03578                         break;
03579                 case PART_DRAW_CIRC:
03580                         /* calculate view aligned matrix: */
03581                         copy_m4_m4(imat, rv3d->viewinv);
03582                         normalize_v3(imat[0]);
03583                         normalize_v3(imat[1]);
03584                         /* no break! */
03585                 case PART_DRAW_CROSS:
03586                 case PART_DRAW_AXIS:
03587                         /* lets calculate the scale: */
03588                         pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
03589                         
03590                         if(part->draw_size==0.0)
03591                                 pixsize *= 2.0f;
03592                         else
03593                                 pixsize*=part->draw_size;
03594 
03595                         if(draw_as==PART_DRAW_AXIS)
03596                                 create_cdata = 1;
03597                         break;
03598                 case PART_DRAW_OB:
03599                         if(part->dup_ob==NULL)
03600                                 draw_as=PART_DRAW_DOT;
03601                         else
03602                                 draw_as=0;
03603                         break;
03604                 case PART_DRAW_GR:
03605                         if(part->dup_group==NULL)
03606                                 draw_as=PART_DRAW_DOT;
03607                         else
03608                                 draw_as=0;
03609                         break;
03610                 case PART_DRAW_BB:
03611                         if(v3d->camera==NULL && part->bb_ob==NULL){
03612                                 printf("Billboards need an active camera or a target object!\n");
03613 
03614                                 draw_as=part->draw_as=PART_DRAW_DOT;
03615 
03616                                 if(part->draw_size)
03617                                         glPointSize(part->draw_size);
03618                                 else
03619                                         glPointSize(2.0); /* default dot size */
03620                         }
03621                         else if(part->bb_ob)
03622                                 bb.ob=part->bb_ob;
03623                         else
03624                                 bb.ob=v3d->camera;
03625 
03626                         bb.align = part->bb_align;
03627                         bb.anim = part->bb_anim;
03628                         bb.lock = part->draw & PART_DRAW_BB_LOCK;
03629                         break;
03630                 case PART_DRAW_PATH:
03631                         break;
03632                 case PART_DRAW_LINE:
03633                         need_v=1;
03634                         break;
03635         }
03636         if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
03637                 copy_m4_m4(imat, rv3d->viewinv);
03638                 normalize_v3(imat[0]);
03639                 normalize_v3(imat[1]);
03640         }
03641 
03642         if(ELEM3(draw_as, PART_DRAW_DOT, PART_DRAW_CROSS, PART_DRAW_LINE)
03643                 && part->draw_col > PART_DRAW_COL_MAT)
03644                 create_cdata = 1;
03645 
03646         if(!create_cdata && pdd && pdd->cdata) {
03647                 MEM_freeN(pdd->cdata);
03648                 pdd->cdata = pdd->cd = NULL;
03649         }
03650 
03651 /* 4. */
03652         if(draw_as && ELEM(draw_as, PART_DRAW_PATH, PART_DRAW_CIRC)==0) {
03653                 int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
03654                 int create_ndata = 0;
03655 
03656                 if(!pdd)
03657                         pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData");
03658 
03659                 if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
03660                         tot_vec_size *= part->trail_count;
03661                         psys_make_temp_pointcache(ob, psys);
03662                 }
03663 
03664                 switch(draw_as) {
03665                         case PART_DRAW_AXIS:
03666                         case PART_DRAW_CROSS:
03667                                 tot_vec_size *= 6;
03668                                 if(draw_as != PART_DRAW_CROSS)
03669                                         create_cdata = 1;
03670                                 break;
03671                         case PART_DRAW_LINE:
03672                                 tot_vec_size *= 2;
03673                                 break;
03674                         case PART_DRAW_BB:
03675                                 tot_vec_size *= 4;
03676                                 create_ndata = 1;
03677                                 break;
03678                 }
03679 
03680                 if(pdd->tot_vec_size != tot_vec_size)
03681                         psys_free_pdd(psys);
03682 
03683                 if(!pdd->vdata)
03684                         pdd->vdata = MEM_callocN(tot_vec_size, "particle_vdata");
03685                 if(create_cdata && !pdd->cdata)
03686                         pdd->cdata = MEM_callocN(tot_vec_size, "particle_cdata");
03687                 if(create_ndata && !pdd->ndata)
03688                         pdd->ndata = MEM_callocN(tot_vec_size, "particle_ndata");
03689 
03690                 if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
03691                         if(!pdd->vedata)
03692                                 pdd->vedata = MEM_callocN(2 * (totpart + totchild) * 3 * sizeof(float), "particle_vedata");
03693 
03694                         need_v = 1;
03695                 } else if (pdd->vedata) {
03696                         /* velocity data not needed, so free it */
03697                         MEM_freeN(pdd->vedata);
03698                         pdd->vedata= NULL;
03699                 }
03700 
03701                 pdd->vd= pdd->vdata;
03702                 pdd->ved= pdd->vedata;
03703                 pdd->cd= pdd->cdata;
03704                 pdd->nd= pdd->ndata;
03705                 pdd->tot_vec_size= tot_vec_size;
03706         }
03707         else if(psys->pdd) {
03708                 psys_free_pdd(psys);
03709                 MEM_freeN(psys->pdd);
03710                 pdd = psys->pdd = NULL;
03711         }
03712 
03713         if(pdd) {
03714                 pdd->ma_r = &ma_r;
03715                 pdd->ma_g = &ma_g;
03716                 pdd->ma_b = &ma_b;
03717         }
03718 
03719         psys->lattice= psys_get_lattice(&sim);
03720 
03721         /* circles don't use drawdata, so have to add a special case here */
03722         if((pdd || draw_as==PART_DRAW_CIRC) && draw_as!=PART_DRAW_PATH){
03723 /* 5. */
03724                 if(pdd && (pdd->flag & PARTICLE_DRAW_DATA_UPDATED)
03725                         && (pdd->vedata || part->draw & (PART_DRAW_SIZE|PART_DRAW_NUM|PART_DRAW_HEALTH))==0) {
03726                         totpoint = pdd->totpoint; /* draw data is up to date */
03727                 }
03728                 else for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
03729                         /* setup per particle individual stuff */
03730                         if(a<totpart){
03731                                 if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
03732                                 if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
03733 
03734                                 pa_time=(cfra-pa->time)/pa->lifetime;
03735                                 pa_birthtime=pa->time;
03736                                 pa_dietime = pa->dietime;
03737                                 pa_size=pa->size;
03738                                 if(part->phystype==PART_PHYS_BOIDS)
03739                                         pa_health = pa->boid->data.health;
03740                                 else
03741                                         pa_health = -1.0;
03742 
03743                                 r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f);
03744                                 r_length = PSYS_FRAND(a + 22);
03745 
03746                                 if(part->draw_col > PART_DRAW_COL_MAT) {
03747                                         switch(part->draw_col) {
03748                                                 case PART_DRAW_COL_VEL:
03749                                                         intensity = len_v3(pa->state.vel)/part->color_vec_max;
03750                                                         break;
03751                                                 case PART_DRAW_COL_ACC:
03752                                                         intensity = len_v3v3(pa->state.vel, pa->prev_state.vel)/((pa->state.time-pa->prev_state.time)*part->color_vec_max);
03753                                                         break;
03754                                                 default:
03755                                                         intensity= 1.0f; /* should never happen */
03756                                         }
03757                                         CLAMP(intensity, 0.f, 1.f);
03758                                         weight_to_rgb(intensity, &ma_r, &ma_g, &ma_b);
03759                                 }
03760                         }
03761                         else{
03762                                 ChildParticle *cpa= &psys->child[a-totpart];
03763 
03764                                 pa_time=psys_get_child_time(psys,cpa,cfra,&pa_birthtime,&pa_dietime);
03765                                 pa_size=psys_get_child_size(psys,cpa,cfra,NULL);
03766 
03767                                 pa_health = -1.0;
03768 
03769                                 r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f);
03770                                 r_length = PSYS_FRAND(a + 22);
03771                         }
03772 
03773                         drawn = 0;
03774                         if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
03775                                 float length = part->path_end * (1.0f - part->randlength * r_length);
03776                                 int trail_count = part->trail_count * (1.0f - part->randlength * r_length);
03777                                 float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
03778                                 float dt = length / (trail_count ? (float)trail_count : 1.0f);
03779                                 int i=0;
03780 
03781                                 ct+=dt;
03782                                 for(i=0; i < trail_count; i++, ct += dt) {
03783                                         if(part->draw & PART_ABS_PATH_TIME) {
03784                                                 if(ct < pa_birthtime || ct > pa_dietime)
03785                                                         continue;
03786                                         }
03787                                         else if(ct < 0.0f || ct > 1.0f)
03788                                                 continue;
03789 
03790                                         state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
03791                                         psys_get_particle_on_path(&sim,a,&state,need_v);
03792                                         
03793                                         if(psys->parent)
03794                                                 mul_m4_v3(psys->parent->obmat, state.co);
03795 
03796                                         /* create actiual particle data */
03797                                         if(draw_as == PART_DRAW_BB) {
03798                                                 bb.offset[0] = part->bb_offset[0];
03799                                                 bb.offset[1] = part->bb_offset[1];
03800                                                 bb.size[0] = part->bb_size[0] * pa_size;
03801                                                 if (part->bb_align==PART_BB_VEL) {
03802                                                         float pa_vel = len_v3(state.vel);
03803                                                         float head = part->bb_vel_head*pa_vel;
03804                                                         float tail = part->bb_vel_tail*pa_vel;
03805                                                         bb.size[1] = part->bb_size[1]*pa_size + head + tail;
03806                                                         /* use offset to adjust the particle center. this is relative to size, so need to divide! */
03807                                                         if (bb.size[1] > 0.0f)
03808                                                                 bb.offset[1] += (head-tail) / bb.size[1];
03809                                                 }
03810                                                 else
03811                                                         bb.size[1] = part->bb_size[1] * pa_size;
03812                                                 bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
03813                                                 bb.time = ct;
03814                                         }
03815 
03816                                         draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd);
03817 
03818                                         totpoint++;
03819                                         drawn = 1;
03820                                 }
03821                         }
03822                         else
03823                         {
03824                                 state.time=cfra;
03825                                 if(psys_get_particle_state(&sim,a,&state,0)){
03826                                         if(psys->parent)
03827                                                 mul_m4_v3(psys->parent->obmat, state.co);
03828 
03829                                         /* create actiual particle data */
03830                                         if(draw_as == PART_DRAW_BB) {
03831                                                 bb.offset[0] = part->bb_offset[0];
03832                                                 bb.offset[1] = part->bb_offset[1];
03833                                                 bb.size[0] = part->bb_size[0] * pa_size;
03834                                                 if (part->bb_align==PART_BB_VEL) {
03835                                                         float pa_vel = len_v3(state.vel);
03836                                                         float head = part->bb_vel_head*pa_vel;
03837                                                         float tail = part->bb_vel_tail*pa_vel;
03838                                                         bb.size[1] = part->bb_size[1]*pa_size + head + tail;
03839                                                         /* use offset to adjust the particle center. this is relative to size, so need to divide! */
03840                                                         if (bb.size[1] > 0.0f)
03841                                                                 bb.offset[1] += (head-tail) / bb.size[1];
03842                                                 }
03843                                                 else
03844                                                         bb.size[1] = part->bb_size[1] * pa_size;
03845                                                 bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
03846                                                 bb.time = pa_time;
03847                                         }
03848 
03849                                         draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd);
03850 
03851                                         totpoint++;
03852                                         drawn = 1;
03853                                 }
03854                         }
03855 
03856                         if(drawn) {
03857                                 /* additional things to draw for each particle  */
03858                                 /* (velocity, size and number)                                  */
03859                                 if((part->draw & PART_DRAW_VEL) && pdd && pdd->vedata){
03860                                         copy_v3_v3(pdd->ved,state.co);
03861                                         pdd->ved += 3;
03862                                         mul_v3_v3fl(vel, state.vel, timestep);
03863                                         add_v3_v3v3(pdd->ved, state.co, vel);
03864                                         pdd->ved+=3;
03865 
03866                                         totve++;
03867                                 }
03868 
03869                                 if(part->draw & PART_DRAW_SIZE){
03870                                         setlinestyle(3);
03871                                         drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
03872                                         setlinestyle(0);
03873                                 }
03874 
03875 
03876                                 if((part->draw & PART_DRAW_NUM || part->draw & PART_DRAW_HEALTH) && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0){
03877                                         float vec_txt[3];
03878                                         char *val_pos= val;
03879                                         val[0]= '\0';
03880 
03881                                         if(part->draw&PART_DRAW_NUM) {
03882                                                 if(a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype==PART_PHYS_BOIDS)) {
03883                                                         sprintf(val_pos, "%d:%.2f", a, pa_health);
03884                                                 }
03885                                                 else {
03886                                                         sprintf(val_pos, "%d", a);
03887                                                 }
03888                                         }
03889                                         else {
03890                                                 if(a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype==PART_PHYS_BOIDS)) {
03891                                                         sprintf(val_pos, "%.2f", pa_health);
03892                                                 }
03893                                         }
03894 
03895                                         /* in path drawing state.co is the end point */
03896                                         /* use worldspace beause object matrix is already applied */
03897                                         mul_v3_m4v3(vec_txt, ob->imat, state.co);
03898                                         view3d_cached_text_draw_add(vec_txt, val, 10, V3D_CACHE_TEXT_WORLDSPACE|V3D_CACHE_TEXT_ASCII, tcol);
03899                                 }
03900                         }
03901                 }
03902         }
03903 /* 6. */
03904 
03905         glGetIntegerv(GL_POLYGON_MODE, polygonmode);
03906         glEnableClientState(GL_VERTEX_ARRAY);
03907 
03908         if(draw_as==PART_DRAW_PATH){
03909                 ParticleCacheKey **cache, *path;
03910                 float *cd2=NULL,*cdata2=NULL;
03911 
03912                 /* setup gl flags */
03913                 if (1) { //ob_dt > OB_WIRE) {
03914                         glEnableClientState(GL_NORMAL_ARRAY);
03915 
03916                         if(part->draw_col == PART_DRAW_COL_MAT)
03917                                 glEnableClientState(GL_COLOR_ARRAY);
03918 
03919                         glEnable(GL_LIGHTING);
03920                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
03921                         glEnable(GL_COLOR_MATERIAL);
03922                 }
03923                 /*else {
03924                         glDisableClientState(GL_NORMAL_ARRAY);
03925 
03926                         glDisable(GL_COLOR_MATERIAL);
03927                         glDisable(GL_LIGHTING);
03928                         UI_ThemeColor(TH_WIRE);
03929                 }*/
03930 
03931                 if(totchild && (part->draw&PART_DRAW_PARENT)==0)
03932                         totpart=0;
03933                 else if(psys->pathcache==NULL)
03934                         totpart=0;
03935 
03936                 /* draw actual/parent particles */
03937                 cache=psys->pathcache;
03938                 for(a=0, pa=psys->particles; a<totpart; a++, pa++){
03939                         path=cache[a];
03940                         if(path->steps > 0) {
03941                                 glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
03942 
03943                                 if(1) { //ob_dt > OB_WIRE) {
03944                                         glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
03945                                         if(part->draw_col == PART_DRAW_COL_MAT)
03946                                                 glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
03947                                 }
03948 
03949                                 glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
03950                         }
03951                 }
03952                 
03953                 /* draw child particles */
03954                 cache=psys->childcache;
03955                 for(a=0; a<totchild; a++){
03956                         path=cache[a];
03957                         glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
03958 
03959                         if(1) { //ob_dt > OB_WIRE) {
03960                                 glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
03961                                 if(part->draw_col == PART_DRAW_COL_MAT)
03962                                         glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
03963                         }
03964 
03965                         glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
03966                 }
03967 
03968 
03969                 /* restore & clean up */
03970                 if(1) { //ob_dt > OB_WIRE) {
03971                         if(part->draw_col == PART_DRAW_COL_MAT)
03972                                 glDisable(GL_COLOR_ARRAY);
03973                         glDisable(GL_COLOR_MATERIAL);
03974                 }
03975 
03976                 if(cdata2)
03977                         MEM_freeN(cdata2);
03978                 cd2=cdata2=NULL;
03979 
03980                 glLineWidth(1.0f);
03981 
03982                 if((part->draw & PART_DRAW_NUM) && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0){
03983                         cache=psys->pathcache;
03984 
03985                         for(a=0, pa=psys->particles; a<totpart; a++, pa++){
03986                                 float vec_txt[3];
03987                                 sprintf(val, "%i", a);
03988                                 /* use worldspace beause object matrix is already applied */
03989                                 mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co);
03990                                 view3d_cached_text_draw_add(vec_txt, val, 10, V3D_CACHE_TEXT_WORLDSPACE|V3D_CACHE_TEXT_ASCII, tcol);
03991                         }
03992                 }
03993         }
03994         else if(pdd && ELEM(draw_as, 0, PART_DRAW_CIRC)==0){
03995                 glDisableClientState(GL_COLOR_ARRAY);
03996 
03997                 /* enable point data array */
03998                 if(pdd->vdata){
03999                         glEnableClientState(GL_VERTEX_ARRAY);
04000                         glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
04001                 }
04002                 else
04003                         glDisableClientState(GL_VERTEX_ARRAY);
04004 
04005                 if(select) {
04006                         UI_ThemeColor(TH_ACTIVE);
04007                         
04008                         if(part->draw_size)
04009                                 glPointSize(part->draw_size + 2);
04010                         else
04011                                 glPointSize(4.0);
04012 
04013                         glLineWidth(3.0);
04014 
04015                         draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
04016                 }
04017 
04018                 /* restore from select */
04019                 glColor3f(ma_r,ma_g,ma_b);
04020                 glPointSize(part->draw_size ? part->draw_size : 2.0);
04021                 glLineWidth(1.0);
04022 
04023                 /* enable other data arrays */
04024 
04025                 /* billboards are drawn this way */
04026                 if(pdd->ndata && ob_dt>OB_WIRE){
04027                         glEnableClientState(GL_NORMAL_ARRAY);
04028                         glNormalPointer(GL_FLOAT, 0, pdd->ndata);
04029                         glEnable(GL_LIGHTING);
04030                 }
04031                 else{
04032                         glDisableClientState(GL_NORMAL_ARRAY);
04033                         glDisable(GL_LIGHTING);
04034                 }
04035 
04036                 if(pdd->cdata){
04037                         glEnableClientState(GL_COLOR_ARRAY);
04038                         glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
04039                 }
04040 
04041                 draw_particle_arrays(draw_as, totpoint, ob_dt, 0);
04042 
04043                 pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
04044                 pdd->totpoint = totpoint;
04045         }
04046 
04047         if(pdd && pdd->vedata){
04048                 glDisableClientState(GL_COLOR_ARRAY);
04049                 cpack(0xC0C0C0);
04050                 
04051                 glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
04052                 
04053                 glDrawArrays(GL_LINES, 0, 2*totve);
04054         }
04055 
04056         glPolygonMode(GL_FRONT, polygonmode[0]);
04057         glPolygonMode(GL_BACK, polygonmode[1]);
04058 
04059 /* 7. */
04060         
04061         glDisable(GL_LIGHTING);
04062         glDisableClientState(GL_COLOR_ARRAY);
04063         glDisableClientState(GL_VERTEX_ARRAY);
04064         glDisableClientState(GL_NORMAL_ARRAY);
04065 
04066         if(states)
04067                 MEM_freeN(states);
04068 
04069         psys->flag &= ~PSYS_DRAWING;
04070 
04071         /* draw data can't be saved for billboards as they must update to target changes */
04072         if(draw_as == PART_DRAW_BB) {
04073                 psys_free_pdd(psys);
04074                 pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
04075         }
04076 
04077         if(psys->lattice){
04078                 end_latt_deform(psys->lattice);
04079                 psys->lattice= NULL;
04080         }
04081 
04082         if(pdd) {
04083                 /* drop references to stack memory */
04084                 pdd->ma_r= pdd->ma_g= pdd->ma_b= NULL;
04085         }
04086 
04087         if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
04088                 glLoadMatrixf(rv3d->viewmat);
04089         }
04090 }
04091 
04092 static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit)
04093 {
04094         if(edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED)
04095                 PE_update_object(scene, ob, 0);
04096 
04097         /* create path and child path cache if it doesn't exist already */
04098         if(edit->pathcache == NULL)
04099                 psys_cache_edit_paths(scene, ob, edit, CFRA);
04100 }
04101 
04102 static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
04103 {
04104         ParticleCacheKey **cache, *path, *pkey;
04105         PTCacheEditPoint *point;
04106         PTCacheEditKey *key;
04107         ParticleEditSettings *pset = PE_settings(scene);
04108         int i, k, totpoint = edit->totpoint, timed = pset->flag & PE_FADE_TIME ? pset->fade_frames : 0;
04109         int steps=1;
04110         float sel_col[3];
04111         float nosel_col[3];
04112         float *pathcol = NULL, *pcol;
04113 
04114         if(edit->pathcache == NULL)
04115                 return;
04116 
04117         PE_hide_keys_time(scene, edit, CFRA);
04118 
04119         /* opengl setup */
04120         if((v3d->flag & V3D_ZBUF_SELECT)==0)
04121                 glDisable(GL_DEPTH_TEST);
04122 
04123         /* get selection theme colors */
04124         UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col);
04125         UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
04126 
04127         /* draw paths */
04128         if(timed) {
04129                 glEnable(GL_BLEND);
04130                 steps = (*edit->pathcache)->steps + 1;
04131                 pathcol = MEM_callocN(steps*4*sizeof(float), "particle path color data");
04132         }
04133 
04134         glEnableClientState(GL_VERTEX_ARRAY);
04135         glEnableClientState(GL_COLOR_ARRAY);
04136 
04137         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
04138         glEnable(GL_COLOR_MATERIAL);
04139         glShadeModel(GL_SMOOTH);
04140 
04141         if(pset->brushtype == PE_BRUSH_WEIGHT) {
04142                 glLineWidth(2.0f);
04143                 glDisable(GL_LIGHTING);
04144         }
04145 
04146         cache=edit->pathcache;
04147         for(i=0; i<totpoint; i++){
04148                 path = cache[i];
04149                 glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
04150 
04151                 if(timed) {
04152                         for(k=0, pcol=pathcol, pkey=path; k<steps; k++, pkey++, pcol+=4){
04153                                 copy_v3_v3(pcol, pkey->col);
04154                                 pcol[3] = 1.0f - fabsf((float)(CFRA) - pkey->time)/(float)pset->fade_frames;
04155                         }
04156 
04157                         glColorPointer(4, GL_FLOAT, 4*sizeof(float), pathcol);
04158                 }
04159                 else
04160                         glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
04161 
04162                 glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
04163         }
04164 
04165         if(pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; }
04166 
04167 
04168         /* draw edit vertices */
04169         if(pset->selectmode!=SCE_SELECT_PATH){
04170                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
04171 
04172                 if(pset->selectmode==SCE_SELECT_POINT){
04173                         float *pd=NULL,*pdata=NULL;
04174                         float *cd=NULL,*cdata=NULL;
04175                         int totkeys = 0;
04176 
04177                         for (i=0, point=edit->points; i<totpoint; i++, point++)
04178                                 if(!(point->flag & PEP_HIDE))
04179                                         totkeys += point->totkey;
04180 
04181                         if(edit->points && !(edit->points->keys->flag & PEK_USE_WCO))
04182                                 pd=pdata=MEM_callocN(totkeys*3*sizeof(float), "particle edit point data");
04183                         cd=cdata=MEM_callocN(totkeys*(timed?4:3)*sizeof(float), "particle edit color data");
04184 
04185                         for(i=0, point=edit->points; i<totpoint; i++, point++){
04186                                 if(point->flag & PEP_HIDE)
04187                                         continue;
04188 
04189                                 for(k=0, key=point->keys; k<point->totkey; k++, key++){
04190                                         if(pd) {
04191                                                 copy_v3_v3(pd, key->co);
04192                                                 pd += 3;
04193                                         }
04194 
04195                                         if(key->flag&PEK_SELECT){
04196                                                 copy_v3_v3(cd,sel_col);
04197                                         }
04198                                         else{
04199                                                 copy_v3_v3(cd,nosel_col);
04200                                         }
04201 
04202                                         if(timed)
04203                                                 *(cd+3) = 1.0f - fabsf((float)CFRA - *key->time)/(float)pset->fade_frames;
04204 
04205                                         cd += (timed?4:3);
04206                                 }
04207                         }
04208                         cd=cdata;
04209                         pd=pdata;
04210                         for(i=0, point=edit->points; i<totpoint; i++, point++){
04211                                 if(point->flag & PEP_HIDE)
04212                                         continue;
04213 
04214                                 if(point->keys->flag & PEK_USE_WCO)
04215                                         glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co);
04216                                 else
04217                                         glVertexPointer(3, GL_FLOAT, 3*sizeof(float), pd);
04218 
04219                                 glColorPointer((timed?4:3), GL_FLOAT, (timed?4:3)*sizeof(float), cd);
04220 
04221                                 glDrawArrays(GL_POINTS, 0, point->totkey);
04222 
04223                                 pd += pd ? 3 * point->totkey : 0;
04224                                 cd += (timed?4:3) * point->totkey;
04225                         }
04226                         if(pdata) { MEM_freeN(pdata); pd=pdata=NULL; }
04227                         if(cdata) { MEM_freeN(cdata); cd=cdata=NULL; }
04228                 }
04229                 else if(pset->selectmode == SCE_SELECT_END){
04230                         for(i=0, point=edit->points; i<totpoint; i++, point++){
04231                                 if((point->flag & PEP_HIDE)==0){
04232                                         key = point->keys + point->totkey - 1;
04233                                         if(key->flag & PEK_SELECT)
04234                                                 glColor3fv(sel_col);
04235                                         else
04236                                                 glColor3fv(nosel_col);
04237                                         /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
04238                                         glBegin(GL_POINTS);
04239                                         glVertex3fv(key->flag & PEK_USE_WCO ? key->world_co : key->co);
04240                                         glEnd();
04241                                 }
04242                         }
04243                 }
04244         }
04245 
04246         glDisable(GL_BLEND);
04247         glDisable(GL_LIGHTING);
04248         glDisable(GL_COLOR_MATERIAL);
04249         glDisableClientState(GL_COLOR_ARRAY);
04250         glDisableClientState(GL_NORMAL_ARRAY);
04251         glDisableClientState(GL_VERTEX_ARRAY);
04252         glShadeModel(GL_FLAT);
04253         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
04254         glLineWidth(1.0f);
04255         glPointSize(1.0);
04256 }
04257 //static void ob_draw_RE_motion(float com[3],float rotscale[3][3],float tw,float th)
04258 static void ob_draw_RE_motion(float com[3],float rotscale[3][3],float itw,float ith,float drw_size)
04259 {
04260         float tr[3][3];
04261         float root[3],tip[3];
04262         float tw,th;
04263         /* take a copy for not spoiling original */
04264         copy_m3_m3(tr,rotscale);
04265         tw = itw * drw_size;
04266         th = ith * drw_size;
04267 
04268         glColor4ub(0x7F, 0x00, 0x00, 155);
04269         glBegin(GL_LINES);
04270         root[1] = root[2] = 0.0f;
04271         root[0] = -drw_size;
04272         mul_m3_v3(tr,root);
04273         add_v3_v3(root, com);
04274         glVertex3fv(root); 
04275         tip[1] = tip[2] = 0.0f;
04276         tip[0] = drw_size;
04277         mul_m3_v3(tr,tip);
04278         add_v3_v3(tip, com);
04279         glVertex3fv(tip); 
04280         glEnd();
04281 
04282         root[1] =0.0f; root[2] = tw;
04283         root[0] = th;
04284         glBegin(GL_LINES);
04285         mul_m3_v3(tr,root);
04286         add_v3_v3(root, com);
04287         glVertex3fv(root); 
04288         glVertex3fv(tip); 
04289         glEnd();
04290 
04291         root[1] =0.0f; root[2] = -tw;
04292         root[0] = th;
04293         glBegin(GL_LINES);
04294         mul_m3_v3(tr,root);
04295         add_v3_v3(root, com);
04296         glVertex3fv(root); 
04297         glVertex3fv(tip); 
04298         glEnd();
04299 
04300         root[1] =tw; root[2] = 0.0f;
04301         root[0] =th;
04302         glBegin(GL_LINES);
04303         mul_m3_v3(tr,root);
04304         add_v3_v3(root, com);
04305         glVertex3fv(root); 
04306         glVertex3fv(tip); 
04307         glEnd();
04308 
04309         root[1] =-tw; root[2] = 0.0f;
04310         root[0] = th;
04311         glBegin(GL_LINES);
04312         mul_m3_v3(tr,root);
04313         add_v3_v3(root, com);
04314         glVertex3fv(root); 
04315         glVertex3fv(tip); 
04316         glEnd();
04317 
04318         glColor4ub(0x00, 0x7F, 0x00, 155);
04319 
04320         glBegin(GL_LINES);
04321         root[0] = root[2] = 0.0f;
04322         root[1] = -drw_size;
04323         mul_m3_v3(tr,root);
04324         add_v3_v3(root, com);
04325         glVertex3fv(root); 
04326         tip[0] = tip[2] = 0.0f;
04327         tip[1] = drw_size;
04328         mul_m3_v3(tr,tip);
04329         add_v3_v3(tip, com);
04330         glVertex3fv(tip); 
04331         glEnd();
04332 
04333         root[0] =0.0f; root[2] = tw;
04334         root[1] = th;
04335         glBegin(GL_LINES);
04336         mul_m3_v3(tr,root);
04337         add_v3_v3(root, com);
04338         glVertex3fv(root); 
04339         glVertex3fv(tip); 
04340         glEnd();
04341 
04342         root[0] =0.0f; root[2] = -tw;
04343         root[1] = th;
04344         glBegin(GL_LINES);
04345         mul_m3_v3(tr,root);
04346         add_v3_v3(root, com);
04347         glVertex3fv(root); 
04348         glVertex3fv(tip); 
04349         glEnd();
04350 
04351         root[0] =tw; root[2] = 0.0f;
04352         root[1] =th;
04353         glBegin(GL_LINES);
04354         mul_m3_v3(tr,root);
04355         add_v3_v3(root, com);
04356         glVertex3fv(root); 
04357         glVertex3fv(tip); 
04358         glEnd();
04359 
04360         root[0] =-tw; root[2] = 0.0f;
04361         root[1] = th;
04362         glBegin(GL_LINES);
04363         mul_m3_v3(tr,root);
04364         add_v3_v3(root, com);
04365         glVertex3fv(root); 
04366         glVertex3fv(tip); 
04367         glEnd();
04368 
04369         glColor4ub(0x00, 0x00, 0x7F, 155);
04370         glBegin(GL_LINES);
04371         root[0] = root[1] = 0.0f;
04372         root[2] = -drw_size;
04373         mul_m3_v3(tr,root);
04374         add_v3_v3(root, com);
04375         glVertex3fv(root); 
04376         tip[0] = tip[1] = 0.0f;
04377         tip[2] = drw_size;
04378         mul_m3_v3(tr,tip);
04379         add_v3_v3(tip, com);
04380         glVertex3fv(tip); 
04381         glEnd();
04382 
04383         root[0] =0.0f; root[1] = tw;
04384         root[2] = th;
04385         glBegin(GL_LINES);
04386         mul_m3_v3(tr,root);
04387         add_v3_v3(root, com);
04388         glVertex3fv(root); 
04389         glVertex3fv(tip); 
04390         glEnd();
04391 
04392         root[0] =0.0f; root[1] = -tw;
04393         root[2] = th;
04394         glBegin(GL_LINES);
04395         mul_m3_v3(tr,root);
04396         add_v3_v3(root, com);
04397         glVertex3fv(root); 
04398         glVertex3fv(tip); 
04399         glEnd();
04400 
04401         root[0] = tw; root[1] = 0.0f;
04402         root[2] = th;
04403         glBegin(GL_LINES);
04404         mul_m3_v3(tr,root);
04405         add_v3_v3(root, com);
04406         glVertex3fv(root); 
04407         glVertex3fv(tip); 
04408         glEnd();
04409 
04410         root[0] = -tw; root[1] = 0.0f;
04411         root[2] = th;
04412         glBegin(GL_LINES);
04413         mul_m3_v3(tr,root);
04414         add_v3_v3(root, com);
04415         glVertex3fv(root); 
04416         glVertex3fv(tip); 
04417         glEnd();
04418 }
04419 
04420 /*place to add drawers */
04421 
04422 static void tekenhandlesN(Nurb *nu, short sel, short hide_handles)
04423 {
04424         BezTriple *bezt;
04425         float *fp;
04426         int basecol;
04427         int a;
04428         
04429         if(nu->hide || hide_handles) return;
04430 
04431         glBegin(GL_LINES); 
04432         
04433         if(nu->type == CU_BEZIER) {
04434                 if(sel) basecol= TH_HANDLE_SEL_FREE;
04435                 else basecol= TH_HANDLE_FREE;
04436 
04437                 bezt= nu->bezt;
04438                 a= nu->pntsu;
04439                 while(a--) {
04440                         if(bezt->hide==0) {
04441                                 if( (bezt->f2 & SELECT)==sel) {
04442                                         fp= bezt->vec[0];
04443 
04444                                         UI_ThemeColor(basecol + bezt->h1);
04445                                         glVertex3fv(fp);
04446                                         glVertex3fv(fp+3); 
04447 
04448                                         UI_ThemeColor(basecol + bezt->h2);
04449                                         glVertex3fv(fp+3); 
04450                                         glVertex3fv(fp+6); 
04451                                 }
04452                                 else if( (bezt->f1 & SELECT)==sel) {
04453                                         fp= bezt->vec[0];
04454 
04455                                         UI_ThemeColor(basecol + bezt->h1);
04456                                         glVertex3fv(fp); 
04457                                         glVertex3fv(fp+3); 
04458                                 }
04459                                 else if( (bezt->f3 & SELECT)==sel) {
04460                                         fp= bezt->vec[1];
04461 
04462                                         UI_ThemeColor(basecol + bezt->h2);
04463                                         glVertex3fv(fp); 
04464                                         glVertex3fv(fp+3); 
04465                                 }
04466                         }
04467                         bezt++;
04468                 }
04469         }
04470         glEnd();
04471 }
04472 
04473 static void tekenhandlesN_active(Nurb *nu)
04474 {
04475         BezTriple *bezt;
04476         float *fp;
04477         int a;
04478 
04479         if(nu->hide) return;
04480 
04481         UI_ThemeColor(TH_ACTIVE_SPLINE);
04482         glLineWidth(2);
04483 
04484         glBegin(GL_LINES);
04485 
04486         if(nu->type == CU_BEZIER) {
04487                 bezt= nu->bezt;
04488                 a= nu->pntsu;
04489                 while(a--) {
04490                         if(bezt->hide==0) {
04491                                 fp= bezt->vec[0];
04492 
04493                                 glVertex3fv(fp);
04494                                 glVertex3fv(fp+3);
04495 
04496                                 glVertex3fv(fp+3);
04497                                 glVertex3fv(fp+6);
04498                         }
04499                         bezt++;
04500                 }
04501         }
04502         glEnd();
04503 
04504         glColor3ub(0,0,0);
04505         glLineWidth(1);
04506 }
04507 
04508 static void tekenvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel)
04509 {
04510         BezTriple *bezt;
04511         BPoint *bp;
04512         float size;
04513         int a, color;
04514 
04515         if(nu->hide) return;
04516 
04517         if(sel) color= TH_VERTEX_SELECT;
04518         else color= TH_VERTEX;
04519 
04520         UI_ThemeColor(color);
04521 
04522         size= UI_GetThemeValuef(TH_VERTEX_SIZE);
04523         glPointSize(size);
04524         
04525         bglBegin(GL_POINTS);
04526         
04527         if(nu->type == CU_BEZIER) {
04528 
04529                 bezt= nu->bezt;
04530                 a= nu->pntsu;
04531                 while(a--) {
04532                         if(bezt->hide==0) {
04533                                 if (sel == 1 && bezt == lastsel) {
04534                                         UI_ThemeColor(TH_LASTSEL_POINT);
04535                                         bglVertex3fv(bezt->vec[1]);
04536 
04537                                         if (!hide_handles) {
04538                                                 if(bezt->f1 & SELECT) bglVertex3fv(bezt->vec[0]);
04539                                                 if(bezt->f3 & SELECT) bglVertex3fv(bezt->vec[2]);
04540                                         }
04541 
04542                                         UI_ThemeColor(color);
04543                                 } else if (hide_handles) {
04544                                         if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]);
04545                                 } else {
04546                                         if((bezt->f1 & SELECT)==sel) bglVertex3fv(bezt->vec[0]);
04547                                         if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]);
04548                                         if((bezt->f3 & SELECT)==sel) bglVertex3fv(bezt->vec[2]);
04549                                 }
04550                         }
04551                         bezt++;
04552                 }
04553         }
04554         else {
04555                 bp= nu->bp;
04556                 a= nu->pntsu*nu->pntsv;
04557                 while(a--) {
04558                         if(bp->hide==0) {
04559                                 if (bp == lastsel) {
04560                                         UI_ThemeColor(TH_LASTSEL_POINT);
04561                                         bglVertex3fv(bp->vec);
04562                                         UI_ThemeColor(color);
04563                                 } else {
04564                                         if((bp->f1 & SELECT)==sel) bglVertex3fv(bp->vec);
04565                                 }
04566                         }
04567                         bp++;
04568                 }
04569         }
04570         
04571         bglEnd();
04572         glPointSize(1.0);
04573 }
04574 
04575 static void editnurb_draw_active_poly(Nurb *nu)
04576 {
04577         BPoint *bp;
04578         int a, b;
04579 
04580         UI_ThemeColor(TH_ACTIVE_SPLINE);
04581         glLineWidth(2);
04582 
04583         bp= nu->bp;
04584         for(b=0; b<nu->pntsv; b++) {
04585                 if(nu->flagu & 1) glBegin(GL_LINE_LOOP);
04586                 else glBegin(GL_LINE_STRIP);
04587 
04588                 for(a=0; a<nu->pntsu; a++, bp++) {
04589                         glVertex3fv(bp->vec);
04590                 }
04591 
04592                 glEnd();
04593         }
04594 
04595         glColor3ub(0,0,0);
04596         glLineWidth(1);
04597 }
04598 
04599 static void editnurb_draw_active_nurbs(Nurb *nu)
04600 {
04601         BPoint *bp, *bp1;
04602         int a, b, ofs;
04603 
04604         UI_ThemeColor(TH_ACTIVE_SPLINE);
04605         glLineWidth(2);
04606 
04607         glBegin(GL_LINES);
04608         bp= nu->bp;
04609         for(b=0; b<nu->pntsv; b++) {
04610                 bp1= bp;
04611                 bp++;
04612 
04613                 for(a=nu->pntsu-1; a>0; a--, bp++) {
04614                         if(bp->hide==0 && bp1->hide==0) {
04615                                 glVertex3fv(bp->vec);
04616                                 glVertex3fv(bp1->vec);
04617                         }
04618                         bp1= bp;
04619                 }
04620         }
04621 
04622         if(nu->pntsv > 1) {     /* surface */
04623 
04624                 ofs= nu->pntsu;
04625                 for(b=0; b<nu->pntsu; b++) {
04626                         bp1= nu->bp+b;
04627                         bp= bp1+ofs;
04628                         for(a=nu->pntsv-1; a>0; a--, bp+=ofs) {
04629                                 if(bp->hide==0 && bp1->hide==0) {
04630                                         glVertex3fv(bp->vec);
04631                                         glVertex3fv(bp1->vec);
04632                                 }
04633                                 bp1= bp;
04634                         }
04635                 }
04636         }
04637 
04638         glEnd();
04639 
04640         glColor3ub(0,0,0);
04641         glLineWidth(1);
04642 }
04643 
04644 static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
04645 {
04646         Nurb *nu;
04647         BPoint *bp, *bp1;
04648         int a, b, ofs, index;
04649         Curve *cu= (Curve*)ob->data;
04650 
04651         index= 0;
04652         nu= nurb;
04653         while(nu) {
04654                 if(nu->hide==0) {
04655                         switch(nu->type) {
04656                         case CU_POLY:
04657                                 if (!sel && index== cu->actnu) {
04658                                         /* we should draw active spline highlight below everything */
04659                                         editnurb_draw_active_poly(nu);
04660                                 }
04661 
04662                                 UI_ThemeColor(TH_NURB_ULINE);
04663                                 bp= nu->bp;
04664                                 for(b=0; b<nu->pntsv; b++) {
04665                                         if(nu->flagu & 1) glBegin(GL_LINE_LOOP);
04666                                         else glBegin(GL_LINE_STRIP);
04667 
04668                                         for(a=0; a<nu->pntsu; a++, bp++) {
04669                                                 glVertex3fv(bp->vec);
04670                                         }
04671 
04672                                         glEnd();
04673                                 }
04674                                 break;
04675                         case CU_NURBS:
04676                                 if (!sel && index== cu->actnu) {
04677                                         /* we should draw active spline highlight below everything */
04678                                         editnurb_draw_active_nurbs(nu);
04679                                 }
04680 
04681                                 bp= nu->bp;
04682                                 for(b=0; b<nu->pntsv; b++) {
04683                                         bp1= bp;
04684                                         bp++;
04685                                         for(a=nu->pntsu-1; a>0; a--, bp++) {
04686                                                 if(bp->hide==0 && bp1->hide==0) {
04687                                                         if(sel) {
04688                                                                 if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT ) ) {
04689                                                                         UI_ThemeColor(TH_NURB_SEL_ULINE);
04690                 
04691                                                                         glBegin(GL_LINE_STRIP);
04692                                                                         glVertex3fv(bp->vec); 
04693                                                                         glVertex3fv(bp1->vec);
04694                                                                         glEnd();
04695                                                                 }
04696                                                         }
04697                                                         else {
04698                                                                 if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) );
04699                                                                 else {
04700                                                                         UI_ThemeColor(TH_NURB_ULINE);
04701                 
04702                                                                         glBegin(GL_LINE_STRIP);
04703                                                                         glVertex3fv(bp->vec); 
04704                                                                         glVertex3fv(bp1->vec);
04705                                                                         glEnd();
04706                                                                 }
04707                                                         }
04708                                                 }
04709                                                 bp1= bp;
04710                                         }
04711                                 }
04712                                 if(nu->pntsv > 1) {     /* surface */
04713 
04714                                         ofs= nu->pntsu;
04715                                         for(b=0; b<nu->pntsu; b++) {
04716                                                 bp1= nu->bp+b;
04717                                                 bp= bp1+ofs;
04718                                                 for(a=nu->pntsv-1; a>0; a--, bp+=ofs) {
04719                                                         if(bp->hide==0 && bp1->hide==0) {
04720                                                                 if(sel) {
04721                                                                         if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) ) {
04722                                                                                 UI_ThemeColor(TH_NURB_SEL_VLINE);
04723                         
04724                                                                                 glBegin(GL_LINE_STRIP);
04725                                                                                 glVertex3fv(bp->vec); 
04726                                                                                 glVertex3fv(bp1->vec);
04727                                                                                 glEnd();
04728                                                                         }
04729                                                                 }
04730                                                                 else {
04731                                                                         if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) );
04732                                                                         else {
04733                                                                                 UI_ThemeColor(TH_NURB_VLINE);
04734                         
04735                                                                                 glBegin(GL_LINE_STRIP);
04736                                                                                 glVertex3fv(bp->vec); 
04737                                                                                 glVertex3fv(bp1->vec);
04738                                                                                 glEnd();
04739                                                                         }
04740                                                                 }
04741                                                         }
04742                                                         bp1= bp;
04743                                                 }
04744                                         }
04745 
04746                                 }
04747                                 break;
04748                         }
04749                 }
04750 
04751                 ++index;
04752                 nu= nu->next;
04753         }
04754 }
04755 
04756 static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, int dt)
04757 {
04758         ToolSettings *ts= scene->toolsettings;
04759         Object *ob= base->object;
04760         Curve *cu = ob->data;
04761         Nurb *nu;
04762         BevList *bl;
04763         short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
04764         int index;
04765 
04766 // XXX  retopo_matrix_update(v3d);
04767 
04768         /* DispList */
04769         UI_ThemeColor(TH_WIRE);
04770         drawDispList(scene, v3d, rv3d, base, dt);
04771 
04772         if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
04773         
04774         /* first non-selected and active handles */
04775         index= 0;
04776         for(nu=nurb; nu; nu=nu->next) {
04777                 if(nu->type == CU_BEZIER) {
04778                         if (index == cu->actnu && !hide_handles)
04779                                 tekenhandlesN_active(nu);
04780                         tekenhandlesN(nu, 0, hide_handles);
04781                 }
04782                 ++index;
04783         }
04784         draw_editnurb(ob, nurb, 0);
04785         draw_editnurb(ob, nurb, 1);
04786         /* selected handles */
04787         for(nu=nurb; nu; nu=nu->next) {
04788                 if(nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES)==0)
04789                         tekenhandlesN(nu, 1, hide_handles);
04790                 tekenvertsN(nu, 0, hide_handles, NULL);
04791         }
04792         
04793         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
04794 
04795         /*      direction vectors for 3d curve paths
04796                 when at its lowest, dont render normals */
04797         if(cu->flag & CU_3D && ts->normalsize > 0.0015f && (cu->drawflag & CU_HIDE_NORMALS)==0) {
04798 
04799                 UI_ThemeColor(TH_WIRE);
04800                 for (bl=cu->bev.first,nu=nurb; nu && bl; bl=bl->next,nu=nu->next) {
04801                         BevPoint *bevp= (BevPoint *)(bl+1);             
04802                         int nr= bl->nr;
04803                         int skip= nu->resolu/16;
04804                         
04805                         while (nr-->0) { /* accounts for empty bevel lists */
04806                                 float fac= bevp->radius * ts->normalsize;
04807                                 float vec_a[3]; // Offset perpendicular to the curve
04808                                 float vec_b[3]; // Delta along the curve
04809 
04810                                 vec_a[0]= fac;
04811                                 vec_a[1]= 0.0f;
04812                                 vec_a[2]= 0.0f;
04813 
04814                                 vec_b[0]= -fac;
04815                                 vec_b[1]= 0.0f;
04816                                 vec_b[2]= 0.0f;
04817                                 
04818                                 mul_qt_v3(bevp->quat, vec_a);
04819                                 mul_qt_v3(bevp->quat, vec_b);
04820                                 add_v3_v3(vec_a, bevp->vec);
04821                                 add_v3_v3(vec_b, bevp->vec);
04822                                 
04823                                 VECSUBFAC(vec_a, vec_a, bevp->dir, fac);
04824                                 VECSUBFAC(vec_b, vec_b, bevp->dir, fac);
04825 
04826                                 glBegin(GL_LINE_STRIP);
04827                                 glVertex3fv(vec_a);
04828                                 glVertex3fv(bevp->vec);
04829                                 glVertex3fv(vec_b);
04830                                 glEnd();
04831                                 
04832                                 bevp += skip+1;
04833                                 nr -= skip;
04834                         }
04835                 }
04836         }
04837 
04838         if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
04839         
04840         for(nu=nurb; nu; nu=nu->next) {
04841                 tekenvertsN(nu, 1, hide_handles, cu->lastsel);
04842         }
04843         
04844         if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
04845 }
04846 
04847 /* draw a sphere for use as an empty drawtype */
04848 static void draw_empty_sphere (float size)
04849 {
04850         static GLuint displist=0;
04851         
04852         if (displist == 0) {
04853                 GLUquadricObj   *qobj;
04854                 
04855                 displist= glGenLists(1);
04856                 glNewList(displist, GL_COMPILE);
04857                 
04858                 glPushMatrix();
04859                 
04860                 qobj    = gluNewQuadric(); 
04861                 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
04862                 gluDisk(qobj, 0.0,  1, 16, 1);
04863                 
04864                 glRotatef(90, 0, 1, 0);
04865                 gluDisk(qobj, 0.0,  1, 16, 1);
04866                 
04867                 glRotatef(90, 1, 0, 0);
04868                 gluDisk(qobj, 0.0,  1, 16, 1);
04869                 
04870                 gluDeleteQuadric(qobj);  
04871                 
04872                 glPopMatrix();
04873                 glEndList();
04874         }
04875         
04876         glScalef(size, size, size);
04877         glCallList(displist);
04878         glScalef(1.0f/size, 1.0f/size, 1.0f/size);
04879 }
04880 
04881 /* draw a cone for use as an empty drawtype */
04882 static void draw_empty_cone (float size)
04883 {
04884         float cent=0;
04885         float radius;
04886         GLUquadricObj *qobj = gluNewQuadric(); 
04887         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
04888         
04889         
04890         glPushMatrix();
04891         
04892         radius = size;
04893         glTranslatef(cent,cent, cent);
04894         glScalef(radius, size * 2.0f, radius);
04895         glRotatef(-90., 1.0, 0.0, 0.0);
04896         gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
04897 
04898         glPopMatrix();
04899         
04900         gluDeleteQuadric(qobj); 
04901 }
04902 
04903 /* draw points on curve speed handles */
04904 #if 0 // XXX old animation system stuff
04905 static void curve_draw_speed(Scene *scene, Object *ob)
04906 {
04907         Curve *cu= ob->data;
04908         IpoCurve *icu;
04909         BezTriple *bezt;
04910         float loc[4], dir[3];
04911         int a;
04912         
04913         if(cu->ipo==NULL)
04914                 return;
04915         
04916         icu= cu->ipo->curve.first; 
04917         if(icu==NULL || icu->totvert<2)
04918                 return;
04919         
04920         glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
04921         bglBegin(GL_POINTS);
04922 
04923         for(a=0, bezt= icu->bezt; a<icu->totvert; a++, bezt++) {
04924                 if( where_on_path(ob, bezt->vec[1][1], loc, dir)) {
04925                         UI_ThemeColor((bezt->f2 & SELECT) && ob==OBACT?TH_VERTEX_SELECT:TH_VERTEX);
04926                         bglVertex3fv(loc);
04927                 }
04928         }
04929 
04930         glPointSize(1.0);
04931         bglEnd();
04932 }
04933 #endif // XXX old animation system stuff
04934 
04935 
04936 static void draw_textcurs(float textcurs[][2])
04937 {
04938         cpack(0);
04939         
04940         set_inverted_drawing(1);
04941         glBegin(GL_QUADS);
04942         glVertex2fv(textcurs[0]);
04943         glVertex2fv(textcurs[1]);
04944         glVertex2fv(textcurs[2]);
04945         glVertex2fv(textcurs[3]);
04946         glEnd();
04947         set_inverted_drawing(0);
04948 }
04949 
04950 static void drawspiral(float *cent, float rad, float tmat[][4], int start)
04951 {
04952         float vec[3], vx[3], vy[3];
04953         int a, tot=32;
04954         char inverse=0;
04955                 
04956         if (start < 0) {
04957                 inverse = 1;
04958                 start *= -1;
04959         }
04960 
04961         mul_v3_v3fl(vx, tmat[0], rad);
04962         mul_v3_v3fl(vy, tmat[1], rad);
04963 
04964         copy_v3_v3(vec, cent);
04965 
04966         if (inverse==0) {
04967                 for(a=0; a<tot; a++) {
04968                         if (a+start>31)
04969                                 start=-a + 1;
04970                         glBegin(GL_LINES);                                                      
04971                         glVertex3fv(vec);
04972                         vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)a/(float)tot) + *(cosval+a+start) * (vy[0] * (float)a/(float)tot);
04973                         vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)a/(float)tot) + *(cosval+a+start) * (vy[1] * (float)a/(float)tot);
04974                         vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)a/(float)tot) + *(cosval+a+start) * (vy[2] * (float)a/(float)tot);
04975                         glVertex3fv(vec);
04976                         glEnd();
04977                 }
04978         }
04979         else {
04980                 a=0;
04981                 vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
04982                 vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
04983                 vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
04984                 for(a=0; a<tot; a++) {
04985                         if (a+start>31)
04986                                 start=-a + 1;
04987                         glBegin(GL_LINES);                                                      
04988                         glVertex3fv(vec);
04989                         vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
04990                         vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
04991                         vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
04992                         glVertex3fv(vec);
04993                         glEnd();
04994                 }
04995         }
04996 }
04997 
04998 /* draws a circle on x-z plane given the scaling of the circle, assuming that 
04999  * all required matrices have been set (used for drawing empties)
05000  */
05001 static void drawcircle_size(float size)
05002 {
05003         float x, y;
05004         short degrees;
05005 
05006         glBegin(GL_LINE_LOOP);
05007 
05008         /* coordinates are: cos(degrees*11.25)=x, sin(degrees*11.25)=y, 0.0f=z */
05009         for (degrees=0; degrees<32; degrees++) {
05010                 x= *(cosval + degrees);
05011                 y= *(sinval + degrees);
05012                 
05013                 glVertex3f(x*size, 0.0f, y*size);
05014         }
05015         
05016         glEnd();
05017 
05018 }
05019 
05020 /* needs fixing if non-identity matrice used */
05021 static void drawtube(float *vec, float radius, float height, float tmat[][4])
05022 {
05023         float cur[3];
05024         drawcircball(GL_LINE_LOOP, vec, radius, tmat);
05025 
05026         copy_v3_v3(cur,vec);
05027         cur[2]+=height;
05028 
05029         drawcircball(GL_LINE_LOOP, cur, radius, tmat);
05030 
05031         glBegin(GL_LINES);
05032                 glVertex3f(vec[0]+radius,vec[1],vec[2]);
05033                 glVertex3f(cur[0]+radius,cur[1],cur[2]);
05034                 glVertex3f(vec[0]-radius,vec[1],vec[2]);
05035                 glVertex3f(cur[0]-radius,cur[1],cur[2]);
05036                 glVertex3f(vec[0],vec[1]+radius,vec[2]);
05037                 glVertex3f(cur[0],cur[1]+radius,cur[2]);
05038                 glVertex3f(vec[0],vec[1]-radius,vec[2]);
05039                 glVertex3f(cur[0],cur[1]-radius,cur[2]);
05040         glEnd();
05041 }
05042 /* needs fixing if non-identity matrice used */
05043 static void drawcone(float *vec, float radius, float height, float tmat[][4])
05044 {
05045         float cur[3];
05046 
05047         copy_v3_v3(cur,vec);
05048         cur[2]+=height;
05049 
05050         drawcircball(GL_LINE_LOOP, cur, radius, tmat);
05051 
05052         glBegin(GL_LINES);
05053                 glVertex3f(vec[0],vec[1],vec[2]);
05054                 glVertex3f(cur[0]+radius,cur[1],cur[2]);
05055                 glVertex3f(vec[0],vec[1],vec[2]);
05056                 glVertex3f(cur[0]-radius,cur[1],cur[2]);
05057                 glVertex3f(vec[0],vec[1],vec[2]);
05058                 glVertex3f(cur[0],cur[1]+radius,cur[2]);
05059                 glVertex3f(vec[0],vec[1],vec[2]);
05060                 glVertex3f(cur[0],cur[1]-radius,cur[2]);
05061         glEnd();
05062 }
05063 /* return 1 if nothing was drawn */
05064 static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
05065 {
05066         Object *ob= base->object;
05067         MetaBall *mb;
05068         MetaElem *ml;
05069         float imat[4][4];
05070         int code= 1;
05071         
05072         mb= ob->data;
05073 
05074         if(mb->editelems) {
05075                 UI_ThemeColor(TH_WIRE);
05076                 if((G.f & G_PICKSEL)==0 ) drawDispList(scene, v3d, rv3d, base, dt);
05077                 ml= mb->editelems->first;
05078         }
05079         else {
05080                 if((base->flag & OB_FROMDUPLI)==0) 
05081                         drawDispList(scene, v3d, rv3d, base, dt);
05082                 ml= mb->elems.first;
05083         }
05084 
05085         if(ml==NULL) return 1;
05086 
05087         if(v3d->flag2 & V3D_RENDER_OVERRIDE) return 0;
05088         
05089         /* in case solid draw, reset wire colors */
05090         if(ob->flag & SELECT) {
05091                 if(ob==OBACT) UI_ThemeColor(TH_ACTIVE);
05092                 else UI_ThemeColor(TH_SELECT);
05093         }
05094         else UI_ThemeColor(TH_WIRE);
05095 
05096         invert_m4_m4(imat, rv3d->viewmatob);
05097         normalize_v3(imat[0]);
05098         normalize_v3(imat[1]);
05099         
05100         while(ml) {
05101         
05102                 /* draw radius */
05103                 if(mb->editelems) {
05104                         if((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0);
05105                         else cpack(0x3030A0);
05106                         
05107                         if(G.f & G_PICKSEL) {
05108                                 ml->selcol1= code;
05109                                 glLoadName(code++);
05110                         }
05111                 }
05112                 drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
05113 
05114                 /* draw stiffness */
05115                 if(mb->editelems) {
05116                         if((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0);
05117                         else cpack(0x30A030);
05118                         
05119                         if(G.f & G_PICKSEL) {
05120                                 ml->selcol2= code;
05121                                 glLoadName(code++);
05122                         }
05123                         drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad*atanf(ml->s)/(float)M_PI_2, imat);
05124                 }
05125                 
05126                 ml= ml->next;
05127         }
05128         return 0;
05129 }
05130 
05131 static void draw_forcefield(Scene *scene, Object *ob, RegionView3D *rv3d)
05132 {
05133         PartDeflect *pd= ob->pd;
05134         float imat[4][4], tmat[4][4];
05135         float vec[3]= {0.0, 0.0, 0.0};
05136         int curcol;
05137         float size;
05138 
05139         /* XXX why? */
05140         if(ob!=scene->obedit && (ob->flag & SELECT)) {
05141                 if(ob==OBACT) curcol= TH_ACTIVE;
05142                 else curcol= TH_SELECT;
05143         }
05144         else curcol= TH_WIRE;
05145         
05146         /* scale size of circle etc with the empty drawsize */
05147         if (ob->type == OB_EMPTY) size = ob->empty_drawsize;
05148         else size = 1.0;
05149         
05150         /* calculus here, is reused in PFIELD_FORCE */
05151         invert_m4_m4(imat, rv3d->viewmatob);
05152 //      normalize_v3(imat[0]);          // we don't do this because field doesnt scale either... apart from wind!
05153 //      normalize_v3(imat[1]);
05154         
05155         if (pd->forcefield == PFIELD_WIND) {
05156                 float force_val;
05157                 
05158                 unit_m4(tmat);
05159                 UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
05160                 
05161                 //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
05162                 //      force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
05163                 //else 
05164                         force_val = pd->f_strength;
05165                 force_val *= 0.1f;
05166                 drawcircball(GL_LINE_LOOP, vec, size, tmat);
05167                 vec[2]= 0.5f * force_val;
05168                 drawcircball(GL_LINE_LOOP, vec, size, tmat);
05169                 vec[2]= 1.0f * force_val;
05170                 drawcircball(GL_LINE_LOOP, vec, size, tmat);
05171                 vec[2]= 1.5f * force_val;
05172                 drawcircball(GL_LINE_LOOP, vec, size, tmat);
05173                 vec[2] = 0.0f; /* reset vec for max dist circle */
05174                 
05175         }
05176         else if (pd->forcefield == PFIELD_FORCE) {
05177                 float ffall_val;
05178 
05179                 //if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
05180                 //      ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra);
05181                 //else 
05182                         ffall_val = pd->f_power;
05183 
05184                 UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
05185                 drawcircball(GL_LINE_LOOP, vec, size, imat);
05186                 UI_ThemeColorBlend(curcol, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val));
05187                 drawcircball(GL_LINE_LOOP, vec, size * 1.5f, imat);
05188                 UI_ThemeColorBlend(curcol, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val));
05189                 drawcircball(GL_LINE_LOOP, vec, size*2.0f, imat);
05190         }
05191         else if (pd->forcefield == PFIELD_VORTEX) {
05192                 float /*ffall_val,*/ force_val;
05193 
05194                 unit_m4(tmat);
05195                 //if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
05196                 //      ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra);
05197                 //else 
05198                 //      ffall_val = pd->f_power;
05199 
05200                 //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
05201                 //      force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
05202                 //else 
05203                         force_val = pd->f_strength;
05204 
05205                 UI_ThemeColorBlend(curcol, TH_BACK, 0.7f);
05206                 if (force_val < 0) {
05207                         drawspiral(vec, size, tmat, 1);
05208                         drawspiral(vec, size, tmat, 16);
05209                 }
05210                 else {
05211                         drawspiral(vec, size, tmat, -1);
05212                         drawspiral(vec, size, tmat, -16);
05213                 }
05214         }
05215         else if (pd->forcefield == PFIELD_GUIDE && ob->type==OB_CURVE) {
05216                 Curve *cu= ob->data;
05217                 if((cu->flag & CU_PATH) && cu->path && cu->path->data) {
05218                         float mindist, guidevec1[4], guidevec2[3];
05219 
05220                         //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
05221                         //      mindist = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
05222                         //else 
05223                                 mindist = pd->f_strength;
05224 
05225                         /*path end*/
05226                         setlinestyle(3);
05227                         where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL);
05228                         UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
05229                         drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
05230 
05231                         /*path beginning*/
05232                         setlinestyle(0);
05233                         where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL);
05234                         UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
05235                         drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
05236                         
05237                         copy_v3_v3(vec, guidevec1);     /* max center */
05238                 }
05239         }
05240 
05241         setlinestyle(3);
05242         UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
05243 
05244         if(pd->falloff==PFIELD_FALL_SPHERE){
05245                 /* as last, guide curve alters it */
05246                 if(pd->flag & PFIELD_USEMAX)
05247                         drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);             
05248 
05249                 if(pd->flag & PFIELD_USEMIN)
05250                         drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat);
05251         }
05252         else if(pd->falloff==PFIELD_FALL_TUBE){
05253                 float radius,distance;
05254 
05255                 unit_m4(tmat);
05256 
05257                 vec[0]=vec[1]=0.0f;
05258                 radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
05259                 distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
05260                 vec[2]=distance;
05261                 distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
05262 
05263                 if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR))
05264                         drawtube(vec,radius,distance,tmat);
05265 
05266                 radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
05267                 distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
05268                 vec[2]=distance;
05269                 distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
05270 
05271                 if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR))
05272                         drawtube(vec,radius,distance,tmat);
05273         }
05274         else if(pd->falloff==PFIELD_FALL_CONE){
05275                 float radius,distance;
05276 
05277                 unit_m4(tmat);
05278 
05279                 radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
05280                 radius*=(float)M_PI/180.0f;
05281                 distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
05282 
05283                 if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR)){
05284                         drawcone(vec, distance * sinf(radius),distance * cosf(radius), tmat);
05285                         if((pd->flag & PFIELD_POSZ)==0)
05286                                 drawcone(vec, distance * sinf(radius),-distance * cosf(radius),tmat);
05287                 }
05288 
05289                 radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
05290                 radius*=(float)M_PI/180.0f;
05291                 distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
05292 
05293                 if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR)){
05294                         drawcone(vec,distance*sinf(radius),distance*cosf(radius),tmat);
05295                         if((pd->flag & PFIELD_POSZ)==0)
05296                                 drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat);
05297                 }
05298         }
05299         setlinestyle(0);
05300 }
05301 
05302 static void draw_box(float vec[8][3])
05303 {
05304         glBegin(GL_LINE_STRIP);
05305         glVertex3fv(vec[0]); glVertex3fv(vec[1]);glVertex3fv(vec[2]); glVertex3fv(vec[3]);
05306         glVertex3fv(vec[0]); glVertex3fv(vec[4]);glVertex3fv(vec[5]); glVertex3fv(vec[6]);
05307         glVertex3fv(vec[7]); glVertex3fv(vec[4]);
05308         glEnd();
05309 
05310         glBegin(GL_LINES);
05311         glVertex3fv(vec[1]); glVertex3fv(vec[5]);
05312         glVertex3fv(vec[2]); glVertex3fv(vec[6]);
05313         glVertex3fv(vec[3]); glVertex3fv(vec[7]);
05314         glEnd();
05315 }
05316 
05317 /* uses boundbox, function used by Ketsji */
05318 #if 0
05319 static void get_local_bounds(Object *ob, float *center, float *size)
05320 {
05321         BoundBox *bb= object_get_boundbox(ob);
05322         
05323         if(bb==NULL) {
05324                 zero_v3(center);
05325                 copy_v3_v3(size, ob->size);
05326         }
05327         else {
05328                 size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
05329                 size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
05330                 size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
05331                 
05332                 center[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
05333                 center[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
05334                 center[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
05335         }
05336 }
05337 #endif
05338 
05339 static void draw_bb_quadric(BoundBox *bb, short type)
05340 {
05341         float size[3], cent[3];
05342         GLUquadricObj *qobj = gluNewQuadric(); 
05343         
05344         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
05345         
05346         size[0]= 0.5f*fabsf(bb->vec[0][0] - bb->vec[4][0]);
05347         size[1]= 0.5f*fabsf(bb->vec[0][1] - bb->vec[2][1]);
05348         size[2]= 0.5f*fabsf(bb->vec[0][2] - bb->vec[1][2]);
05349         
05350         cent[0]= 0.5f*(bb->vec[0][0] + bb->vec[4][0]);
05351         cent[1]= 0.5f*(bb->vec[0][1] + bb->vec[2][1]);
05352         cent[2]= 0.5f*(bb->vec[0][2] + bb->vec[1][2]);
05353         
05354         glPushMatrix();
05355         if(type==OB_BOUND_SPHERE) {
05356                 glTranslatef(cent[0], cent[1], cent[2]);
05357                 glScalef(size[0], size[1], size[2]);
05358                 gluSphere(qobj, 1.0, 8, 5);
05359         }       
05360         else if(type==OB_BOUND_CYLINDER) {
05361                 float radius = size[0] > size[1] ? size[0] : size[1];
05362                 glTranslatef(cent[0], cent[1], cent[2]-size[2]);
05363                 glScalef(radius, radius, 2.0f * size[2]);
05364                 gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
05365         }
05366         else if(type==OB_BOUND_CONE) {
05367                 float radius = size[0] > size[1] ? size[0] : size[1];
05368                 glTranslatef(cent[0], cent[2]-size[2], cent[1]);
05369                 glScalef(radius, 2.0f * size[2], radius);
05370                 glRotatef(-90., 1.0, 0.0, 0.0);
05371                 gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
05372         }
05373         glPopMatrix();
05374         
05375         gluDeleteQuadric(qobj); 
05376 }
05377 
05378 static void draw_bounding_volume(Scene *scene, Object *ob)
05379 {
05380         BoundBox *bb= NULL;
05381         
05382         if(ob->type==OB_MESH) {
05383                 bb= mesh_get_bb(ob);
05384         }
05385         else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
05386                 bb= ob->bb ? ob->bb : ( (Curve *)ob->data )->bb;
05387         }
05388         else if(ob->type==OB_MBALL) {
05389                 if(is_basis_mball(ob)) {
05390                         bb= ob->bb;
05391                         if(bb==NULL) {
05392                                 makeDispListMBall(scene, ob);
05393                                 bb= ob->bb;
05394                         }
05395                 }
05396         }
05397         else {
05398                 drawcube();
05399                 return;
05400         }
05401         
05402         if(bb==NULL) return;
05403         
05404         if(ob->boundtype==OB_BOUND_BOX) draw_box(bb->vec);
05405         else draw_bb_quadric(bb, ob->boundtype);
05406         
05407 }
05408 
05409 static void drawtexspace(Object *ob)
05410 {
05411         float vec[8][3], loc[3], size[3];
05412         
05413         if(ob->type==OB_MESH) {
05414                 mesh_get_texspace(ob->data, loc, NULL, size);
05415         }
05416         else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
05417                 Curve *cu= ob->data;
05418                 copy_v3_v3(size, cu->size);
05419                 copy_v3_v3(loc, cu->loc);
05420         }
05421         else if(ob->type==OB_MBALL) {
05422                 MetaBall *mb= ob->data;
05423                 copy_v3_v3(size, mb->size);
05424                 copy_v3_v3(loc, mb->loc);
05425         }
05426         else return;
05427         
05428         vec[0][0]=vec[1][0]=vec[2][0]=vec[3][0]= loc[0]-size[0];
05429         vec[4][0]=vec[5][0]=vec[6][0]=vec[7][0]= loc[0]+size[0];
05430         
05431         vec[0][1]=vec[1][1]=vec[4][1]=vec[5][1]= loc[1]-size[1];
05432         vec[2][1]=vec[3][1]=vec[6][1]=vec[7][1]= loc[1]+size[1];
05433 
05434         vec[0][2]=vec[3][2]=vec[4][2]=vec[7][2]= loc[2]-size[2];
05435         vec[1][2]=vec[2][2]=vec[5][2]=vec[6][2]= loc[2]+size[2];
05436         
05437         setlinestyle(2);
05438 
05439         draw_box(vec);
05440 
05441         setlinestyle(0);
05442 }
05443 
05444 /* draws wire outline */
05445 static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
05446 {
05447         RegionView3D *rv3d= ar->regiondata;
05448         Object *ob= base->object;
05449         
05450         glLineWidth(2.0);
05451         glDepthMask(0);
05452         
05453         if(ELEM3(ob->type, OB_FONT,OB_CURVE, OB_SURF)) {
05454                 Curve *cu = ob->data;
05455                 DerivedMesh *dm = ob->derivedFinal;
05456                 int hasfaces= 0;
05457 
05458                 if (dm) {
05459                         hasfaces= dm->getNumFaces(dm);
05460                 } else {
05461                         hasfaces= displist_has_faces(&ob->disp);
05462                 }
05463 
05464                 if (hasfaces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
05465                         draw_index_wire= 0;
05466                         if (dm) {
05467                                 draw_mesh_object_outline(v3d, ob, dm);
05468                         } else {
05469                                 drawDispListwire(&ob->disp);
05470                         }
05471                         draw_index_wire= 1;
05472                 }
05473         } else if (ob->type==OB_MBALL) {
05474                 if(is_basis_mball(ob)) {
05475                         if((base->flag & OB_FROMDUPLI)==0)
05476                                 drawDispListwire(&ob->disp);
05477                 }
05478         }
05479         else if(ob->type==OB_ARMATURE) {
05480                 if(!(ob->mode & OB_MODE_POSE))
05481                         draw_armature(scene, v3d, ar, base, OB_WIRE, FALSE, TRUE);
05482         }
05483 
05484         glLineWidth(1.0);
05485         glDepthMask(1);
05486 }
05487 
05488 static void drawWireExtra(Scene *scene, RegionView3D *rv3d, Object *ob) 
05489 {
05490         if(ob!=scene->obedit && (ob->flag & SELECT)) {
05491                 if(ob==OBACT) {
05492                         if(ob->flag & OB_FROMGROUP) UI_ThemeColor(TH_GROUP_ACTIVE);
05493                         else UI_ThemeColor(TH_ACTIVE);
05494                 }
05495                 else if(ob->flag & OB_FROMGROUP)
05496                         UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
05497                 else
05498                         UI_ThemeColor(TH_SELECT);
05499         }
05500         else {
05501                 if(ob->flag & OB_FROMGROUP)
05502                         UI_ThemeColor(TH_GROUP);
05503                 else {
05504                         if(ob->dtx & OB_DRAWWIRE) {
05505                                 glColor3ub(80,80,80);
05506                         } else {
05507                                 UI_ThemeColor(TH_WIRE);
05508                         }
05509                 }
05510         }
05511         
05512         bglPolygonOffset(rv3d->dist, 1.0);
05513         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
05514         
05515         if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
05516                 Curve *cu = ob->data;
05517                 if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
05518                         if (ob->type==OB_CURVE)
05519                                 draw_index_wire= 0;
05520 
05521                         if (ob->derivedFinal) {
05522                                 drawCurveDMWired(ob);
05523                         } else {
05524                                 drawDispListwire(&ob->disp);
05525                         }
05526 
05527                         if (ob->type==OB_CURVE)
05528                                 draw_index_wire= 1;
05529                 }
05530         } else if (ob->type==OB_MBALL) {
05531                 if(is_basis_mball(ob)) {
05532                         drawDispListwire(&ob->disp);
05533                 }
05534         }
05535 
05536         glDepthMask(1);
05537         bglPolygonOffset(rv3d->dist, 0.0);
05538 }
05539 
05540 /* should be called in view space */
05541 static void draw_hooks(Object *ob)
05542 {
05543         ModifierData *md;
05544         float vec[3];
05545         
05546         for (md=ob->modifiers.first; md; md=md->next) {
05547                 if (md->type==eModifierType_Hook) {
05548                         HookModifierData *hmd = (HookModifierData*) md;
05549 
05550                         mul_v3_m4v3(vec, ob->obmat, hmd->cent);
05551 
05552                         if(hmd->object) {
05553                                 setlinestyle(3);
05554                                 glBegin(GL_LINES);
05555                                 glVertex3fv(hmd->object->obmat[3]);
05556                                 glVertex3fv(vec);
05557                                 glEnd();
05558                                 setlinestyle(0);
05559                         }
05560 
05561                         glPointSize(3.0);
05562                         bglBegin(GL_POINTS);
05563                         bglVertex3fv(vec);
05564                         bglEnd();
05565                         glPointSize(1.0);
05566                 }
05567         }
05568 }
05569 
05570 static void drawRBpivot(bRigidBodyJointConstraint *data)
05571 {
05572         int axis;
05573         float mat[4][4];
05574 
05575         /* color */
05576         float curcol[4];
05577         unsigned char tcol[4];
05578         glGetFloatv(GL_CURRENT_COLOR, curcol);
05579         rgb_float_to_byte(curcol, tcol);
05580         tcol[3]= 255;
05581 
05582         eul_to_mat4(mat,&data->axX);
05583         glLineWidth (4.0f);
05584         setlinestyle(2);
05585         for (axis=0; axis<3; axis++) {
05586                 float dir[3] = {0,0,0};
05587                 float v[3];
05588 
05589                 copy_v3_v3(v, &data->pivX);
05590 
05591                 dir[axis] = 1.f;
05592                 glBegin(GL_LINES);
05593                 mul_m4_v3(mat,dir);
05594                 add_v3_v3(v, dir);
05595                 glVertex3fv(&data->pivX);
05596                 glVertex3fv(v);                 
05597                 glEnd();
05598                 if (axis==0)
05599                         view3d_cached_text_draw_add(v, "px", 0, V3D_CACHE_TEXT_ASCII, tcol);
05600                 else if (axis==1)
05601                         view3d_cached_text_draw_add(v, "py", 0, V3D_CACHE_TEXT_ASCII, tcol);
05602                 else
05603                         view3d_cached_text_draw_add(v, "pz", 0, V3D_CACHE_TEXT_ASCII, tcol);
05604         }
05605         glLineWidth (1.0f);
05606         setlinestyle(0);
05607 }
05608 
05609 /* flag can be DRAW_PICKING     and/or DRAW_CONSTCOLOR, DRAW_SCENESET */
05610 void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
05611 {
05612         static int warning_recursive= 0;
05613         ModifierData *md = NULL;
05614         Object *ob;
05615         Curve *cu;
05616         RegionView3D *rv3d= ar->regiondata;
05617         //float cfraont;
05618         float vec1[3], vec2[3];
05619         unsigned int col=0;
05620         int /*sel, drawtype,*/ colindex= 0;
05621         int i, selstart, selend, empty_object=0;
05622         short dt, dtx, zbufoff= 0;
05623 
05624         /* only once set now, will be removed too, should become a global standard */
05625         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
05626 
05627         ob= base->object;
05628 
05629         if (ob!=scene->obedit) {
05630                 if (ob->restrictflag & OB_RESTRICT_VIEW) 
05631                         return;
05632                 if ((ob->restrictflag & OB_RESTRICT_RENDER) && 
05633                         (v3d->flag2 & V3D_RENDER_OVERRIDE))
05634                         return;
05635         }
05636 
05637         /* XXX particles are not safe for simultaneous threaded render */
05638         if(G.rendering && ob->particlesystem.first)
05639                 return;
05640 
05641         /* xray delay? */
05642         if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) {
05643                 /* don't do xray in particle mode, need the z-buffer */
05644                 if(!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
05645                         /* xray and transp are set when it is drawing the 2nd/3rd pass */
05646                         if(!v3d->xray && !v3d->transp && (ob->dtx & OB_DRAWXRAY) && !(ob->dtx & OB_DRAWTRANSP)) {
05647                                 add_view3d_after(&v3d->afterdraw_xray, base, flag);
05648                                 return;
05649                         }
05650                 }
05651         }
05652 
05653         /* no return after this point, otherwise leaks */
05654         view3d_cached_text_draw_begin();
05655         
05656 
05657         /* draw keys? */
05658 #if 0 // XXX old animation system
05659         if(base==(scene->basact) || (base->flag & (SELECT+BA_WAS_SEL))) {
05660                 if(flag==0 && warning_recursive==0 && ob!=scene->obedit) {
05661                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
05662                                 ListBase elems;
05663                                 CfraElem *ce;
05664                                 float temp[7][3];
05665 
05666                                 warning_recursive= 1;
05667 
05668                                 elems.first= elems.last= 0;
05669                                 // warning: no longer checks for certain ob-keys only... (so does this need to use the proper ipokeys then?)
05670                                 make_cfra_list(ob->ipo, &elems); 
05671 
05672                                 cfraont= (scene->r.cfra);
05673                                 drawtype= v3d->drawtype;
05674                                 if(drawtype>OB_WIRE) v3d->drawtype= OB_WIRE;
05675                                 sel= base->flag;
05676                                 memcpy(temp, &ob->loc, 7*3*sizeof(float));
05677 
05678                                 ipoflag= ob->ipoflag;
05679                                 ob->ipoflag &= ~OB_OFFS_OB;
05680 
05681                                 set_no_parent_ipo(1);
05682                                 disable_speed_curve(1);
05683 
05684                                 if ((ob->ipoflag & OB_DRAWKEYSEL)==0) {
05685                                         ce= elems.first;
05686                                         while(ce) {
05687                                                 if(!ce->sel) {
05688                                                         (scene->r.cfra)= ce->cfra/scene->r.framelen;
05689 
05690                                                         base->flag= 0;
05691 
05692                                                         where_is_object_time(scene, ob, (scene->r.cfra));
05693                                                         draw_object(scene, ar, v3d, base, 0);
05694                                                 }
05695                                                 ce= ce->next;
05696                                         }
05697                                 }
05698 
05699                                 ce= elems.first;
05700                                 while(ce) {
05701                                         if(ce->sel) {
05702                                                 (scene->r.cfra)= ce->cfra/scene->r.framelen;
05703 
05704                                                 base->flag= SELECT;
05705 
05706                                                 where_is_object_time(scene, ob, (scene->r.cfra));
05707                                                 draw_object(scene, ar, v3d, base, 0);
05708                                         }
05709                                         ce= ce->next;
05710                                 }
05711 
05712                                 set_no_parent_ipo(0);
05713                                 disable_speed_curve(0);
05714 
05715                                 base->flag= sel;
05716                                 ob->ipoflag= ipoflag;
05717 
05718                                 /* restore icu->curval */
05719                                 (scene->r.cfra)= cfraont;
05720 
05721                                 memcpy(&ob->loc, temp, 7*3*sizeof(float));
05722                                 where_is_object(scene, ob);
05723                                 v3d->drawtype= drawtype;
05724 
05725                                 BLI_freelistN(&elems);
05726 
05727                                 warning_recursive= 0;
05728                         }
05729                 }
05730         }
05731 #endif // XXX old animation system
05732 
05733         /* patch? children objects with a timeoffs change the parents. How to solve! */
05734         /* if( ((int)ob->ctime) != F_(scene->r.cfra)) where_is_object(scene, ob); */
05735         
05736         /* draw motion paths (in view space) */
05737         if (ob->mpath && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
05738                 bAnimVizSettings *avs= &ob->avs;
05739                 
05740                 /* setup drawing environment for paths */
05741                 draw_motion_paths_init(v3d, ar);
05742                 
05743                 /* draw motion path for object */
05744                 draw_motion_path_instance(scene, ob, NULL, avs, ob->mpath);
05745                 
05746                 /* cleanup after drawing */
05747                 draw_motion_paths_cleanup(v3d);
05748         }
05749 
05750         /* multiply view with object matrix.
05751          * local viewmat and persmat, to calculate projections */
05752         ED_view3d_init_mats_rv3d_gl(ob, rv3d);
05753 
05754         /* which wire color */
05755         if((flag & DRAW_CONSTCOLOR) == 0) {
05756                 project_short(ar, ob->obmat[3], &base->sx);
05757 
05758                 if( (!scene->obedit) && (G.moving & G_TRANSFORM_OBJ) && (base->flag & (SELECT+BA_WAS_SEL))) UI_ThemeColor(TH_TRANSFORM);
05759                 else {
05760 
05761                         if(ob->type==OB_LAMP) UI_ThemeColor(TH_LAMP);
05762                         else UI_ThemeColor(TH_WIRE);
05763 
05764                         if((scene->basact)==base) {
05765                                 if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
05766                         }
05767                         else {
05768                                 if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
05769                         }
05770 
05771                         // no theme yet
05772                         if(ob->id.lib) {
05773                                 if(base->flag & (SELECT+BA_WAS_SEL)) colindex = 4;
05774                                 else colindex = 3;
05775                         }
05776                         else if(warning_recursive==1) {
05777                                 if(base->flag & (SELECT+BA_WAS_SEL)) {
05778                                         if(scene->basact==base) colindex = 8;
05779                                         else colindex= 7;
05780                                 }
05781                                 else colindex = 6;
05782                         }
05783                         else if(ob->flag & OB_FROMGROUP) {
05784                                 if(base->flag & (SELECT+BA_WAS_SEL)) {
05785                                         if(scene->basact==base) UI_ThemeColor(TH_GROUP_ACTIVE);
05786                                         else UI_ThemeColorShade(TH_GROUP_ACTIVE, -16); 
05787                                 }
05788                                 else UI_ThemeColor(TH_GROUP);
05789                                 colindex= 0;
05790                         }
05791 
05792                 }       
05793 
05794                 if(colindex) {
05795                         col= colortab[colindex];
05796                         cpack(col);
05797                 }
05798         }
05799 
05800         /* maximum drawtype */
05801         dt= MIN2(v3d->drawtype, ob->dt);
05802         if(v3d->zbuf==0 && dt>OB_WIRE) dt= OB_WIRE;
05803         dtx= 0;
05804 
05805         /* faceselect exception: also draw solid when dt==wire, except in editmode */
05806         if(ob==OBACT && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))) {
05807                 if(ob->type==OB_MESH) {
05808 
05809                         if(ob->mode & OB_MODE_EDIT);
05810                         else {
05811                                 if(dt<OB_SOLID) {
05812                                         zbufoff= 1;
05813                                         dt= OB_SOLID;
05814                                 }
05815                                 else {
05816                                         dt= OB_SHADED;
05817                                 }
05818 
05819                                 glEnable(GL_DEPTH_TEST);
05820                         }
05821                 }
05822                 else {
05823                         if(dt<OB_SOLID) {
05824                                 dt= OB_SOLID;
05825                                 glEnable(GL_DEPTH_TEST);
05826                                 zbufoff= 1;
05827                         }
05828                 }
05829         }
05830         
05831         /* draw-extra supported for boundbox drawmode too */
05832         if(dt>=OB_BOUNDBOX ) {
05833 
05834                 dtx= ob->dtx;
05835                 if(ob->mode & OB_MODE_EDIT) {
05836                         // the only 2 extra drawtypes alowed in editmode
05837                         dtx= dtx & (OB_DRAWWIRE|OB_TEXSPACE);
05838                 }
05839 
05840         }
05841 
05842         /* bad exception, solve this! otherwise outline shows too late */
05843         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
05844                 /* still needed for curves hidden in other layers. depgraph doesnt handle that yet */
05845                 if (ob->disp.first==NULL) makeDispListCurveTypes(scene, ob, 0);
05846         }
05847         
05848         /* draw outline for selected objects, mesh does itself */
05849         if((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && ob->type!=OB_MESH) {
05850                 if(dt>OB_WIRE && (ob->mode & OB_MODE_EDIT)==0 && (flag & DRAW_SCENESET)==0) {
05851                         if (!(ob->dtx&OB_DRAWWIRE) && (ob->flag&SELECT) && !(flag&DRAW_PICKING)) {
05852                                 
05853                                 drawObjectSelect(scene, v3d, ar, base);
05854                         }
05855                 }
05856         }
05857 
05858         switch( ob->type) {
05859                 case OB_MESH:
05860                         empty_object= draw_mesh_object(scene, ar, v3d, rv3d, base, dt, flag);
05861                         if(flag!=DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself
05862 
05863                         break;
05864                 case OB_FONT:
05865                         cu= ob->data;
05866                         if(cu->editfont) {
05867                                 draw_textcurs(cu->editfont->textcurs);
05868 
05869                                 if (cu->flag & CU_FAST) {
05870                                         cpack(0xFFFFFF);
05871                                         set_inverted_drawing(1);
05872                                         drawDispList(scene, v3d, rv3d, base, OB_WIRE);
05873                                         set_inverted_drawing(0);
05874                                 } else {
05875                                         drawDispList(scene, v3d, rv3d, base, dt);
05876                                 }
05877 
05878                                 if (cu->linewidth != 0.0f) {
05879                                         cpack(0xff44ff);
05880                                         UI_ThemeColor(TH_WIRE);
05881                                         copy_v3_v3(vec1, ob->orig);
05882                                         copy_v3_v3(vec2, ob->orig);
05883                                         vec1[0] += cu->linewidth;
05884                                         vec2[0] += cu->linewidth;
05885                                         vec1[1] += cu->linedist * cu->fsize;
05886                                         vec2[1] -= cu->lines * cu->linedist * cu->fsize;
05887                                         setlinestyle(3);
05888                                         glBegin(GL_LINE_STRIP); 
05889                                         glVertex2fv(vec1); 
05890                                         glVertex2fv(vec2); 
05891                                         glEnd();
05892                                         setlinestyle(0);
05893                                 }
05894 
05895                                 setlinestyle(3);
05896                                 for (i=0; i<cu->totbox; i++) {
05897                                         if (cu->tb[i].w != 0.0f) {
05898                                                 if (i == (cu->actbox-1))
05899                                                         UI_ThemeColor(TH_ACTIVE);
05900                                                 else
05901                                                         UI_ThemeColor(TH_WIRE);
05902                                                 vec1[0] = (cu->xof * cu->fsize) + cu->tb[i].x;
05903                                                 vec1[1] = (cu->yof * cu->fsize) + cu->tb[i].y + cu->fsize;
05904                                                 vec1[2] = 0.001;
05905                                                 glBegin(GL_LINE_STRIP);
05906                                                 glVertex3fv(vec1);
05907                                                 vec1[0] += cu->tb[i].w;
05908                                                 glVertex3fv(vec1);
05909                                                 vec1[1] -= cu->tb[i].h;
05910                                                 glVertex3fv(vec1);
05911                                                 vec1[0] -= cu->tb[i].w;
05912                                                 glVertex3fv(vec1);
05913                                                 vec1[1] += cu->tb[i].h;
05914                                                 glVertex3fv(vec1);
05915                                                 glEnd();
05916                                         }
05917                                 }
05918                                 setlinestyle(0);
05919 
05920 
05921                                 if (BKE_font_getselection(ob, &selstart, &selend) && cu->selboxes) {
05922                                         float selboxw;
05923 
05924                                         cpack(0xffffff);
05925                                         set_inverted_drawing(1);
05926                                         for (i=0; i<(selend-selstart+1); i++) {
05927                                                 SelBox *sb = &(cu->selboxes[i]);
05928 
05929                                                 if (i<(selend-selstart)) {
05930                                                         if (cu->selboxes[i+1].y == sb->y)
05931                                                                 selboxw= cu->selboxes[i+1].x - sb->x;
05932                                                         else
05933                                                                 selboxw= sb->w;
05934                                                 }
05935                                                 else {
05936                                                         selboxw= sb->w;
05937                                                 }
05938                                                 glBegin(GL_QUADS);
05939                                                 glVertex3f(sb->x, sb->y, 0.001);
05940                                                 glVertex3f(sb->x+selboxw, sb->y, 0.001);
05941                                                 glVertex3f(sb->x+selboxw, sb->y+sb->h, 0.001);
05942                                                 glVertex3f(sb->x, sb->y+sb->h, 0.001);
05943                                                 glEnd();
05944                                         }
05945                                         set_inverted_drawing(0);
05946                                 }
05947                         }
05948                         else if(dt==OB_BOUNDBOX) {
05949                                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
05950                                         draw_bounding_volume(scene, ob);
05951                         }
05952                         else if(ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb))
05953                                 empty_object= drawDispList(scene, v3d, rv3d, base, dt);
05954 
05955                         break;
05956                 case OB_CURVE:
05957                 case OB_SURF:
05958                         cu= ob->data;
05959 
05960                         if(cu->editnurb) {
05961                                 ListBase *nurbs= ED_curve_editnurbs(cu);
05962                                 drawnurb(scene, v3d, rv3d, base, nurbs->first, dt);
05963                         }
05964                         else if(dt==OB_BOUNDBOX) {
05965                                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
05966                                         draw_bounding_volume(scene, ob);
05967                         }
05968                         else if(ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
05969                                 empty_object= drawDispList(scene, v3d, rv3d, base, dt);
05970 
05971 //XXX old animsys                               if(cu->path)
05972 //                                                      curve_draw_speed(scene, ob);
05973                         }
05974                         break;
05975                 case OB_MBALL:
05976                 {
05977                         MetaBall *mb= ob->data;
05978                         
05979                         if(mb->editelems) 
05980                                 drawmball(scene, v3d, rv3d, base, dt);
05981                         else if(dt==OB_BOUNDBOX) {
05982                                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
05983                                         draw_bounding_volume(scene, ob);
05984                         }
05985                         else 
05986                                 empty_object= drawmball(scene, v3d, rv3d, base, dt);
05987                         break;
05988                 }
05989                 case OB_EMPTY:
05990                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
05991                                 if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
05992                                         draw_empty_image(ob);
05993                                 }
05994                                 else {
05995                                         drawaxes(ob->empty_drawsize, ob->empty_drawtype);
05996                                 }
05997                         }
05998                         break;
05999                 case OB_LAMP:
06000                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
06001                                 drawlamp(scene, v3d, rv3d, base, dt, flag);
06002                                 if(dtx || (base->flag & SELECT)) glMultMatrixf(ob->obmat);
06003                         }
06004                         break;
06005                 case OB_CAMERA:
06006                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0 || (rv3d->persp==RV3D_CAMOB && v3d->camera==ob)) /* special exception for active camera */
06007                                 drawcamera(scene, v3d, rv3d, ob, flag);
06008                         break;
06009                 case OB_LATTICE:
06010                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
06011                                 drawlattice(scene, v3d, ob);
06012                         }
06013                         break;
06014                 case OB_ARMATURE:
06015                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
06016                                 if(dt>OB_WIRE) GPU_enable_material(0, NULL); // we use default material
06017                                 empty_object= draw_armature(scene, v3d, ar, base, dt, flag, FALSE);
06018                                 if(dt>OB_WIRE) GPU_disable_material();
06019                         }
06020                         break;
06021                 default:
06022                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
06023                                 drawaxes(1.0, OB_ARROWS);
06024                         }
06025         }
06026 
06027         if((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
06028 
06029                 if(ob->soft /*&& flag & OB_SBMOTION*/){
06030                         float mrt[3][3],msc[3][3],mtr[3][3]; 
06031                         SoftBody *sb= NULL;
06032                         float tipw = 0.5f, tiph = 0.5f,drawsize = 4.0f;
06033                         if ((sb= ob->soft)){
06034                                 if(sb->solverflags & SBSO_ESTIMATEIPO){
06035 
06036                                         glLoadMatrixf(rv3d->viewmat);
06037                                         copy_m3_m3(msc,sb->lscale);
06038                                         copy_m3_m3(mrt,sb->lrot);
06039                                         mul_m3_m3m3(mtr,mrt,msc); 
06040                                         ob_draw_RE_motion(sb->lcom,mtr,tipw,tiph,drawsize);
06041                                         glMultMatrixf(ob->obmat);
06042                                 }
06043                         }
06044                 }
06045 
06046                 if(ob->pd && ob->pd->forcefield) {
06047                         draw_forcefield(scene, ob, rv3d);
06048                 }
06049         }
06050 
06051         /* code for new particle system */
06052         if(             (warning_recursive==0) &&
06053                         (ob->particlesystem.first) &&
06054                         (flag & DRAW_PICKING)==0 &&
06055                         (ob!=scene->obedit)     
06056           ) {
06057                 ParticleSystem *psys;
06058 
06059                 if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */
06060                 //glDepthMask(GL_FALSE);
06061 
06062                 glLoadMatrixf(rv3d->viewmat);
06063                 
06064                 view3d_cached_text_draw_begin();
06065 
06066                 for(psys=ob->particlesystem.first; psys; psys=psys->next) {
06067                         /* run this so that possible child particles get cached */
06068                         if(ob->mode & OB_MODE_PARTICLE_EDIT && ob==OBACT) {
06069                                 PTCacheEdit *edit = PE_create_current(scene, ob);
06070                                 if(edit && edit->psys == psys)
06071                                         draw_update_ptcache_edit(scene, ob, edit);
06072                         }
06073 
06074                         draw_new_particle_system(scene, v3d, rv3d, base, psys, dt);
06075                 }
06076                 invert_m4_m4(ob->imat, ob->obmat);
06077                 view3d_cached_text_draw_end(v3d, ar, 0, NULL);
06078 
06079                 glMultMatrixf(ob->obmat);
06080                 
06081                 //glDepthMask(GL_TRUE);
06082                 if(col) cpack(col);
06083         }
06084 
06085         /* draw edit particles last so that they can draw over child particles */
06086         if(             (warning_recursive==0) &&
06087                         (flag & DRAW_PICKING)==0 &&
06088                         (!scene->obedit)        
06089           ) {
06090 
06091                 if(ob->mode & OB_MODE_PARTICLE_EDIT && ob==OBACT) {
06092                         PTCacheEdit *edit = PE_create_current(scene, ob);
06093                         if(edit) {
06094                                 glLoadMatrixf(rv3d->viewmat);
06095                                 draw_update_ptcache_edit(scene, ob, edit);
06096                                 draw_ptcache_edit(scene, v3d, edit);
06097                                 glMultMatrixf(ob->obmat);
06098                         }
06099                 }
06100         }
06101 
06102         /* draw code for smoke */
06103         if((md = modifiers_findByType(ob, eModifierType_Smoke)))
06104         {
06105                 SmokeModifierData *smd = (SmokeModifierData *)md;
06106 
06107                 // draw collision objects
06108                 if((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll)
06109                 {
06110                         /*SmokeCollSettings *scs = smd->coll;
06111                         if(scs->points)
06112                         {
06113                                 size_t i;
06114 
06115                                 glLoadMatrixf(rv3d->viewmat);
06116 
06117                                 if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); 
06118                                 glDepthMask(GL_FALSE);
06119                                 glEnable(GL_BLEND);
06120                                 
06121 
06122                                 // glPointSize(3.0);
06123                                 bglBegin(GL_POINTS);
06124 
06125                                 for(i = 0; i < scs->numpoints; i++)
06126                                 {
06127                                         bglVertex3fv(&scs->points[3*i]);
06128                                 }
06129 
06130                                 bglEnd();
06131                                 glPointSize(1.0);
06132 
06133                                 glMultMatrixf(ob->obmat);
06134                                 glDisable(GL_BLEND);
06135                                 glDepthMask(GL_TRUE);
06136                                 if(col) cpack(col);
06137                                 
06138                         }
06139                         */
06140                 }
06141 
06142                 // only draw domains
06143                 if(smd->domain && smd->domain->fluid)
06144                 {
06145                         if(CFRA < smd->domain->point_cache[0]->startframe)
06146                                 ; /* don't show smoke before simulation starts, this could be made an option in the future */
06147                         else if(!smd->domain->wt || !(smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG))
06148                         {
06149 // #if 0
06150                                 smd->domain->tex = NULL;
06151                                 GPU_create_smoke(smd, 0);
06152                                 draw_volume(ar, smd->domain->tex, smd->domain->p0, smd->domain->p1, smd->domain->res, smd->domain->dx, smd->domain->tex_shadow);
06153                                 GPU_free_smoke(smd);
06154 // #endif
06155 #if 0
06156                                 int x, y, z;
06157                                 float *density = smoke_get_density(smd->domain->fluid);
06158 
06159                                 glLoadMatrixf(rv3d->viewmat);
06160                                 // glMultMatrixf(ob->obmat);    
06161 
06162                                 if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); 
06163                                 glDepthMask(GL_FALSE);
06164                                 glEnable(GL_BLEND);
06165                                 
06166 
06167                                 // glPointSize(3.0);
06168                                 bglBegin(GL_POINTS);
06169 
06170                                 for(x = 0; x < smd->domain->res[0]; x++)
06171                                         for(y = 0; y < smd->domain->res[1]; y++)
06172                                                 for(z = 0; z < smd->domain->res[2]; z++)
06173                                 {
06174                                         float tmp[3];
06175                                         int index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z);
06176 
06177                                         if(density[index] > FLT_EPSILON)
06178                                         {
06179                                                 float color[3];
06180                                                 copy_v3_v3(tmp, smd->domain->p0);
06181                                                 tmp[0] += smd->domain->dx * x + smd->domain->dx * 0.5;
06182                                                 tmp[1] += smd->domain->dx * y + smd->domain->dx * 0.5;
06183                                                 tmp[2] += smd->domain->dx * z + smd->domain->dx * 0.5;
06184                                                 color[0] = color[1] = color[2] = density[index];
06185                                                 glColor3fv(color);
06186                                                 bglVertex3fv(tmp);
06187                                         }
06188                                 }
06189 
06190                                 bglEnd();
06191                                 glPointSize(1.0);
06192 
06193                                 glMultMatrixf(ob->obmat);
06194                                 glDisable(GL_BLEND);
06195                                 glDepthMask(GL_TRUE);
06196                                 if(col) cpack(col);
06197 #endif
06198                         }
06199                         else if(smd->domain->wt && (smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG))
06200                         {
06201                                 smd->domain->tex = NULL;
06202                                 GPU_create_smoke(smd, 1);
06203                                 draw_volume(ar, smd->domain->tex, smd->domain->p0, smd->domain->p1, smd->domain->res_wt, smd->domain->dx_wt, smd->domain->tex_shadow);
06204                                 GPU_free_smoke(smd);
06205                         }
06206                 }
06207         }
06208 
06209         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
06210 
06211                 bConstraint *con;
06212                 for(con=ob->constraints.first; con; con= con->next) 
06213                 {
06214                         if(con->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) 
06215                         {
06216                                 bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint*)con->data;
06217                                 if(data->flag&CONSTRAINT_DRAW_PIVOT)
06218                                         drawRBpivot(data);
06219                         }
06220                 }
06221 
06222                 /* draw extra: after normal draw because of makeDispList */
06223                 if(dtx && (G.f & G_RENDER_OGL)==0) {
06224 
06225                         if(dtx & OB_AXIS) {
06226                                 drawaxes(1.0f, OB_ARROWS);
06227                         }
06228                         if(dtx & OB_BOUNDBOX) {
06229                                 if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
06230                                         draw_bounding_volume(scene, ob);
06231                         }
06232                         if(dtx & OB_TEXSPACE) drawtexspace(ob);
06233                         if(dtx & OB_DRAWNAME) {
06234                                 /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */
06235                                 /* but, we also dont draw names for sets or duplicators */
06236                                 if(flag == 0) {
06237                                         float zero[3]= {0,0,0};
06238                                         float curcol[4];
06239                                         unsigned char tcol[4];
06240                                         glGetFloatv(GL_CURRENT_COLOR, curcol);
06241                                         rgb_float_to_byte(curcol, tcol);
06242                                         tcol[3]= 255;
06243                                         view3d_cached_text_draw_add(zero, ob->id.name+2, 10, 0, tcol);
06244                                 }
06245                         }
06246                         /*if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/
06247                         if((dtx & OB_DRAWWIRE) && dt>=OB_SOLID) drawWireExtra(scene, rv3d, ob);
06248                 }
06249         }
06250 
06251         if(dt<=OB_SOLID && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
06252                 if((ob->gameflag & OB_DYNAMIC) || 
06253                         ((ob->gameflag & OB_BOUNDS) && (ob->boundtype == OB_BOUND_SPHERE))) {
06254                         float imat[4][4], vec[3]= {0.0f, 0.0f, 0.0f};
06255 
06256                         invert_m4_m4(imat, rv3d->viewmatob);
06257 
06258                         setlinestyle(2);
06259                         drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat);
06260                         setlinestyle(0);
06261                 }
06262         }
06263         
06264         /* return warning, this is cached text draw */
06265         invert_m4_m4(ob->imat, ob->obmat);
06266         view3d_cached_text_draw_end(v3d, ar, 1, NULL);
06267 
06268         glLoadMatrixf(rv3d->viewmat);
06269 
06270         if(zbufoff) glDisable(GL_DEPTH_TEST);
06271 
06272         if(warning_recursive) return;
06273         if(base->flag & OB_FROMDUPLI) return;
06274         if(v3d->flag2 & V3D_RENDER_OVERRIDE) return;
06275 
06276         /* object centers, need to be drawn in viewmat space for speed, but OK for picking select */
06277         if(ob!=OBACT || !(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))) {
06278                 int do_draw_center= -1; /* defines below are zero or positive... */
06279 
06280                 if(v3d->flag2 & V3D_RENDER_OVERRIDE) {
06281                         /* dont draw */
06282                 } else if((scene->basact)==base)
06283                         do_draw_center= ACTIVE;
06284                 else if(base->flag & SELECT) 
06285                         do_draw_center= SELECT;
06286                 else if(empty_object || (v3d->flag & V3D_DRAW_CENTERS)) 
06287                         do_draw_center= DESELECT;
06288 
06289                 if(do_draw_center != -1) {
06290                         if(flag & DRAW_PICKING) {
06291                                 /* draw a single point for opengl selection */
06292                                 glBegin(GL_POINTS);
06293                                 glVertex3fv(ob->obmat[3]);
06294                                 glEnd();
06295                         } 
06296                         else if((flag & DRAW_CONSTCOLOR)==0) {
06297                                 /* we don't draw centers for duplicators and sets */
06298                                 if(U.obcenter_dia > 0) {
06299                                         /* check > 0 otherwise grease pencil can draw into the circle select which is annoying. */
06300                                         drawcentercircle(v3d, rv3d, ob->obmat[3], do_draw_center, ob->id.lib || ob->id.us>1);
06301                                 }
06302                         }
06303                 }
06304         }
06305 
06306         /* not for sets, duplicators or picking */
06307         if(flag==0 && (v3d->flag & V3D_HIDE_HELPLINES)== 0 && (v3d->flag2 & V3D_RENDER_OVERRIDE)== 0) {
06308                 ListBase *list;
06309                 
06310                 /* draw hook center and offset line */
06311                 if(ob!=scene->obedit) draw_hooks(ob);
06312                 
06313                 /* help lines and so */
06314                 if(ob!=scene->obedit && ob->parent && (ob->parent->lay & v3d->lay)) {
06315                         setlinestyle(3);
06316                         glBegin(GL_LINES);
06317                         glVertex3fv(ob->obmat[3]);
06318                         glVertex3fv(ob->orig);
06319                         glEnd();
06320                         setlinestyle(0);
06321                 }
06322 
06323                 /* Drawing the constraint lines */
06324                 if (ob->constraints.first) {
06325                         bConstraint *curcon;
06326                         bConstraintOb *cob;
06327                         unsigned char col1[4], col2[4];
06328                         
06329                         list = &ob->constraints;
06330                         
06331                         UI_GetThemeColor3ubv(TH_GRID, col1);
06332                         UI_make_axis_color(col1, col2, 'Z');
06333                         glColor3ubv(col2);
06334                         
06335                         cob= constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
06336                         
06337                         for (curcon = list->first; curcon; curcon=curcon->next) {
06338                                 bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
06339                                 ListBase targets = {NULL, NULL};
06340                                 bConstraintTarget *ct;
06341                                 
06342                                 if ((curcon->flag & CONSTRAINT_EXPAND) && (cti) && (cti->get_constraint_targets)) {
06343                                         cti->get_constraint_targets(curcon, &targets);
06344                                         
06345                                         for (ct= targets.first; ct; ct= ct->next) {
06346                                                 /* calculate target's matrix */
06347                                                 if (cti->get_target_matrix) 
06348                                                         cti->get_target_matrix(curcon, cob, ct, bsystem_time(scene, ob, (float)(scene->r.cfra), give_timeoffset(ob)));
06349                                                 else
06350                                                         unit_m4(ct->matrix);
06351                                                 
06352                                                 setlinestyle(3);
06353                                                 glBegin(GL_LINES);
06354                                                 glVertex3fv(ct->matrix[3]);
06355                                                 glVertex3fv(ob->obmat[3]);
06356                                                 glEnd();
06357                                                 setlinestyle(0);
06358                                         }
06359                                         
06360                                         if (cti->flush_constraint_targets)
06361                                                 cti->flush_constraint_targets(curcon, &targets, 1);
06362                                 }
06363                         }
06364                         
06365                         constraints_clear_evalob(cob);
06366                 }
06367         }
06368 
06369         free_old_images();
06370 }
06371 
06372 /* ***************** BACKBUF SEL (BBS) ********* */
06373 
06374 static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
06375 {
06376         int offset = (intptr_t) userData;
06377         EditVert *eve = EM_get_vert_for_index(index);
06378 
06379         if (eve->h==0) {
06380                 WM_set_framebuffer_index_color(offset+index);
06381                 bglVertex3fv(co);
06382         }
06383 }
06384 static void bbs_mesh_verts(DerivedMesh *dm, int offset)
06385 {
06386         glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
06387         bglBegin(GL_POINTS);
06388         dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, (void*)(intptr_t) offset);
06389         bglEnd();
06390         glPointSize(1.0);
06391 }               
06392 
06393 static int bbs_mesh_wire__setDrawOptions(void *userData, int index)
06394 {
06395         int offset = (intptr_t) userData;
06396         EditEdge *eed = EM_get_edge_for_index(index);
06397 
06398         if (eed->h==0) {
06399                 WM_set_framebuffer_index_color(offset+index);
06400                 return 1;
06401         } else {
06402                 return 0;
06403         }
06404 }
06405 static void bbs_mesh_wire(DerivedMesh *dm, int offset)
06406 {
06407         dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, (void*)(intptr_t) offset);
06408 }               
06409 
06410 static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
06411 {
06412         if (EM_get_face_for_index(index)->h==0) {
06413                 if (userData) {
06414                         WM_set_framebuffer_index_color(index+1);
06415                 }
06416                 return 1;
06417         } else {
06418                 return 0;
06419         }
06420 }
06421 
06422 static void bbs_mesh_solid__drawCenter(void *UNUSED(userData), int index, float *cent, float *UNUSED(no))
06423 {
06424         EditFace *efa = EM_get_face_for_index(index);
06425 
06426         if (efa->h==0 && efa->fgonf!=EM_FGON) {
06427                 WM_set_framebuffer_index_color(index+1);
06428 
06429                 bglVertex3fv(cent);
06430         }
06431 }
06432 
06433 /* two options, facecolors or black */
06434 static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, int facecol)
06435 {
06436         cpack(0);
06437 
06438         if (facecol) {
06439                 dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0, GPU_enable_material);
06440 
06441                 if(check_ob_drawface_dot(scene, v3d, ob->dt)) {
06442                         glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
06443                 
06444                         bglBegin(GL_POINTS);
06445                         dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, NULL);
06446                         bglEnd();
06447                 }
06448 
06449         } else {
06450                 dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0, GPU_enable_material);
06451         }
06452 }
06453 
06454 static int bbs_mesh_solid__setDrawOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
06455 {
06456         WM_set_framebuffer_index_color(index+1);
06457         return 1;
06458 }
06459 
06460 static int bbs_mesh_solid_hide__setDrawOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
06461 {
06462         Mesh *me = userData;
06463 
06464         if (!(me->mface[index].flag&ME_HIDE)) {
06465                 WM_set_framebuffer_index_color(index+1);
06466                 return 1;
06467         } else {
06468                 return 0;
06469         }
06470 }
06471 
06472 static void bbs_mesh_solid(Scene *scene, Object *ob)
06473 {
06474         DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
06475         Mesh *me = (Mesh*)ob->data;
06476         
06477         glColor3ub(0, 0, 0);
06478                 
06479         if((me->editflag & ME_EDIT_PAINT_MASK)) dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, me, 0, GPU_enable_material);
06480         else                                                                    dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0, GPU_enable_material);
06481 
06482         dm->release(dm);
06483 }
06484 
06485 void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
06486 {
06487         ToolSettings *ts= scene->toolsettings;
06488 
06489         glMultMatrixf(ob->obmat);
06490 
06491         glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
06492         glEnable(GL_DEPTH_TEST);
06493 
06494         switch( ob->type) {
06495         case OB_MESH:
06496         {
06497                 if(ob->mode & OB_MODE_EDIT) {
06498                         Mesh *me= ob->data;
06499                         EditMesh *em= me->edit_mesh;
06500 
06501                         DerivedMesh *dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
06502 
06503                         EM_init_index_arrays(em, 1, 1, 1);
06504 
06505                         bbs_mesh_solid_EM(scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
06506                         if(ts->selectmode & SCE_SELECT_FACE)
06507                                 em_solidoffs = 1+em->totface;
06508                         else
06509                                 em_solidoffs= 1;
06510                         
06511                         bglPolygonOffset(rv3d->dist, 1.0);
06512                         
06513                         // we draw edges always, for loop (select) tools
06514                         bbs_mesh_wire(dm, em_solidoffs);
06515                         em_wireoffs= em_solidoffs + em->totedge;
06516                         
06517                         // we draw verts if vert select mode or if in transform (for snap).
06518                         if(ts->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
06519                                 bbs_mesh_verts(dm, em_wireoffs);
06520                                 em_vertoffs= em_wireoffs + em->totvert;
06521                         }
06522                         else em_vertoffs= em_wireoffs;
06523                         
06524                         bglPolygonOffset(rv3d->dist, 0.0);
06525 
06526                         dm->release(dm);
06527 
06528                         EM_free_index_arrays();
06529                 }
06530                 else bbs_mesh_solid(scene, ob);
06531         }
06532                 break;
06533         case OB_CURVE:
06534         case OB_SURF:
06535                 break;
06536         }
06537 
06538         glLoadMatrixf(rv3d->viewmat);
06539 }
06540 
06541 
06542 /* ************* draw object instances for bones, for example ****************** */
06543 /*               assumes all matrices/etc set OK */
06544 
06545 /* helper function for drawing object instances - meshes */
06546 static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, 
06547                                                                           Object *ob, int dt, int outline)
06548 {
06549         Mesh *me= ob->data;
06550         DerivedMesh *dm=NULL, *edm=NULL;
06551         int glsl;
06552         
06553         if(ob->mode & OB_MODE_EDIT)
06554                 edm= editmesh_get_derived_base(ob, me->edit_mesh);
06555         else 
06556                 dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
06557 
06558         if(dt<=OB_WIRE) {
06559                 if(dm)
06560                         dm->drawEdges(dm, 1, 0);
06561                 else if(edm)
06562                         edm->drawEdges(edm, 1, 0);      
06563         }
06564         else {
06565                 if(outline)
06566                         draw_mesh_object_outline(v3d, ob, dm?dm:edm);
06567 
06568                 if(dm) {
06569                         glsl = draw_glsl_material(scene, ob, v3d, dt);
06570                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
06571                 }
06572                 else {
06573                         glEnable(GL_COLOR_MATERIAL);
06574                         UI_ThemeColor(TH_BONE_SOLID);
06575                         glDisable(GL_COLOR_MATERIAL);
06576                 }
06577                 
06578                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
06579                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
06580                 glEnable(GL_LIGHTING);
06581                 
06582                 if(dm) {
06583                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
06584                         GPU_end_object_materials();
06585                 }
06586                 else if(edm)
06587                         edm->drawMappedFaces(edm, NULL, NULL, 0, GPU_enable_material);
06588                 
06589                 glDisable(GL_LIGHTING);
06590         }
06591 
06592         if(edm) edm->release(edm);
06593         if(dm) dm->release(dm);
06594 }
06595 
06596 void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int outline)
06597 {
06598         if (ob == NULL) 
06599                 return;
06600                 
06601         switch (ob->type) {
06602                 case OB_MESH:
06603                         draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline);
06604                         break;
06605                 case OB_EMPTY:
06606                         if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
06607                                 draw_empty_image(ob);
06608                         }
06609                         else {
06610                                 drawaxes(ob->empty_drawsize, ob->empty_drawtype);
06611                         }
06612                         break;
06613         }
06614 }