View3D: take clipping into account for Frame All
Clamp the min/max used for Frame All/Selected by the clipping region if it's set. Resolve T81050
This commit is contained in:
parent
19a0df25e3
commit
a452fcb9a5
Notes:
blender-bot
2023-10-18 15:23:11 +02:00
Referenced by issue #81050, Take Clipping Region into account for Frame All
|
@ -459,6 +459,8 @@ void ED_view3d_clipping_calc(struct BoundBox *bb,
|
|||
const struct ARegion *region,
|
||||
const struct Object *ob,
|
||||
const struct rcti *rect);
|
||||
bool ED_view3d_clipping_clamp_minmax(const struct RegionView3D *rv3d, float min[3], float max[3]);
|
||||
|
||||
void ED_view3d_clipping_local(struct RegionView3D *rv3d, const float mat[4][4]);
|
||||
bool ED_view3d_clipping_test(const struct RegionView3D *rv3d,
|
||||
const float co[3],
|
||||
|
|
|
@ -2978,6 +2978,11 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
|
||||
/* This is an approximation, see function documentation for details. */
|
||||
ED_view3d_clipping_clamp_minmax(rv3d, min, max);
|
||||
}
|
||||
|
||||
if (use_all_regions) {
|
||||
view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
|
||||
}
|
||||
|
@ -3125,6 +3130,11 @@ static int viewselected_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
|
||||
/* This is an approximation, see function documentation for details. */
|
||||
ED_view3d_clipping_clamp_minmax(rv3d, min, max);
|
||||
}
|
||||
|
||||
if (use_all_regions) {
|
||||
view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx);
|
||||
}
|
||||
|
|
|
@ -330,6 +330,76 @@ void ED_view3d_clipping_calc(
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name View Clipping Clamp Min/Max
|
||||
* \{ */
|
||||
|
||||
struct PointsInPlanesMinMax_UserData {
|
||||
float min[3];
|
||||
float max[3];
|
||||
};
|
||||
|
||||
static void points_in_planes_minmax_fn(
|
||||
const float co[3], int UNUSED(i), int UNUSED(j), int UNUSED(k), void *user_data_p)
|
||||
{
|
||||
struct PointsInPlanesMinMax_UserData *user_data = user_data_p;
|
||||
minmax_v3v3_v3(user_data->min, user_data->max, co);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamp min/max by the viewport clipping.
|
||||
*
|
||||
* \note This is an approximation, with the limitation that the bounding box from the (mix, max)
|
||||
* calculation might not have any geometry inside the clipped region.
|
||||
* Performing a clipping test on each vertex would work well enough for most cases,
|
||||
* although it's not perfect either as edges/faces may intersect the clipping without having any
|
||||
* of their vertices inside it.
|
||||
* A more accurate result would be quite involved.
|
||||
*
|
||||
* \return True when the arguments were clamped.
|
||||
*/
|
||||
bool ED_view3d_clipping_clamp_minmax(const RegionView3D *rv3d, float min[3], float max[3])
|
||||
{
|
||||
/* 6 planes for the cube, 4..6 for the current view clipping planes. */
|
||||
float planes[6 + 6][4];
|
||||
|
||||
/* Convert the min/max to 6 planes. */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
float *plane_min = planes[(i * 2) + 0];
|
||||
float *plane_max = planes[(i * 2) + 1];
|
||||
zero_v3(plane_min);
|
||||
zero_v3(plane_max);
|
||||
plane_min[i] = -1.0f;
|
||||
plane_min[3] = +min[i];
|
||||
plane_max[i] = +1.0f;
|
||||
plane_max[3] = -max[i];
|
||||
}
|
||||
|
||||
/* Copy planes from the viewport & flip. */
|
||||
int planes_len = 6;
|
||||
int clip_len = (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) ? 4 : 6;
|
||||
for (int i = 0; i < clip_len; i++) {
|
||||
negate_v4_v4(planes[planes_len], rv3d->clip[i]);
|
||||
planes_len += 1;
|
||||
}
|
||||
|
||||
/* Calculate points intersecting all planes (effectively intersecting two bounding boxes). */
|
||||
struct PointsInPlanesMinMax_UserData user_data;
|
||||
INIT_MINMAX(user_data.min, user_data.max);
|
||||
|
||||
const float eps_coplanar = 1e-4f;
|
||||
const float eps_isect = 1e-6f;
|
||||
if (isect_planes_v3_fn(
|
||||
planes, planes_len, eps_coplanar, eps_isect, points_in_planes_minmax_fn, &user_data)) {
|
||||
copy_v3_v3(min, user_data.min);
|
||||
copy_v3_v3(max, user_data.max);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name View Bound-Box Utilities
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue