diff options
-rw-r--r-- | source/blender/editors/space_view3d/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw.c | 473 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw_legacy.c | 578 |
3 files changed, 471 insertions, 581 deletions
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 95d7f79f666..9e3c9d6725d 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -48,7 +48,6 @@ set(SRC view3d_buttons.c view3d_camera_control.c view3d_draw.c - view3d_draw_legacy.c view3d_edit.c view3d_fly.c view3d_gizmo_armature.c diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 0e5592abfd2..6704fc9908f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -33,7 +33,9 @@ #include "BKE_camera.h" #include "BKE_collection.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_key.h" #include "BKE_main.h" #include "BKE_scene.h" @@ -56,11 +58,13 @@ #include "DNA_windowmanager_types.h" #include "DRW_engine.h" +#include "DRW_select_buffer.h" #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_gpencil.h" #include "ED_screen.h" +#include "ED_screen_types.h" #include "ED_transform.h" #include "DEG_depsgraph_query.h" @@ -1936,11 +1940,476 @@ static bool view3d_clipping_test(const float co[3], const float clip[6][4]) return true; } -/* for 'local' ED_view3d_clipping_local must run first - * then all comparisons can be done in localspace */ +/* For 'local' ED_view3d_clipping_local must run first + * then all comparisons can be done in localspace. */ bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) { return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); } +/* Legacy 2.7x, now use shaders that use clip distance instead. + * Remove once clipping is working properly. */ +#define USE_CLIP_PLANES + +void ED_view3d_clipping_set(RegionView3D *rv3d) +{ +#ifdef USE_CLIP_PLANES + double plane[4]; + const uint tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; + + for (unsigned a = 0; a < tot; a++) { + copy_v4db_v4fl(plane, rv3d->clip[a]); + glClipPlane(GL_CLIP_PLANE0 + a, plane); + glEnable(GL_CLIP_PLANE0 + a); + glEnable(GL_CLIP_DISTANCE0 + a); + } +#else + for (unsigned a = 0; a < 6; a++) { + glEnable(GL_CLIP_DISTANCE0 + a); + } +#endif +} + +/* Use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set. */ +void ED_view3d_clipping_disable(void) +{ + for (unsigned a = 0; a < 6; a++) { +#ifdef USE_CLIP_PLANES + glDisable(GL_CLIP_PLANE0 + a); +#endif + glDisable(GL_CLIP_DISTANCE0 + a); + } +} +void ED_view3d_clipping_enable(void) +{ + for (unsigned a = 0; a < 6; a++) { +#ifdef USE_CLIP_PLANES + glEnable(GL_CLIP_PLANE0 + a); +#endif + glEnable(GL_CLIP_DISTANCE0 + a); + } +} + +/* *********************** backdraw for selection *************** */ + +/** + * \note Only use in object mode. + */ +static void validate_object_select_id( + struct Depsgraph *depsgraph, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Object *obact) +{ + Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); + + BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); + UNUSED_VARS_NDEBUG(ar); + + if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || + BKE_paint_select_face_test(obact_eval))) { + /* do nothing */ + } + /* texture paint mode sampling */ + else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) && + (v3d->shading.type > OB_WIRE)) { + /* do nothing */ + } + else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { + /* do nothing */ + } + else { + v3d->flag &= ~V3D_INVALID_BACKBUF; + return; + } + + if (!(v3d->flag & V3D_INVALID_BACKBUF)) { + return; + } + + if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { + Base *base = BKE_view_layer_base_find(view_layer, obact); + DRW_select_buffer_context_create(&base, 1, -1); + } + + /* TODO: Create a flag in `DRW_manager` because the drawing is no longer + * made on the backbuffer in this case. */ + v3d->flag &= ~V3D_INVALID_BACKBUF; +} + +/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. + * Calling this function should be avoided during interactive drawing. */ +static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) +{ + DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); + + GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); + GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0); + GPU_framebuffer_bind(tmp_fb); + + glReadPixels(rect->xmin, + rect->ymin, + BLI_rcti_size_x(rect), + BLI_rcti_size_y(rect), + GL_DEPTH_COMPONENT, + GL_FLOAT, + data); + + GPU_framebuffer_restore(); + GPU_framebuffer_free(tmp_fb); +} + +void ED_view3d_select_id_validate(ViewContext *vc) +{ + /* TODO: Create a flag in `DRW_manager` because the drawing is no longer + * made on the backbuffer in this case. */ + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + validate_object_select_id(vc->depsgraph, vc->view_layer, vc->ar, vc->v3d, vc->obact); + } +} + +void ED_view3d_backbuf_depth_validate(ViewContext *vc) +{ + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + ARegion *ar = vc->ar; + Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); + + if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + DRW_draw_depth_object(vc->ar, vc->v3d, viewport, obact_eval); + } + + vc->v3d->flag &= ~V3D_INVALID_BACKBUF; + } +} + +/** + * allow for small values [0.5 - 2.5], + * and large values, FLT_MAX by clamping by the area size + */ +int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +{ + return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); +} + +/* *********************** */ + +void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) +{ + /* clamp rect by region */ + rcti r = { + .xmin = 0, + .xmax = ar->winx - 1, + .ymin = 0, + .ymax = ar->winy - 1, + }; + + /* Constrain rect to depth bounds */ + BLI_rcti_isect(&r, rect, rect); + + /* assign values to compare with the ViewDepths */ + int x = rect->xmin; + int y = rect->ymin; + + int w = BLI_rcti_size_x(rect); + int h = BLI_rcti_size_y(rect); + + if (w <= 0 || h <= 0) { + if (d->depths) { + MEM_freeN(d->depths); + } + d->depths = NULL; + + d->damaged = false; + } + else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) { + d->x = x; + d->y = y; + d->w = w; + d->h = h; + + if (d->depths) { + MEM_freeN(d->depths); + } + + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); + + d->damaged = true; + } + + if (d->damaged) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + view3d_opengl_read_Z_pixels(viewport, rect, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + d->damaged = false; + } +} + +/* Note, with nouveau drivers the glReadPixels() is very slow. [#24339]. */ +void ED_view3d_depth_update(ARegion *ar) +{ + RegionView3D *rv3d = ar->regiondata; + + /* Create storage for, and, if necessary, copy depth buffer. */ + if (!rv3d->depths) { + rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); + } + if (rv3d->depths) { + ViewDepths *d = rv3d->depths; + if (d->w != ar->winx || d->h != ar->winy || !d->depths) { + d->w = ar->winx; + d->h = ar->winy; + if (d->depths) { + MEM_freeN(d->depths); + } + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); + d->damaged = true; + } + + if (d->damaged) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + rcti r = { + .xmin = 0, + .xmax = d->w, + .ymin = 0, + .ymax = d->h, + }; + view3d_opengl_read_Z_pixels(viewport, &r, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + d->damaged = false; + } + } +} + +/* Utility function to find the closest Z value, use for autodepth. */ +float view3d_depth_near(ViewDepths *d) +{ + /* Convert to float for comparisons. */ + const float near = (float)d->depth_range[0]; + const float far_real = (float)d->depth_range[1]; + float far = far_real; + + const float *depths = d->depths; + float depth = FLT_MAX; + int i = (int)d->w * (int)d->h; /* Cast to avoid short overflow. */ + + /* Far is both the starting 'far' value + * and the closest value found. */ + while (i--) { + depth = *depths++; + if ((depth < far) && (depth > near)) { + far = depth; + } + } + + return far == far_real ? FLT_MAX : far; +} + +void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d) +{ + /* Setup view matrix. */ + ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL); + + GPU_clear(GPU_DEPTH_BIT); + + GPU_depth_test(true); + + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport); + + GPU_depth_test(false); +} + +/* *********************** customdata **************** */ + +void ED_view3d_datamask(const bContext *C, + const Scene *UNUSED(scene), + const View3D *v3d, + CustomData_MeshMasks *r_cddata_masks) +{ + if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) { + r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; + r_cddata_masks->vmask |= CD_MASK_ORCO; + } + else if (v3d->shading.type == OB_SOLID) { + if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) { + r_cddata_masks->lmask |= CD_MASK_MLOOPUV; + } + if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) { + r_cddata_masks->lmask |= CD_MASK_MLOOPCOL; + } + } + + if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) && + (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) { + r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; + } +} + +/* Goes over all modes and view3d settings. */ +void ED_view3d_screen_datamask(const bContext *C, + const Scene *scene, + const bScreen *screen, + CustomData_MeshMasks *r_cddata_masks) +{ + CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH); + + /* Check if we need tfaces & mcols due to view mode. */ + for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_VIEW3D) { + ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks); + } + } +} + +/** + * Store values from #RegionView3D, set when drawing. + * This is needed when we draw with to a viewport using a different matrix + * (offscreen drawing for example). + * + * Values set by #ED_view3d_update_viewmat should be handled here. + */ +struct RV3DMatrixStore { + float winmat[4][4]; + float viewmat[4][4]; + float viewinv[4][4]; + float persmat[4][4]; + float persinv[4][4]; + float viewcamtexcofac[4]; + float pixsize; +}; + +struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) +{ + struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); + copy_m4_m4(rv3dmat->winmat, rv3d->winmat); + copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); + copy_m4_m4(rv3dmat->persmat, rv3d->persmat); + copy_m4_m4(rv3dmat->persinv, rv3d->persinv); + copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); + copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); + rv3dmat->pixsize = rv3d->pixsize; + return (void *)rv3dmat; +} + +void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt) +{ + struct RV3DMatrixStore *rv3dmat = rv3dmat_pt; + copy_m4_m4(rv3d->winmat, rv3dmat->winmat); + copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); + copy_m4_m4(rv3d->persmat, rv3dmat->persmat); + copy_m4_m4(rv3d->persinv, rv3dmat->persinv); + copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); + copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); + rv3d->pixsize = rv3dmat->pixsize; +} + +/** + * \note The info that this uses is updated in #ED_refresh_viewport_fps, + * which currently gets called during #SCREEN_OT_animation_step. + */ +void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset) +{ + ScreenFrameRateInfo *fpsi = scene->fps_info; + char printable[16]; + + if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) { + return; + } + + printable[0] = '\0'; + + /* Doing an average for a more robust calculation. */ + fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / + (fpsi->lredrawtime - fpsi->redrawtime)); + + float fps = 0.0f; + int tot = 0; + for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) { + if (fpsi->redrawtimes_fps[i]) { + fps += fpsi->redrawtimes_fps[i]; + tot++; + } + } + if (tot) { + fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; + fps = fps / tot; + } + + const int font_id = BLF_default(); + + /* Is this more than half a frame behind? */ + if (fps + 0.5f < (float)(FPS)) { + UI_FontThemeColor(font_id, TH_REDALERT); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); + } + else { + UI_FontThemeColor(font_id, TH_TEXT_HI); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); + } + + BLF_enable(font_id, BLF_SHADOW); + BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); + BLF_shadow_offset(font_id, 1, -1); + + *yoffset -= U.widget_unit; + +#ifdef WITH_INTERNATIONAL + BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); +#else + BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); +#endif + + BLF_disable(font_id, BLF_SHADOW); +} + +static bool view3d_main_region_do_render_draw(const Scene *scene) +{ + RenderEngineType *type = RE_engines_find(scene->r.engine); + return (type && type->view_update && type->view_draw); +} + +bool ED_view3d_calc_render_border( + const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect) +{ + RegionView3D *rv3d = ar->regiondata; + bool use_border; + + /* Test if there is a 3d view rendering. */ + if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) { + return false; + } + + /* Test if there is a border render. */ + if (rv3d->persp == RV3D_CAMOB) { + use_border = (scene->r.mode & R_BORDER) != 0; + } + else { + use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; + } + + if (!use_border) { + return false; + } + + /* Compute border. */ + if (rv3d->persp == RV3D_CAMOB) { + rctf viewborder; + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false); + + rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); + rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); + rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); + rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + } + else { + rect->xmin = v3d->render_border.xmin * ar->winx; + rect->xmax = v3d->render_border.xmax * ar->winx; + rect->ymin = v3d->render_border.ymin * ar->winy; + rect->ymax = v3d->render_border.ymax * ar->winy; + } + + BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); + BLI_rcti_isect(&ar->winrct, rect, rect); + + return true; +} + /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c deleted file mode 100644 index 38cb5ad8651..00000000000 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup spview3d - */ - -#include <string.h> -#include <stdio.h> -#include <math.h> - -#include "DNA_armature_types.h" -#include "DNA_camera_types.h" -#include "DNA_collection_types.h" -#include "DNA_customdata_types.h" -#include "DNA_object_types.h" -#include "DNA_mesh_types.h" -#include "DNA_key_types.h" -#include "DNA_light_types.h" -#include "DNA_scene_types.h" -#include "DNA_world_types.h" -#include "DNA_brush_types.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_utildefines.h" -#include "BLI_endian_switch.h" -#include "BLI_threads.h" - -#include "BKE_anim.h" -#include "BKE_camera.h" -#include "BKE_context.h" -#include "BKE_customdata.h" -#include "BKE_image.h" -#include "BKE_key.h" -#include "BKE_layer.h" -#include "BKE_object.h" -#include "BKE_global.h" -#include "BKE_paint.h" -#include "BKE_scene.h" -#include "BKE_unit.h" -#include "BKE_movieclip.h" - -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" - -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" -#include "IMB_colormanagement.h" - -#include "BIF_glutil.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "BLF_api.h" -#include "BLT_translation.h" - -#include "ED_armature.h" -#include "ED_keyframing.h" -#include "ED_gpencil.h" -#include "ED_mesh.h" -#include "ED_screen.h" -#include "ED_space_api.h" -#include "ED_screen_types.h" -#include "ED_transform.h" -#include "ED_view3d.h" - -#include "UI_interface.h" -#include "UI_interface_icons.h" -#include "UI_resources.h" - -#include "GPU_framebuffer.h" -#include "GPU_immediate.h" -#include "GPU_state.h" -#include "GPU_viewport.h" - -#include "RE_engine.h" - -#include "DRW_engine.h" -#include "DRW_select_buffer.h" - -#include "view3d_intern.h" /* own include */ - -/* ********* custom clipping *********** */ - -/* Legacy 2.7x, now use shaders that use clip distance instead. - * Remove once clipping is working properly. */ -#define USE_CLIP_PLANES - -void ED_view3d_clipping_set(RegionView3D *rv3d) -{ -#ifdef USE_CLIP_PLANES - double plane[4]; - const uint tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; - - for (unsigned a = 0; a < tot; a++) { - copy_v4db_v4fl(plane, rv3d->clip[a]); - glClipPlane(GL_CLIP_PLANE0 + a, plane); - glEnable(GL_CLIP_PLANE0 + a); - glEnable(GL_CLIP_DISTANCE0 + a); - } -#else - for (unsigned a = 0; a < 6; a++) { - glEnable(GL_CLIP_DISTANCE0 + a); - } -#endif -} - -/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */ -void ED_view3d_clipping_disable(void) -{ - for (unsigned a = 0; a < 6; a++) { -#ifdef USE_CLIP_PLANES - glDisable(GL_CLIP_PLANE0 + a); -#endif - glDisable(GL_CLIP_DISTANCE0 + a); - } -} -void ED_view3d_clipping_enable(void) -{ - for (unsigned a = 0; a < 6; a++) { -#ifdef USE_CLIP_PLANES - glEnable(GL_CLIP_PLANE0 + a); -#endif - glEnable(GL_CLIP_DISTANCE0 + a); - } -} - -/* *********************** backdraw for selection *************** */ - -/** - * \note Only use in object mode. - */ -static void validate_object_select_id( - struct Depsgraph *depsgraph, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Object *obact) -{ - Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); - - BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); - UNUSED_VARS_NDEBUG(ar); - - if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || - BKE_paint_select_face_test(obact_eval))) { - /* do nothing */ - } - /* texture paint mode sampling */ - else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) && - (v3d->shading.type > OB_WIRE)) { - /* do nothing */ - } - else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { - /* do nothing */ - } - else { - v3d->flag &= ~V3D_INVALID_BACKBUF; - return; - } - - if (!(v3d->flag & V3D_INVALID_BACKBUF)) { - return; - } - - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { - Base *base = BKE_view_layer_base_find(view_layer, obact); - DRW_select_buffer_context_create(&base, 1, -1); - } - - /* TODO: Create a flag in `DRW_manager` because the drawing is no longer - * made on the backbuffer in this case. */ - v3d->flag &= ~V3D_INVALID_BACKBUF; -} - -/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. - * Calling this function should be avoided during interactive drawing. */ -static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) -{ - DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); - - GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); - GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0); - GPU_framebuffer_bind(tmp_fb); - - glReadPixels(rect->xmin, - rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - GL_DEPTH_COMPONENT, - GL_FLOAT, - data); - - GPU_framebuffer_restore(); - GPU_framebuffer_free(tmp_fb); -} - -void ED_view3d_select_id_validate(ViewContext *vc) -{ - /* TODO: Create a flag in `DRW_manager` because the drawing is no longer - * made on the backbuffer in this case. */ - if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - validate_object_select_id(vc->depsgraph, vc->view_layer, vc->ar, vc->v3d, vc->obact); - } -} - -void ED_view3d_backbuf_depth_validate(ViewContext *vc) -{ - if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - ARegion *ar = vc->ar; - Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); - - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - DRW_draw_depth_object(vc->ar, vc->v3d, viewport, obact_eval); - } - - vc->v3d->flag &= ~V3D_INVALID_BACKBUF; - } -} - -/** - * allow for small values [0.5 - 2.5], - * and large values, FLT_MAX by clamping by the area size - */ -int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) -{ - return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); -} - -/* *********************** */ - -void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) -{ - /* clamp rect by region */ - rcti r = { - .xmin = 0, - .xmax = ar->winx - 1, - .ymin = 0, - .ymax = ar->winy - 1, - }; - - /* Constrain rect to depth bounds */ - BLI_rcti_isect(&r, rect, rect); - - /* assign values to compare with the ViewDepths */ - int x = rect->xmin; - int y = rect->ymin; - - int w = BLI_rcti_size_x(rect); - int h = BLI_rcti_size_y(rect); - - if (w <= 0 || h <= 0) { - if (d->depths) { - MEM_freeN(d->depths); - } - d->depths = NULL; - - d->damaged = false; - } - else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) { - d->x = x; - d->y = y; - d->w = w; - d->h = h; - - if (d->depths) { - MEM_freeN(d->depths); - } - - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); - - d->damaged = true; - } - - if (d->damaged) { - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - view3d_opengl_read_Z_pixels(viewport, rect, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - d->damaged = false; - } -} - -/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ -void ED_view3d_depth_update(ARegion *ar) -{ - RegionView3D *rv3d = ar->regiondata; - - /* Create storage for, and, if necessary, copy depth buffer */ - if (!rv3d->depths) { - rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); - } - if (rv3d->depths) { - ViewDepths *d = rv3d->depths; - if (d->w != ar->winx || d->h != ar->winy || !d->depths) { - d->w = ar->winx; - d->h = ar->winy; - if (d->depths) { - MEM_freeN(d->depths); - } - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); - d->damaged = true; - } - - if (d->damaged) { - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - rcti r = { - .xmin = 0, - .xmax = d->w, - .ymin = 0, - .ymax = d->h, - }; - view3d_opengl_read_Z_pixels(viewport, &r, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - d->damaged = false; - } - } -} - -/* utility function to find the closest Z value, use for autodepth */ -float view3d_depth_near(ViewDepths *d) -{ - /* convert to float for comparisons */ - const float near = (float)d->depth_range[0]; - const float far_real = (float)d->depth_range[1]; - float far = far_real; - - const float *depths = d->depths; - float depth = FLT_MAX; - int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ - - /* far is both the starting 'far' value - * and the closest value found. */ - while (i--) { - depth = *depths++; - if ((depth < far) && (depth > near)) { - far = depth; - } - } - - return far == far_real ? FLT_MAX : far; -} - -void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d) -{ - /* Setup view matrix. */ - ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL); - - GPU_clear(GPU_DEPTH_BIT); - - GPU_depth_test(true); - - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport); - - GPU_depth_test(false); -} - -/* *********************** customdata **************** */ - -void ED_view3d_datamask(const bContext *C, - const Scene *UNUSED(scene), - const View3D *v3d, - CustomData_MeshMasks *r_cddata_masks) -{ - if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) { - r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; - r_cddata_masks->vmask |= CD_MASK_ORCO; - } - else if (v3d->shading.type == OB_SOLID) { - if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) { - r_cddata_masks->lmask |= CD_MASK_MLOOPUV; - } - if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) { - r_cddata_masks->lmask |= CD_MASK_MLOOPCOL; - } - } - - if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) && - (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) { - r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; - } -} - -/* goes over all modes and view3d settings */ -void ED_view3d_screen_datamask(const bContext *C, - const Scene *scene, - const bScreen *screen, - CustomData_MeshMasks *r_cddata_masks) -{ - CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH); - - /* check if we need tfaces & mcols due to view mode */ - for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_VIEW3D) { - ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks); - } - } -} - -/** - * Store values from #RegionView3D, set when drawing. - * This is needed when we draw with to a viewport using a different matrix - * (offscreen drawing for example). - * - * Values set by #ED_view3d_update_viewmat should be handled here. - */ -struct RV3DMatrixStore { - float winmat[4][4]; - float viewmat[4][4]; - float viewinv[4][4]; - float persmat[4][4]; - float persinv[4][4]; - float viewcamtexcofac[4]; - float pixsize; -}; - -struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) -{ - struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); - copy_m4_m4(rv3dmat->winmat, rv3d->winmat); - copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); - copy_m4_m4(rv3dmat->persmat, rv3d->persmat); - copy_m4_m4(rv3dmat->persinv, rv3d->persinv); - copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); - copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); - rv3dmat->pixsize = rv3d->pixsize; - return (void *)rv3dmat; -} - -void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt) -{ - struct RV3DMatrixStore *rv3dmat = rv3dmat_pt; - copy_m4_m4(rv3d->winmat, rv3dmat->winmat); - copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); - copy_m4_m4(rv3d->persmat, rv3dmat->persmat); - copy_m4_m4(rv3d->persinv, rv3dmat->persinv); - copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); - copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); - rv3d->pixsize = rv3dmat->pixsize; -} - -/** - * \note The info that this uses is updated in #ED_refresh_viewport_fps, - * which currently gets called during #SCREEN_OT_animation_step. - */ -void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset) -{ - ScreenFrameRateInfo *fpsi = scene->fps_info; - char printable[16]; - - if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) { - return; - } - - printable[0] = '\0'; - -#if 0 - /* this is too simple, better do an average */ - fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)) -#else - fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / - (fpsi->lredrawtime - fpsi->redrawtime)); - - float fps = 0.0f; - int tot = 0; - for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) { - if (fpsi->redrawtimes_fps[i]) { - fps += fpsi->redrawtimes_fps[i]; - tot++; - } - } - if (tot) { - fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; - - // fpsi->redrawtime_index++; - // if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) { - // fpsi->redrawtime = 0; - //} - - fps = fps / tot; - } -#endif - - const int font_id = BLF_default(); - - /* is this more than half a frame behind? */ - if (fps + 0.5f < (float)(FPS)) { - UI_FontThemeColor(font_id, TH_REDALERT); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); - } - else { - UI_FontThemeColor(font_id, TH_TEXT_HI); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); - } - - BLF_enable(font_id, BLF_SHADOW); - BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); - BLF_shadow_offset(font_id, 1, -1); - - *yoffset -= U.widget_unit; - -#ifdef WITH_INTERNATIONAL - BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); -#else - BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); -#endif - - BLF_disable(font_id, BLF_SHADOW); -} - -static bool view3d_main_region_do_render_draw(const Scene *scene) -{ - RenderEngineType *type = RE_engines_find(scene->r.engine); - return (type && type->view_update && type->view_draw); -} - -bool ED_view3d_calc_render_border( - const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - bool use_border; - - /* test if there is a 3d view rendering */ - if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) { - return false; - } - - /* test if there is a border render */ - if (rv3d->persp == RV3D_CAMOB) { - use_border = (scene->r.mode & R_BORDER) != 0; - } - else { - use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; - } - - if (!use_border) { - return false; - } - - /* compute border */ - if (rv3d->persp == RV3D_CAMOB) { - rctf viewborder; - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false); - - rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); - rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); - rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); - rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); - } - else { - rect->xmin = v3d->render_border.xmin * ar->winx; - rect->xmax = v3d->render_border.xmax * ar->winx; - rect->ymin = v3d->render_border.ymin * ar->winy; - rect->ymax = v3d->render_border.ymax * ar->winy; - } - - BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); - BLI_rcti_isect(&ar->winrct, rect, rect); - - return true; -} |