|
Blender
V2.59
|
00001 /* 00002 * $Id: view3d_draw.c 38908 2011-08-02 04:28:05Z merwin $ 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) 2008 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * 00024 * Contributor(s): Blender Foundation 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include <string.h> 00035 #include <stdio.h> 00036 #include <math.h> 00037 00038 #include "DNA_armature_types.h" 00039 #include "DNA_camera_types.h" 00040 #include "DNA_customdata_types.h" 00041 #include "DNA_object_types.h" 00042 #include "DNA_group_types.h" 00043 #include "DNA_key_types.h" 00044 #include "DNA_lamp_types.h" 00045 #include "DNA_scene_types.h" 00046 #include "DNA_world_types.h" 00047 00048 #include "MEM_guardedalloc.h" 00049 00050 #include "BLI_blenlib.h" 00051 #include "BLI_math.h" 00052 #include "BLI_rand.h" 00053 #include "BLI_utildefines.h" 00054 00055 #include "BKE_anim.h" 00056 #include "BKE_context.h" 00057 #include "BKE_customdata.h" 00058 #include "BKE_image.h" 00059 #include "BKE_key.h" 00060 #include "BKE_object.h" 00061 #include "BKE_global.h" 00062 #include "BKE_paint.h" 00063 #include "BKE_scene.h" 00064 #include "BKE_screen.h" 00065 #include "BKE_unit.h" 00066 00067 #include "RE_pipeline.h" // make_stars 00068 00069 #include "IMB_imbuf_types.h" 00070 #include "IMB_imbuf.h" 00071 00072 #include "BIF_gl.h" 00073 #include "BIF_glutil.h" 00074 00075 #include "WM_api.h" 00076 #include "BLF_api.h" 00077 00078 #include "ED_armature.h" 00079 #include "ED_keyframing.h" 00080 #include "ED_gpencil.h" 00081 #include "ED_screen.h" 00082 #include "ED_space_api.h" 00083 #include "ED_screen_types.h" 00084 #include "ED_transform.h" 00085 00086 #include "UI_interface.h" 00087 #include "UI_interface_icons.h" 00088 #include "UI_resources.h" 00089 00090 #include "GPU_draw.h" 00091 #include "GPU_material.h" 00092 #include "GPU_extensions.h" 00093 00094 #include "view3d_intern.h" // own include 00095 00096 00097 00098 static void star_stuff_init_func(void) 00099 { 00100 cpack(-1); 00101 glPointSize(1.0); 00102 glBegin(GL_POINTS); 00103 } 00104 static void star_stuff_vertex_func(float* i) 00105 { 00106 glVertex3fv(i); 00107 } 00108 static void star_stuff_term_func(void) 00109 { 00110 glEnd(); 00111 } 00112 00113 void circf(float x, float y, float rad) 00114 { 00115 GLUquadricObj *qobj = gluNewQuadric(); 00116 00117 gluQuadricDrawStyle(qobj, GLU_FILL); 00118 00119 glPushMatrix(); 00120 00121 glTranslatef(x, y, 0.); 00122 00123 gluDisk( qobj, 0.0, rad, 32, 1); 00124 00125 glPopMatrix(); 00126 00127 gluDeleteQuadric(qobj); 00128 } 00129 00130 void circ(float x, float y, float rad) 00131 { 00132 GLUquadricObj *qobj = gluNewQuadric(); 00133 00134 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 00135 00136 glPushMatrix(); 00137 00138 glTranslatef(x, y, 0.); 00139 00140 gluDisk( qobj, 0.0, rad, 32, 1); 00141 00142 glPopMatrix(); 00143 00144 gluDeleteQuadric(qobj); 00145 } 00146 00147 00148 /* ********* custom clipping *********** */ 00149 00150 static void view3d_draw_clipping(RegionView3D *rv3d) 00151 { 00152 BoundBox *bb= rv3d->clipbb; 00153 00154 if(bb) { 00155 UI_ThemeColorShade(TH_BACK, -8); 00156 00157 glBegin(GL_QUADS); 00158 00159 glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[3]); 00160 glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[1]); 00161 glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[5]); 00162 glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[3]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[6]); 00163 glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[2]); 00164 glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[3]); 00165 00166 glEnd(); 00167 } 00168 } 00169 00170 void view3d_set_clipping(RegionView3D *rv3d) 00171 { 00172 double plane[4]; 00173 int a, tot=4; 00174 00175 if(rv3d->viewlock) tot= 6; 00176 00177 for(a=0; a<tot; a++) { 00178 QUATCOPY(plane, rv3d->clip[a]); 00179 glClipPlane(GL_CLIP_PLANE0+a, plane); 00180 glEnable(GL_CLIP_PLANE0+a); 00181 } 00182 } 00183 00184 void view3d_clr_clipping(void) 00185 { 00186 int a; 00187 00188 for(a=0; a<6; a++) { 00189 glDisable(GL_CLIP_PLANE0+a); 00190 } 00191 } 00192 00193 static int test_clipping(const float vec[3], float clip[][4]) 00194 { 00195 float view[3]; 00196 copy_v3_v3(view, vec); 00197 00198 if(0.0f < clip[0][3] + INPR(view, clip[0])) 00199 if(0.0f < clip[1][3] + INPR(view, clip[1])) 00200 if(0.0f < clip[2][3] + INPR(view, clip[2])) 00201 if(0.0f < clip[3][3] + INPR(view, clip[3])) 00202 return 0; 00203 00204 return 1; 00205 } 00206 00207 /* for 'local' ED_view3d_local_clipping must run first 00208 * then all comparisons can be done in localspace */ 00209 int ED_view3d_test_clipping(RegionView3D *rv3d, const float vec[3], const int local) 00210 { 00211 return test_clipping(vec, local ? rv3d->clip_local : rv3d->clip); 00212 } 00213 00214 /* ********* end custom clipping *********** */ 00215 00216 00217 static void drawgrid_draw(ARegion *ar, float wx, float wy, float x, float y, float dx) 00218 { 00219 float v1[2], v2[2]; 00220 00221 x+= (wx); 00222 y+= (wy); 00223 00224 v1[1]= 0.0f; 00225 v2[1]= (float)ar->winy; 00226 00227 v1[0] = v2[0] = x-dx*floorf(x/dx); 00228 00229 glBegin(GL_LINES); 00230 00231 while(v1[0] < ar->winx) { 00232 glVertex2fv(v1); 00233 glVertex2fv(v2); 00234 v1[0] = v2[0] = v1[0] + dx; 00235 } 00236 00237 v1[0]= 0.0f; 00238 v2[0]= (float)ar->winx; 00239 00240 v1[1]= v2[1]= y-dx*floorf(y/dx); 00241 00242 while(v1[1] < ar->winy) { 00243 glVertex2fv(v1); 00244 glVertex2fv(v2); 00245 v1[1] = v2[1] = v1[1] + dx; 00246 } 00247 00248 glEnd(); 00249 } 00250 00251 #define GRID_MIN_PX 6.0f 00252 00253 static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit) 00254 { 00255 /* extern short bgpicmode; */ 00256 RegionView3D *rv3d= ar->regiondata; 00257 float wx, wy, x, y, fw, fx, fy, dx; 00258 float vec4[4]; 00259 unsigned char col[3], col2[3]; 00260 00261 vec4[0]=vec4[1]=vec4[2]=0.0; 00262 vec4[3]= 1.0; 00263 mul_m4_v4(rv3d->persmat, vec4); 00264 fx= vec4[0]; 00265 fy= vec4[1]; 00266 fw= vec4[3]; 00267 00268 wx= (ar->winx/2.0); /* because of rounding errors, grid at wrong location */ 00269 wy= (ar->winy/2.0); 00270 00271 x= (wx)*fx/fw; 00272 y= (wy)*fy/fw; 00273 00274 vec4[0]=vec4[1]= v3d->grid; 00275 00276 vec4[2]= 0.0; 00277 vec4[3]= 1.0; 00278 mul_m4_v4(rv3d->persmat, vec4); 00279 fx= vec4[0]; 00280 fy= vec4[1]; 00281 fw= vec4[3]; 00282 00283 dx= fabs(x-(wx)*fx/fw); 00284 if(dx==0) dx= fabs(y-(wy)*fy/fw); 00285 00286 glDepthMask(0); // disable write in zbuffer 00287 00288 /* check zoom out */ 00289 UI_ThemeColor(TH_GRID); 00290 00291 if(unit->system) { 00292 /* Use GRID_MIN_PX*2 for units because very very small grid 00293 * items are less useful when dealing with units */ 00294 void *usys; 00295 int len, i; 00296 float dx_scalar; 00297 float blend_fac; 00298 00299 bUnit_GetSystem(&usys, &len, unit->system, B_UNIT_LENGTH); 00300 00301 if(usys) { 00302 i= len; 00303 while(i--) { 00304 float scalar= bUnit_GetScaler(usys, i); 00305 00306 dx_scalar = dx * scalar / unit->scale_length; 00307 if (dx_scalar < (GRID_MIN_PX*2)) 00308 continue; 00309 00310 /* Store the smallest drawn grid size units name so users know how big each grid cell is */ 00311 if(*grid_unit==NULL) { 00312 *grid_unit= bUnit_GetNameDisplay(usys, i); 00313 rv3d->gridview= (scalar * v3d->grid) / unit->scale_length; 00314 } 00315 blend_fac= 1-((GRID_MIN_PX*2)/dx_scalar); 00316 00317 /* tweak to have the fade a bit nicer */ 00318 blend_fac= (blend_fac * blend_fac) * 2.0f; 00319 CLAMP(blend_fac, 0.3f, 1.0f); 00320 00321 00322 UI_ThemeColorBlend(TH_BACK, TH_GRID, blend_fac); 00323 00324 drawgrid_draw(ar, wx, wy, x, y, dx_scalar); 00325 } 00326 } 00327 } 00328 else { 00329 short sublines = v3d->gridsubdiv; 00330 00331 if(dx<GRID_MIN_PX) { 00332 rv3d->gridview*= sublines; 00333 dx*= sublines; 00334 00335 if(dx<GRID_MIN_PX) { 00336 rv3d->gridview*= sublines; 00337 dx*= sublines; 00338 00339 if(dx<GRID_MIN_PX) { 00340 rv3d->gridview*= sublines; 00341 dx*=sublines; 00342 if(dx<GRID_MIN_PX); 00343 else { 00344 UI_ThemeColor(TH_GRID); 00345 drawgrid_draw(ar, wx, wy, x, y, dx); 00346 } 00347 } 00348 else { // start blending out 00349 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6)); 00350 drawgrid_draw(ar, wx, wy, x, y, dx); 00351 00352 UI_ThemeColor(TH_GRID); 00353 drawgrid_draw(ar, wx, wy, x, y, sublines*dx); 00354 } 00355 } 00356 else { // start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX*10)) 00357 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6)); 00358 drawgrid_draw(ar, wx, wy, x, y, dx); 00359 00360 UI_ThemeColor(TH_GRID); 00361 drawgrid_draw(ar, wx, wy, x, y, sublines*dx); 00362 } 00363 } 00364 else { 00365 if(dx>(GRID_MIN_PX*10)) { // start blending in 00366 rv3d->gridview/= sublines; 00367 dx/= sublines; 00368 if(dx>(GRID_MIN_PX*10)) { // start blending in 00369 rv3d->gridview/= sublines; 00370 dx/= sublines; 00371 if(dx>(GRID_MIN_PX*10)) { 00372 UI_ThemeColor(TH_GRID); 00373 drawgrid_draw(ar, wx, wy, x, y, dx); 00374 } 00375 else { 00376 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6)); 00377 drawgrid_draw(ar, wx, wy, x, y, dx); 00378 UI_ThemeColor(TH_GRID); 00379 drawgrid_draw(ar, wx, wy, x, y, dx*sublines); 00380 } 00381 } 00382 else { 00383 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6)); 00384 drawgrid_draw(ar, wx, wy, x, y, dx); 00385 UI_ThemeColor(TH_GRID); 00386 drawgrid_draw(ar, wx, wy, x, y, dx*sublines); 00387 } 00388 } 00389 else { 00390 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6)); 00391 drawgrid_draw(ar, wx, wy, x, y, dx); 00392 UI_ThemeColor(TH_GRID); 00393 drawgrid_draw(ar, wx, wy, x, y, dx*sublines); 00394 } 00395 } 00396 } 00397 00398 00399 x+= (wx); 00400 y+= (wy); 00401 UI_GetThemeColor3ubv(TH_GRID, col); 00402 00403 setlinestyle(0); 00404 00405 /* center cross */ 00406 /* horizontal line */ 00407 if( ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) 00408 UI_make_axis_color(col, col2, 'Y'); 00409 else UI_make_axis_color(col, col2, 'X'); 00410 glColor3ubv(col2); 00411 00412 fdrawline(0.0, y, (float)ar->winx, y); 00413 00414 /* vertical line */ 00415 if( ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) 00416 UI_make_axis_color(col, col2, 'Y'); 00417 else UI_make_axis_color(col, col2, 'Z'); 00418 glColor3ubv(col2); 00419 00420 fdrawline(x, 0.0, x, (float)ar->winy); 00421 00422 glDepthMask(1); // enable write in zbuffer 00423 } 00424 #undef GRID_MIN_PX 00425 00426 static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) 00427 { 00428 float vert[3], grid, grid_scale; 00429 int a, gridlines, emphasise; 00430 unsigned char col[3], col2[3]; 00431 short draw_line = 0; 00432 00433 vert[2]= 0.0; 00434 00435 if(v3d->gridlines<3) return; 00436 00437 grid_scale= v3d->grid; 00438 /* use 'grid_scale' instead of 'v3d->grid' from now on */ 00439 00440 /* apply units */ 00441 if(scene->unit.system) { 00442 void *usys; 00443 int len; 00444 00445 bUnit_GetSystem(&usys, &len, scene->unit.system, B_UNIT_LENGTH); 00446 00447 if(usys) { 00448 int i= bUnit_GetBaseUnit(usys); 00449 *grid_unit= bUnit_GetNameDisplay(usys, i); 00450 grid_scale = (grid_scale * (float)bUnit_GetScaler(usys, i)) / scene->unit.scale_length; 00451 } 00452 } 00453 00454 if(v3d->zbuf && scene->obedit) glDepthMask(0); // for zbuffer-select 00455 00456 gridlines= v3d->gridlines/2; 00457 grid= gridlines * grid_scale; 00458 00459 UI_GetThemeColor3ubv(TH_GRID, col); 00460 UI_GetThemeColor3ubv(TH_BACK, col2); 00461 00462 /* emphasise division lines lighter instead of darker, if background is darker than grid */ 00463 if ( ((col[0]+col[1]+col[2])/3+10) > (col2[0]+col2[1]+col2[2])/3 ) 00464 emphasise = 20; 00465 else 00466 emphasise = -10; 00467 00468 /* draw the Y axis and/or grid lines */ 00469 for(a= -gridlines;a<=gridlines;a++) { 00470 if(a==0) { 00471 /* check for the 'show Y axis' preference */ 00472 if (v3d->gridflag & V3D_SHOW_Y) { 00473 UI_make_axis_color(col, col2, 'Y'); 00474 glColor3ubv(col2); 00475 00476 draw_line = 1; 00477 } else if (v3d->gridflag & V3D_SHOW_FLOOR) { 00478 UI_ThemeColorShade(TH_GRID, emphasise); 00479 } else { 00480 draw_line = 0; 00481 } 00482 } else { 00483 /* check for the 'show grid floor' preference */ 00484 if (v3d->gridflag & V3D_SHOW_FLOOR) { 00485 if( (a % 10)==0) { 00486 UI_ThemeColorShade(TH_GRID, emphasise); 00487 } 00488 else UI_ThemeColorShade(TH_GRID, 10); 00489 00490 draw_line = 1; 00491 } else { 00492 draw_line = 0; 00493 } 00494 } 00495 00496 if (draw_line) { 00497 glBegin(GL_LINE_STRIP); 00498 vert[0]= a * grid_scale; 00499 vert[1]= grid; 00500 glVertex3fv(vert); 00501 vert[1]= -grid; 00502 glVertex3fv(vert); 00503 glEnd(); 00504 } 00505 } 00506 00507 /* draw the X axis and/or grid lines */ 00508 for(a= -gridlines;a<=gridlines;a++) { 00509 if(a==0) { 00510 /* check for the 'show X axis' preference */ 00511 if (v3d->gridflag & V3D_SHOW_X) { 00512 UI_make_axis_color(col, col2, 'X'); 00513 glColor3ubv(col2); 00514 00515 draw_line = 1; 00516 } else if (v3d->gridflag & V3D_SHOW_FLOOR) { 00517 UI_ThemeColorShade(TH_GRID, emphasise); 00518 } else { 00519 draw_line = 0; 00520 } 00521 } else { 00522 /* check for the 'show grid floor' preference */ 00523 if (v3d->gridflag & V3D_SHOW_FLOOR) { 00524 if( (a % 10)==0) { 00525 UI_ThemeColorShade(TH_GRID, emphasise); 00526 } 00527 else UI_ThemeColorShade(TH_GRID, 10); 00528 00529 draw_line = 1; 00530 } else { 00531 draw_line = 0; 00532 } 00533 } 00534 00535 if (draw_line) { 00536 glBegin(GL_LINE_STRIP); 00537 vert[1]= a * grid_scale; 00538 vert[0]= grid; 00539 glVertex3fv(vert ); 00540 vert[0]= -grid; 00541 glVertex3fv(vert); 00542 glEnd(); 00543 } 00544 } 00545 00546 /* draw the Z axis line */ 00547 /* check for the 'show Z axis' preference */ 00548 if (v3d->gridflag & V3D_SHOW_Z) { 00549 UI_make_axis_color(col, col2, 'Z'); 00550 glColor3ubv(col2); 00551 00552 glBegin(GL_LINE_STRIP); 00553 vert[0]= 0; 00554 vert[1]= 0; 00555 vert[2]= grid; 00556 glVertex3fv(vert ); 00557 vert[2]= -grid; 00558 glVertex3fv(vert); 00559 glEnd(); 00560 } 00561 00562 if(v3d->zbuf && scene->obedit) glDepthMask(1); 00563 00564 } 00565 00566 static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) 00567 { 00568 int mx, my, co[2]; 00569 int flag; 00570 00571 /* we dont want the clipping for cursor */ 00572 flag= v3d->flag; 00573 v3d->flag= 0; 00574 project_int(ar, give_cursor(scene, v3d), co); 00575 v3d->flag= flag; 00576 00577 mx = co[0]; 00578 my = co[1]; 00579 00580 if(mx!=IS_CLIPPED) { 00581 setlinestyle(0); 00582 cpack(0xFF); 00583 circ((float)mx, (float)my, 10.0); 00584 setlinestyle(4); 00585 cpack(0xFFFFFF); 00586 circ((float)mx, (float)my, 10.0); 00587 setlinestyle(0); 00588 cpack(0x0); 00589 00590 sdrawline(mx-20, my, mx-5, my); 00591 sdrawline(mx+5, my, mx+20, my); 00592 sdrawline(mx, my-20, mx, my-5); 00593 sdrawline(mx, my+5, mx, my+20); 00594 } 00595 } 00596 00597 /* Draw a live substitute of the view icon, which is always shown 00598 * colors copied from transform_manipulator.c, we should keep these matching. */ 00599 static void draw_view_axis(RegionView3D *rv3d) 00600 { 00601 const float k = U.rvisize; /* axis size */ 00602 const float toll = 0.5; /* used to see when view is quasi-orthogonal */ 00603 const float start = k + 1.0f;/* axis center in screen coordinates, x=y */ 00604 float ydisp = 0.0; /* vertical displacement to allow obj info text */ 00605 int bright = 25*(float)U.rvibright + 5; /* axis alpha (rvibright has range 0-10) */ 00606 00607 float vec[3]; 00608 float dx, dy; 00609 00610 /* thickness of lines is proportional to k */ 00611 glLineWidth(2); 00612 00613 glEnable(GL_BLEND); 00614 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00615 00616 /* X */ 00617 vec[0] = 1; 00618 vec[1] = vec[2] = 0; 00619 mul_qt_v3(rv3d->viewquat, vec); 00620 dx = vec[0] * k; 00621 dy = vec[1] * k; 00622 00623 glColor4ub(220, 0, 0, bright); 00624 glBegin(GL_LINES); 00625 glVertex2f(start, start + ydisp); 00626 glVertex2f(start + dx, start + dy + ydisp); 00627 glEnd(); 00628 00629 if (fabsf(dx) > toll || fabsf(dy) > toll) { 00630 BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "x", 1); 00631 } 00632 00633 /* BLF_draw_default disables blending */ 00634 glEnable(GL_BLEND); 00635 00636 /* Y */ 00637 vec[1] = 1; 00638 vec[0] = vec[2] = 0; 00639 mul_qt_v3(rv3d->viewquat, vec); 00640 dx = vec[0] * k; 00641 dy = vec[1] * k; 00642 00643 glColor4ub(0, 220, 0, bright); 00644 glBegin(GL_LINES); 00645 glVertex2f(start, start + ydisp); 00646 glVertex2f(start + dx, start + dy + ydisp); 00647 glEnd(); 00648 00649 if (fabsf(dx) > toll || fabsf(dy) > toll) { 00650 BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "y", 1); 00651 } 00652 00653 glEnable(GL_BLEND); 00654 00655 /* Z */ 00656 vec[2] = 1; 00657 vec[1] = vec[0] = 0; 00658 mul_qt_v3(rv3d->viewquat, vec); 00659 dx = vec[0] * k; 00660 dy = vec[1] * k; 00661 00662 glColor4ub(30, 30, 220, bright); 00663 glBegin(GL_LINES); 00664 glVertex2f(start, start + ydisp); 00665 glVertex2f(start + dx, start + dy + ydisp); 00666 glEnd(); 00667 00668 if (fabsf(dx) > toll || fabsf(dy) > toll) { 00669 BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "z", 1); 00670 } 00671 00672 /* restore line-width */ 00673 00674 glLineWidth(1.0); 00675 glDisable(GL_BLEND); 00676 } 00677 00678 /* draw center and axis of rotation for ongoing 3D mouse navigation */ 00679 static void draw_rotation_guide(RegionView3D *rv3d) 00680 { 00681 float o[3]; // center of rotation 00682 float end[3]; // endpoints for drawing 00683 00684 float color[4] = {0.f ,0.4235f, 1.f, 1.f}; // bright blue so it matches device LEDs 00685 00686 negate_v3_v3(o, rv3d->ofs); 00687 00688 glEnable(GL_BLEND); 00689 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00690 glShadeModel(GL_SMOOTH); 00691 glPointSize(5); 00692 glEnable(GL_POINT_SMOOTH); 00693 glDepthMask(0); // don't overwrite zbuf 00694 00695 if (rv3d->rot_angle != 0.f) { 00696 // -- draw rotation axis -- 00697 float scaled_axis[3]; 00698 const float scale = rv3d->dist; 00699 mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); 00700 00701 glBegin(GL_LINE_STRIP); 00702 color[3] = 0.f; // more transparent toward the ends 00703 glColor4fv(color); 00704 add_v3_v3v3(end, o, scaled_axis); 00705 glVertex3fv(end); 00706 00707 // color[3] = 0.2f + fabsf(rv3d->rot_angle); // modulate opacity with angle 00708 // ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 00709 00710 color[3] = 0.5f; // more opaque toward the center 00711 glColor4fv(color); 00712 glVertex3fv(o); 00713 00714 color[3] = 0.f; 00715 glColor4fv(color); 00716 sub_v3_v3v3(end, o, scaled_axis); 00717 glVertex3fv(end); 00718 glEnd(); 00719 00720 // -- draw ring around rotation center -- 00721 { 00722 #define ROT_AXIS_DETAIL 13 00723 const float s = 0.05f * scale; 00724 const float step = 2.f * M_PI / ROT_AXIS_DETAIL; 00725 float angle; 00726 int i; 00727 00728 float q[4]; // rotate ring so it's perpendicular to axis 00729 const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; 00730 if (!upright) 00731 { 00732 const float up[3] = {0.f, 0.f, 1.f}; 00733 float vis_angle, vis_axis[3]; 00734 00735 cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); 00736 vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); 00737 axis_angle_to_quat(q, vis_axis, vis_angle); 00738 } 00739 00740 color[3] = 0.25f; // somewhat faint 00741 glColor4fv(color); 00742 glBegin(GL_LINE_LOOP); 00743 for (i = 0, angle = 0.f; i < ROT_AXIS_DETAIL; ++i, angle += step) 00744 { 00745 float p[3] = { s * cosf(angle), s * sinf(angle), 0.f }; 00746 00747 if (!upright) 00748 mul_qt_v3(q, p); 00749 00750 add_v3_v3(p, o); 00751 glVertex3fv(p); 00752 } 00753 glEnd(); 00754 } 00755 00756 color[3] = 1.f; // solid dot 00757 } 00758 else 00759 color[3] = 0.5f; // see-through dot 00760 00761 // -- draw rotation center -- 00762 glColor4fv(color); 00763 glBegin(GL_POINTS); 00764 glVertex3fv(o); 00765 glEnd(); 00766 00767 // find screen coordinates for rotation center, then draw pretty icon 00768 // mul_m4_v3(rv3d->persinv, rot_center); 00769 // UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); 00770 // ^^ just playing around, does not work 00771 00772 glDisable(GL_BLEND); 00773 glDisable(GL_POINT_SMOOTH); 00774 glDepthMask(1); 00775 } 00776 00777 static void draw_view_icon(RegionView3D *rv3d) 00778 { 00779 BIFIconID icon; 00780 00781 if( ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) 00782 icon= ICON_AXIS_TOP; 00783 else if( ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) 00784 icon= ICON_AXIS_FRONT; 00785 else if( ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) 00786 icon= ICON_AXIS_SIDE; 00787 else return ; 00788 00789 glEnable(GL_BLEND); 00790 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00791 00792 UI_icon_draw(5.0, 5.0, icon); 00793 00794 glDisable(GL_BLEND); 00795 } 00796 00797 static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d) 00798 { 00799 const char *name = NULL; 00800 00801 switch (rv3d->view) { 00802 case RV3D_VIEW_FRONT: 00803 if (rv3d->persp == RV3D_ORTHO) name = "Front Ortho"; 00804 else name = "Front Persp"; 00805 break; 00806 case RV3D_VIEW_BACK: 00807 if (rv3d->persp == RV3D_ORTHO) name = "Back Ortho"; 00808 else name = "Back Persp"; 00809 break; 00810 case RV3D_VIEW_TOP: 00811 if (rv3d->persp == RV3D_ORTHO) name = "Top Ortho"; 00812 else name = "Top Persp"; 00813 break; 00814 case RV3D_VIEW_BOTTOM: 00815 if (rv3d->persp == RV3D_ORTHO) name = "Bottom Ortho"; 00816 else name = "Bottom Persp"; 00817 break; 00818 case RV3D_VIEW_RIGHT: 00819 if (rv3d->persp == RV3D_ORTHO) name = "Right Ortho"; 00820 else name = "Right Persp"; 00821 break; 00822 case RV3D_VIEW_LEFT: 00823 if (rv3d->persp == RV3D_ORTHO) name = "Left Ortho"; 00824 else name = "Left Persp"; 00825 break; 00826 00827 default: 00828 if (rv3d->persp==RV3D_CAMOB) { 00829 if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) { 00830 Camera *cam; 00831 cam = v3d->camera->data; 00832 name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho"; 00833 } else { 00834 name = "Object as Camera"; 00835 } 00836 } else { 00837 name = (rv3d->persp == RV3D_ORTHO) ? "User Ortho" : "User Persp"; 00838 } 00839 break; 00840 } 00841 00842 return name; 00843 } 00844 00845 static void draw_viewport_name(ARegion *ar, View3D *v3d) 00846 { 00847 RegionView3D *rv3d= ar->regiondata; 00848 const char *name= view3d_get_name(v3d, rv3d); 00849 char tmpstr[24]; 00850 00851 if (v3d->localvd) { 00852 BLI_snprintf(tmpstr, sizeof(tmpstr), "%s (Local)", name); 00853 name= tmpstr; 00854 } 00855 00856 if (name) { 00857 UI_ThemeColor(TH_TEXT_HI); 00858 BLF_draw_default_ascii(22, ar->winy-17, 0.0f, name, sizeof(tmpstr)); 00859 } 00860 } 00861 00862 /* draw info beside axes in bottom left-corner: 00863 * framenum, object name, bone name (if available), marker name (if available) 00864 */ 00865 static void draw_selected_name(Scene *scene, Object *ob) 00866 { 00867 char info[256], *markern; 00868 short offset=30; 00869 00870 /* get name of marker on current frame (if available) */ 00871 markern= scene_find_marker_name(scene, CFRA); 00872 00873 /* check if there is an object */ 00874 if(ob) { 00875 /* name(s) to display depends on type of object */ 00876 if(ob->type==OB_ARMATURE) { 00877 bArmature *arm= ob->data; 00878 char *name= NULL; 00879 00880 /* show name of active bone too (if possible) */ 00881 if(arm->edbo) { 00882 00883 if(arm->act_edbone) 00884 name= ((EditBone *)arm->act_edbone)->name; 00885 00886 } 00887 else if(ob->mode & OB_MODE_POSE) { 00888 if(arm->act_bone) { 00889 00890 if(arm->act_bone->layer & arm->layer) 00891 name= arm->act_bone->name; 00892 00893 } 00894 } 00895 if(name && markern) 00896 sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern); 00897 else if(name) 00898 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); 00899 else 00900 sprintf(info, "(%d) %s", CFRA, ob->id.name+2); 00901 } 00902 else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { 00903 Key *key= NULL; 00904 KeyBlock *kb = NULL; 00905 char shapes[75]; 00906 00907 /* try to display active shapekey too */ 00908 shapes[0] = 0; 00909 key = ob_get_key(ob); 00910 if(key){ 00911 kb = BLI_findlink(&key->block, ob->shapenr-1); 00912 if(kb){ 00913 sprintf(shapes, ": %s ", kb->name); 00914 if(ob->shapeflag == OB_SHAPE_LOCK){ 00915 strcat(shapes, " (Pinned)"); 00916 } 00917 } 00918 } 00919 00920 if(markern) 00921 sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern); 00922 else 00923 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); 00924 } 00925 else { 00926 /* standard object */ 00927 if (markern) 00928 sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern); 00929 else 00930 sprintf(info, "(%d) %s", CFRA, ob->id.name+2); 00931 } 00932 00933 /* color depends on whether there is a keyframe */ 00934 if (id_frame_has_keyframe((ID *)ob, /*BKE_curframe(scene)*/(float)(CFRA), ANIMFILTER_KEYS_LOCAL)) 00935 UI_ThemeColor(TH_VERTEX_SELECT); 00936 else 00937 UI_ThemeColor(TH_TEXT_HI); 00938 } 00939 else { 00940 /* no object */ 00941 if (markern) 00942 sprintf(info, "(%d) <%s>", CFRA, markern); 00943 else 00944 sprintf(info, "(%d)", CFRA); 00945 00946 /* color is always white */ 00947 UI_ThemeColor(TH_TEXT_HI); 00948 } 00949 00950 if (U.uiflag & USER_SHOW_ROTVIEWICON) 00951 offset = 14 + (U.rvisize * 2); 00952 00953 BLF_draw_default(offset, 10, 0.0f, info, sizeof(info)-1); 00954 } 00955 00956 void view3d_viewborder_size_get(Scene *scene, ARegion *ar, float size_r[2]) 00957 { 00958 float winmax= MAX2(ar->winx, ar->winy); 00959 float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp); 00960 00961 if(aspect > 1.0f) { 00962 size_r[0]= winmax; 00963 size_r[1]= winmax/aspect; 00964 } else { 00965 size_r[0]= winmax*aspect; 00966 size_r[1]= winmax; 00967 } 00968 } 00969 00970 void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, rctf *viewborder_r, short do_shift) 00971 { 00972 const float zoomfac= BKE_screen_view3d_zoom_to_fac((float)rv3d->camzoom); 00973 float size[2]; 00974 float dx= 0.0f, dy= 0.0f; 00975 00976 view3d_viewborder_size_get(scene, ar, size); 00977 00978 size[0]= size[0]*zoomfac; 00979 size[1]= size[1]*zoomfac; 00980 00981 /* center in window */ 00982 viewborder_r->xmin= 0.5f * ar->winx - 0.5f * size[0]; 00983 viewborder_r->ymin= 0.5f * ar->winy - 0.5f * size[1]; 00984 viewborder_r->xmax= viewborder_r->xmin + size[0]; 00985 viewborder_r->ymax= viewborder_r->ymin + size[1]; 00986 00987 dx= ar->winx*rv3d->camdx*zoomfac*2.0f; 00988 dy= ar->winy*rv3d->camdy*zoomfac*2.0f; 00989 00990 /* apply offset */ 00991 viewborder_r->xmin-= dx; 00992 viewborder_r->ymin-= dy; 00993 viewborder_r->xmax-= dx; 00994 viewborder_r->ymax-= dy; 00995 00996 if(do_shift && v3d->camera && v3d->camera->type==OB_CAMERA) { 00997 Camera *cam= v3d->camera->data; 00998 float w = viewborder_r->xmax - viewborder_r->xmin; 00999 float h = viewborder_r->ymax - viewborder_r->ymin; 01000 float side = MAX2(w, h); 01001 01002 if(do_shift == -1) side *= -1; 01003 viewborder_r->xmin+= cam->shiftx*side; 01004 viewborder_r->xmax+= cam->shiftx*side; 01005 viewborder_r->ymin+= cam->shifty*side; 01006 viewborder_r->ymax+= cam->shifty*side; 01007 } 01008 } 01009 01010 static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac) 01011 { 01012 float x3, y3, x4, y4; 01013 01014 x3= x1 + fac * (x2-x1); 01015 y3= y1 + fac * (y2-y1); 01016 x4= x1 + (1.0f - fac) * (x2-x1); 01017 y4= y1 + (1.0f - fac) * (y2-y1); 01018 01019 glBegin(GL_LINES); 01020 glVertex2f(x1, y3); 01021 glVertex2f(x2, y3); 01022 01023 glVertex2f(x1, y4); 01024 glVertex2f(x2, y4); 01025 01026 glVertex2f(x3, y1); 01027 glVertex2f(x3, y2); 01028 01029 glVertex2f(x4, y1); 01030 glVertex2f(x4, y2); 01031 glEnd(); 01032 } 01033 01034 /* harmonious triangle */ 01035 static void drawviewborder_triangle(float x1, float x2, float y1, float y2, const char golden, const char dir) 01036 { 01037 float ofs; 01038 float w= x2 - x1; 01039 float h= y2 - y1; 01040 01041 glBegin(GL_LINES); 01042 if(w > h) { 01043 if(golden) { 01044 ofs = w * (1.0f-(1.0f/1.61803399)); 01045 } 01046 else { 01047 ofs = h * (h / w); 01048 } 01049 if(dir == 'B') SWAP(float, y1, y2); 01050 01051 glVertex2f(x1, y1); 01052 glVertex2f(x2, y2); 01053 01054 glVertex2f(x2, y1); 01055 glVertex2f(x1 + (w - ofs), y2); 01056 01057 glVertex2f(x1, y2); 01058 glVertex2f(x1 + ofs, y1); 01059 } 01060 else { 01061 if(golden) { 01062 ofs = h * (1.0f-(1.0f/1.61803399)); 01063 } 01064 else { 01065 ofs = w * (w / h); 01066 } 01067 if(dir == 'B') SWAP(float, x1, x2); 01068 01069 glVertex2f(x1, y1); 01070 glVertex2f(x2, y2); 01071 01072 glVertex2f(x2, y1); 01073 glVertex2f(x1, y1 + ofs); 01074 01075 glVertex2f(x1, y2); 01076 glVertex2f(x2, y1 + (h - ofs)); 01077 } 01078 glEnd(); 01079 } 01080 01081 static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) 01082 { 01083 float fac, a; 01084 float x1, x2, y1, y2; 01085 float x1i, x2i, y1i, y2i; 01086 float x3, y3, x4, y4; 01087 rctf viewborder; 01088 Camera *ca= NULL; 01089 RegionView3D *rv3d= (RegionView3D *)ar->regiondata; 01090 01091 if(v3d->camera==NULL) 01092 return; 01093 if(v3d->camera->type==OB_CAMERA) 01094 ca = v3d->camera->data; 01095 01096 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE); 01097 /* the offsets */ 01098 x1= viewborder.xmin; 01099 y1= viewborder.ymin; 01100 x2= viewborder.xmax; 01101 y2= viewborder.ymax; 01102 01103 /* apply offsets so the real 3D camera shows through */ 01104 01105 /* note: quite un-scientific but without this bit extra 01106 * 0.0001 on the lower left the 2D border sometimes 01107 * obscures the 3D camera border */ 01108 /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticable 01109 * but keep it here incase we need to remove the workaround */ 01110 x1i= (int)(x1 - 1.0001f); 01111 y1i= (int)(y1 - 1.0001f); 01112 x2i= (int)(x2 + (1.0f-0.0001f)); 01113 y2i= (int)(y2 + (1.0f-0.0001f)); 01114 01115 /* passepartout, specified in camera edit buttons */ 01116 if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { 01117 if (ca->passepartalpha == 1.0f) { 01118 glColor3f(0, 0, 0); 01119 } else { 01120 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 01121 glEnable(GL_BLEND); 01122 glColor4f(0, 0, 0, ca->passepartalpha); 01123 } 01124 if (x1i > 0.0f) 01125 glRectf(0.0, (float)ar->winy, x1i, 0.0); 01126 if (x2i < (float)ar->winx) 01127 glRectf(x2i, (float)ar->winy, (float)ar->winx, 0.0); 01128 if (y2i < (float)ar->winy) 01129 glRectf(x1i, (float)ar->winy, x2i, y2i); 01130 if (y2i > 0.0f) 01131 glRectf(x1i, y1i, x2i, 0.0); 01132 01133 glDisable(GL_BLEND); 01134 } 01135 01136 /* edge */ 01137 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 01138 01139 setlinestyle(0); 01140 UI_ThemeColor(TH_BACK); 01141 glRectf(x1i, y1i, x2i, y2i); 01142 01143 #ifdef VIEW3D_CAMERA_BORDER_HACK 01144 { 01145 if(view3d_camera_border_hack_test == TRUE) { 01146 glColor4fv(view3d_camera_border_hack_col); 01147 glRectf(x1i+1, y1i+1, x2i-1, y2i-1); 01148 view3d_camera_border_hack_test= FALSE; 01149 } 01150 } 01151 #endif 01152 01153 setlinestyle(3); 01154 UI_ThemeColor(TH_WIRE); 01155 glRectf(x1i, y1i, x2i, y2i); 01156 01157 /* border */ 01158 if(scene->r.mode & R_BORDER) { 01159 01160 cpack(0); 01161 x3= x1+ scene->r.border.xmin*(x2-x1); 01162 y3= y1+ scene->r.border.ymin*(y2-y1); 01163 x4= x1+ scene->r.border.xmax*(x2-x1); 01164 y4= y1+ scene->r.border.ymax*(y2-y1); 01165 01166 cpack(0x4040FF); 01167 glRectf(x3, y3, x4, y4); 01168 } 01169 01170 /* safety border */ 01171 if(ca) { 01172 if (ca->dtx & CAM_DTX_CENTER) { 01173 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01174 01175 x3= x1+ 0.5f*(x2-x1); 01176 y3= y1+ 0.5f*(y2-y1); 01177 01178 glBegin(GL_LINES); 01179 glVertex2f(x1, y3); 01180 glVertex2f(x2, y3); 01181 01182 glVertex2f(x3, y1); 01183 glVertex2f(x3, y2); 01184 glEnd(); 01185 } 01186 01187 if (ca->dtx & CAM_DTX_CENTER_DIAG) { 01188 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01189 01190 glBegin(GL_LINES); 01191 glVertex2f(x1, y1); 01192 glVertex2f(x2, y2); 01193 01194 glVertex2f(x1, y2); 01195 glVertex2f(x2, y1); 01196 glEnd(); 01197 } 01198 01199 if (ca->dtx & CAM_DTX_THIRDS) { 01200 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01201 drawviewborder_grid3(x1, x2, y1, y2, 1.0f/3.0f); 01202 } 01203 01204 if (ca->dtx & CAM_DTX_GOLDEN) { 01205 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01206 drawviewborder_grid3(x1, x2, y1, y2, 1.0f-(1.0f/1.61803399)); 01207 } 01208 01209 if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) { 01210 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01211 drawviewborder_triangle(x1, x2, y1, y2, 0, 'A'); 01212 } 01213 01214 if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) { 01215 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01216 drawviewborder_triangle(x1, x2, y1, y2, 0, 'B'); 01217 } 01218 01219 if (ca->dtx & CAM_DTX_HARMONY_TRI_A) { 01220 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01221 drawviewborder_triangle(x1, x2, y1, y2, 1, 'A'); 01222 } 01223 01224 if (ca->dtx & CAM_DTX_HARMONY_TRI_B) { 01225 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01226 drawviewborder_triangle(x1, x2, y1, y2, 1, 'B'); 01227 } 01228 01229 if (ca->flag & CAM_SHOWTITLESAFE) { 01230 fac= 0.1; 01231 01232 a= fac*(x2-x1); 01233 x1+= a; 01234 x2-= a; 01235 01236 a= fac*(y2-y1); 01237 y1+= a; 01238 y2-= a; 01239 01240 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); 01241 01242 uiSetRoundBox(15); 01243 uiDrawBox(GL_LINE_LOOP, x1, y1, x2, y2, 12.0); 01244 } 01245 } 01246 01247 setlinestyle(0); 01248 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 01249 01250 /* camera name - draw in highlighted text color */ 01251 if (ca && (ca->flag & CAM_SHOWNAME)) { 01252 UI_ThemeColor(TH_TEXT_HI); 01253 BLF_draw_default(x1i, y1i-15, 0.0f, v3d->camera->id.name+2, sizeof(v3d->camera->id.name)-2); 01254 UI_ThemeColor(TH_WIRE); 01255 } 01256 } 01257 01258 /* *********************** backdraw for selection *************** */ 01259 01260 static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) 01261 { 01262 RegionView3D *rv3d= ar->regiondata; 01263 struct Base *base = scene->basact; 01264 rcti winrct; 01265 01266 BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); 01267 01268 if(base && (base->object->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT) || 01269 paint_facesel_test(base->object))); 01270 else if((base && (base->object->mode & OB_MODE_TEXTURE_PAINT)) && 01271 scene->toolsettings && (scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)); 01272 else if((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)); 01273 else if(scene->obedit && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)); 01274 else { 01275 v3d->flag &= ~V3D_INVALID_BACKBUF; 01276 return; 01277 } 01278 01279 if( !(v3d->flag & V3D_INVALID_BACKBUF) ) return; 01280 01281 // if(test) { 01282 // if(qtest()) { 01283 // addafterqueue(ar->win, BACKBUFDRAW, 1); 01284 // return; 01285 // } 01286 // } 01287 01288 if(v3d->drawtype > OB_WIRE) v3d->zbuf= TRUE; 01289 01290 glDisable(GL_DITHER); 01291 01292 region_scissor_winrct(ar, &winrct); 01293 glScissor(winrct.xmin, winrct.ymin, winrct.xmax - winrct.xmin, winrct.ymax - winrct.ymin); 01294 01295 glClearColor(0.0, 0.0, 0.0, 0.0); 01296 if(v3d->zbuf) { 01297 glEnable(GL_DEPTH_TEST); 01298 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 01299 } 01300 else { 01301 glClear(GL_COLOR_BUFFER_BIT); 01302 glDisable(GL_DEPTH_TEST); 01303 } 01304 01305 if(rv3d->rflag & RV3D_CLIPPING) 01306 view3d_set_clipping(rv3d); 01307 01308 G.f |= G_BACKBUFSEL; 01309 01310 if(base && (base->lay & v3d->lay)) { 01311 draw_object_backbufsel(scene, v3d, rv3d, base->object); 01312 } 01313 01314 v3d->flag &= ~V3D_INVALID_BACKBUF; 01315 ar->swap= 0; /* mark invalid backbuf for wm draw */ 01316 01317 G.f &= ~G_BACKBUFSEL; 01318 v3d->zbuf= FALSE; 01319 glDisable(GL_DEPTH_TEST); 01320 glEnable(GL_DITHER); 01321 01322 if(rv3d->rflag & RV3D_CLIPPING) 01323 view3d_clr_clipping(); 01324 01325 /* it is important to end a view in a transform compatible with buttons */ 01326 // persp(PERSP_WIN); // set ortho 01327 01328 } 01329 01330 void view3d_validate_backbuf(ViewContext *vc) 01331 { 01332 if(vc->v3d->flag & V3D_INVALID_BACKBUF) 01333 backdrawview3d(vc->scene, vc->ar, vc->v3d); 01334 } 01335 01336 /* samples a single pixel (copied from vpaint) */ 01337 unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) 01338 { 01339 unsigned int col; 01340 01341 if(x >= vc->ar->winx || y >= vc->ar->winy) return 0; 01342 x+= vc->ar->winrct.xmin; 01343 y+= vc->ar->winrct.ymin; 01344 01345 view3d_validate_backbuf(vc); 01346 01347 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); 01348 glReadBuffer(GL_BACK); 01349 01350 if(ENDIAN_ORDER==B_ENDIAN) SWITCH_INT(col); 01351 01352 return WM_framebuffer_to_index(col); 01353 } 01354 01355 /* reads full rect, converts indices */ 01356 ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) 01357 { 01358 unsigned int *dr, *rd; 01359 struct ImBuf *ibuf, *ibuf1; 01360 int a; 01361 short xminc, yminc, xmaxc, ymaxc, xs, ys; 01362 01363 /* clip */ 01364 if(xmin<0) xminc= 0; else xminc= xmin; 01365 if(xmax >= vc->ar->winx) xmaxc= vc->ar->winx-1; else xmaxc= xmax; 01366 if(xminc > xmaxc) return NULL; 01367 01368 if(ymin<0) yminc= 0; else yminc= ymin; 01369 if(ymax >= vc->ar->winy) ymaxc= vc->ar->winy-1; else ymaxc= ymax; 01370 if(yminc > ymaxc) return NULL; 01371 01372 ibuf= IMB_allocImBuf((xmaxc-xminc+1), (ymaxc-yminc+1), 32, IB_rect); 01373 01374 view3d_validate_backbuf(vc); 01375 01376 glReadPixels(vc->ar->winrct.xmin+xminc, vc->ar->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); 01377 glReadBuffer(GL_BACK); 01378 01379 if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); 01380 01381 a= (xmaxc-xminc+1)*(ymaxc-yminc+1); 01382 dr= ibuf->rect; 01383 while(a--) { 01384 if(*dr) *dr= WM_framebuffer_to_index(*dr); 01385 dr++; 01386 } 01387 01388 /* put clipped result back, if needed */ 01389 if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) 01390 return ibuf; 01391 01392 ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect); 01393 rd= ibuf->rect; 01394 dr= ibuf1->rect; 01395 01396 for(ys= ymin; ys<=ymax; ys++) { 01397 for(xs= xmin; xs<=xmax; xs++, dr++) { 01398 if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) { 01399 *dr= *rd; 01400 rd++; 01401 } 01402 } 01403 } 01404 IMB_freeImBuf(ibuf); 01405 return ibuf1; 01406 } 01407 01408 /* smart function to sample a rect spiralling outside, nice for backbuf selection */ 01409 unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size, 01410 unsigned int min, unsigned int max, int *dist, short strict, 01411 void *handle, unsigned int (*indextest)(void *handle, unsigned int index)) 01412 { 01413 struct ImBuf *buf; 01414 unsigned int *bufmin, *bufmax, *tbuf; 01415 int minx, miny; 01416 int a, b, rc, nr, amount, dirvec[4][2]; 01417 int distance=0; 01418 unsigned int index = 0; 01419 short indexok = 0; 01420 01421 amount= (size-1)/2; 01422 01423 minx = mval[0]-(amount+1); 01424 miny = mval[1]-(amount+1); 01425 buf = view3d_read_backbuf(vc, minx, miny, minx+size-1, miny+size-1); 01426 if (!buf) return 0; 01427 01428 rc= 0; 01429 01430 dirvec[0][0]= 1; dirvec[0][1]= 0; 01431 dirvec[1][0]= 0; dirvec[1][1]= -size; 01432 dirvec[2][0]= -1; dirvec[2][1]= 0; 01433 dirvec[3][0]= 0; dirvec[3][1]= size; 01434 01435 bufmin = buf->rect; 01436 tbuf = buf->rect; 01437 bufmax = buf->rect + size*size; 01438 tbuf+= amount*size+ amount; 01439 01440 for(nr=1; nr<=size; nr++) { 01441 01442 for(a=0; a<2; a++) { 01443 for(b=0; b<nr; b++, distance++) { 01444 if (*tbuf && *tbuf>=min && *tbuf<max) { //we got a hit 01445 if(strict){ 01446 indexok = indextest(handle, *tbuf - min+1); 01447 if(indexok){ 01448 *dist= (short) sqrt( (float)distance ); 01449 index = *tbuf - min+1; 01450 goto exit; 01451 } 01452 } 01453 else{ 01454 *dist= (short) sqrt( (float)distance ); // XXX, this distance is wrong - 01455 index = *tbuf - min+1; // messy yah, but indices start at 1 01456 goto exit; 01457 } 01458 } 01459 01460 tbuf+= (dirvec[rc][0]+dirvec[rc][1]); 01461 01462 if(tbuf<bufmin || tbuf>=bufmax) { 01463 goto exit; 01464 } 01465 } 01466 rc++; 01467 rc &= 3; 01468 } 01469 } 01470 01471 exit: 01472 IMB_freeImBuf(buf); 01473 return index; 01474 } 01475 01476 01477 /* ************************************************************* */ 01478 01479 static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d) 01480 { 01481 RegionView3D *rv3d= ar->regiondata; 01482 BGpic *bgpic; 01483 Image *ima; 01484 ImBuf *ibuf= NULL; 01485 float vec[4], fac, asp, zoomx, zoomy; 01486 float x1, y1, x2, y2, cx, cy; 01487 01488 01489 for ( bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next ) { 01490 01491 if( (bgpic->view == 0) || /* zero for any */ 01492 (bgpic->view & (1<<rv3d->view)) || /* check agaist flags */ 01493 (rv3d->persp==RV3D_CAMOB && bgpic->view == (1<<RV3D_VIEW_CAMERA)) 01494 ) { 01495 ima= bgpic->ima; 01496 if(ima==NULL) 01497 continue; 01498 BKE_image_user_calc_frame(&bgpic->iuser, CFRA, 0); 01499 ibuf= BKE_image_get_ibuf(ima, &bgpic->iuser); 01500 if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL) ) 01501 continue; 01502 if(ibuf->channels!=4) 01503 continue; 01504 if(ibuf->rect==NULL) 01505 IMB_rect_from_float(ibuf); 01506 01507 if(rv3d->persp==RV3D_CAMOB) { 01508 rctf vb; 01509 01510 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE); 01511 01512 x1= vb.xmin; 01513 y1= vb.ymin; 01514 x2= vb.xmax; 01515 y2= vb.ymax; 01516 } 01517 else { 01518 float sco[2]; 01519 const float mval_f[2]= {1.0f, 0.0f}; 01520 01521 /* calc window coord */ 01522 initgrabz(rv3d, 0.0, 0.0, 0.0); 01523 ED_view3d_win_to_delta(ar, mval_f, vec); 01524 fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) ); 01525 fac= 1.0f/fac; 01526 01527 asp= ( (float)ibuf->y)/(float)ibuf->x; 01528 01529 vec[0] = vec[1] = vec[2] = 0.0; 01530 ED_view3d_project_float(ar, vec, sco, rv3d->persmat); 01531 cx = sco[0]; 01532 cy = sco[1]; 01533 01534 x1= cx+ fac*(bgpic->xof-bgpic->size); 01535 y1= cy+ asp*fac*(bgpic->yof-bgpic->size); 01536 x2= cx+ fac*(bgpic->xof+bgpic->size); 01537 y2= cy+ asp*fac*(bgpic->yof+bgpic->size); 01538 } 01539 01540 /* complete clip? */ 01541 01542 if(x2 < 0 ) continue; 01543 if(y2 < 0 ) continue; 01544 if(x1 > ar->winx ) continue; 01545 if(y1 > ar->winy ) continue; 01546 01547 zoomx= (x2-x1)/ibuf->x; 01548 zoomy= (y2-y1)/ibuf->y; 01549 01550 /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */ 01551 if(zoomx < 1.0f || zoomy < 1.0f) { 01552 float tzoom= MIN2(zoomx, zoomy); 01553 int mip= 0; 01554 01555 if((ibuf->userflags&IB_MIPMAP_INVALID) != 0) { 01556 IMB_remakemipmap(ibuf, 0); 01557 ibuf->userflags&= ~IB_MIPMAP_INVALID; 01558 } 01559 else if(ibuf->mipmap[0]==NULL) 01560 IMB_makemipmap(ibuf, 0); 01561 01562 while(tzoom < 1.0f && mip<8 && ibuf->mipmap[mip]) { 01563 tzoom*= 2.0f; 01564 zoomx*= 2.0f; 01565 zoomy*= 2.0f; 01566 mip++; 01567 } 01568 if(mip>0) 01569 ibuf= ibuf->mipmap[mip-1]; 01570 } 01571 01572 if(v3d->zbuf) glDisable(GL_DEPTH_TEST); 01573 glDepthMask(0); 01574 01575 glEnable(GL_BLEND); 01576 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 01577 01578 glMatrixMode(GL_PROJECTION); 01579 glPushMatrix(); 01580 glMatrixMode(GL_MODELVIEW); 01581 glPushMatrix(); 01582 ED_region_pixelspace(ar); 01583 01584 glPixelZoom(zoomx, zoomy); 01585 glColor4f(1.0f, 1.0f, 1.0f, 1.0f-bgpic->blend); 01586 glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); 01587 01588 glPixelZoom(1.0, 1.0); 01589 glPixelTransferf(GL_ALPHA_SCALE, 1.0f); 01590 01591 glMatrixMode(GL_PROJECTION); 01592 glPopMatrix(); 01593 glMatrixMode(GL_MODELVIEW); 01594 glPopMatrix(); 01595 01596 glDisable(GL_BLEND); 01597 01598 glDepthMask(1); 01599 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 01600 } 01601 } 01602 } 01603 01604 /* ****************** View3d afterdraw *************** */ 01605 01606 typedef struct View3DAfter { 01607 struct View3DAfter *next, *prev; 01608 struct Base *base; 01609 int flag; 01610 } View3DAfter; 01611 01612 /* temp storage of Objects that need to be drawn as last */ 01613 void add_view3d_after(ListBase *lb, Base *base, int flag) 01614 { 01615 View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after"); 01616 BLI_addtail(lb, v3da); 01617 v3da->base= base; 01618 v3da->flag= flag; 01619 } 01620 01621 /* disables write in zbuffer and draws it over */ 01622 static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d) 01623 { 01624 View3DAfter *v3da, *next; 01625 01626 glDepthMask(0); 01627 v3d->transp= TRUE; 01628 01629 for(v3da= v3d->afterdraw_transp.first; v3da; v3da= next) { 01630 next= v3da->next; 01631 draw_object(scene, ar, v3d, v3da->base, v3da->flag); 01632 BLI_remlink(&v3d->afterdraw_transp, v3da); 01633 MEM_freeN(v3da); 01634 } 01635 v3d->transp= FALSE; 01636 01637 glDepthMask(1); 01638 01639 } 01640 01641 /* clears zbuffer and draws it over */ 01642 static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, int clear) 01643 { 01644 View3DAfter *v3da, *next; 01645 01646 if(clear && v3d->zbuf) 01647 glClear(GL_DEPTH_BUFFER_BIT); 01648 01649 v3d->xray= TRUE; 01650 for(v3da= v3d->afterdraw_xray.first; v3da; v3da= next) { 01651 next= v3da->next; 01652 draw_object(scene, ar, v3d, v3da->base, v3da->flag); 01653 BLI_remlink(&v3d->afterdraw_xray, v3da); 01654 MEM_freeN(v3da); 01655 } 01656 v3d->xray= FALSE; 01657 } 01658 01659 01660 /* clears zbuffer and draws it over */ 01661 static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, int clear) 01662 { 01663 View3DAfter *v3da, *next; 01664 01665 if(clear && v3d->zbuf) 01666 glClear(GL_DEPTH_BUFFER_BIT); 01667 01668 v3d->xray= TRUE; 01669 v3d->transp= TRUE; 01670 01671 for(v3da= v3d->afterdraw_xraytransp.first; v3da; v3da= next) { 01672 next= v3da->next; 01673 draw_object(scene, ar, v3d, v3da->base, v3da->flag); 01674 BLI_remlink(&v3d->afterdraw_xraytransp, v3da); 01675 MEM_freeN(v3da); 01676 } 01677 01678 v3d->transp= FALSE; 01679 v3d->xray= FALSE; 01680 01681 } 01682 01683 /* *********************** */ 01684 01685 /* 01686 In most cases call draw_dupli_objects, 01687 draw_dupli_objects_color was added because when drawing set dupli's 01688 we need to force the color 01689 */ 01690 01691 #if 0 01692 int dupli_ob_sort(void *arg1, void *arg2) 01693 { 01694 void *p1= ((DupliObject *)arg1)->ob; 01695 void *p2= ((DupliObject *)arg2)->ob; 01696 int val = 0; 01697 if (p1 < p2) val = -1; 01698 else if (p1 > p2) val = 1; 01699 return val; 01700 } 01701 #endif 01702 01703 01704 static DupliObject *dupli_step(DupliObject *dob) 01705 { 01706 while(dob && dob->no_draw) 01707 dob= dob->next; 01708 return dob; 01709 } 01710 01711 static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int color) 01712 { 01713 RegionView3D *rv3d= ar->regiondata; 01714 ListBase *lb; 01715 DupliObject *dob_prev= NULL, *dob, *dob_next= NULL; 01716 Base tbase; 01717 BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */ 01718 GLuint displist=0; 01719 short transflag, use_displist= -1; /* -1 is initialize */ 01720 char dt, dtx; 01721 01722 if (base->object->restrictflag & OB_RESTRICT_VIEW) return; 01723 01724 tbase.flag= OB_FROMDUPLI|base->flag; 01725 lb= object_duplilist(scene, base->object); 01726 // BLI_sortlist(lb, dupli_ob_sort); // might be nice to have if we have a dupli list with mixed objects. 01727 01728 dob=dupli_step(lb->first); 01729 if(dob) dob_next= dupli_step(dob->next); 01730 01731 for( ; dob ; dob_prev= dob, dob= dob_next, dob_next= dob_next ? dupli_step(dob_next->next) : NULL) { 01732 tbase.object= dob->ob; 01733 01734 /* extra service: draw the duplicator in drawtype of parent */ 01735 /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ 01736 dt= tbase.object->dt; tbase.object->dt= MIN2(tbase.object->dt, base->object->dt); 01737 dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx; 01738 01739 /* negative scale flag has to propagate */ 01740 transflag= tbase.object->transflag; 01741 if(base->object->transflag & OB_NEG_SCALE) 01742 tbase.object->transflag ^= OB_NEG_SCALE; 01743 01744 UI_ThemeColorBlend(color, TH_BACK, 0.5); 01745 01746 /* generate displist, test for new object */ 01747 if(dob_prev && dob_prev->ob != dob->ob) { 01748 if(use_displist==1) 01749 glDeleteLists(displist, 1); 01750 01751 use_displist= -1; 01752 } 01753 01754 /* generate displist */ 01755 if(use_displist == -1) { 01756 01757 /* note, since this was added, its checked dob->type==OB_DUPLIGROUP 01758 * however this is very slow, it was probably needed for the NLA 01759 * offset feature (used in group-duplicate.blend but no longer works in 2.5) 01760 * so for now it should be ok to - campbell */ 01761 01762 if( (dob_next==NULL || dob_next->ob != dob->ob) || /* if this is the last no need to make a displist */ 01763 (dob->ob->type == OB_LAMP) || /* lamp drawing messes with matrices, could be handled smarter... but this works */ 01764 (dob->type == OB_DUPLIGROUP && dob->animated) || 01765 !(bb_tmp= object_get_boundbox(dob->ob)) 01766 ) { 01767 // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name+2); 01768 use_displist= 0; 01769 } 01770 else { 01771 // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name+2); 01772 bb= *bb_tmp; /* must make a copy */ 01773 01774 /* disable boundbox check for list creation */ 01775 object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1); 01776 /* need this for next part of code */ 01777 unit_m4(dob->ob->obmat); /* obmat gets restored */ 01778 01779 displist= glGenLists(1); 01780 glNewList(displist, GL_COMPILE); 01781 draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR); 01782 glEndList(); 01783 01784 use_displist= 1; 01785 object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0); 01786 } 01787 } 01788 if(use_displist) { 01789 glMultMatrixf(dob->mat); 01790 if(ED_view3d_boundbox_clip(rv3d, dob->mat, &bb)) 01791 glCallList(displist); 01792 glLoadMatrixf(rv3d->viewmat); 01793 } 01794 else { 01795 copy_m4_m4(dob->ob->obmat, dob->mat); 01796 draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR); 01797 } 01798 01799 tbase.object->dt= dt; 01800 tbase.object->dtx= dtx; 01801 tbase.object->transflag= transflag; 01802 } 01803 01804 /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */ 01805 01806 free_object_duplilist(lb); /* does restore */ 01807 01808 if(use_displist) 01809 glDeleteLists(displist, 1); 01810 } 01811 01812 static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base) 01813 { 01814 /* define the color here so draw_dupli_objects_color can be called 01815 * from the set loop */ 01816 01817 int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE; 01818 /* debug */ 01819 if(base->object->dup_group && base->object->dup_group->id.us<1) 01820 color= TH_REDALERT; 01821 01822 draw_dupli_objects_color(scene, ar, v3d, base, color); 01823 } 01824 01825 void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) 01826 { 01827 int x, y, w, h; 01828 rcti r; 01829 /* clamp rect by area */ 01830 01831 r.xmin= 0; 01832 r.xmax= ar->winx-1; 01833 r.ymin= 0; 01834 r.ymax= ar->winy-1; 01835 01836 /* Constrain rect to depth bounds */ 01837 BLI_isect_rcti(&r, rect, rect); 01838 01839 /* assign values to compare with the ViewDepths */ 01840 x= rect->xmin; 01841 y= rect->ymin; 01842 01843 w= rect->xmax - rect->xmin; 01844 h= rect->ymax - rect->ymin; 01845 01846 if(w <= 0 || h <= 0) { 01847 if(d->depths) 01848 MEM_freeN(d->depths); 01849 d->depths= NULL; 01850 01851 d->damaged= FALSE; 01852 } 01853 else if( d->w != w || 01854 d->h != h || 01855 d->x != x || 01856 d->y != y || 01857 d->depths==NULL 01858 ) { 01859 d->x= x; 01860 d->y= y; 01861 d->w= w; 01862 d->h= h; 01863 01864 if(d->depths) 01865 MEM_freeN(d->depths); 01866 01867 d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths Subset"); 01868 01869 d->damaged= TRUE; 01870 } 01871 01872 if(d->damaged) { 01873 glReadPixels(ar->winrct.xmin+d->x,ar->winrct.ymin+d->y, d->w,d->h, GL_DEPTH_COMPONENT,GL_FLOAT, d->depths); 01874 glGetDoublev(GL_DEPTH_RANGE,d->depth_range); 01875 d->damaged= FALSE; 01876 } 01877 } 01878 01879 /* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ 01880 void ED_view3d_depth_update(ARegion *ar) 01881 { 01882 RegionView3D *rv3d= ar->regiondata; 01883 01884 /* Create storage for, and, if necessary, copy depth buffer */ 01885 if(!rv3d->depths) rv3d->depths= MEM_callocN(sizeof(ViewDepths),"ViewDepths"); 01886 if(rv3d->depths) { 01887 ViewDepths *d= rv3d->depths; 01888 if(d->w != ar->winx || 01889 d->h != ar->winy || 01890 !d->depths) { 01891 d->w= ar->winx; 01892 d->h= ar->winy; 01893 if(d->depths) 01894 MEM_freeN(d->depths); 01895 d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths"); 01896 d->damaged= 1; 01897 } 01898 01899 if(d->damaged) { 01900 glReadPixels(ar->winrct.xmin,ar->winrct.ymin,d->w,d->h, 01901 GL_DEPTH_COMPONENT,GL_FLOAT, d->depths); 01902 01903 glGetDoublev(GL_DEPTH_RANGE,d->depth_range); 01904 01905 d->damaged= 0; 01906 } 01907 } 01908 } 01909 01910 /* utility function to find the closest Z value, use for autodepth */ 01911 float view3d_depth_near(ViewDepths *d) 01912 { 01913 /* convert to float for comparisons */ 01914 const float near= (float)d->depth_range[0]; 01915 const float far_real= (float)d->depth_range[1]; 01916 float far= far_real; 01917 01918 const float *depths= d->depths; 01919 float depth= FLT_MAX; 01920 int i= (int)d->w * (int)d->h; /* cast to avoid short overflow */ 01921 01922 /* far is both the starting 'far' value 01923 * and the closest value found. */ 01924 while(i--) { 01925 depth= *depths++; 01926 if((depth < far) && (depth > near)) { 01927 far= depth; 01928 } 01929 } 01930 01931 return far == far_real ? FLT_MAX : far; 01932 } 01933 01934 void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) 01935 { 01936 short zbuf= v3d->zbuf; 01937 RegionView3D *rv3d= ar->regiondata; 01938 01939 setwinmatrixview3d(ar, v3d, NULL); /* 0= no pick rect */ 01940 setviewmatrixview3d(scene, v3d, rv3d); /* note: calls where_is_object for camera... */ 01941 01942 mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat); 01943 invert_m4_m4(rv3d->persinv, rv3d->persmat); 01944 invert_m4_m4(rv3d->viewinv, rv3d->viewmat); 01945 01946 glClear(GL_DEPTH_BUFFER_BIT); 01947 01948 glLoadMatrixf(rv3d->viewmat); 01949 01950 v3d->zbuf= TRUE; 01951 glEnable(GL_DEPTH_TEST); 01952 01953 draw_gpencil_view3d_ext(scene, v3d, ar, 1); 01954 01955 v3d->zbuf= zbuf; 01956 01957 } 01958 01959 void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *)) 01960 { 01961 RegionView3D *rv3d= ar->regiondata; 01962 Base *base; 01963 short zbuf= v3d->zbuf; 01964 short flag= v3d->flag; 01965 float glalphaclip= U.glalphaclip; 01966 int obcenter_dia= U.obcenter_dia; 01967 /* temp set drawtype to solid */ 01968 01969 /* Setting these temporarily is not nice */ 01970 v3d->flag &= ~V3D_SELECT_OUTLINE; 01971 U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */ 01972 U.obcenter_dia= 0; 01973 01974 setwinmatrixview3d(ar, v3d, NULL); /* 0= no pick rect */ 01975 setviewmatrixview3d(scene, v3d, rv3d); /* note: calls where_is_object for camera... */ 01976 01977 mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat); 01978 invert_m4_m4(rv3d->persinv, rv3d->persmat); 01979 invert_m4_m4(rv3d->viewinv, rv3d->viewmat); 01980 01981 glClear(GL_DEPTH_BUFFER_BIT); 01982 01983 glLoadMatrixf(rv3d->viewmat); 01984 // persp(PERSP_STORE); // store correct view for persp(PERSP_VIEW) calls 01985 01986 if(rv3d->rflag & RV3D_CLIPPING) { 01987 view3d_set_clipping(rv3d); 01988 } 01989 01990 v3d->zbuf= TRUE; 01991 glEnable(GL_DEPTH_TEST); 01992 01993 /* draw set first */ 01994 if(scene->set) { 01995 Scene *sce_iter; 01996 for(SETLOOPER(scene->set, sce_iter, base)) { 01997 if(v3d->lay & base->lay) { 01998 if (func == NULL || func(base)) { 01999 draw_object(scene, ar, v3d, base, 0); 02000 if(base->object->transflag & OB_DUPLI) { 02001 draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE); 02002 } 02003 } 02004 } 02005 } 02006 } 02007 02008 for(base= scene->base.first; base; base= base->next) { 02009 if(v3d->lay & base->lay) { 02010 if (func == NULL || func(base)) { 02011 /* dupli drawing */ 02012 if(base->object->transflag & OB_DUPLI) { 02013 draw_dupli_objects(scene, ar, v3d, base); 02014 } 02015 draw_object(scene, ar, v3d, base, 0); 02016 } 02017 } 02018 } 02019 02020 /* this isnt that nice, draw xray objects as if they are normal */ 02021 if ( v3d->afterdraw_transp.first || 02022 v3d->afterdraw_xray.first || 02023 v3d->afterdraw_xraytransp.first 02024 ) { 02025 View3DAfter *v3da, *next; 02026 int mask_orig; 02027 02028 v3d->xray= TRUE; 02029 02030 /* transp materials can change the depth mask, see #21388 */ 02031 glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); 02032 02033 02034 if(v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) { 02035 glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */ 02036 for(v3da= v3d->afterdraw_xray.first; v3da; v3da= next) { 02037 next= v3da->next; 02038 draw_object(scene, ar, v3d, v3da->base, 0); 02039 } 02040 glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */ 02041 } 02042 02043 /* draw 3 passes, transp/xray/xraytransp */ 02044 v3d->xray= FALSE; 02045 v3d->transp= TRUE; 02046 for(v3da= v3d->afterdraw_transp.first; v3da; v3da= next) { 02047 next= v3da->next; 02048 draw_object(scene, ar, v3d, v3da->base, 0); 02049 BLI_remlink(&v3d->afterdraw_transp, v3da); 02050 MEM_freeN(v3da); 02051 } 02052 02053 v3d->xray= TRUE; 02054 v3d->transp= FALSE; 02055 for(v3da= v3d->afterdraw_xray.first; v3da; v3da= next) { 02056 next= v3da->next; 02057 draw_object(scene, ar, v3d, v3da->base, 0); 02058 BLI_remlink(&v3d->afterdraw_xray, v3da); 02059 MEM_freeN(v3da); 02060 } 02061 02062 v3d->xray= TRUE; 02063 v3d->transp= TRUE; 02064 for(v3da= v3d->afterdraw_xraytransp.first; v3da; v3da= next) { 02065 next= v3da->next; 02066 draw_object(scene, ar, v3d, v3da->base, 0); 02067 BLI_remlink(&v3d->afterdraw_xraytransp, v3da); 02068 MEM_freeN(v3da); 02069 } 02070 02071 02072 v3d->xray= FALSE; 02073 v3d->transp= FALSE; 02074 02075 glDepthMask(mask_orig); 02076 } 02077 02078 if(rv3d->rflag & RV3D_CLIPPING) 02079 view3d_clr_clipping(); 02080 02081 v3d->zbuf = zbuf; 02082 if(!v3d->zbuf) glDisable(GL_DEPTH_TEST); 02083 02084 U.glalphaclip = glalphaclip; 02085 v3d->flag = flag; 02086 U.obcenter_dia= obcenter_dia; 02087 } 02088 02089 typedef struct View3DShadow { 02090 struct View3DShadow *next, *prev; 02091 GPULamp *lamp; 02092 } View3DShadow; 02093 02094 static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows) 02095 { 02096 GPULamp *lamp; 02097 Lamp *la = (Lamp*)ob->data; 02098 View3DShadow *shadow; 02099 02100 lamp = GPU_lamp_from_blender(scene, ob, par); 02101 02102 if(lamp) { 02103 GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat); 02104 GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy); 02105 02106 if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) { 02107 shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow"); 02108 shadow->lamp = lamp; 02109 BLI_addtail(shadows, shadow); 02110 } 02111 } 02112 } 02113 02114 static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) 02115 { 02116 ListBase shadows; 02117 View3DShadow *shadow; 02118 Scene *sce_iter; 02119 Base *base; 02120 Object *ob; 02121 02122 shadows.first= shadows.last= NULL; 02123 02124 /* update lamp transform and gather shadow lamps */ 02125 for(SETLOOPER(scene, sce_iter, base)) { 02126 ob= base->object; 02127 02128 if(ob->type == OB_LAMP) 02129 gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows); 02130 02131 if (ob->transflag & OB_DUPLI) { 02132 DupliObject *dob; 02133 ListBase *lb = object_duplilist(scene, ob); 02134 02135 for(dob=lb->first; dob; dob=dob->next) 02136 if(dob->ob->type==OB_LAMP) 02137 gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows); 02138 02139 free_object_duplilist(lb); 02140 } 02141 } 02142 02143 /* render shadows after updating all lamps, nested object_duplilist 02144 * don't work correct since it's replacing object matrices */ 02145 for(shadow=shadows.first; shadow; shadow=shadow->next) { 02146 /* this needs to be done better .. */ 02147 float viewmat[4][4], winmat[4][4]; 02148 int drawtype, lay, winsize, flag2=v3d->flag2; 02149 ARegion ar= {NULL}; 02150 RegionView3D rv3d= {{{0}}}; 02151 02152 drawtype= v3d->drawtype; 02153 lay= v3d->lay; 02154 02155 v3d->drawtype = OB_SOLID; 02156 v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); 02157 v3d->flag2 &= ~V3D_SOLID_TEX; 02158 v3d->flag2 |= V3D_RENDER_OVERRIDE; 02159 02160 GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); 02161 02162 ar.regiondata= &rv3d; 02163 ar.regiontype= RGN_TYPE_WINDOW; 02164 rv3d.persp= RV3D_CAMOB; 02165 copy_m4_m4(rv3d.winmat, winmat); 02166 copy_m4_m4(rv3d.viewmat, viewmat); 02167 invert_m4_m4(rv3d.viewinv, rv3d.viewmat); 02168 mul_m4_m4m4(rv3d.persmat, rv3d.viewmat, rv3d.winmat); 02169 invert_m4_m4(rv3d.persinv, rv3d.viewinv); 02170 02171 ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat); 02172 GPU_lamp_shadow_buffer_unbind(shadow->lamp); 02173 02174 v3d->drawtype= drawtype; 02175 v3d->lay= lay; 02176 v3d->flag2 = flag2; 02177 } 02178 02179 BLI_freelistN(&shadows); 02180 } 02181 02182 /* *********************** customdata **************** */ 02183 02184 CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d) 02185 { 02186 CustomDataMask mask= 0; 02187 if((v3d->drawtype == OB_TEXTURE) || ((v3d->drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) { 02188 mask |= CD_MASK_MTFACE | CD_MASK_MCOL; 02189 02190 if(scene->gm.matmode == GAME_MAT_GLSL) 02191 mask |= CD_MASK_ORCO; 02192 } 02193 02194 return mask; 02195 } 02196 /* goes over all modes and view3d settings */ 02197 CustomDataMask ED_viewedit_datamask(bScreen *screen) 02198 { 02199 Scene *scene= screen->scene; 02200 Object *ob= scene->basact ? scene->basact->object : NULL; 02201 CustomDataMask mask = CD_MASK_BAREMESH; 02202 ScrArea *sa; 02203 02204 /* check if we need tfaces & mcols due to face select or texture paint */ 02205 if(paint_facesel_test(ob) || (ob && ob->mode & OB_MODE_TEXTURE_PAINT)) 02206 mask |= CD_MASK_MTFACE | CD_MASK_MCOL; 02207 02208 /* check if we need tfaces & mcols due to view mode */ 02209 for(sa = screen->areabase.first; sa; sa = sa->next) { 02210 if(sa->spacetype == SPACE_VIEW3D) { 02211 mask |= ED_view3d_datamask(scene, (View3D *)sa->spacedata.first); 02212 } 02213 } 02214 02215 /* check if we need mcols due to vertex paint or weightpaint */ 02216 if(ob) { 02217 if(ob->mode & OB_MODE_VERTEX_PAINT) 02218 mask |= CD_MASK_MCOL; 02219 if(ob->mode & OB_MODE_WEIGHT_PAINT) 02220 mask |= CD_MASK_WEIGHT_MCOL; 02221 } 02222 02223 return mask; 02224 } 02225 02226 static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[][4], float winmat[][4]) 02227 { 02228 RegionView3D *rv3d= ar->regiondata; 02229 02230 /* setup window matrices */ 02231 if(winmat) 02232 copy_m4_m4(rv3d->winmat, winmat); 02233 else 02234 setwinmatrixview3d(ar, v3d, NULL); /* NULL= no pickrect */ 02235 02236 /* setup view matrix */ 02237 if(viewmat) 02238 copy_m4_m4(rv3d->viewmat, viewmat); 02239 else 02240 setviewmatrixview3d(scene, v3d, rv3d); /* note: calls where_is_object for camera... */ 02241 02242 /* update utilitity matrices */ 02243 mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat); 02244 invert_m4_m4(rv3d->persinv, rv3d->persmat); 02245 invert_m4_m4(rv3d->viewinv, rv3d->viewmat); 02246 02247 /* calculate pixelsize factor once, is used for lamps and obcenters */ 02248 { 02249 /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' 02250 * because of float point precision problems at large values [#23908] */ 02251 float v1[3], v2[3]; 02252 float len1, len2; 02253 02254 v1[0]= rv3d->persmat[0][0]; 02255 v1[1]= rv3d->persmat[1][0]; 02256 v1[2]= rv3d->persmat[2][0]; 02257 02258 v2[0]= rv3d->persmat[0][1]; 02259 v2[1]= rv3d->persmat[1][1]; 02260 v2[2]= rv3d->persmat[2][1]; 02261 02262 len1= 1.0f / len_v3(v1); 02263 len2= 1.0f / len_v3(v2); 02264 02265 rv3d->pixsize = (2.0f * MAX2(len1, len2)) / (float)MAX2(ar->winx, ar->winy); 02266 } 02267 02268 /* set for opengl */ 02269 glMatrixMode(GL_PROJECTION); 02270 glLoadMatrixf(rv3d->winmat); 02271 glMatrixMode(GL_MODELVIEW); 02272 glLoadMatrixf(rv3d->viewmat); 02273 } 02274 02275 void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[][4], float winmat[][4]) 02276 { 02277 Base *base; 02278 float backcol[3]; 02279 int bwinx, bwiny; 02280 rcti brect; 02281 02282 glPushMatrix(); 02283 02284 /* set temporary new size */ 02285 bwinx= ar->winx; 02286 bwiny= ar->winy; 02287 brect= ar->winrct; 02288 02289 ar->winx= winx; 02290 ar->winy= winy; 02291 ar->winrct.xmin= 0; 02292 ar->winrct.ymin= 0; 02293 ar->winrct.xmax= winx; 02294 ar->winrct.ymax= winy; 02295 02296 02297 /* set flags */ 02298 G.f |= G_RENDER_OGL; 02299 02300 /* free images which can have changed on frame-change 02301 * warning! can be slow so only free animated images - campbell */ 02302 GPU_free_images_anim(); 02303 02304 /* shadow buffers, before we setup matrices */ 02305 if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) 02306 gpu_update_lamps_shadows(scene, v3d); 02307 02308 /* set background color, fallback on the view background color */ 02309 if(scene->world) { 02310 if(scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) 02311 linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); 02312 else 02313 copy_v3_v3(backcol, &scene->world->horr); 02314 glClearColor(backcol[0], backcol[1], backcol[2], 0.0); 02315 } 02316 else { 02317 UI_ThemeClearColor(TH_BACK); 02318 } 02319 02320 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 02321 02322 /* setup view matrices */ 02323 view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); 02324 02325 /* set zbuffer */ 02326 if(v3d->drawtype > OB_WIRE) { 02327 v3d->zbuf= TRUE; 02328 glEnable(GL_DEPTH_TEST); 02329 } 02330 else 02331 v3d->zbuf= FALSE; 02332 02333 /* draw set first */ 02334 if(scene->set) { 02335 Scene *sce_iter; 02336 for(SETLOOPER(scene->set, sce_iter, base)) { 02337 if(v3d->lay & base->lay) { 02338 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); 02339 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET); 02340 02341 if(base->object->transflag & OB_DUPLI) 02342 draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE); 02343 } 02344 } 02345 } 02346 02347 /* then draw not selected and the duplis, but skip editmode object */ 02348 for(base= scene->base.first; base; base= base->next) { 02349 if(v3d->lay & base->lay) { 02350 /* dupli drawing */ 02351 if(base->object->transflag & OB_DUPLI) 02352 draw_dupli_objects(scene, ar, v3d, base); 02353 02354 draw_object(scene, ar, v3d, base, 0); 02355 } 02356 } 02357 02358 /* must be before xray draw which clears the depth buffer */ 02359 if(v3d->zbuf) glDisable(GL_DEPTH_TEST); 02360 draw_gpencil_view3d_ext(scene, v3d, ar, 1); 02361 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 02362 02363 /* transp and X-ray afterdraw stuff */ 02364 if(v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d); 02365 if(v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, 1); // clears zbuffer if it is used! 02366 if(v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, 1); 02367 02368 /* cleanup */ 02369 if(v3d->zbuf) { 02370 v3d->zbuf= FALSE; 02371 glDisable(GL_DEPTH_TEST); 02372 } 02373 02374 /* draw grease-pencil stuff */ 02375 ED_region_pixelspace(ar); 02376 02377 /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ 02378 draw_gpencil_view3d_ext(scene, v3d, ar, 0); 02379 02380 /* freeing the images again here could be done after the operator runs, leaving for now */ 02381 GPU_free_images_anim(); 02382 02383 /* restore size */ 02384 ar->winx= bwinx; 02385 ar->winy= bwiny; 02386 ar->winrct = brect; 02387 02388 glPopMatrix(); 02389 02390 glColor4ub(255, 255, 255, 255); // XXX, without this the sequencer flickers with opengl draw enabled, need to find out why - campbell 02391 02392 G.f &= ~G_RENDER_OGL; 02393 } 02394 02395 /* utility func for ED_view3d_draw_offscreen */ 02396 ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag, char err_out[256]) 02397 { 02398 RegionView3D *rv3d= ar->regiondata; 02399 ImBuf *ibuf; 02400 GPUOffScreen *ofs; 02401 02402 /* state changes make normal drawing go weird otherwise */ 02403 glPushAttrib(GL_LIGHTING_BIT); 02404 02405 /* bind */ 02406 ofs= GPU_offscreen_create(&sizex, &sizey, err_out); 02407 if(ofs == NULL) 02408 return NULL; 02409 02410 GPU_offscreen_bind(ofs); 02411 02412 /* render 3d view */ 02413 if(rv3d->persp==RV3D_CAMOB && v3d->camera) { 02414 float winmat[4][4]; 02415 float _clipsta, _clipend, _lens, _yco, _dx, _dy; 02416 rctf _viewplane; 02417 02418 object_camera_matrix(&scene->r, v3d->camera, sizex, sizey, 0, winmat, &_viewplane, &_clipsta, &_clipend, &_lens, &_yco, &_dx, &_dy); 02419 02420 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat); 02421 } 02422 else { 02423 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL); 02424 } 02425 02426 /* read in pixels & stamp */ 02427 ibuf= IMB_allocImBuf(sizex, sizey, 32, flag); 02428 02429 if(ibuf->rect_float) 02430 glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, ibuf->rect_float); 02431 else if(ibuf->rect) 02432 glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); 02433 02434 //if((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) 02435 // BKE_stamp_buf(scene, NULL, rr->rectf, rr->rectx, rr->recty, 4); 02436 02437 /* unbind */ 02438 GPU_offscreen_unbind(ofs); 02439 GPU_offscreen_free(ofs); 02440 02441 glPopAttrib(); 02442 02443 if(ibuf->rect_float && ibuf->rect) 02444 IMB_rect_from_float(ibuf); 02445 02446 return ibuf; 02447 } 02448 02449 /* creates own 3d views, used by the sequencer */ 02450 ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, unsigned int flag, int drawtype, char err_out[256]) 02451 { 02452 View3D v3d= {NULL}; 02453 ARegion ar= {NULL}; 02454 RegionView3D rv3d= {{{0}}}; 02455 02456 /* connect data */ 02457 v3d.regionbase.first= v3d.regionbase.last= &ar; 02458 ar.regiondata= &rv3d; 02459 ar.regiontype= RGN_TYPE_WINDOW; 02460 02461 v3d.camera= camera; 02462 v3d.lay= scene->lay; 02463 v3d.drawtype = drawtype; 02464 v3d.flag2 = V3D_RENDER_OVERRIDE; 02465 02466 rv3d.persp= RV3D_CAMOB; 02467 02468 copy_m4_m4(rv3d.viewinv, v3d.camera->obmat); 02469 normalize_m4(rv3d.viewinv); 02470 invert_m4_m4(rv3d.viewmat, rv3d.viewinv); 02471 02472 { 02473 float _yco, _dx, _dy; 02474 rctf _viewplane; 02475 object_camera_matrix(&scene->r, v3d.camera, width, height, 0, rv3d.winmat, &_viewplane, &v3d.near, &v3d.far, &v3d.lens, &_yco, &_dx, &_dy); 02476 } 02477 02478 mul_m4_m4m4(rv3d.persmat, rv3d.viewmat, rv3d.winmat); 02479 invert_m4_m4(rv3d.persinv, rv3d.viewinv); 02480 02481 return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, err_out); 02482 02483 // seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty); 02484 } 02485 02486 02487 /* NOTE: the info that this uses is updated in ED_refresh_viewport_fps(), 02488 * which currently gets called during SCREEN_OT_animation_step. 02489 */ 02490 static void draw_viewport_fps(Scene *scene, ARegion *ar) 02491 { 02492 ScreenFrameRateInfo *fpsi= scene->fps_info; 02493 float fps; 02494 char printable[16]; 02495 int i, tot; 02496 02497 if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) 02498 return; 02499 02500 printable[0] = '\0'; 02501 02502 #if 0 02503 /* this is too simple, better do an average */ 02504 fps = (float)(1.0/(fpsi->lredrawtime-fpsi->redrawtime)) 02505 #else 02506 fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0/(fpsi->lredrawtime-fpsi->redrawtime)); 02507 02508 for (i=0, tot=0, fps=0.0f ; i < REDRAW_FRAME_AVERAGE ; i++) { 02509 if (fpsi->redrawtimes_fps[i]) { 02510 fps += fpsi->redrawtimes_fps[i]; 02511 tot++; 02512 } 02513 } 02514 if (tot) { 02515 fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; 02516 02517 //fpsi->redrawtime_index++; 02518 //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) 02519 // fpsi->redrawtime = 0; 02520 02521 fps = fps / tot; 02522 } 02523 #endif 02524 02525 /* is this more then half a frame behind? */ 02526 if (fps+0.5f < (float)(FPS)) { 02527 UI_ThemeColor(TH_REDALERT); 02528 BLI_snprintf(printable, sizeof(printable), "fps: %.2f", fps); 02529 } 02530 else { 02531 UI_ThemeColor(TH_TEXT_HI); 02532 BLI_snprintf(printable, sizeof(printable), "fps: %i", (int)(fps+0.5f)); 02533 } 02534 02535 BLF_draw_default_ascii(22, ar->winy-17, 0.0f, printable, sizeof(printable)-1); 02536 } 02537 02538 /* warning: this function has duplicate drawing in ED_view3d_draw_offscreen() */ 02539 void view3d_main_area_draw(const bContext *C, ARegion *ar) 02540 { 02541 Scene *scene= CTX_data_scene(C); 02542 View3D *v3d = CTX_wm_view3d(C); 02543 RegionView3D *rv3d= CTX_wm_region_view3d(C); 02544 Base *base; 02545 Object *ob; 02546 float backcol[3]; 02547 unsigned int lay_used; 02548 const char *grid_unit= NULL; 02549 02550 /* shadow buffers, before we setup matrices */ 02551 if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) 02552 gpu_update_lamps_shadows(scene, v3d); 02553 02554 /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */ 02555 if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) { 02556 rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE; 02557 GPU_default_lights(); 02558 } 02559 02560 /* clear background */ 02561 if((v3d->flag2 & V3D_RENDER_OVERRIDE) && scene->world) { 02562 if(scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) 02563 linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); 02564 else 02565 copy_v3_v3(backcol, &scene->world->horr); 02566 glClearColor(backcol[0], backcol[1], backcol[2], 0.0); 02567 } 02568 else 02569 UI_ThemeClearColor(TH_BACK); 02570 02571 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 02572 02573 /* setup view matrices */ 02574 view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL); 02575 02576 ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); 02577 02578 if(rv3d->rflag & RV3D_CLIPPING) 02579 view3d_draw_clipping(rv3d); 02580 02581 /* set zbuffer after we draw clipping region */ 02582 if(v3d->drawtype > OB_WIRE) { 02583 v3d->zbuf= TRUE; 02584 glEnable(GL_DEPTH_TEST); 02585 } 02586 else 02587 v3d->zbuf= FALSE; 02588 02589 /* enables anti-aliasing for 3D view drawing */ 02590 /*if (!(U.gameflags & USER_DISABLE_AA)) 02591 glEnable(GL_MULTISAMPLE_ARB);*/ 02592 02593 // needs to be done always, gridview is adjusted in drawgrid() now 02594 rv3d->gridview= v3d->grid; 02595 02596 if((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { 02597 if ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { 02598 drawfloor(scene, v3d, &grid_unit); 02599 } 02600 if(rv3d->persp==RV3D_CAMOB) { 02601 if(scene->world) { 02602 if(scene->world->mode & WO_STARS) { 02603 RE_make_stars(NULL, scene, star_stuff_init_func, star_stuff_vertex_func, 02604 star_stuff_term_func); 02605 } 02606 } 02607 if ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { 02608 if(v3d->flag & V3D_DISPBGPICS) draw_bgpic(scene, ar, v3d); 02609 } 02610 } 02611 } 02612 else { 02613 if ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { 02614 ED_region_pixelspace(ar); 02615 drawgrid(&scene->unit, ar, v3d, &grid_unit); 02616 /* XXX make function? replaces persp(1) */ 02617 glMatrixMode(GL_PROJECTION); 02618 glLoadMatrixf(rv3d->winmat); 02619 glMatrixMode(GL_MODELVIEW); 02620 glLoadMatrixf(rv3d->viewmat); 02621 02622 if(v3d->flag & V3D_DISPBGPICS) { 02623 draw_bgpic(scene, ar, v3d); 02624 } 02625 } 02626 } 02627 02628 if(rv3d->rflag & RV3D_CLIPPING) 02629 view3d_set_clipping(rv3d); 02630 02631 /* draw set first */ 02632 if(scene->set) { 02633 Scene *sce_iter; 02634 for(SETLOOPER(scene->set, sce_iter, base)) { 02635 02636 if(v3d->lay & base->lay) { 02637 02638 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); 02639 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET); 02640 02641 if(base->object->transflag & OB_DUPLI) { 02642 draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE); 02643 } 02644 } 02645 } 02646 02647 /* Transp and X-ray afterdraw stuff for sets is done later */ 02648 } 02649 02650 lay_used= 0; 02651 02652 /* then draw not selected and the duplis, but skip editmode object */ 02653 for(base= scene->base.first; base; base= base->next) { 02654 lay_used |= base->lay & ((1<<20)-1); 02655 02656 if(v3d->lay & base->lay) { 02657 02658 /* dupli drawing */ 02659 if(base->object->transflag & OB_DUPLI) { 02660 draw_dupli_objects(scene, ar, v3d, base); 02661 } 02662 if((base->flag & SELECT)==0) { 02663 if(base->object!=scene->obedit) 02664 draw_object(scene, ar, v3d, base, 0); 02665 } 02666 } 02667 } 02668 02669 if(v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */ 02670 /* find header and force tag redraw */ 02671 ScrArea *sa= CTX_wm_area(C); 02672 ARegion *ar_header= BKE_area_find_region_type(sa, RGN_TYPE_HEADER); 02673 ED_region_tag_redraw(ar_header); /* can be NULL */ 02674 v3d->lay_used= lay_used; 02675 } 02676 02677 /* draw selected and editmode */ 02678 for(base= scene->base.first; base; base= base->next) { 02679 if(v3d->lay & base->lay) { 02680 if (base->object==scene->obedit || ( base->flag & SELECT) ) 02681 draw_object(scene, ar, v3d, base, 0); 02682 } 02683 } 02684 02685 // REEB_draw(); 02686 02687 if ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { 02688 /* must be before xray draw which clears the depth buffer */ 02689 if(v3d->zbuf) glDisable(GL_DEPTH_TEST); 02690 draw_gpencil_view3d((bContext *)C, 1); 02691 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 02692 } 02693 02694 /* Transp and X-ray afterdraw stuff */ 02695 if(v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d); 02696 if(v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, 1); // clears zbuffer if it is used! 02697 if(v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, 1); 02698 02699 ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); 02700 02701 if(rv3d->rflag & RV3D_CLIPPING) 02702 view3d_clr_clipping(); 02703 02704 BIF_draw_manipulator(C); 02705 02706 /* Disable back anti-aliasing */ 02707 /*if (!(U.gameflags & USER_DISABLE_AA)) 02708 glDisable(GL_MULTISAMPLE_ARB);*/ 02709 02710 if(v3d->zbuf) { 02711 v3d->zbuf= FALSE; 02712 glDisable(GL_DEPTH_TEST); 02713 } 02714 02715 if ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { 02716 BDR_drawSketch(C); 02717 } 02718 02719 if ((U.ndof_flag & NDOF_SHOW_GUIDE) && (rv3d->viewlock != RV3D_LOCKED) && (rv3d->persp != RV3D_CAMOB)) 02720 // TODO: draw something else (but not this) during fly mode 02721 draw_rotation_guide(rv3d); 02722 02723 ED_region_pixelspace(ar); 02724 02725 // retopo_paint_view_update(v3d); 02726 // retopo_draw_paint_lines(); 02727 02728 /* Draw particle edit brush XXX (removed) */ 02729 02730 02731 if(rv3d->persp==RV3D_CAMOB) 02732 drawviewborder(scene, ar, v3d); 02733 02734 if ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) { 02735 /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ 02736 // if (v3d->flag2 & V3D_DISPGP) 02737 draw_gpencil_view3d((bContext *)C, 0); 02738 02739 drawcursor(scene, ar, v3d); 02740 } 02741 02742 if(U.uiflag & USER_SHOW_ROTVIEWICON) 02743 draw_view_axis(rv3d); 02744 else 02745 draw_view_icon(rv3d); 02746 02747 if((U.uiflag & USER_SHOW_FPS) && (CTX_wm_screen(C)->animtimer)) { 02748 draw_viewport_fps(scene, ar); 02749 } 02750 else if(U.uiflag & USER_SHOW_VIEWPORTNAME) { 02751 draw_viewport_name(ar, v3d); 02752 } 02753 if (grid_unit) { /* draw below the viewport name */ 02754 char tstr[32]= ""; 02755 02756 UI_ThemeColor(TH_TEXT_HI); 02757 if(v3d->grid != 1.0f) { 02758 BLI_snprintf(tstr, sizeof(tstr), "%s x %.4g", grid_unit, v3d->grid); 02759 } 02760 02761 BLF_draw_default_ascii(22, ar->winy-(USER_SHOW_VIEWPORTNAME?40:20), 0.0f, tstr[0]?tstr : grid_unit, sizeof(tstr)); /* XXX, use real length */ 02762 } 02763 02764 ob= OBACT; 02765 if(U.uiflag & USER_DRAWVIEWINFO) 02766 draw_selected_name(scene, ob); 02767 02768 /* XXX here was the blockhandlers for floating panels */ 02769 02770 v3d->flag |= V3D_INVALID_BACKBUF; 02771 }