Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano <germano.costa@ig.com.br>2018-03-07 01:27:43 +0300
committerGermano <germano.costa@ig.com.br>2018-03-07 01:27:43 +0300
commit267e816b9a603026d951f8e8e318ceaed04ca944 (patch)
tree84a83007544b904821c2ec7fc6c146791077b4f5 /source/blender/draw/intern
parentfaf70e1e64b88e047efbc34004f46466f0b48c8a (diff)
Draw Manager: Simplify the algorithm that extract the BoundingSphere of a Frustum
The idea is to separate the most common case from symmetrical frustum. And to make a simple but efficient calculation. The new radius is usually 98% the size of the radius size of the asymmetric solution. Thanks to @fclem for reviewing the patch on IRC
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c78
1 files changed, 53 insertions, 25 deletions
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 7b97709d51b..a984a0b782f 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -420,15 +420,57 @@ static void draw_clipping_setup_from_view(void)
}
/* Extract Bounding Sphere */
- /**
- * Compute bounding sphere for the general case and not only symmetric frustum:
- * We put the sphere center on the line that goes from origin to the center of the far clipping plane.
- * This is the optimal position if the frustum is symmetric or very asymmetric and probably close
- * to optimal for the general case. The sphere center position is computed so that the distance to
- * the near and far extreme frustum points are equal.
- **/
- if (projmat[3][3] == 0.0f) {
- /* Perspective */
+ if (projmat[3][3] != 0.0f) {
+ /* Orthographic */
+ /* The most extreme points on the near and far plane. (normalized device coords). */
+ float *nearpoint = bbox.vec[0];
+ float *farpoint = bbox.vec[6];
+
+ mul_project_m4_v3(projinv, nearpoint);
+ mul_project_m4_v3(projinv, farpoint);
+
+ /* just use median point */
+ mid_v3_v3v3(bsphere->center, farpoint, nearpoint);
+ bsphere->radius = len_v3v3(bsphere->center, farpoint);
+ }
+ else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) {
+ /* Perspective with symmetrical frustum. */
+
+ /* 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 */
+
+ /* center of each clipping plane */
+ float mid_min[3], mid_max[3];
+ mid_v3_v3v3(mid_min, bbox.vec[3], bbox.vec[4]);
+ mid_v3_v3v3(mid_max, bbox.vec[2], bbox.vec[5]);
+
+ /* square length of the diagonals of each clipping plane */
+ float a_sq = len_squared_v3v3(bbox.vec[3], bbox.vec[4]);
+ float b_sq = len_squared_v3v3(bbox.vec[2], bbox.vec[5]);
+
+ /* distance squared between clipping planes */
+ float h_sq = len_squared_v3v3(mid_min, mid_max);
+
+ float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq);
+ BLI_assert(fac >= 0.0f);
+
+ /* The goal is to get the smallest sphere,
+ * not the sphere that passes through each corner */
+ if (fac > 1.0f) {
+ fac = 1.0f;
+ }
+
+ 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) */
+ bsphere->radius = len_v3v3(bsphere->center, bbox.vec[1]);
+ }
+ else {
+ /* Perspective with asymmetrical frustum. */
+
+ /* We put the sphere center on the line that goes from origin
+ * to the center of the far clipping plane. */
+
/* Detect which of the corner of the far clipping plane is the farthest to the origin */
float nfar[4]; /* most extreme far point in NDC space */
float farxy[2]; /* farpoint projection onto the near plane */
@@ -483,24 +525,10 @@ static void draw_clipping_setup_from_view(void)
bsphere->center[1] = farcenter[1] * z/e;
bsphere->center[2] = z;
bsphere->radius = len_v3v3(bsphere->center, farpoint);
- }
- else {
- /* Orthographic */
- /* The most extreme points on the near and far plane. (normalized device coords) */
- float nearpoint[3] = {-1.0f, -1.0f, -1.0f};
- float farpoint[3] = { 1.0f, 1.0f, 1.0f};
- mul_project_m4_v3(projinv, nearpoint);
- mul_project_m4_v3(projinv, farpoint);
-
- /* just use median point */
- mid_v3_v3v3(bsphere->center, farpoint, nearpoint);
- bsphere->radius = len_v3v3(bsphere->center, farpoint);
+ /* Transform to world space. */
+ mul_m4_v3(viewinv, bsphere->center);
}
-
- /* Transform to world space. */
- mul_m4_v3(viewinv, bsphere->center);
-
}
/* Return True if the given BoundSphere intersect the current view frustum */