From dcca1699d3233e45021044c5bc56116dd80a26e5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Apr 2013 11:29:31 -0700 Subject: [PATCH] Adding first cut at ViewFrustum pointIn,SphereIn,BoxIn code. - Added Plane class - Added AABox class - Removed some experimental "slightly inside" code from view frustum --- libraries/voxels/src/AABox.cpp | 76 +++++++++++++++++++++++++ libraries/voxels/src/AABox.h | 33 +++++++++++ libraries/voxels/src/Plane.cpp | 83 ++++++++++++++++++++++++++++ libraries/voxels/src/Plane.h | 35 ++++++++++++ libraries/voxels/src/ViewFrustum.cpp | 65 ++++++++++++++++++---- libraries/voxels/src/ViewFrustum.h | 11 ++++ 6 files changed, 292 insertions(+), 11 deletions(-) create mode 100755 libraries/voxels/src/AABox.cpp create mode 100755 libraries/voxels/src/AABox.h create mode 100755 libraries/voxels/src/Plane.cpp create mode 100755 libraries/voxels/src/Plane.h diff --git a/libraries/voxels/src/AABox.cpp b/libraries/voxels/src/AABox.cpp new file mode 100755 index 0000000000..bc36bca7a9 --- /dev/null +++ b/libraries/voxels/src/AABox.cpp @@ -0,0 +1,76 @@ +/* ------------------------------------------------------ + + Axis Aligned Boxes - Lighthouse3D + + -----------------------------------------------------*/ + +#include "AABox.h" + + +AABox::AABox(const glm::vec3& corner, float x, float y, float z) { + setBox(corner,x,y,z); +} + +AABox::AABox(void) { + corner.x = 0; corner.y = 0; corner.z = 0; + x = 1.0f; + y = 1.0f; + z = 1.0f; +} + + +AABox::~AABox() {} + + + +void AABox::setBox(const glm::vec3& corner, float x, float y, float z) { + this->corner = corner; + if (x < 0.0) { + x = -x; + this->corner.x -= x; + } + if (y < 0.0) { + y = -y; + this->corner.y -= y; + } + if (z < 0.0) { + z = -z; + this->corner.z -= z; + } + this->x = x; + this->y = y; + this->z = z; +} + + + +glm::vec3 AABox::getVertexP(const glm::vec3 &normal) { + glm::vec3 res = corner; + if (normal.x > 0) + res.x += x; + + if (normal.y > 0) + res.y += y; + + if (normal.z > 0) + res.z += z; + + return(res); +} + + + +glm::vec3 AABox::getVertexN(const glm::vec3 &normal) { + glm::vec3 res = corner; + + if (normal.x < 0) + res.x += x; + + if (normal.y < 0) + res.y += y; + + if (normal.z < 0) + res.z += z; + + return(res); +} diff --git a/libraries/voxels/src/AABox.h b/libraries/voxels/src/AABox.h new file mode 100755 index 0000000000..abc20f38d5 --- /dev/null +++ b/libraries/voxels/src/AABox.h @@ -0,0 +1,33 @@ +/* ------------------------------------------------------ + + Axis Aligned Boxes - Lighthouse3D + + -----------------------------------------------------*/ + + +#ifndef _AABOX_ +#define _AABOX_ + +#include + +class AABox +{ + +public: + + glm::vec3 corner; + float x,y,z; + + AABox(const glm::vec3 &corner, float x, float y, float z); + AABox(void); + ~AABox(); + + void setBox(const glm::vec3& corner, float x, float y, float z); + + // for use in frustum computations + glm::vec3 getVertexP(const glm::vec3& normal); + glm::vec3 getVertexN(const glm::vec3& normal); +}; + + +#endif \ No newline at end of file diff --git a/libraries/voxels/src/Plane.cpp b/libraries/voxels/src/Plane.cpp new file mode 100755 index 0000000000..fa23affe6c --- /dev/null +++ b/libraries/voxels/src/Plane.cpp @@ -0,0 +1,83 @@ +// Plane.cpp +// +////////////////////////////////////////////////////////////////////// + +#include "Plane.h" +#include + +// These are some useful utilities that vec3 is missing +float vec3_length(const glm::vec3& v) { + return((float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z)); +} + +void vec3_normalize(glm::vec3& v) { + + float len; + + len = vec3_length(v); + if (len) { + v.x /= len;; + v.y /= len; + v.z /= len; + } +} + +float vec3_innerProduct(const glm::vec3& v1,const glm::vec3& v2) { + + return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z); +} + + + +Plane::Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { + + set3Points(v1,v2,v3); +} + + +Plane::Plane() {} + +Plane::~Plane() {} + + +void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { + + + glm::vec3 aux1, aux2; + + aux1 = v1 - v2; + aux2 = v3 - v2; + + normal = aux2 * aux1; + + vec3_normalize(normal); + point = v2; + d = -(vec3_innerProduct(normal,point)); +} + +void Plane::setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point) { + + this->normal = normal; + vec3_normalize(this->normal); + d = -(vec3_innerProduct(this->normal,point)); +} + +void Plane::setCoefficients(float a, float b, float c, float d) { + + // set the normal vector + normal = glm::vec3(a,b,c); + //compute the lenght of the vector + float l = normal.length(); + // normalize the vector + normal = glm::vec3(a/l,b/l,c/l); + // and divide d by th length as well + this->d = d/l; +} + +float Plane::distance(const glm::vec3 &p) { + return (d + vec3_innerProduct(normal,p)); +} + +void Plane::print() { + //printf("Plane(");normal.print();printf("# %f)",d); +} diff --git a/libraries/voxels/src/Plane.h b/libraries/voxels/src/Plane.h new file mode 100755 index 0000000000..5c23993dc9 --- /dev/null +++ b/libraries/voxels/src/Plane.h @@ -0,0 +1,35 @@ +////////////////////////////////////////////////////////////////////// +// Plane.h - inspired and modified from lighthouse3d.com +// + + +#ifndef _PLANE_ +#define _PLANE_ + +#include + + +class Plane +{ + +public: + + glm::vec3 normal,point; + float d; + + + Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3); + Plane(void); + ~Plane(); + + void set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3); + void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point); + void setCoefficients(float a, float b, float c, float d); + float distance(const glm::vec3 &p); + + void print(); + +}; + + +#endif \ No newline at end of file diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index 1de5c11d6a..487b715ca6 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -55,34 +55,43 @@ void ViewFrustum::calculate() { float twoTimesTanHalfFOV = 2.0f * tan(fovInRadians/2.0f); - float slightlySmaller = 0.0f; - float slightlyInsideWidth= 0.0f - slightlySmaller; - float slightlyInsideNear = 0.0f + slightlySmaller; - float slightlyInsideFar = 0.0f - slightlySmaller; - - float nearClip = this->_nearClip + slightlyInsideNear; - float farClip = this->_farClip + slightlyInsideFar; + // Do we need this? + //tang = (float)tan(ANG2RAD * angle * 0.5) ; + + float nearClip = this->_nearClip; + float farClip = this->_farClip; this->_nearHeight = (twoTimesTanHalfFOV * nearClip); this->_nearWidth = this->_nearHeight * this->_aspectRatio; this->_farHeight = (twoTimesTanHalfFOV * farClip); this->_farWidth = this->_farHeight * this->_aspectRatio; - float farHalfHeight = (this->_farHeight * 0.5f) + slightlyInsideWidth; - float farHalfWidth = (this->_farWidth * 0.5f) + slightlyInsideWidth; + float farHalfHeight = (this->_farHeight * 0.5f); + float farHalfWidth = (this->_farWidth * 0.5f); this->_farCenter = this->_position+front * farClip; this->_farTopLeft = this->_farCenter + (this->_up * farHalfHeight) - (this->_right * farHalfWidth); this->_farTopRight = this->_farCenter + (this->_up * farHalfHeight) + (this->_right * farHalfWidth); this->_farBottomLeft = this->_farCenter - (this->_up * farHalfHeight) - (this->_right * farHalfWidth); this->_farBottomRight = this->_farCenter - (this->_up * farHalfHeight) + (this->_right * farHalfWidth); - float nearHalfHeight = (this->_nearHeight * 0.5f) + slightlyInsideWidth; - float nearHalfWidth = (this->_nearWidth * 0.5f) + slightlyInsideWidth; + float nearHalfHeight = (this->_nearHeight * 0.5f); + float nearHalfWidth = (this->_nearWidth * 0.5f); this->_nearCenter = this->_position+front * nearClip; this->_nearTopLeft = this->_nearCenter + (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth); this->_nearTopRight = this->_nearCenter + (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth); this->_nearBottomLeft = this->_nearCenter - (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth); this->_nearBottomRight = this->_nearCenter - (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth); + + // compute the six planes + // the function set3Points assumes that the points + // are given in counter clockwise order + this->_planes[TOPP].set3Points(this->_nearTopRight,this->_nearTopLeft,this->_farTopLeft); + this->_planes[BOTTOMP].set3Points(this->_nearBottomLeft,this->_nearBottomRight,this->_farBottomRight); + this->_planes[LEFTP].set3Points(this->_nearTopLeft,this->_nearBottomLeft,this->_farBottomLeft); + this->_planes[RIGHTP].set3Points(this->_nearBottomRight,this->_nearTopRight,this->_farBottomRight); + this->_planes[NEARP].set3Points(this->_nearTopLeft,this->_nearTopRight,this->_nearBottomRight); + this->_planes[FARP].set3Points(this->_farTopRight,this->_farTopLeft,this->_farBottomLeft); + } void ViewFrustum::dump() { @@ -124,3 +133,37 @@ void ViewFrustum::dump() { } +int ViewFrustum::pointInFrustum(glm::vec3 &p) { + int result = INSIDE; + for(int i=0; i < 6; i++) { + if (this->_planes[i].distance(p) < 0) + return OUTSIDE; + } + return(result); +} + +int ViewFrustum::sphereInFrustum(glm::vec3 ¢er, float radius) { + int result = INSIDE; + float distance; + for(int i=0; i < 6; i++) { + distance = this->_planes[i].distance(center); + if (distance < -radius) + return OUTSIDE; + else if (distance < radius) + result = INTERSECT; + } + return(result); +} + + +int ViewFrustum::boxInFrustum(AABox &b) { + int result = INSIDE; + for(int i=0; i < 6; i++) { + if (this->_planes[i].distance(b.getVertexP(this->_planes[i].normal)) < 0) + return OUTSIDE; + else if (this->_planes[i].distance(b.getVertexN(this->_planes[i].normal)) < 0) + result = INTERSECT; + } + return(result); + } + diff --git a/libraries/voxels/src/ViewFrustum.h b/libraries/voxels/src/ViewFrustum.h index ed704e5755..15bdb484fb 100644 --- a/libraries/voxels/src/ViewFrustum.h +++ b/libraries/voxels/src/ViewFrustum.h @@ -12,6 +12,8 @@ #define __hifi__ViewFrustum__ #include +#include "Plane.h" +#include "AABox.h" class ViewFrustum { private: @@ -43,6 +45,8 @@ private: glm::vec3 _nearTopRight; glm::vec3 _nearBottomLeft; glm::vec3 _nearBottomRight; + enum { TOPP = 0, BOTTOMP, LEFTP, RIGHTP, NEARP, FARP }; + Plane _planes[6]; // How will this be used? public: // setters for camera attributes @@ -79,6 +83,13 @@ public: ViewFrustum(); void dump(); + + enum {OUTSIDE, INTERSECT, INSIDE}; + + int pointInFrustum(glm::vec3 &p); + int sphereInFrustum(glm::vec3 ¢er, float radius); + int boxInFrustum(AABox &b); + };