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