diff --git a/lib/linux64/mathlib.a b/lib/linux64/mathlib.a index 0b9b056f..5f3e4e2a 100644 Binary files a/lib/linux64/mathlib.a and b/lib/linux64/mathlib.a differ diff --git a/lib/public/win64/mathlib.lib b/lib/public/win64/mathlib.lib index 94e971dc..b5a658dd 100644 Binary files a/lib/public/win64/mathlib.lib and b/lib/public/win64/mathlib.lib differ diff --git a/mathlib/mathlib_base.cpp b/mathlib/mathlib_base.cpp index 24d084e6..2c34b02e 100644 --- a/mathlib/mathlib_base.cpp +++ b/mathlib/mathlib_base.cpp @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: Math primitives. // @@ -1567,7 +1567,9 @@ float QuaternionAngleDiff( const Quaternion &p, const Quaternion &q ) QuaternionConjugate( q, qInv ); QuaternionMult( p, qInv, diff ); - float sinang = sqrt( diff.x * diff.x + diff.y * diff.y + diff.z * diff.z ); + // Note if the quaternion is slightly non-normalized the square root below may be more than 1, + // the value is clamped to one otherwise it may result in asin() returning an undefined result. + float sinang = MIN( 1.0f, sqrt( diff.x * diff.x + diff.y * diff.y + diff.z * diff.z ) ); float angle = RAD2DEG( 2 * asin( sinang ) ); return angle; #else @@ -3029,7 +3031,7 @@ void CalcClosestPointOnLineSegment( const Vector &P, const Vector &vLineA, const { Vector vDir; float t = CalcClosestPointToLineT( P, vLineA, vLineB, vDir ); - t = clamp( t, 0, 1 ); + t = clamp( t, 0.f, 1.f ); if ( outT ) { *outT = t; @@ -3101,7 +3103,7 @@ void CalcClosestPointOnLineSegment2D( const Vector2D &P, const Vector2D &vLineA, { Vector2D vDir; float t = CalcClosestPointToLineT2D( P, vLineA, vLineB, vDir ); - t = clamp( t, 0, 1 ); + t = clamp( t, 0.f, 1.f ); if ( outT ) { *outT = t; @@ -4075,6 +4077,47 @@ void GetInterpolationData( float const *pKnotPositions, return; } +float RandomVectorInUnitSphere( Vector *pVector ) +{ + // Guarantee uniform random distribution within a sphere + // Graphics gems III contains this algorithm ("Nonuniform random point sets via warping") + float u = ((float)rand() / VALVE_RAND_MAX); + float v = ((float)rand() / VALVE_RAND_MAX); + float w = ((float)rand() / VALVE_RAND_MAX); + + float flPhi = acos( 1 - 2 * u ); + float flTheta = 2 * M_PI * v; + float flRadius = powf( w, 1.0f / 3.0f ); + + float flSinPhi, flCosPhi; + float flSinTheta, flCosTheta; + SinCos( flPhi, &flSinPhi, &flCosPhi ); + SinCos( flTheta, &flSinTheta, &flCosTheta ); + + pVector->x = flRadius * flSinPhi * flCosTheta; + pVector->y = flRadius * flSinPhi * flSinTheta; + pVector->z = flRadius * flCosPhi; + return flRadius; +} + +float RandomVectorInUnitCircle( Vector2D *pVector ) +{ + // Guarantee uniform random distribution within a sphere + // Graphics gems III contains this algorithm ("Nonuniform random point sets via warping") + float u = ((float)rand() / VALVE_RAND_MAX); + float v = ((float)rand() / VALVE_RAND_MAX); + + float flTheta = 2 * M_PI * v; + float flRadius = powf( u, 1.0f / 2.0f ); + + float flSinTheta, flCosTheta; + SinCos( flTheta, &flSinTheta, &flCosTheta ); + + pVector->x = flRadius * flCosTheta; + pVector->y = flRadius * flSinTheta; + return flRadius; +} + /* Reverse engineered code ahead */ void fourplanes_t::ComputeSignbits() diff --git a/public/tier0/platform.h b/public/tier0/platform.h index 0d24f058..86a41c7d 100644 --- a/public/tier0/platform.h +++ b/public/tier0/platform.h @@ -574,6 +574,11 @@ typedef unsigned int uint; #define abstract_class class NO_VTABLE #endif +// MSVC CRT uses 0x7fff while gcc uses MAX_INT, leading to mismatches between platforms +// As a result, we pick the least common denominator here. This should be used anywhere +// you might typically want to use RAND_MAX +#define VALVE_RAND_MAX 0x7fff + //----------------------------------------------------------------------------- // Why do we need this? It would be nice to make it die die die