Blender V2.61 - r43446
|
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 }