Blender V2.61 - r43446

drawobject.c

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