exposes function to fetch glFrustum arguments

This commit is contained in:
tosh 2013-03-25 02:47:24 +01:00
parent e965b88c88
commit 6a9134d4a5
2 changed files with 39 additions and 33 deletions

View file

@ -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);

View file

@ -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