Implement Sphere::RandomPointOnSurface() RandomPointInside()
This commit is contained in:
@@ -24,6 +24,28 @@ namespace J3ML::Geometry
|
||||
Sphere() {}
|
||||
Sphere(const Vector3& pos, float radius) : Position(pos), Radius(radius) {}
|
||||
|
||||
/// Generates a random point on the surface of this sphere
|
||||
/** The points are distributed uniformly.
|
||||
This function uses the rejection method to generate a uniform distribution of points on the surface.
|
||||
Therefore, it is assumed that this sphere is not degenerate, i.e. it has a positive radius.
|
||||
A fixed number of 1000 tries is performed, after which a fixed point on the surface is returned as a fallback.
|
||||
@param rng A pre-seeded random number generator object that is to be used by this function to generate random vlaues.
|
||||
@see class RNG, RandomPointInside(), IsDegenerate()
|
||||
@todo Add Sphere::PointOnSurface(polarYaw, polarPitch). */
|
||||
Vector3 RandomPointOnSurface(RNG& rng) const;
|
||||
static Vector3 RandomPointOnSurface(RNG& rng, const Vector3& center, float radius);
|
||||
|
||||
/// Generates a random point inside this sphere.
|
||||
/** The points are distributed uniformly.
|
||||
This function uses the rejection method to generate a uniform distribution of points inside a sphere.
|
||||
Therefore, it is assumed that this sphere is not degenerate, i.e. it has a positive radius.
|
||||
A fixed number of 1000 tries is performed, after which the sphere center position is returned as a fallback.
|
||||
@param rng A pre-seeded random number generator object that is to be used by this function to generate random values.
|
||||
@see class RNG, RandomPointOnSurface(), IsDegenerate().
|
||||
@todo Add Sphere::Point(polarYaw, polarPitch, radius). */
|
||||
Vector3 RandomPointInside(RNG& rng);
|
||||
static Vector3 RandomPointInside(RNG& rng, const Vector3& center, float radius);
|
||||
public:
|
||||
/// Quickly returns an arbitrary point inside this Sphere. Used in GJK intersection test.
|
||||
Vector3 AnyPointFast() const { return Position; }
|
||||
/// Computes the extreme point of this Sphere in the given direction.
|
||||
|
@@ -25,4 +25,47 @@ namespace J3ML::Geometry
|
||||
projectionDistance = extremePoint.Dot(direction);
|
||||
return extremePoint;
|
||||
}
|
||||
|
||||
Vector3 Sphere::RandomPointOnSurface(RNG &rng) const {
|
||||
Vector3 v = Vector3::Zero;
|
||||
// Rejection sampling analysis: The unit sphere fills ~52.4% of the volume of its enclosing box,
|
||||
// so this loop is expected to take only very few iterations before succeeding.
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
v.x = rng.FloatNeg1_1();
|
||||
v.y = rng.FloatNeg1_1();
|
||||
v.z = rng.FloatNeg1_1();
|
||||
float lenSq = v.LengthSquared();
|
||||
if (lenSq >= 1e-6f && lenSq <= 1.f)
|
||||
return Position + (Radius / std::sqrt(lenSq)) * v;
|
||||
}
|
||||
// Astronomically small probability to reach here, and if we do so, the provided RNG must have been in a bad state.
|
||||
assert(false && "Sphere::RandomPointOnSurface failed!");
|
||||
|
||||
// Failed to generate a point inside this sphere. Return an arbitrary point on the surface as fallback.
|
||||
return Position + Vector3(Radius, 0, 0);
|
||||
}
|
||||
|
||||
Vector3 Sphere::RandomPointInside(RNG &rng) {
|
||||
assert(Radius > 1e-3f);
|
||||
Vector3 v = Vector3::Zero;
|
||||
|
||||
// Rejection sampling analysis: The unit sphere fills ~52.4% of the volume of its enclosing box
|
||||
// so this loop is expected to take only very few iterations before succeeding.
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
v.x = rng.Float(-Radius, Radius);
|
||||
v.y = rng.Float(-Radius, Radius);
|
||||
v.z = rng.Float(-Radius, Radius);
|
||||
|
||||
if (v.LengthSquared() <= Radius*Radius)
|
||||
return Position + v;
|
||||
}
|
||||
assert(false && "Sphere::RandomPointInside failed!");
|
||||
|
||||
// Failed to generate a point inside this sphere. Return the sphere center as fallback.
|
||||
return Position;
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user