diff options
Diffstat (limited to 'dep/g3dlite/source/Cone.cpp')
-rw-r--r-- | dep/g3dlite/source/Cone.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/dep/g3dlite/source/Cone.cpp b/dep/g3dlite/source/Cone.cpp index 3104b8424a7..586ccfd6761 100644 --- a/dep/g3dlite/source/Cone.cpp +++ b/dep/g3dlite/source/Cone.cpp @@ -17,6 +17,24 @@ namespace G3D { + +float Cone::solidAngleFromHalfAngle(float halfAngle){ + return 2.0f * pif() * (1 - cosf(halfAngle)); +} + +double Cone::solidAngleFromHalfAngle(double halfAngle){ + return 2.0 * pi() * (1.0 - cos(halfAngle)); +} + +float Cone::halfAngleFromSolidAngle(float solidAngle){ + return acos((1.0f - (solidAngle / (2.0f * pif())))); +} + +double Cone::halfAngleFromSolidAngle(double solidAngle){ + return aCos((1.0 - (solidAngle / (2.0 * pi())))); +} + + Cone::Cone(const Vector3 &tip, const Vector3 &direction, float angle) { this->tip = tip; this->direction = direction.direction(); @@ -26,6 +44,42 @@ Cone::Cone(const Vector3 &tip, const Vector3 &direction, float angle) { debugAssert(angle <= pi()); } +Vector3 Cone::randomDirectionInCone(Random& rng) const { + const float cosThresh = cos(angle); + + float cosAngle; + float normalizer; + Vector3 v; + do { + float vlenSquared; + + // Sample uniformly on a sphere by rejection sampling and then normalizing + do { + v.x = rng.uniform(-1, 1); + v.y = rng.uniform(-1, 1); + v.z = rng.uniform(-1, 1); + + // Sample uniformly on a cube + vlenSquared = v.squaredLength(); + } while (vlenSquared > 1); + + + const float temp = v.dot(direction); + + // Compute 1 / ||v||, but + // if the vector is in the wrong hemisphere, flip the sign + normalizer = rsqrt(vlenSquared) * sign(temp); + + // Cosine of the angle between v and the light's negative-z axis + cosAngle = temp * normalizer; + + } while (cosAngle < cosThresh); + + // v was within the cone. Normalize it and maybe flip the hemisphere. + return v * normalizer; + } + + /** Forms the smallest cone that contains the box. Undefined if the tip is inside or on the box. |