Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/intern/draw_view.cc
| Show All 18 Lines | |||||
| { | { | ||||
| data_[view_id].viewmat = view_mat; | data_[view_id].viewmat = view_mat; | ||||
| data_[view_id].viewinv = view_mat.inverted(); | data_[view_id].viewinv = view_mat.inverted(); | ||||
| data_[view_id].winmat = win_mat; | data_[view_id].winmat = win_mat; | ||||
| data_[view_id].wininv = win_mat.inverted(); | data_[view_id].wininv = win_mat.inverted(); | ||||
| is_inverted_ = (is_negative_m4(view_mat.ptr()) == is_negative_m4(win_mat.ptr())); | is_inverted_ = (is_negative_m4(view_mat.ptr()) == is_negative_m4(win_mat.ptr())); | ||||
| BoundBox &bound_box = *reinterpret_cast<BoundBox *>(&culling_[view_id].corners); | frustum_boundbox_calc(view_id); | ||||
| BoundSphere &bound_sphere = *reinterpret_cast<BoundSphere *>(&culling_[view_id].bound_sphere); | |||||
| frustum_boundbox_calc(bound_box, view_id); | |||||
| frustum_culling_planes_calc(view_id); | frustum_culling_planes_calc(view_id); | ||||
| frustum_culling_sphere_calc(bound_box, bound_sphere, view_id); | frustum_culling_sphere_calc(view_id); | ||||
| dirty_ = true; | dirty_ = true; | ||||
| } | } | ||||
| void View::frustum_boundbox_calc(BoundBox &bbox, int view_id) | void View::frustum_boundbox_calc(int view_id) | ||||
| { | { | ||||
| /* Extract the 8 corners from a Projection Matrix. */ | /* Extract the 8 corners from a Projection Matrix. */ | ||||
| #if 0 /* Equivalent to this but it has accuracy problems. */ | #if 0 /* Equivalent to this but it has accuracy problems. */ | ||||
| BKE_boundbox_init_from_minmax(&bbox, float3(-1.0f),float3(1.0f)); | BKE_boundbox_init_from_minmax(&bbox, float3(-1.0f),float3(1.0f)); | ||||
| for (int i = 0; i < 8; i++) { | for (int i = 0; i < 8; i++) { | ||||
| mul_project_m4_v3(data_.wininv.ptr(), bbox.vec[i]); | mul_project_m4_v3(data_.wininv.ptr(), bbox.vec[i]); | ||||
| } | } | ||||
| #endif | #endif | ||||
| MutableSpan<float4> corners = {culling_[view_id].corners, ARRAY_SIZE(culling_[view_id].corners)}; | |||||
fclem: Same here. | |||||
| float left, right, bottom, top, near, far; | float left, right, bottom, top, near, far; | ||||
| bool is_persp = data_[view_id].winmat[3][3] == 0.0f; | bool is_persp = data_[view_id].winmat[3][3] == 0.0f; | ||||
| projmat_dimensions(data_[view_id].winmat.ptr(), &left, &right, &bottom, &top, &near, &far); | projmat_dimensions(data_[view_id].winmat.ptr(), &left, &right, &bottom, &top, &near, &far); | ||||
| bbox.vec[0][2] = bbox.vec[3][2] = bbox.vec[7][2] = bbox.vec[4][2] = -near; | corners[0][2] = corners[3][2] = corners[7][2] = corners[4][2] = -near; | ||||
| bbox.vec[0][0] = bbox.vec[3][0] = left; | corners[0][0] = corners[3][0] = left; | ||||
| bbox.vec[4][0] = bbox.vec[7][0] = right; | corners[4][0] = corners[7][0] = right; | ||||
| bbox.vec[0][1] = bbox.vec[4][1] = bottom; | corners[0][1] = corners[4][1] = bottom; | ||||
| bbox.vec[7][1] = bbox.vec[3][1] = top; | corners[7][1] = corners[3][1] = top; | ||||
| /* Get the coordinates of the far plane. */ | /* Get the coordinates of the far plane. */ | ||||
| if (is_persp) { | if (is_persp) { | ||||
| float sca_far = far / near; | float sca_far = far / near; | ||||
| left *= sca_far; | left *= sca_far; | ||||
| right *= sca_far; | right *= sca_far; | ||||
| bottom *= sca_far; | bottom *= sca_far; | ||||
| top *= sca_far; | top *= sca_far; | ||||
| } | } | ||||
| bbox.vec[1][2] = bbox.vec[2][2] = bbox.vec[6][2] = bbox.vec[5][2] = -far; | corners[1][2] = corners[2][2] = corners[6][2] = corners[5][2] = -far; | ||||
| bbox.vec[1][0] = bbox.vec[2][0] = left; | corners[1][0] = corners[2][0] = left; | ||||
| bbox.vec[6][0] = bbox.vec[5][0] = right; | corners[6][0] = corners[5][0] = right; | ||||
| bbox.vec[1][1] = bbox.vec[5][1] = bottom; | corners[1][1] = corners[5][1] = bottom; | ||||
| bbox.vec[2][1] = bbox.vec[6][1] = top; | corners[2][1] = corners[6][1] = top; | ||||
| /* Transform into world space. */ | /* Transform into world space. */ | ||||
| for (int i = 0; i < 8; i++) { | for (float4 &corner : corners) { | ||||
| mul_m4_v3(data_[view_id].viewinv.ptr(), bbox.vec[i]); | mul_m4_v3(data_[view_id].viewinv.ptr(), corner); | ||||
| corner.w = 1.0; | |||||
| } | } | ||||
| } | } | ||||
| void View::frustum_culling_planes_calc(int view_id) | void View::frustum_culling_planes_calc(int view_id) | ||||
| { | { | ||||
| float4x4 persmat = data_[view_id].winmat * data_[view_id].viewmat; | float4x4 persmat = data_[view_id].winmat * data_[view_id].viewmat; | ||||
| planes_from_projmat(persmat.ptr(), | planes_from_projmat(persmat.ptr(), | ||||
| culling_[view_id].planes[0], | culling_[view_id].planes[0], | ||||
| culling_[view_id].planes[5], | culling_[view_id].planes[5], | ||||
| culling_[view_id].planes[1], | culling_[view_id].planes[1], | ||||
| culling_[view_id].planes[3], | culling_[view_id].planes[3], | ||||
| culling_[view_id].planes[4], | culling_[view_id].planes[4], | ||||
| culling_[view_id].planes[2]); | culling_[view_id].planes[2]); | ||||
| /* Normalize. */ | /* Normalize. */ | ||||
| for (int p = 0; p < 6; p++) { | for (float4 &plane : culling_[view_id].planes) { | ||||
| culling_[view_id].planes[p].w /= normalize_v3(culling_[view_id].planes[p]); | plane.w /= normalize_v3(plane); | ||||
| } | } | ||||
| } | } | ||||
| void View::frustum_culling_sphere_calc(const BoundBox &bbox, BoundSphere &bsphere, int view_id) | void View::frustum_culling_sphere_calc(int view_id) | ||||
| { | { | ||||
| BoundSphere &bsphere = *reinterpret_cast<BoundSphere *>(&culling_[view_id].bound_sphere); | |||||
| Span<float4> corners = {culling_[view_id].corners, ARRAY_SIZE(culling_[view_id].corners)}; | |||||
Done Inline ActionsPrefer using blender::Span<float4> corners(culling_[view_id].corners, ARRAY_SIZE(culling_[view_id].corners));. This adds bound checks on access and allow to iterate over its data. fclem: Prefer using `blender::Span<float4> corners(culling_[view_id].corners, ARRAY_SIZE(culling_… | |||||
| /* Extract Bounding Sphere */ | /* Extract Bounding Sphere */ | ||||
| if (data_[view_id].winmat[3][3] != 0.0f) { | if (data_[view_id].winmat[3][3] != 0.0f) { | ||||
| /* Orthographic */ | /* Orthographic */ | ||||
| /* The most extreme points on the near and far plane. (normalized device coords). */ | /* The most extreme points on the near and far plane. (normalized device coords). */ | ||||
| const float *nearpoint = bbox.vec[0]; | const float *nearpoint = corners[0]; | ||||
| const float *farpoint = bbox.vec[6]; | const float *farpoint = corners[6]; | ||||
| /* just use median point */ | /* just use median point */ | ||||
| mid_v3_v3v3(bsphere.center, farpoint, nearpoint); | mid_v3_v3v3(bsphere.center, farpoint, nearpoint); | ||||
| bsphere.radius = len_v3v3(bsphere.center, farpoint); | bsphere.radius = len_v3v3(bsphere.center, farpoint); | ||||
| } | } | ||||
| else if (data_[view_id].winmat[2][0] == 0.0f && data_[view_id].winmat[2][1] == 0.0f) { | else if (data_[view_id].winmat[2][0] == 0.0f && data_[view_id].winmat[2][1] == 0.0f) { | ||||
| /* Perspective with symmetrical frustum. */ | /* Perspective with symmetrical frustum. */ | ||||
| /* We obtain the center and radius of the circumscribed circle of the | /* We obtain the center and radius of the circumscribed circle of the | ||||
| * isosceles trapezoid composed by the diagonals of the near and far clipping plane */ | * isosceles trapezoid composed by the diagonals of the near and far clipping plane */ | ||||
| /* center of each clipping plane */ | /* center of each clipping plane */ | ||||
| float mid_min[3], mid_max[3]; | float mid_min[3], mid_max[3]; | ||||
| mid_v3_v3v3(mid_min, bbox.vec[3], bbox.vec[4]); | mid_v3_v3v3(mid_min, corners[3], corners[4]); | ||||
| mid_v3_v3v3(mid_max, bbox.vec[2], bbox.vec[5]); | mid_v3_v3v3(mid_max, corners[2], corners[5]); | ||||
| /* square length of the diagonals of each clipping plane */ | /* square length of the diagonals of each clipping plane */ | ||||
| float a_sq = len_squared_v3v3(bbox.vec[3], bbox.vec[4]); | float a_sq = len_squared_v3v3(corners[3], corners[4]); | ||||
| float b_sq = len_squared_v3v3(bbox.vec[2], bbox.vec[5]); | float b_sq = len_squared_v3v3(corners[2], corners[5]); | ||||
| /* distance squared between clipping planes */ | /* distance squared between clipping planes */ | ||||
| float h_sq = len_squared_v3v3(mid_min, mid_max); | float h_sq = len_squared_v3v3(mid_min, mid_max); | ||||
| float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq); | float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq); | ||||
| /* The goal is to get the smallest sphere, | /* The goal is to get the smallest sphere, | ||||
| * not the sphere that passes through each corner */ | * not the sphere that passes through each corner */ | ||||
| CLAMP(fac, 0.0f, 1.0f); | CLAMP(fac, 0.0f, 1.0f); | ||||
| interp_v3_v3v3(bsphere.center, mid_min, mid_max, fac); | interp_v3_v3v3(bsphere.center, mid_min, mid_max, fac); | ||||
| /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */ | /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */ | ||||
| bsphere.radius = len_v3v3(bsphere.center, bbox.vec[1]); | bsphere.radius = len_v3v3(bsphere.center, corners[1]); | ||||
| } | } | ||||
| else { | else { | ||||
| /* Perspective with asymmetrical frustum. */ | /* Perspective with asymmetrical frustum. */ | ||||
| /* We put the sphere center on the line that goes from origin | /* We put the sphere center on the line that goes from origin | ||||
| * to the center of the far clipping plane. */ | * to the center of the far clipping plane. */ | ||||
| /* Detect which of the corner of the far clipping plane is the farthest to the origin */ | /* Detect which of the corner of the far clipping plane is the farthest to the origin */ | ||||
| ▲ Show 20 Lines • Show All 127 Lines • Show Last 20 Lines | |||||
Same here.