aboutsummaryrefslogtreecommitdiff
path: root/mp/src/public/collisionutils.h
diff options
context:
space:
mode:
Diffstat (limited to 'mp/src/public/collisionutils.h')
-rw-r--r--mp/src/public/collisionutils.h450
1 files changed, 450 insertions, 0 deletions
diff --git a/mp/src/public/collisionutils.h b/mp/src/public/collisionutils.h
new file mode 100644
index 00000000..28fc28d6
--- /dev/null
+++ b/mp/src/public/collisionutils.h
@@ -0,0 +1,450 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Common collision utility methods
+//
+// $Header: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef COLLISIONUTILS_H
+#define COLLISIONUTILS_H
+
+#include "tier0/platform.h"
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "mathlib/ssemath.h"
+
+//-----------------------------------------------------------------------------
+// forward declarations
+//-----------------------------------------------------------------------------
+struct Ray_t;
+class Vector;
+class Vector2D;
+class Vector4D;
+struct cplane_t;
+class QAngle;
+class CBaseTrace;
+struct matrix3x4_t;
+
+
+//-----------------------------------------------------------------------------
+//
+// IntersectRayWithTriangle
+//
+// Intersects a ray with a triangle, returns distance t along ray.
+// t will be less than zero if no intersection occurred
+// oneSided will cull collisions which approach the triangle from the back
+// side, assuming the vertices are specified in counter-clockwise order
+// The vertices need not be specified in that order if oneSided is not used
+//
+//-----------------------------------------------------------------------------
+float IntersectRayWithTriangle( const Ray_t& ray,
+ const Vector& v1, const Vector& v2, const Vector& v3,
+ bool oneSided );
+
+//-----------------------------------------------------------------------------
+//
+// ComputeIntersectionBarycentricCoordinates
+//
+// Figures out the barycentric coordinates (u,v) where a ray hits a
+// triangle. Note that this will ignore the ray extents, and it also ignores
+// the ray length. Note that the edge from v1->v2 represents u (v2: u = 1),
+// and the edge from v1->v3 represents v (v3: v = 1). It returns false
+// if the ray is parallel to the triangle (or when t is specified if t is less
+// than zero).
+//
+//-----------------------------------------------------------------------------
+bool ComputeIntersectionBarycentricCoordinates( const Ray_t& ray,
+ const Vector& v1, const Vector& v2, const Vector& v3, float& u, float& v,
+ float *t = 0 );
+
+//-----------------------------------------------------------------------------
+//
+// IntersectRayWithRay
+//
+// Returns whether or not there was an intersection. The "t" paramter is the
+// distance along ray0 and the "s" parameter is the distance along ray1. If
+// the two lines to not intersect the "t" and "s" represent the closest approach.
+// "t" and "s" will not change if the rays are parallel.
+//
+//-----------------------------------------------------------------------------
+bool IntersectRayWithRay( const Ray_t &ray0, const Ray_t &ray1, float &t, float &s );
+
+
+//-----------------------------------------------------------------------------
+//
+// IntersectRayWithSphere
+//
+// Returns whether or not there was an intersection. Returns the two intersection points.
+// NOTE: The point of closest approach can be found at the average t value.
+//
+//-----------------------------------------------------------------------------
+bool IntersectRayWithSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta, const Vector &vecSphereCenter, float flRadius, float *pT1, float *pT2 );
+
+
+//-----------------------------------------------------------------------------
+//
+// IntersectInfiniteRayWithSphere
+//
+// Returns whether or not there was an intersection of a sphere against an infinitely
+// extending ray.
+// Returns the two intersection points
+//
+//-----------------------------------------------------------------------------
+bool IntersectInfiniteRayWithSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta,
+ const Vector &vecSphereCenter, float flRadius, float *pT1, float *pT2 );
+
+
+// returns true if the sphere and cone intersect
+// NOTE: cone sine/cosine are the half angle of the cone
+bool IsSphereIntersectingCone( const Vector &sphereCenter, float sphereRadius, const Vector &coneOrigin, const Vector &coneNormal, float coneSine, float coneCosine );
+
+//-----------------------------------------------------------------------------
+//
+// IntersectRayWithPlane
+//
+// Intersects a ray with a plane, returns distance t along ray.
+// t will be less than zero the intersection occurs in the opposite direction of the ray.
+//
+//-----------------------------------------------------------------------------
+float IntersectRayWithPlane( const Ray_t& ray, const cplane_t& plane );
+float IntersectRayWithPlane( const Vector& org, const Vector& dir, const cplane_t& plane );
+float IntersectRayWithPlane( const Vector& org, const Vector& dir, const Vector& normal, float dist );
+
+// This version intersects a ray with an axis-aligned plane
+float IntersectRayWithAAPlane( const Vector& vecStart, const Vector& vecEnd, int nAxis, float flSign, float flDist );
+
+
+//-----------------------------------------------------------------------------
+// IntersectRayWithBox
+//
+// Purpose: Computes the intersection of a ray with a box (AABB)
+// Output : Returns true if there is an intersection + trace information
+//-----------------------------------------------------------------------------
+bool IntersectRayWithBox( const Vector &rayStart, const Vector &rayDelta, const Vector &boxMins, const Vector &boxMaxs, float epsilon, CBaseTrace *pTrace, float *pFractionLeftSolid = NULL );
+bool IntersectRayWithBox( const Ray_t &ray, const Vector &boxMins, const Vector &boxMaxs, float epsilon, CBaseTrace *pTrace, float *pFractionLeftSolid = NULL );
+
+//-----------------------------------------------------------------------------
+// Intersects a ray against a box
+//-----------------------------------------------------------------------------
+struct BoxTraceInfo_t
+{
+ float t1;
+ float t2;
+ int hitside;
+ bool startsolid;
+};
+
+bool IntersectRayWithBox( const Vector &vecRayStart, const Vector &vecRayDelta,
+ const Vector &boxMins, const Vector &boxMaxs, float flTolerance, BoxTraceInfo_t *pTrace );
+
+
+//-----------------------------------------------------------------------------
+// IntersectRayWithOBB
+//
+// Purpose: Computes the intersection of a ray with a oriented box (OBB)
+// Output : Returns true if there is an intersection + trace information
+//-----------------------------------------------------------------------------
+bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta,
+ const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs,
+ float flTolerance, CBaseTrace *pTrace );
+
+bool IntersectRayWithOBB( const Vector &vecRayOrigin, const Vector &vecRayDelta,
+ const Vector &vecBoxOrigin, const QAngle &angBoxRotation,
+ const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace );
+
+bool IntersectRayWithOBB( const Ray_t &ray, const Vector &vecBoxOrigin, const QAngle &angBoxRotation,
+ const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace );
+
+bool IntersectRayWithOBB( const Ray_t &ray, const matrix3x4_t &matOBBToWorld,
+ const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace );
+
+bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta,
+ const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs,
+ float flTolerance, BoxTraceInfo_t *pTrace );
+
+//-----------------------------------------------------------------------------
+//
+// IsSphereIntersectingSphere
+//
+// returns true if there's an intersection between sphere and sphere
+//
+//-----------------------------------------------------------------------------
+bool IsSphereIntersectingSphere( const Vector& center1, float radius1,
+ const Vector& center2, float radius2 );
+
+
+//-----------------------------------------------------------------------------
+//
+// IsBoxIntersectingSphere
+//
+// returns true if there's an intersection between box and sphere
+//
+//-----------------------------------------------------------------------------
+bool IsBoxIntersectingSphere( const Vector& boxMin, const Vector& boxMax,
+ const Vector& center, float radius );
+
+bool IsBoxIntersectingSphereExtents( const Vector& boxCenter, const Vector& boxHalfDiag,
+ const Vector& center, float radius );
+
+//-----------------------------------------------------------------------------
+// returns true if there's an intersection between ray and sphere
+//-----------------------------------------------------------------------------
+bool IsRayIntersectingSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta,
+ const Vector &vecSphereCenter, float flRadius, float flTolerance = 0.0f );
+
+
+//-----------------------------------------------------------------------------
+//
+// IsCircleIntersectingRectangle
+//
+// returns true if there's an intersection between rectangle and circle
+//
+//-----------------------------------------------------------------------------
+bool IsCircleIntersectingRectangle( const Vector2D& boxMin, const Vector2D& boxMax,
+ const Vector2D& center, float radius );
+
+
+//-----------------------------------------------------------------------------
+//
+// IsBoxIntersectingBox
+//
+// returns true if there's an intersection between two boxes
+//
+//-----------------------------------------------------------------------------
+bool IsBoxIntersectingBox( const Vector& boxMin1, const Vector& boxMax1,
+ const Vector& boxMin2, const Vector& boxMax2 );
+
+bool IsBoxIntersectingBoxExtents( const Vector& boxCenter1, const Vector& boxHalfDiagonal1,
+ const Vector& boxCenter2, const Vector& boxHalfDiagonal2 );
+
+
+#ifdef _X360
+// inline version:
+#include "mathlib/ssemath.h"
+inline bool IsBoxIntersectingBoxExtents( const fltx4 boxCenter1, const fltx4 boxHalfDiagonal1,
+ const fltx4 boxCenter2, const fltx4 boxHalfDiagonal2 );
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// IsOBBIntersectingOBB
+//
+// returns true if there's an intersection between two OBBs
+//
+//-----------------------------------------------------------------------------
+bool IsOBBIntersectingOBB( const Vector &vecOrigin1, const QAngle &vecAngles1, const Vector& boxMin1, const Vector& boxMax1,
+ const Vector &vecOrigin2, const QAngle &vecAngles2, const Vector& boxMin2, const Vector& boxMax2, float flTolerance = 0.0f );
+
+
+//-----------------------------------------------------------------------------
+//
+// IsBoxIntersectingRay
+//
+// returns true if there's an intersection between box and ray
+//
+//-----------------------------------------------------------------------------
+
+bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax,
+ const Vector& origin, const Vector& delta, float flTolerance = 0.0f );
+
+bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax,
+ const Ray_t& ray, float flTolerance = 0.0f );
+
+bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax,
+ const Vector& origin, const Vector& delta,
+ const Vector& invDelta, float flTolerance = 0.0f );
+
+
+// On the PC, we can't pass fltx4's in registers like this. On the x360, it is
+// much better if we do.
+#ifdef _X360
+bool FASTCALL IsBoxIntersectingRay( fltx4 boxMin, fltx4 boxMax,
+ fltx4 origin, fltx4 delta, fltx4 invDelta, // ray parameters
+ fltx4 vTolerance = LoadZeroSIMD() ///< eg from ReplicateX4(flTolerance)
+ );
+#else
+bool FASTCALL IsBoxIntersectingRay( const fltx4 &boxMin, const fltx4 &boxMax,
+ const fltx4 & origin, const fltx4 & delta, const fltx4 & invDelta, // ray parameters
+ const fltx4 & vTolerance = Four_Zeros ///< eg from ReplicateX4(flTolerance)
+ );
+#endif
+
+bool inline FASTCALL IsBoxIntersectingRay( const fltx4& boxMin, const fltx4& boxMax,
+ const fltx4& origin, const fltx4& delta, float flTolerance = 0.0f )
+{
+ return IsBoxIntersectingRay( boxMin, boxMax, origin, delta, ReciprocalSIMD(delta), ReplicateX4(flTolerance) );
+}
+
+
+bool FASTCALL IsBoxIntersectingRay( const fltx4& boxMin, const fltx4& boxMax,
+ const Ray_t& ray, float flTolerance = 0.0f );
+
+
+
+//-----------------------------------------------------------------------------
+//
+// IsPointInBox
+//
+// returns true if the point is in the box
+//
+//-----------------------------------------------------------------------------
+bool IsPointInBox( const Vector& pt, const Vector& boxMin, const Vector& boxMax );
+
+
+// SIMD version
+FORCEINLINE bool IsPointInBox( const fltx4& pt, const fltx4& boxMin, const fltx4& boxMax )
+{
+ fltx4 greater = CmpGtSIMD( pt,boxMax );
+ fltx4 less = CmpLtSIMD( pt, boxMin );
+ return (IsAllZeros(SetWToZeroSIMD(OrSIMD(greater,less))));
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if pt intersects the truncated cone
+// origin - cone tip, axis unit cone axis, cosAngle - cosine of cone axis to surface angle
+//-----------------------------------------------------------------------------
+bool IsPointInCone( const Vector &pt, const Vector &origin, const Vector &axis, float cosAngle, float length );
+
+//-----------------------------------------------------------------------------
+// Intersects a plane with a triangle (using barycentric definition)
+// The return value, in pIntersection, is an array of barycentric coordinates
+// describing at most 2 intersection points.
+// The return value is the number of intersection points
+//-----------------------------------------------------------------------------
+int IntersectTriangleWithPlaneBarycentric( const Vector& org, const Vector& edgeU, const Vector& edgeV,
+ const Vector4D& plane, Vector2D* pIntersection );
+
+//-----------------------------------------------------------------------------
+//
+// PointInQuadBarycentric
+//
+// Given a point and a quad in a plane return the u and v (barycentric) positions
+// of the point relative to the quad. The points (v1,v2,v3,v4) should be given
+// in a counter-clockwise order with v1 acting as the primary corner (u=0, v=0).
+// Thus, u0 = v2 - v1, and v0 = v4 - v1.
+//
+//-----------------------------------------------------------------------------
+
+enum QuadBarycentricRetval_t
+{
+ BARY_QUADRATIC_FALSE = 0,
+ BARY_QUADRATIC_TRUE = 1,
+ BARY_QUADRATIC_NEGATIVE_DISCRIMINANT = 2
+};
+
+QuadBarycentricRetval_t PointInQuadToBarycentric( const Vector &v1, const Vector &v2,
+ const Vector &v3, const Vector &v4, const Vector &point, Vector2D &uv );
+
+
+void PointInQuadFromBarycentric( const Vector &v1, const Vector &v2, const Vector &v3, const Vector &v4,
+ const Vector2D &uv, Vector &point );
+void TexCoordInQuadFromBarycentric( const Vector2D &v1, const Vector2D &v2, const Vector2D &v3, const Vector2D &v4,
+ const Vector2D &uv, Vector2D &texCoord );
+
+
+//-----------------------------------------------------------------------------
+// Compute point from barycentric specification
+// Edge u goes from v0 to v1, edge v goes from v0 to v2
+//-----------------------------------------------------------------------------
+void ComputePointFromBarycentric( const Vector& v0, const Vector& v1, const Vector& v2,
+ float u, float v, Vector& pt );
+void ComputePointFromBarycentric( const Vector2D& v0, const Vector2D& v1, const Vector2D& v2,
+ float u, float v, Vector2D& pt );
+
+
+//-----------------------------------------------------------------------------
+// Swept OBB test
+//-----------------------------------------------------------------------------
+bool IsRayIntersectingOBB( const Ray_t &ray, const Vector& org, const QAngle& angles,
+ const Vector& mins, const Vector& maxs );
+
+
+//-----------------------------------------------------------------------------
+// Compute a separating plane between two boxes (expensive!)
+// Returns false if no separating plane exists
+//-----------------------------------------------------------------------------
+bool ComputeSeparatingPlane( const Vector& org1, const QAngle& angles1, const Vector& min1, const Vector& max1,
+ const Vector& org2, const QAngle& angles2, const Vector& min2, const Vector& max2,
+ float tolerance, cplane_t* pPlane );
+
+//-----------------------------------------------------------------------------
+// IsBoxIntersectingTriangle
+//
+// Test for an intersection (overlap) between an axial-aligned bounding
+// box (AABB) and a triangle.
+//
+// Triangle points are in counter-clockwise order with the normal facing "out."
+//
+// Using the "Separating-Axis Theorem" to test for intersections between
+// a triangle and an axial-aligned bounding box (AABB).
+// 1. 3 Axis Plane Tests - x, y, z
+// 2. 9 Edge Planes Tests - the 3 edges of the triangle crossed with all 3 axial
+// planes (x, y, z)
+// 3. 1 Face Plane Test - the plane the triangle resides in (cplane_t plane)
+//-----------------------------------------------------------------------------
+bool IsBoxIntersectingTriangle( const Vector &vecBoxCenter, const Vector &vecBoxExtents,
+ const Vector &v1, const Vector &v2, const Vector &v3,
+ const cplane_t &plane, float flTolerance );
+
+
+Vector CalcClosestPointOnTriangle( const Vector &P, const Vector &v0, const Vector &v1, const Vector &v2 );
+
+
+//-----------------------------------------------------------------------------
+// Compute if the OBB intersects the quad plane, and whether the entire
+// OBB/Quad intersection is contained within the quad itself
+//
+// False if no intersection exists, or if part of the intersection is
+// outside the quad's extents
+//-----------------------------------------------------------------------------
+bool OBBHasFullyContainedIntersectionWithQuad( const Vector &vOBBExtent1_Scaled, const Vector &vOBBExtent2_Scaled, const Vector &vOBBExtent3_Scaled, const Vector &ptOBBCenter,
+ const Vector &vQuadNormal, float fQuadPlaneDist, const Vector &ptQuadCenter,
+ const Vector &vQuadExtent1_Normalized, float fQuadExtent1Length,
+ const Vector &vQuadExtent2_Normalized, float fQuadExtent2Length );
+
+
+//-----------------------------------------------------------------------------
+// Compute if the Ray intersects the quad plane, and whether the entire
+// Ray/Quad intersection is contained within the quad itself
+//
+// False if no intersection exists, or if part of the intersection is
+// outside the quad's extents
+//-----------------------------------------------------------------------------
+bool RayHasFullyContainedIntersectionWithQuad( const Ray_t &ray,
+ const Vector &vQuadNormal, float fQuadPlaneDist, const Vector &ptQuadCenter,
+ const Vector &vQuadExtent1_Normalized, float fQuadExtent1Length,
+ const Vector &vQuadExtent2_Normalized, float fQuadExtent2Length );
+
+
+
+//-----------------------------------------------------------------------------
+// INLINES
+//-----------------------------------------------------------------------------
+
+
+#ifdef _X360
+inline bool IsBoxIntersectingBoxExtents( const fltx4 boxCenter1, const fltx4 boxHalfDiagonal1,
+ const fltx4 boxCenter2, const fltx4 boxHalfDiagonal2 )
+{
+ fltx4 vecDelta, vecSize;
+
+ vecDelta = SubSIMD(boxCenter1, boxCenter2);
+ vecSize = AddSIMD(boxHalfDiagonal1, boxHalfDiagonal2);
+
+ uint condition;
+ XMVectorInBoundsR(&condition, vecDelta, vecSize);
+ // we want the top three words to be all 1's ; that means in bounds
+
+
+ return XMComparisonAllInBounds( condition );
+}
+#endif
+
+
+#endif // COLLISIONUTILS_H