From 6a9134d4a5f43aaf10b35b02d8df943dc0b63075 Mon Sep 17 00:00:00 2001 From: tosh Date: Mon, 25 Mar 2013 02:47:24 +0100 Subject: [PATCH] exposes function to fetch glFrustum arguments --- interface/src/FieldOfView.cpp | 48 +++++++++++++++++------------------ interface/src/FieldOfView.h | 24 ++++++++++++------ 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/interface/src/FieldOfView.cpp b/interface/src/FieldOfView.cpp index 5b7ae3ee8e..d1f535bb39 100644 --- a/interface/src/FieldOfView.cpp +++ b/interface/src/FieldOfView.cpp @@ -17,8 +17,8 @@ using namespace glm; FieldOfView::FieldOfView() : mat_orientation(mat4(1.0f)), - vec_frustum_low(vec3(-1.0f,-1.0f,-1.0f)), - vec_frustum_high(vec3(1.0f,1.0f,1.0f)), + vec_bounds_low(vec3(-1.0f,-1.0f,-1.0f)), + vec_bounds_high(vec3(1.0f,1.0f,1.0f)), val_width(256.0f), val_height(256.0f), val_angle(0.61), @@ -31,7 +31,7 @@ mat4 FieldOfView::getViewerScreenXform() const { mat4 projection; vec3 low, high; - calcGlFrustum(low, high); + getFrustum(low, high); // perspective projection? determine correct near distance if (val_angle != 0.0f) @@ -51,19 +51,19 @@ mat4 FieldOfView::getViewerScreenXform() const mat4 FieldOfView::getWorldViewerXform() const { return translate(affineInverse(mat_orientation), - vec3(0.0f, 0.0f, -vec_frustum_high.z) ); + vec3(0.0f, 0.0f, -vec_bounds_high.z) ); } mat4 FieldOfView::getWorldScreenXform() const { return translate( getViewerScreenXform() * affineInverse(mat_orientation), - vec3(0.0f, 0.0f, -vec_frustum_high.z) ); + vec3(0.0f, 0.0f, -vec_bounds_high.z) ); } mat4 FieldOfView::getViewerWorldXform() const { - vec3 n_translate = vec3(0.0f, 0.0f, vec_frustum_high.z); + vec3 n_translate = vec3(0.0f, 0.0f, vec_bounds_high.z); return translate( translate(mat4(1.0f), n_translate) @@ -73,26 +73,21 @@ mat4 FieldOfView::getViewerWorldXform() const float FieldOfView::getPixelSize() const { vec3 low, high; - calcGlFrustum(low, high); + getFrustum(low, high); return std::min( abs(high.x - low.x) / val_width, abs(high.y - low.y) / val_height); } -void FieldOfView::calcGlFrustum(vec3& low, vec3& high) const +void FieldOfView::getFrustum(vec3& low, vec3& high) const { - low = vec_frustum_low; - high = vec_frustum_high; + low = vec_bounds_low; + high = vec_bounds_high; - // apply zoom + // start with uniform zoom float inv_zoom = 1.0f / val_zoom; - float ax = (low.x + high.x) / 2.0f, ay = (low.y + high.y) / 2.0f; - low.x = (low.x - ax) * inv_zoom + ax; - high.x = (high.x - ax) * inv_zoom + ax; - low.y = (low.y - ay) * inv_zoom + ay; - high.y = (high.y - ay) * inv_zoom + ay; - low.z = (low.z - high.z) * inv_zoom + high.z; + float adj_x = inv_zoom, adj_y = inv_zoom; // balance aspect if (enm_aspect_balancing != stretch) @@ -100,28 +95,31 @@ void FieldOfView::calcGlFrustum(vec3& low, vec3& high) const float f_aspect = (high.x - low.x) / (high.y - low.y); float vp_aspect = val_width / val_height; - float adj; if ((enm_aspect_balancing == expose_more) != (f_aspect > vp_aspect)) { // expose_more -> f_aspect <= vp_aspect <=> adj >= 1 // expose_less -> f_aspect > vp_aspect <=> adj < 1 - adj = vp_aspect / f_aspect; - low.x *= adj; - high.x *= adj; + adj_x = vp_aspect / f_aspect; } else { // expose_more -> f_aspect > vp_aspect <=> adj > 1 // expose_less -> f_aspect <= vp_aspect <=> adj <= 1 - adj = f_aspect / vp_aspect; - low.y *= adj; - high.y *= adj; + adj_y = f_aspect / vp_aspect; } } - float w = high.x - low.x, h = high.y - low.y; + // scale according to zoom / aspect correction + float ax = (low.x + high.x) / 2.0f, ay = (low.y + high.y) / 2.0f; + low.x = (low.x - ax) * adj_x + ax; + high.x = (high.x - ax) * adj_x + ax; + low.y = (low.y - ay) * adj_y + ay; + high.y = (high.y - ay) * adj_y + ay; + low.z = (low.z - high.z) * inv_zoom + high.z; + // calc and apply near distance based on near diagonal and perspective + float w = high.x - low.x, h = high.y - low.y; high.z -= low.z; low.z = val_angle == 0.0f ? 0.0f : sqrt(w*w+h*h) * 0.5f / tan(val_angle * 0.5f); diff --git a/interface/src/FieldOfView.h b/interface/src/FieldOfView.h index 254123edb4..d9f8918526 100644 --- a/interface/src/FieldOfView.h +++ b/interface/src/FieldOfView.h @@ -17,8 +17,8 @@ class FieldOfView { glm::mat4 mat_orientation; - glm::vec3 vec_frustum_low; - glm::vec3 vec_frustum_high; + glm::vec3 vec_bounds_low; + glm::vec3 vec_bounds_high; float val_width; float val_height; float val_angle; @@ -30,8 +30,8 @@ class FieldOfView // mutators - FieldOfView& setFrustum(glm::vec3 const& low, glm::vec3 const& high) - { vec_frustum_low = low; vec_frustum_high = high; return *this; } + FieldOfView& setBounds(glm::vec3 const& low, glm::vec3 const& high) + { vec_bounds_low = low; vec_bounds_high = high; return *this; } FieldOfView& setOrientation(glm::mat4 const& matrix) { mat_orientation = matrix; return *this; } @@ -57,8 +57,6 @@ class FieldOfView // dumb accessors - glm::vec3 const& getFrustumLow() const { return vec_frustum_low; } - glm::vec3 const& getFrustumHigh() const { return vec_frustum_high; } glm::mat4 const& getOrientation() const { return mat_orientation; } float getWidthInPixels() const { return val_width; } float getHeightInPixels() const { return val_height; } @@ -106,9 +104,19 @@ class FieldOfView */ float getPixelSize() const; - private: + /** + * Returns the frustum as used for the projection matrices. + * The result depdends on the bounds, eventually aspect correction + * for the current resolution, the perspective angle (specified in + * respect to diagonal) and zoom. + */ + void getFrustum(glm::vec3& low, glm::vec3& high) const; - void calcGlFrustum(glm::vec3& low, glm::vec3& high) const; + /** + * Returns the z-offset from the origin to where orientation ia + * applied. + */ + float getTransformOffset() const { return vec_bounds_high.z; } }; #endif