Skip to content

Commit 2b2022b

Browse files
committed
Implemented member function ProjectToAxis() to most of the geometry classes.
1 parent 831bfef commit 2b2022b

18 files changed

+173
-0
lines changed

src/Geometry/Capsule.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ float3 Capsule::ExtremePoint(const float3 &direction) const
8484
return (Dot(direction, l.b - l.a) >= 0.f ? l.b : l.a) + direction.ScaledToLength(r);
8585
}
8686

87+
void Capsule::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
88+
{
89+
outMin = Dot(direction, l.a);
90+
outMax = Dot(direction, l.b);
91+
if (outMax < outMin)
92+
Swap(outMin, outMax);
93+
94+
// The following requires that direction is normalized, otherwise we would have to sub/add 'r * direction.Length()', but
95+
// don't want to do that for performance reasons.
96+
assume(direction.IsNormalized());
97+
outMin -= r;
98+
outMax += r;
99+
}
100+
87101
float3 Capsule::Top() const
88102
{
89103
return l.b + UpDirection() * r;

src/Geometry/Capsule.h

+9
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ class Capsule
9595
@return The extreme point of this Capsule in the given direction. */
9696
float3 ExtremePoint(const float3 &direction) const;
9797

98+
/// Projects this Capsule onto the given 1D axis direction vector.
99+
/** This function collapses this Capsule onto an 1D axis for the purposes of e.g. separate axis test computations.
100+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
101+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
102+
of this function gets scaled by the length of this vector.
103+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
104+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
105+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
106+
98107
/// Returns the topmost point of this Capsule.
99108
/** <img src="CapsuleFunctions.png" />
100109
@note The topmost point is only a naming convention, and does not correspond to the topmost point along any world axis. The returned

src/Geometry/Frustum.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,15 @@ float3 Frustum::ExtremePoint(const float3 &direction) const
508508
return mostExtreme;
509509
}
510510

511+
void Frustum::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
512+
{
513+
///\todo Optimize!
514+
float3 minPt = ExtremePoint(-direction);
515+
float3 maxPt = ExtremePoint(direction);
516+
outMin = Dot(minPt, direction);
517+
outMax = Dot(maxPt, direction);
518+
}
519+
511520
AABB Frustum::MinimalEnclosingAABB() const
512521
{
513522
AABB aabb;

src/Geometry/Frustum.h

+9
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ class Frustum
173173
@see CornerPoint(). */
174174
float3 ExtremePoint(const float3 &direction) const;
175175

176+
/// Projects this Frustum onto the given 1D axis direction vector.
177+
/** This function collapses this Frustum onto an 1D axis for the purposes of e.g. separate axis test computations.
178+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
179+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
180+
of this function gets scaled by the length of this vector.
181+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
182+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
183+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
184+
176185
/// Sets the pos, front and up members of this frustum from the given world transform.
177186
/** This function sets the 'front' parameter of this Frustum to look towards the -Z axis of the given matrix,
178187
and the 'up' parameter of this Frustum to point towards the +Y axis of the given matrix.

src/Geometry/Line.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,20 @@ LineSegment Line::ToLineSegment(float d) const
321321
return LineSegment(pos, GetPoint(d));
322322
}
323323

324+
void Line::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
325+
{
326+
// Most of the time, the projection of a line spans the whole 1D axis.
327+
// As a special case, if the line is perpendicular to the direction vector in question,
328+
// then the projection interval of this line is a single point.
329+
if (dir.IsPerpendicular(direction))
330+
outMin = outMax = Dot(direction, pos);
331+
else
332+
{
333+
outMin = -FLOAT_INF;
334+
outMax = FLOAT_INF;
335+
}
336+
}
337+
324338
LineSegment Line::ToLineSegment(float dStart, float dEnd) const
325339
{
326340
return LineSegment(GetPoint(dStart), GetPoint(dEnd));

src/Geometry/Line.h

+9
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@ class Line
191191
@see pos, dir, Line::Line, class LineSegment, ToLine(). */
192192
LineSegment ToLineSegment(float dStart, float dEnd) const;
193193

194+
/// Projects this Line onto the given 1D axis direction vector.
195+
/** This function collapses this Line onto an 1D axis for the purposes of e.g. separate axis test computations.
196+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
197+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
198+
of this function gets scaled by the length of this vector.
199+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
200+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
201+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
202+
194203
/// Tests if the given three points are collinear.
195204
/** This function tests whether the given three functions all lie on the same line.
196205
@param epsilon The comparison threshold to use to account for floating-point inaccuracies. */

src/Geometry/LineSegment.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,14 @@ Line LineSegment::ToLine() const
333333
return Line(a, Dir());
334334
}
335335

336+
void LineSegment::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
337+
{
338+
outMin = Dot(direction, a);
339+
outMax = Dot(direction, b);
340+
if (outMax < outMin)
341+
Swap(outMin, outMax);
342+
}
343+
336344
LineSegment operator *(const float3x3 &transform, const LineSegment &l)
337345
{
338346
return LineSegment(transform * l.a, transform * l.b);

src/Geometry/LineSegment.h

+9
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,15 @@ class LineSegment
207207
@see class Line, ToRay(). */
208208
Line ToLine() const;
209209

210+
/// Projects this LineSegment onto the given 1D axis direction vector.
211+
/** This function collapses this LineSegment onto an 1D axis for the purposes of e.g. separate axis test computations.
212+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
213+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
214+
of this function gets scaled by the length of this vector.
215+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
216+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
217+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
218+
210219
#ifdef MATH_ENABLE_STL_SUPPORT
211220
/// Returns a human-readable representation of this LineSegment. Most useful for debugging purposes.
212221
std::string ToString() const;

src/Geometry/OBB.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,16 @@ float3 OBB::ExtremePoint(const float3 &direction) const
297297
return pt;
298298
}
299299

300+
void OBB::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
301+
{
302+
float x = Abs(Dot(direction, axis[0]) * r.x);
303+
float y = Abs(Dot(direction, axis[1]) * r.y);
304+
float z = Abs(Dot(direction, axis[2]) * r.z);
305+
float pt = Dot(direction, pos);
306+
outMin = pt - x - y - z;
307+
outMax = pt + x + y + z;
308+
}
309+
300310
float3 OBB::PointOnEdge(int edgeIndex, float u) const
301311
{
302312
assume(0 <= edgeIndex && edgeIndex <= 11);

src/Geometry/OBB.h

+9
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,15 @@ class OBB
234234
@see CornerPoint(). */
235235
float3 ExtremePoint(const float3 &direction) const;
236236

237+
/// Projects this OBB onto the given 1D axis direction vector.
238+
/** This function collapses this OBB onto an 1D axis for the purposes of e.g. separate axis test computations.
239+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
240+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
241+
of this function gets scaled by the length of this vector.
242+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
243+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
244+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
245+
237246
/// Returns a point on an edge of this OBB.
238247
/** @param edgeIndex The index of the edge to generate a point to, in the range [0, 11]. @todo Document which index generates which one.
239248
@param u A normalized value between [0,1]. This specifies the relative distance of the point along the edge.

src/Geometry/Polygon.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,15 @@ float3 Polygon::ExtremePoint(const float3 &direction) const
566566
return mostExtreme;
567567
}
568568

569+
void Polygon::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
570+
{
571+
///\todo Optimize!
572+
float3 minPt = ExtremePoint(-direction);
573+
float3 maxPt = ExtremePoint(direction);
574+
outMin = Dot(minPt, direction);
575+
outMax = Dot(maxPt, direction);
576+
}
577+
569578
/*
570579
/// Returns true if the edges of this polygon self-intersect.
571580
bool IsSelfIntersecting() const;

src/Geometry/Polygon.h

+9
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ class Polygon
9797
@see Vertex(). */
9898
float3 ExtremePoint(const float3 &direction) const;
9999

100+
/// Projects this Polygon onto the given 1D axis direction vector.
101+
/** This function collapses this Polygon onto an 1D axis for the purposes of e.g. separate axis test computations.
102+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
103+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
104+
of this function gets scaled by the length of this vector.
105+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
106+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
107+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
108+
100109
/// Tests if the given diagonal exists.
101110
/** This function tests whether the diagonal that joins the two given vertices lies inside this polygon and is not intersected
102111
by the edges of this polygon.

src/Geometry/Polyhedron.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@ float3 Polyhedron::ExtremePoint(const float3 &direction) const
191191
return Vertex(ExtremeVertex(direction));
192192
}
193193

194+
void Polyhedron::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
195+
{
196+
///\todo Optimize!
197+
float3 minPt = ExtremePoint(-direction);
198+
float3 maxPt = ExtremePoint(direction);
199+
outMin = Dot(minPt, direction);
200+
outMax = Dot(maxPt, direction);
201+
}
202+
194203
float3 Polyhedron::Centroid() const
195204
{
196205
float3 centroid = float3::zero;

src/Geometry/Polyhedron.h

+9
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,15 @@ class Polyhedron
144144
@see CornerPoint(). */
145145
float3 ExtremePoint(const float3 &direction) const;
146146

147+
/// Projects this Polyhedron onto the given 1D axis direction vector.
148+
/** This function collapses this Polyhedron onto an 1D axis for the purposes of e.g. separate axis test computations.
149+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
150+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
151+
of this function gets scaled by the length of this vector.
152+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
153+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
154+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
155+
147156
/// Returns the arithmetic mean of all the corner vertices.
148157
/** @bug This is not the proper centroid of the polyhedron! */
149158
/** @see SurfaceArea(), Volume(). */

src/Geometry/Ray.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,18 @@ LineSegment Ray::ToLineSegment(float dStart, float dEnd) const
290290
return LineSegment(GetPoint(dStart), GetPoint(dEnd));
291291
}
292292

293+
void Ray::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
294+
{
295+
outMin = outMax = Dot(direction, pos);
296+
float d = Dot(direction, dir);
297+
298+
// Most of the time, the projection interval will be a half-infinite range, extending to either -inf or +inf.
299+
if (d > 1e-4f)
300+
outMax = FLOAT_INF;
301+
else if (d < -1e4f)
302+
outMin = -FLOAT_INF;
303+
}
304+
293305
#ifdef MATH_ENABLE_STL_SUPPORT
294306
std::string Ray::ToString() const
295307
{

src/Geometry/Ray.h

+9
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,15 @@ class Ray
183183
@see pos, dir, Ray::Ray, class LineSegment, ToLine(). */
184184
LineSegment ToLineSegment(float d) const;
185185

186+
/// Projects this Ray onto the given 1D axis direction vector.
187+
/** This function collapses this Ray onto an 1D axis for the purposes of e.g. separate axis test computations.
188+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
189+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
190+
of this function gets scaled by the length of this vector.
191+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
192+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
193+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
194+
186195
/// Converts this Ray to a LineSegment.
187196
/** @param dStart Specifies the position of the first endpoint along this Ray. This parameter may be negative,
188197
in which case the starting point lies outside this Ray to the opposite direction of the Ray.

src/Geometry/Sphere.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ float3 Sphere::ExtremePoint(const float3 &direction) const
140140
return pos + direction.ScaledToLength(r);
141141
}
142142

143+
void Sphere::ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const
144+
{
145+
float d = Dot(direction, pos);
146+
outMin = d - r;
147+
outMax = d + r;
148+
}
149+
143150
bool Sphere::IsFinite() const
144151
{
145152
return pos.IsFinite() && isfinite(r);

src/Geometry/Sphere.h

+9
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,15 @@ class Sphere
112112
@return The extreme point of this Sphere in the given direction. */
113113
float3 ExtremePoint(const float3 &direction) const;
114114

115+
/// Projects this Sphere onto the given 1D axis direction vector.
116+
/** This function collapses this Sphere onto an 1D axis for the purposes of e.g. separate axis test computations.
117+
The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
118+
@param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
119+
of this function gets scaled by the length of this vector.
120+
@param outMin [out] Returns the minimum extent of this object along the projection axis.
121+
@param outMax [out] Returns the maximum extent of this object along the projection axis. */
122+
void ProjectToAxis(const float3 &direction, float &outMin, float &outMax) const;
123+
115124
/// Tests if this Sphere is finite.
116125
/** A sphere is <b><i>finite</i></b> if its members pos and r do not contain floating-point NaNs or +/-infs
117126
in them.

0 commit comments

Comments
 (0)