mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Mathlib implementation
SourceSDK mathlib port with light modifications. Renamed Vector to Vector3D (to avoid confusion with std::vector (declared as vector) and Vector2D/Vector4D).
This commit is contained in:
parent
2af10efe23
commit
7d89a42b56
@ -6,6 +6,7 @@
|
||||
#include <WinSock2.h>
|
||||
#include <comdef.h>
|
||||
#include <gdiplus.h>
|
||||
#include <timeapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <Psapi.h>
|
||||
#include <setjmp.h>
|
||||
|
@ -100,25 +100,33 @@ void DestroyOverlay(OverlayBase_t* pOverlay)
|
||||
LeaveCriticalSection(&*s_OverlayMutex);
|
||||
}
|
||||
|
||||
//script_client DrawAngledBox(<0,0,0>, <10,10,10>, <0,0,0>, <1000,1000,1000>, 20, 200, 220, true, 10)
|
||||
|
||||
void DrawBoxTest(OverlayBox_t* pBox) // FIXME: center within box and angles.
|
||||
{
|
||||
|
||||
//Vector3D test = Vector3D(10, 10, 10).ToForward();
|
||||
//printf("<%f, %f, %f>\n", test.x, test.y, test.z);
|
||||
|
||||
//v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false); // WIREFRAME
|
||||
|
||||
// Vertical
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
|
||||
// Lower horizontal
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
|
||||
// Upper horizontal
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, { pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
v_RenderLine({ pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, { pBox->origin_X + pBox->maxs.x, pBox->origin_Y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
v_RenderLine({ pBox->origin_X + pBox->maxs.x, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, { pBox->origin_X, pBox->origin_Y + pBox->maxs.y, pBox->origin_Z + pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, pBox->a), false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -145,6 +153,9 @@ void DrawOverlay(OverlayBase_t* pOverlay)
|
||||
//v_RenderWireframeSphere({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, pBox->maxs.x, 8, 8, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
//v_RenderLine({ pBox->origin_X, pBox->origin_Y, pBox->origin_Z }, { pBox->origin_X, pBox->origin_Y, pBox->origin_Z+pBox->maxs.z }, Color(pBox->r, pBox->g, pBox->b, 255), false);
|
||||
|
||||
|
||||
if (pBox->a < 1)
|
||||
pBox->a = 255;
|
||||
DrawBoxTest(pBox);
|
||||
|
||||
//if (pBox->a < 255)
|
||||
|
@ -58,8 +58,8 @@ struct OverlayLine_t : public OverlayBase_t
|
||||
{
|
||||
OverlayLine_t(void) { m_Type = OverlayType_t::OVERLAY_LINE; }
|
||||
|
||||
Vector3 origin{};
|
||||
Vector3 dest{};
|
||||
Vector3D origin{};
|
||||
Vector3D dest{};
|
||||
int r{};
|
||||
int g{};
|
||||
int b{};
|
||||
@ -73,12 +73,12 @@ struct OverlayBox_t : public OverlayBase_t
|
||||
|
||||
QAngle angles{}; //0x0020 - this isn't angles but idrk where it is
|
||||
float origin_X{}; //0x002C
|
||||
Vector3 unk30{}; //0x0030
|
||||
Vector3D unk30{}; //0x0030
|
||||
float origin_Y{}; //0x003C
|
||||
Vector3 unk40{}; //0x0040
|
||||
Vector3D unk40{}; //0x0040
|
||||
float origin_Z{}; //0x004C
|
||||
Vector3 mins{}; //0x0050
|
||||
Vector3 maxs{}; //0x005C
|
||||
Vector3D mins{}; //0x0050
|
||||
Vector3D maxs{}; //0x005C
|
||||
int r{};
|
||||
int g{};
|
||||
int b{};
|
||||
@ -89,7 +89,7 @@ struct OverlaySphere_t : public OverlayBase_t
|
||||
{
|
||||
OverlaySphere_t(void) { m_Type = OverlayType_t::OVERLAY_SPHERE; }
|
||||
|
||||
Vector3 vOrigin{};
|
||||
Vector3D vOrigin{};
|
||||
float flRadius{};
|
||||
int nTheta{};
|
||||
int nPhi{};
|
||||
@ -108,13 +108,13 @@ inline CMemory p_DrawAllOverlays;
|
||||
inline auto v_DrawAllOverlays = p_DrawAllOverlays.RCast<void (*)(char a1)>();
|
||||
|
||||
inline CMemory p_RenderWireframeBox; // one of the vector parameters is probably the angles, vmins might no longer be used.
|
||||
inline auto v_RenderWireframeBox = p_RenderWireframeBox.RCast<void* (*)(Vector3 origin, Vector3 vMins, Vector3 vMaxs, Color color, bool bZBuffer)>();
|
||||
inline auto v_RenderWireframeBox = p_RenderWireframeBox.RCast<void* (*)(Vector3D origin, Vector3D vMins, Vector3D vMaxs, Color color, bool bZBuffer)>();
|
||||
|
||||
inline CMemory p_RenderLine;
|
||||
inline auto v_RenderLine = p_RenderLine.RCast<void* (*)(Vector3 origin, Vector3 dest, Color color, bool bZBuffer)>();
|
||||
inline auto v_RenderLine = p_RenderLine.RCast<void* (*)(Vector3D origin, Vector3D dest, Color color, bool bZBuffer)>();
|
||||
|
||||
inline CMemory p_RenderWireframeSphere;
|
||||
inline auto v_RenderWireframeSphere = p_RenderWireframeSphere.RCast<void* (*)(Vector3 vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer)>();
|
||||
inline auto v_RenderWireframeSphere = p_RenderWireframeSphere.RCast<void* (*)(Vector3D vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer)>();
|
||||
|
||||
inline CMemory p_DestroyOverlay;
|
||||
inline auto v_DestroyOverlay = p_DestroyOverlay.RCast<void (*)(OverlayBase_t* pOverlay)>();
|
||||
@ -161,9 +161,9 @@ class VDebugOverlay : public IDetour
|
||||
|
||||
v_DrawAllOverlays = p_DrawAllOverlays.RCast<void (*)(char)>(); /*40 55 48 83 EC 30 48 8B 05 ?? ?? ?? ?? 0F B6 E9*/
|
||||
v_DestroyOverlay = p_DestroyOverlay.RCast<void (*)(OverlayBase_t*)>(); /*40 53 48 83 EC 20 48 8B D9 48 8D 0D ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 48 63 03 */
|
||||
v_RenderWireframeBox = p_RenderWireframeBox.RCast<void* (*)(Vector3, Vector3, Vector3, Color, bool)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 44 89 4C 24 ??*/
|
||||
v_RenderWireframeSphere = p_RenderWireframeSphere.RCast<void* (*)(Vector3, float, int, int, Color, bool)>(); /*40 56 41 54 41 55 48 81 EC ?? ?? ?? ??*/
|
||||
v_RenderLine = p_RenderLine.RCast<void* (*)(Vector3, Vector3, Color, bool)>(); /*48 89 74 24 ?? 44 89 44 24 ?? 57 41 56*/
|
||||
v_RenderWireframeBox = p_RenderWireframeBox.RCast<void* (*)(Vector3D, Vector3D, Vector3D, Color, bool)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 44 89 4C 24 ??*/
|
||||
v_RenderWireframeSphere = p_RenderWireframeSphere.RCast<void* (*)(Vector3D, float, int, int, Color, bool)>(); /*40 56 41 54 41 55 48 81 EC ?? ?? ?? ??*/
|
||||
v_RenderLine = p_RenderLine.RCast<void* (*)(Vector3D, Vector3D, Color, bool)>(); /*48 89 74 24 ?? 44 89 44 24 ?? 57 41 56*/
|
||||
}
|
||||
virtual void GetVar(void) const
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ struct model_t // !! CONFIRMED !!
|
||||
int flags; // MODELFLAG_???
|
||||
|
||||
// volume occupied by the model graphics
|
||||
Vector3 mins, maxs;
|
||||
Vector3D mins, maxs;
|
||||
float radius;
|
||||
KeyValues* m_pKeyValues;
|
||||
union
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
public:
|
||||
HostStates_t m_iCurrentState; //0x0000
|
||||
HostStates_t m_iNextState; //0x0004
|
||||
Vector3 m_vecLocation; //0x0008
|
||||
Vector3D m_vecLocation; //0x0008
|
||||
QAngle m_angLocation; //0x0014
|
||||
char m_levelName[MAX_MAP_NAME_HOST]; //0x0020
|
||||
char m_mapGroupName[256]; //0x0060
|
||||
|
@ -39,7 +39,7 @@ struct CAI_NodeLinkDisk
|
||||
struct CAI_Node
|
||||
{
|
||||
int m_nIndex; // Not present on disk
|
||||
Vector3 m_vOrigin;
|
||||
Vector3D m_vOrigin;
|
||||
float m_fHulls[MAX_HULLS];
|
||||
float m_flYaw;
|
||||
|
||||
@ -68,7 +68,7 @@ struct CAI_Node
|
||||
//=============================================================================
|
||||
struct CAI_NodeDisk // The way CAI_Nodes are represented in on-disk ain files
|
||||
{
|
||||
Vector3 m_vOrigin;
|
||||
Vector3D m_vOrigin;
|
||||
|
||||
float m_flYaw;
|
||||
float hulls[MAX_HULLS];
|
||||
@ -87,7 +87,7 @@ struct CAI_NodeDisk // The way CAI_Nodes are represented in on-disk ain files
|
||||
//=============================================================================
|
||||
struct CAI_ScriptNode
|
||||
{
|
||||
Vector3 m_vOrigin;
|
||||
Vector3D m_vOrigin;
|
||||
uint64_t scriptdata;
|
||||
};
|
||||
|
||||
@ -98,7 +98,7 @@ struct AINodeClusters
|
||||
char unk1; // Maps to unk1 on disk
|
||||
char pad0[2]; // Padding to +8
|
||||
|
||||
Vector3 m_vOrigin;
|
||||
Vector3D m_vOrigin;
|
||||
|
||||
char pad5[4];
|
||||
int* unk2; // Maps to unk5 on disk;
|
||||
|
95
r5dev/mathlib/almostequal.cpp
Normal file
95
r5dev/mathlib/almostequal.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Fast ways to compare equality of two floats. Assumes
|
||||
// sizeof(float) == sizeof(int) and we are using IEEE format.
|
||||
//
|
||||
// Source: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
|
||||
//=====================================================================================//
|
||||
|
||||
#include "core/stdafx.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
static inline bool AE_IsInfinite(float a)
|
||||
{
|
||||
const int kInfAsInt = 0x7F800000;
|
||||
|
||||
// An infinity has an exponent of 255 (shift left 23 positions) and
|
||||
// a zero mantissa. There are two infinities - positive and negative.
|
||||
if ((*(int*)&a & 0x7FFFFFFF) == kInfAsInt)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool AE_IsNan(float a)
|
||||
{
|
||||
// a NAN has an exponent of 255 (shifted left 23 positions) and
|
||||
// a non-zero mantissa.
|
||||
int exp = *(int*)&a & 0x7F800000;
|
||||
int mantissa = *(int*)&a & 0x007FFFFF;
|
||||
if (exp == 0x7F800000 && mantissa != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int AE_Sign(float a)
|
||||
{
|
||||
// The sign bit of a number is the high bit.
|
||||
return (*(int*)&a) & 0x80000000;
|
||||
}
|
||||
|
||||
// This is the 'final' version of the AlmostEqualUlps function.
|
||||
// The optional checks are included for completeness, but in many
|
||||
// cases they are not necessary, or even not desirable.
|
||||
bool AlmostEqual(float a, float b, int maxUlps)
|
||||
{
|
||||
// There are several optional checks that you can do, depending
|
||||
// on what behavior you want from your floating point comparisons.
|
||||
// These checks should not be necessary and they are included
|
||||
// mainly for completeness.
|
||||
|
||||
// If a or b are infinity (positive or negative) then
|
||||
// only return true if they are exactly equal to each other -
|
||||
// that is, if they are both infinities of the same sign.
|
||||
// This check is only needed if you will be generating
|
||||
// infinities and you don't want them 'close' to numbers
|
||||
// near FLT_MAX.
|
||||
if (AE_IsInfinite(a) || AE_IsInfinite(b))
|
||||
return a == b;
|
||||
|
||||
// If a or b are a NAN, return false. NANs are equal to nothing,
|
||||
// not even themselves.
|
||||
// This check is only needed if you will be generating NANs
|
||||
// and you use a maxUlps greater than 4 million or you want to
|
||||
// ensure that a NAN does not equal itself.
|
||||
if (AE_IsNan(a) || AE_IsNan(b))
|
||||
return false;
|
||||
|
||||
// After adjusting floats so their representations are lexicographically
|
||||
// ordered as twos-complement integers a very small positive number
|
||||
// will compare as 'close' to a very small negative number. If this is
|
||||
// not desireable, and if you are on a platform that supports
|
||||
// subnormals (which is the only place the problem can show up) then
|
||||
// you need this check.
|
||||
// The check for a == b is because zero and negative zero have different
|
||||
// signs but are equal to each other.
|
||||
if (AE_Sign(a) != AE_Sign(b))
|
||||
return a == b;
|
||||
|
||||
int aInt = *(int*)&a;
|
||||
// Make aInt lexicographically ordered as a twos-complement int
|
||||
if (aInt < 0)
|
||||
aInt = 0x80000000 - aInt;
|
||||
// Make bInt lexicographically ordered as a twos-complement int
|
||||
int bInt = *(int*)&b;
|
||||
if (bInt < 0)
|
||||
bInt = 0x80000000 - bInt;
|
||||
|
||||
// Now we can compare aInt and bInt to find out how far apart a and b
|
||||
// are.
|
||||
int intDiff = abs(aInt - bInt);
|
||||
if (intDiff <= maxUlps)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ unsigned long FloatAbsBits(float f)
|
||||
|
||||
float FloatMakePositive(float f)
|
||||
{
|
||||
return fabsf(f);
|
||||
return fabsf(f); // was since 2002: BitsToFloat( FloatBits(f) & 0x7FFFFFFF ); fixed in 2010
|
||||
}
|
||||
|
||||
float FloatNegate(float f)
|
||||
|
@ -5,6 +5,10 @@ unsigned long const& FloatBits(float const& f);
|
||||
float BitsToFloat(unsigned long i);
|
||||
bool IsFinite(float f);
|
||||
unsigned long FloatAbsBits(float f);
|
||||
float FloatMakePositive(float f);
|
||||
float FloatNegate(float f);
|
||||
|
||||
#define FLOAT32_NAN_BITS (std::uint32_t)0x7FC00000 // NaN!
|
||||
#define FLOAT32_NAN BitsToFloat( FLOAT32_NAN_BITS )
|
||||
|
||||
#define VEC_T_NAN FLOAT32_NAN
|
||||
|
635
r5dev/mathlib/color_conversion.cpp
Normal file
635
r5dev/mathlib/color_conversion.cpp
Normal file
@ -0,0 +1,635 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Color conversion routines.
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "core/stdafx.h"
|
||||
#include "tier0/basetypes.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
//#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gamma conversion support
|
||||
//-----------------------------------------------------------------------------
|
||||
static byte texgammatable[256]; // palette is sent through this to convert to screen gamma
|
||||
|
||||
static float texturetolinear[256]; // texture (0..255) to linear (0..1)
|
||||
static int lineartotexture[1024]; // linear (0..1) to texture (0..255)
|
||||
static int lineartoscreen[1024]; // linear (0..1) to gamma corrected vertex light (0..255)
|
||||
|
||||
// build a lightmap texture to combine with surface texture, adjust for src*dst+dst*src, ramp reprogramming, etc
|
||||
float lineartovertex[4096]; // linear (0..4) to screen corrected vertex space (0..1?)
|
||||
unsigned char lineartolightmap[4096]; // linear (0..4) to screen corrected texture value (0..255)
|
||||
|
||||
static float g_Mathlib_GammaToLinear[256]; // gamma (0..1) to linear (0..1)
|
||||
static float g_Mathlib_LinearToGamma[256]; // linear (0..1) to gamma (0..1)
|
||||
|
||||
// This is aligned to 16-byte boundaries so that we can load it
|
||||
// onto SIMD registers easily if needed (used by SSE version of lightmaps)
|
||||
// TODO: move this into the one DLL that actually uses it, instead of statically
|
||||
// linking it everywhere via mathlib.
|
||||
ALIGN128 float power2_n[256] = // 2**(index - 128) / 255
|
||||
{
|
||||
1.152445441982634800E-041, 2.304890883965269600E-041, 4.609781767930539200E-041, 9.219563535861078400E-041,
|
||||
1.843912707172215700E-040, 3.687825414344431300E-040, 7.375650828688862700E-040, 1.475130165737772500E-039,
|
||||
2.950260331475545100E-039, 5.900520662951090200E-039, 1.180104132590218000E-038, 2.360208265180436100E-038,
|
||||
4.720416530360872100E-038, 9.440833060721744200E-038, 1.888166612144348800E-037, 3.776333224288697700E-037,
|
||||
7.552666448577395400E-037, 1.510533289715479100E-036, 3.021066579430958200E-036, 6.042133158861916300E-036,
|
||||
1.208426631772383300E-035, 2.416853263544766500E-035, 4.833706527089533100E-035, 9.667413054179066100E-035,
|
||||
1.933482610835813200E-034, 3.866965221671626400E-034, 7.733930443343252900E-034, 1.546786088668650600E-033,
|
||||
3.093572177337301200E-033, 6.187144354674602300E-033, 1.237428870934920500E-032, 2.474857741869840900E-032,
|
||||
4.949715483739681800E-032, 9.899430967479363700E-032, 1.979886193495872700E-031, 3.959772386991745500E-031,
|
||||
7.919544773983491000E-031, 1.583908954796698200E-030, 3.167817909593396400E-030, 6.335635819186792800E-030,
|
||||
1.267127163837358600E-029, 2.534254327674717100E-029, 5.068508655349434200E-029, 1.013701731069886800E-028,
|
||||
2.027403462139773700E-028, 4.054806924279547400E-028, 8.109613848559094700E-028, 1.621922769711818900E-027,
|
||||
3.243845539423637900E-027, 6.487691078847275800E-027, 1.297538215769455200E-026, 2.595076431538910300E-026,
|
||||
5.190152863077820600E-026, 1.038030572615564100E-025, 2.076061145231128300E-025, 4.152122290462256500E-025,
|
||||
8.304244580924513000E-025, 1.660848916184902600E-024, 3.321697832369805200E-024, 6.643395664739610400E-024,
|
||||
1.328679132947922100E-023, 2.657358265895844200E-023, 5.314716531791688300E-023, 1.062943306358337700E-022,
|
||||
2.125886612716675300E-022, 4.251773225433350700E-022, 8.503546450866701300E-022, 1.700709290173340300E-021,
|
||||
3.401418580346680500E-021, 6.802837160693361100E-021, 1.360567432138672200E-020, 2.721134864277344400E-020,
|
||||
5.442269728554688800E-020, 1.088453945710937800E-019, 2.176907891421875500E-019, 4.353815782843751100E-019,
|
||||
8.707631565687502200E-019, 1.741526313137500400E-018, 3.483052626275000900E-018, 6.966105252550001700E-018,
|
||||
1.393221050510000300E-017, 2.786442101020000700E-017, 5.572884202040001400E-017, 1.114576840408000300E-016,
|
||||
2.229153680816000600E-016, 4.458307361632001100E-016, 8.916614723264002200E-016, 1.783322944652800400E-015,
|
||||
3.566645889305600900E-015, 7.133291778611201800E-015, 1.426658355722240400E-014, 2.853316711444480700E-014,
|
||||
5.706633422888961400E-014, 1.141326684577792300E-013, 2.282653369155584600E-013, 4.565306738311169100E-013,
|
||||
9.130613476622338300E-013, 1.826122695324467700E-012, 3.652245390648935300E-012, 7.304490781297870600E-012,
|
||||
1.460898156259574100E-011, 2.921796312519148200E-011, 5.843592625038296500E-011, 1.168718525007659300E-010,
|
||||
2.337437050015318600E-010, 4.674874100030637200E-010, 9.349748200061274400E-010, 1.869949640012254900E-009,
|
||||
3.739899280024509800E-009, 7.479798560049019500E-009, 1.495959712009803900E-008, 2.991919424019607800E-008,
|
||||
5.983838848039215600E-008, 1.196767769607843100E-007, 2.393535539215686200E-007, 4.787071078431372500E-007,
|
||||
9.574142156862745000E-007, 1.914828431372549000E-006, 3.829656862745098000E-006, 7.659313725490196000E-006,
|
||||
1.531862745098039200E-005, 3.063725490196078400E-005, 6.127450980392156800E-005, 1.225490196078431400E-004,
|
||||
2.450980392156862700E-004, 4.901960784313725400E-004, 9.803921568627450800E-004, 1.960784313725490200E-003,
|
||||
3.921568627450980300E-003, 7.843137254901960700E-003, 1.568627450980392100E-002, 3.137254901960784300E-002,
|
||||
6.274509803921568500E-002, 1.254901960784313700E-001, 2.509803921568627400E-001, 5.019607843137254800E-001,
|
||||
1.003921568627451000E+000, 2.007843137254901900E+000, 4.015686274509803900E+000, 8.031372549019607700E+000,
|
||||
1.606274509803921500E+001, 3.212549019607843100E+001, 6.425098039215686200E+001, 1.285019607843137200E+002,
|
||||
2.570039215686274500E+002, 5.140078431372548900E+002, 1.028015686274509800E+003, 2.056031372549019600E+003,
|
||||
4.112062745098039200E+003, 8.224125490196078300E+003, 1.644825098039215700E+004, 3.289650196078431300E+004,
|
||||
6.579300392156862700E+004, 1.315860078431372500E+005, 2.631720156862745100E+005, 5.263440313725490100E+005,
|
||||
1.052688062745098000E+006, 2.105376125490196000E+006, 4.210752250980392100E+006, 8.421504501960784200E+006,
|
||||
1.684300900392156800E+007, 3.368601800784313700E+007, 6.737203601568627400E+007, 1.347440720313725500E+008,
|
||||
2.694881440627450900E+008, 5.389762881254901900E+008, 1.077952576250980400E+009, 2.155905152501960800E+009,
|
||||
4.311810305003921500E+009, 8.623620610007843000E+009, 1.724724122001568600E+010, 3.449448244003137200E+010,
|
||||
6.898896488006274400E+010, 1.379779297601254900E+011, 2.759558595202509800E+011, 5.519117190405019500E+011,
|
||||
1.103823438081003900E+012, 2.207646876162007800E+012, 4.415293752324015600E+012, 8.830587504648031200E+012,
|
||||
1.766117500929606200E+013, 3.532235001859212500E+013, 7.064470003718425000E+013, 1.412894000743685000E+014,
|
||||
2.825788001487370000E+014, 5.651576002974740000E+014, 1.130315200594948000E+015, 2.260630401189896000E+015,
|
||||
4.521260802379792000E+015, 9.042521604759584000E+015, 1.808504320951916800E+016, 3.617008641903833600E+016,
|
||||
7.234017283807667200E+016, 1.446803456761533400E+017, 2.893606913523066900E+017, 5.787213827046133800E+017,
|
||||
1.157442765409226800E+018, 2.314885530818453500E+018, 4.629771061636907000E+018, 9.259542123273814000E+018,
|
||||
1.851908424654762800E+019, 3.703816849309525600E+019, 7.407633698619051200E+019, 1.481526739723810200E+020,
|
||||
2.963053479447620500E+020, 5.926106958895241000E+020, 1.185221391779048200E+021, 2.370442783558096400E+021,
|
||||
4.740885567116192800E+021, 9.481771134232385600E+021, 1.896354226846477100E+022, 3.792708453692954200E+022,
|
||||
7.585416907385908400E+022, 1.517083381477181700E+023, 3.034166762954363400E+023, 6.068333525908726800E+023,
|
||||
1.213666705181745400E+024, 2.427333410363490700E+024, 4.854666820726981400E+024, 9.709333641453962800E+024,
|
||||
1.941866728290792600E+025, 3.883733456581585100E+025, 7.767466913163170200E+025, 1.553493382632634000E+026,
|
||||
3.106986765265268100E+026, 6.213973530530536200E+026, 1.242794706106107200E+027, 2.485589412212214500E+027,
|
||||
4.971178824424429000E+027, 9.942357648848857900E+027, 1.988471529769771600E+028, 3.976943059539543200E+028,
|
||||
7.953886119079086300E+028, 1.590777223815817300E+029, 3.181554447631634500E+029, 6.363108895263269100E+029,
|
||||
1.272621779052653800E+030, 2.545243558105307600E+030, 5.090487116210615300E+030, 1.018097423242123100E+031,
|
||||
2.036194846484246100E+031, 4.072389692968492200E+031, 8.144779385936984400E+031, 1.628955877187396900E+032,
|
||||
3.257911754374793800E+032, 6.515823508749587500E+032, 1.303164701749917500E+033, 2.606329403499835000E+033,
|
||||
5.212658806999670000E+033, 1.042531761399934000E+034, 2.085063522799868000E+034, 4.170127045599736000E+034,
|
||||
8.340254091199472000E+034, 1.668050818239894400E+035, 3.336101636479788800E+035, 6.672203272959577600E+035
|
||||
};
|
||||
|
||||
// You can use this to double check the exponent table and assert that
|
||||
// the precomputation is correct.
|
||||
#ifdef DBGFLAG_ASSERT
|
||||
#pragma warning(push)
|
||||
#pragma warning( disable : 4189 ) // disable unused local variable warning
|
||||
static void CheckExponentTable()
|
||||
{
|
||||
for( int i = 0; i < 256; i++ )
|
||||
{
|
||||
float testAgainst = pow( 2.0f, i - 128 ) / 255.0f;
|
||||
float diff = testAgainst - power2_n[i] ;
|
||||
float relativeDiff = diff / testAgainst;
|
||||
Assert( testAgainst == 0 ?
|
||||
power2_n[i] < 1.16E-041 :
|
||||
power2_n[i] == testAgainst );
|
||||
}
|
||||
}
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
void BuildGammaTable( float gamma, float texGamma, float brightness, int overbright )
|
||||
{
|
||||
int i, inf;
|
||||
float g1, g3;
|
||||
|
||||
// Con_Printf("BuildGammaTable %.1f %.1f %.1f\n", g, v_lightgamma.GetFloat(), v_texgamma.GetFloat() );
|
||||
|
||||
float g = gamma;
|
||||
if (g > 3.0)
|
||||
{
|
||||
g = 3.0;
|
||||
}
|
||||
|
||||
g = 1.0 / g;
|
||||
g1 = texGamma * g;
|
||||
|
||||
if (brightness <= 0.0)
|
||||
{
|
||||
g3 = 0.125;
|
||||
}
|
||||
else if (brightness > 1.0)
|
||||
{
|
||||
g3 = 0.05;
|
||||
}
|
||||
else
|
||||
{
|
||||
g3 = 0.125 - (brightness * brightness) * 0.075;
|
||||
}
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
inf = 255 * pow ( i/255.f, g1 );
|
||||
if (inf < 0)
|
||||
inf = 0;
|
||||
if (inf > 255)
|
||||
inf = 255;
|
||||
texgammatable[i] = inf;
|
||||
}
|
||||
|
||||
for (i=0 ; i<1024 ; i++)
|
||||
{
|
||||
float f;
|
||||
|
||||
f = i / 1023.0;
|
||||
|
||||
// scale up
|
||||
if (brightness > 1.0)
|
||||
f = f * brightness;
|
||||
|
||||
// shift up
|
||||
if (f <= g3)
|
||||
f = (f / g3) * 0.125;
|
||||
else
|
||||
f = 0.125 + ((f - g3) / (1.0 - g3)) * 0.875;
|
||||
|
||||
// convert linear space to desired gamma space
|
||||
inf = 255 * pow ( f, g );
|
||||
|
||||
if (inf < 0)
|
||||
inf = 0;
|
||||
if (inf > 255)
|
||||
inf = 255;
|
||||
lineartoscreen[i] = inf;
|
||||
}
|
||||
|
||||
/*
|
||||
for (i=0 ; i<1024 ; i++)
|
||||
{
|
||||
// convert from screen gamma space to linear space
|
||||
lineargammatable[i] = 1023 * pow ( i/1023.0, v_gamma.GetFloat() );
|
||||
// convert from linear gamma space to screen space
|
||||
screengammatable[i] = 1023 * pow ( i/1023.0, 1.0 / v_gamma.GetFloat() );
|
||||
}
|
||||
*/
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
// convert from nonlinear texture space (0..255) to linear space (0..1)
|
||||
texturetolinear[i] = pow( i / 255.f, texGamma );
|
||||
|
||||
// convert from linear space (0..1) to nonlinear (sRGB) space (0..1)
|
||||
g_Mathlib_LinearToGamma[i] = LinearToGammaFullRange( i / 255.f );
|
||||
|
||||
// convert from sRGB gamma space (0..1) to linear space (0..1)
|
||||
g_Mathlib_GammaToLinear[i] = GammaToLinearFullRange( i / 255.f );
|
||||
}
|
||||
|
||||
for (i=0 ; i<1024 ; i++)
|
||||
{
|
||||
// convert from linear space (0..1) to nonlinear texture space (0..255)
|
||||
lineartotexture[i] = pow( i / 1023.0, 1.0 / texGamma ) * 255;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
float f;
|
||||
|
||||
// convert from nonlinear lightmap space (0..255) to linear space (0..4)
|
||||
// f = (i / 255.0) * sqrt( 4 );
|
||||
f = i * (2.0 / 255.0);
|
||||
f = f * f;
|
||||
|
||||
texlighttolinear[i] = f;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
float f;
|
||||
float overbrightFactor = 1.0f;
|
||||
|
||||
// Can't do overbright without texcombine
|
||||
// UNDONE: Add GAMMA ramp to rectify this
|
||||
if ( overbright == 2 )
|
||||
{
|
||||
overbrightFactor = 0.5;
|
||||
}
|
||||
else if ( overbright == 4 )
|
||||
{
|
||||
overbrightFactor = 0.25;
|
||||
}
|
||||
|
||||
for (i=0 ; i<4096 ; i++)
|
||||
{
|
||||
// convert from linear 0..4 (x1024) to screen corrected vertex space (0..1?)
|
||||
f = pow ( i/1024.0, 1.0 / gamma );
|
||||
|
||||
lineartovertex[i] = f * overbrightFactor;
|
||||
if (lineartovertex[i] > 1)
|
||||
lineartovertex[i] = 1;
|
||||
|
||||
int nLightmap = RoundFloatToInt( f * 255 * overbrightFactor );
|
||||
nLightmap = clamp( nLightmap, 0, 255 );
|
||||
lineartolightmap[i] = (unsigned char)nLightmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float GammaToLinearFullRange( float gamma )
|
||||
{
|
||||
return pow( gamma, 2.2f );
|
||||
}
|
||||
|
||||
float LinearToGammaFullRange( float linear )
|
||||
{
|
||||
return pow( linear, 1.0f / 2.2f );
|
||||
}
|
||||
|
||||
float GammaToLinear( float gamma )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
if ( gamma < 0.0f )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if ( gamma >= 0.95f )
|
||||
{
|
||||
// Use GammaToLinearFullRange maybe if you trip this.
|
||||
// X360TEMP
|
||||
// Assert( gamma <= 1.0f );
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
int index = RoundFloatToInt( gamma * 255.0f );
|
||||
Assert( index >= 0 && index < 256 );
|
||||
return g_Mathlib_GammaToLinear[index];
|
||||
}
|
||||
|
||||
float LinearToGamma( float linear )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
if ( linear < 0.0f )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
if ( linear > 1.0f )
|
||||
{
|
||||
// Use LinearToGammaFullRange maybe if you trip this.
|
||||
Assert( 0 );
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
int index = RoundFloatToInt( linear * 255.0f );
|
||||
Assert( index >= 0 && index < 256 );
|
||||
return g_Mathlib_LinearToGamma[index];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helper functions to convert between sRGB and 360 gamma space
|
||||
//-----------------------------------------------------------------------------
|
||||
float SrgbGammaToLinear( float flSrgbGammaValue )
|
||||
{
|
||||
float x = clamp( flSrgbGammaValue, 0.0f, 1.0f );
|
||||
return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) );
|
||||
}
|
||||
|
||||
float SrgbLinearToGamma( float flLinearValue )
|
||||
{
|
||||
float x = clamp( flLinearValue, 0.0f, 1.0f );
|
||||
return ( x <= 0.0031308f ) ? ( x * 12.92f ) : ( 1.055f * pow( x, ( 1.0f / 2.4f ) ) ) - 0.055f;
|
||||
}
|
||||
|
||||
float X360GammaToLinear( float fl360GammaValue )
|
||||
{
|
||||
float flLinearValue;
|
||||
|
||||
fl360GammaValue = clamp( fl360GammaValue, 0.0f, 1.0f );
|
||||
if ( fl360GammaValue < ( 96.0f / 255.0f ) )
|
||||
{
|
||||
if ( fl360GammaValue < ( 64.0f / 255.0f ) )
|
||||
{
|
||||
flLinearValue = fl360GammaValue * 255.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
flLinearValue = fl360GammaValue * ( 255.0f * 2.0f ) - 64.0f;
|
||||
flLinearValue += floor( flLinearValue * ( 1.0f / 512.0f ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fl360GammaValue < ( 192.0f / 255.0f ) )
|
||||
{
|
||||
flLinearValue = fl360GammaValue * ( 255.0f * 4.0f ) - 256.0f;
|
||||
flLinearValue += floor( flLinearValue * ( 1.0f / 256.0f ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
flLinearValue = fl360GammaValue * ( 255.0f * 8.0f ) - 1024.0f;
|
||||
flLinearValue += floor( flLinearValue * ( 1.0f / 128.0f ) );
|
||||
}
|
||||
}
|
||||
|
||||
flLinearValue *= 1.0f / 1023.0f;
|
||||
|
||||
flLinearValue = clamp( flLinearValue, 0.0f, 1.0f );
|
||||
return flLinearValue;
|
||||
}
|
||||
|
||||
float X360LinearToGamma( float flLinearValue )
|
||||
{
|
||||
float fl360GammaValue;
|
||||
|
||||
flLinearValue = clamp( flLinearValue, 0.0f, 1.0f );
|
||||
if ( flLinearValue < ( 128.0f / 1023.0f ) )
|
||||
{
|
||||
if ( flLinearValue < ( 64.0f / 1023.0f ) )
|
||||
{
|
||||
fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( flLinearValue < ( 512.0f / 1023.0f ) )
|
||||
{
|
||||
fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016
|
||||
if ( fl360GammaValue > 1.0f )
|
||||
{
|
||||
fl360GammaValue = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fl360GammaValue = clamp( fl360GammaValue, 0.0f, 1.0f );
|
||||
return fl360GammaValue;
|
||||
}
|
||||
|
||||
float SrgbGammaTo360Gamma( float flSrgbGammaValue )
|
||||
{
|
||||
float flLinearValue = SrgbGammaToLinear( flSrgbGammaValue );
|
||||
float fl360GammaValue = X360LinearToGamma( flLinearValue );
|
||||
return fl360GammaValue;
|
||||
}
|
||||
|
||||
// convert texture to linear 0..1 value
|
||||
float TextureToLinear( int c )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
if (c < 0)
|
||||
return 0;
|
||||
if (c > 255)
|
||||
return 1.0;
|
||||
|
||||
return texturetolinear[c];
|
||||
}
|
||||
|
||||
// convert texture to linear 0..1 value
|
||||
int LinearToTexture( float f )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
int i;
|
||||
i = f * 1023; // assume 0..1 range
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
if (i > 1023)
|
||||
i = 1023;
|
||||
|
||||
return lineartotexture[i];
|
||||
}
|
||||
|
||||
|
||||
// converts 0..1 linear value to screen gamma (0..255)
|
||||
int LinearToScreenGamma( float f )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
int i;
|
||||
i = f * 1023; // assume 0..1 range
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
if (i > 1023)
|
||||
i = 1023;
|
||||
|
||||
return lineartoscreen[i];
|
||||
}
|
||||
|
||||
void ColorRGBExp32ToVector( const ColorRGBExp32& in, Vector3D& out )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
// FIXME: Why is there a factor of 255 built into this?
|
||||
out.x = 255.0f * TexLightToLinear( in.r, in.exponent );
|
||||
out.y = 255.0f * TexLightToLinear( in.g, in.exponent );
|
||||
out.z = 255.0f * TexLightToLinear( in.b, in.exponent );
|
||||
}
|
||||
|
||||
#if 0
|
||||
// assumes that the desired mantissa range is 128..255
|
||||
static int VectorToColorRGBExp32_CalcExponent( float in )
|
||||
{
|
||||
int power = 0;
|
||||
|
||||
if( in != 0.0f )
|
||||
{
|
||||
while( in > 255.0f )
|
||||
{
|
||||
power += 1;
|
||||
in *= 0.5f;
|
||||
}
|
||||
|
||||
while( in < 128.0f )
|
||||
{
|
||||
power -= 1;
|
||||
in *= 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return power;
|
||||
}
|
||||
|
||||
void VectorToColorRGBExp32( const Vector& vin, ColorRGBExp32 &c )
|
||||
{
|
||||
Vector v = vin;
|
||||
Assert( s_bMathlibInitialized );
|
||||
Assert( v.x >= 0.0f && v.y >= 0.0f && v.z >= 0.0f );
|
||||
int i;
|
||||
float max = v[0];
|
||||
for( i = 1; i < 3; i++ )
|
||||
{
|
||||
// Get the maximum value.
|
||||
if( v[i] > max )
|
||||
{
|
||||
max = v[i];
|
||||
}
|
||||
}
|
||||
|
||||
// figure out the exponent for this luxel.
|
||||
int exponent = VectorToColorRGBExp32_CalcExponent( max );
|
||||
|
||||
// make the exponent fits into a signed byte.
|
||||
if( exponent < -128 )
|
||||
{
|
||||
exponent = -128;
|
||||
}
|
||||
else if( exponent > 127 )
|
||||
{
|
||||
exponent = 127;
|
||||
}
|
||||
|
||||
// undone: optimize with a table
|
||||
float scalar = pow( 2.0f, -exponent );
|
||||
// convert to mantissa x 2^exponent format
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
v[i] *= scalar;
|
||||
// clamp
|
||||
if( v[i] > 255.0f )
|
||||
{
|
||||
v[i] = 255.0f;
|
||||
}
|
||||
}
|
||||
c.r = ( unsigned char )v[0];
|
||||
c.g = ( unsigned char )v[1];
|
||||
c.b = ( unsigned char )v[2];
|
||||
c.exponent = ( signed char )exponent;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// given a floating point number f, return an exponent e such that
|
||||
// for f' = f * 2^e, f is on [128..255].
|
||||
// Uses IEEE 754 representation to directly extract this information
|
||||
// from the float.
|
||||
inline static int VectorToColorRGBExp32_CalcExponent( const float *pin )
|
||||
{
|
||||
// The thing we will take advantage of here is that the exponent component
|
||||
// is stored in the float itself, and because we want to map to 128..255, we
|
||||
// want an "ideal" exponent of 2^7. So, we compute the difference between the
|
||||
// input exponent and 7 to work out the normalizing exponent. Thus if you pass in
|
||||
// 32 (represented in IEEE 754 as 2^5), this function will return 2
|
||||
// (because 32 * 2^2 = 128)
|
||||
if (*pin == 0.0f)
|
||||
return 0;
|
||||
|
||||
unsigned int fbits = *reinterpret_cast<const unsigned int *>(pin);
|
||||
|
||||
// the exponent component is bits 23..30, and biased by +127
|
||||
const unsigned int biasedSeven = 7 + 127;
|
||||
|
||||
signed int expComponent = ( fbits & 0x7F800000 ) >> 23;
|
||||
expComponent -= biasedSeven; // now the difference from seven (positive if was less than, etc)
|
||||
return expComponent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Slightly faster version of the function to turn a float-vector color into
|
||||
/// a compressed-exponent notation 32bit color. However, still not SIMD optimized.
|
||||
/// PS3 developer: note there is a movement of a float onto an int here, which is
|
||||
/// bad on the base registers -- consider doing this as Altivec code, or better yet
|
||||
/// moving it onto the cell.
|
||||
/// \warning: Assumes an IEEE 754 single-precision float representation! Those of you
|
||||
/// porting to an 8080 are out of luck.
|
||||
void VectorToColorRGBExp32( const Vector3D& vin, ColorRGBExp32 &c )
|
||||
{
|
||||
Assert( s_bMathlibInitialized );
|
||||
Assert( vin.x >= 0.0f && vin.y >= 0.0f && vin.z >= 0.0f );
|
||||
|
||||
// work out which of the channels is the largest ( we will use that to map the exponent )
|
||||
// this is a sluggish branch-based decision tree -- most architectures will offer a [max]
|
||||
// assembly opcode to do this faster.
|
||||
const float *pMax;
|
||||
if (vin.x > vin.y)
|
||||
{
|
||||
if (vin.x > vin.z)
|
||||
{
|
||||
pMax = &vin.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMax = &vin.z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vin.y > vin.z)
|
||||
{
|
||||
pMax = &vin.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMax = &vin.z;
|
||||
}
|
||||
}
|
||||
|
||||
// now work out the exponent for this luxel.
|
||||
signed int exponent = VectorToColorRGBExp32_CalcExponent( pMax );
|
||||
|
||||
// make sure the exponent fits into a signed byte.
|
||||
// (in single precision format this is assured because it was a signed byte to begin with)
|
||||
Assert(exponent > -128 && exponent <= 127);
|
||||
|
||||
// promote the exponent back onto a scalar that we'll use to normalize all the numbers
|
||||
float scalar;
|
||||
{
|
||||
unsigned int fbits = (127 - exponent) << 23;
|
||||
scalar = *reinterpret_cast<float *>(&fbits);
|
||||
}
|
||||
|
||||
// We can totally wind up above 255 and that's okay--but above 256 would be right out.
|
||||
Assert(vin.x * scalar < 256.0f &&
|
||||
vin.y * scalar < 256.0f &&
|
||||
vin.z * scalar < 256.0f);
|
||||
|
||||
// This awful construction is necessary to prevent VC2005 from using the
|
||||
// fldcw/fnstcw control words around every float-to-unsigned-char operation.
|
||||
{
|
||||
int red = (vin.x * scalar);
|
||||
int green = (vin.y * scalar);
|
||||
int blue = (vin.z * scalar);
|
||||
|
||||
c.r = red;
|
||||
c.g = green;
|
||||
c.b = blue;
|
||||
}
|
||||
/*
|
||||
c.r = ( unsigned char )(vin.x * scalar);
|
||||
c.g = ( unsigned char )(vin.y * scalar);
|
||||
c.b = ( unsigned char )(vin.z * scalar);
|
||||
*/
|
||||
|
||||
c.exponent = ( signed char )exponent;
|
||||
}
|
||||
|
||||
#endif
|
56
r5dev/mathlib/halton.cpp
Normal file
56
r5dev/mathlib/halton.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "core/stdafx.h"
|
||||
#include "mathlib/halton.h"
|
||||
|
||||
// NOTE: This has to be the last file included!
|
||||
//#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
HaltonSequenceGenerator_t::HaltonSequenceGenerator_t(int b)
|
||||
{
|
||||
base = b;
|
||||
fbase = (float)b;
|
||||
seed = 1;
|
||||
|
||||
}
|
||||
|
||||
float HaltonSequenceGenerator_t::GetElement(int elem)
|
||||
{
|
||||
int tmpseed = seed;
|
||||
float ret = 0.0;
|
||||
float base_inv = 1.0 / fbase;
|
||||
while (tmpseed)
|
||||
{
|
||||
int dig = tmpseed % base;
|
||||
ret += ((float)dig) * base_inv;
|
||||
base_inv /= fbase;
|
||||
tmpseed /= base;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int InsideOut(int nTotal, int nCounter)
|
||||
{
|
||||
int b = 0;
|
||||
for (int m = nTotal, k = 1; k < nTotal; k <<= 1)
|
||||
{
|
||||
if (nCounter << 1 >= m)
|
||||
{
|
||||
b += k;
|
||||
nCounter -= (m + 1) >> 1;
|
||||
m >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = (m + 1) >> 1;
|
||||
}
|
||||
}
|
||||
Assert((b >= 0) && (b < nTotal));
|
||||
return b;
|
||||
}
|
140
r5dev/mathlib/halton.h
Normal file
140
r5dev/mathlib/halton.h
Normal file
@ -0,0 +1,140 @@
|
||||
// $Id$
|
||||
|
||||
// halton.h - classes, etc for generating numbers using the Halton pseudo-random sequence. See
|
||||
// http://halton-sequences.wikiverse.org/.
|
||||
//
|
||||
// what this function is useful for is any sort of sampling/integration problem where
|
||||
// you want to solve it by random sampling. Each call the NextValue() generates
|
||||
// a random number between 0 and 1, in an unclumped manner, so that the space can be more
|
||||
// or less evenly sampled with a minimum number of samples.
|
||||
//
|
||||
// It is NOT useful for generating random numbers dynamically, since the outputs aren't
|
||||
// particularly random.
|
||||
//
|
||||
// To generate multidimensional sample values (points in a plane, etc), use two
|
||||
// HaltonSequenceGenerator_t's, with different (primes) bases.
|
||||
|
||||
#ifndef HALTON_H
|
||||
#define HALTON_H
|
||||
|
||||
#include <tier0/platform.h>
|
||||
#include <mathlib/vector.h>
|
||||
|
||||
class HaltonSequenceGenerator_t
|
||||
{
|
||||
int seed;
|
||||
int base;
|
||||
float fbase; //< base as a float
|
||||
|
||||
public:
|
||||
HaltonSequenceGenerator_t(int base); //< base MUST be prime, >=2
|
||||
|
||||
float GetElement(int element);
|
||||
|
||||
inline float NextValue(void)
|
||||
{
|
||||
return GetElement(seed++);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class DirectionalSampler_t //< pseudo-random sphere sampling
|
||||
{
|
||||
HaltonSequenceGenerator_t zdot;
|
||||
HaltonSequenceGenerator_t vrot;
|
||||
public:
|
||||
DirectionalSampler_t(void)
|
||||
: zdot(2), vrot(3)
|
||||
{
|
||||
}
|
||||
|
||||
Vector3D NextValue(void)
|
||||
{
|
||||
float zvalue = zdot.NextValue();
|
||||
zvalue = 2 * zvalue - 1.0; // map from 0..1 to -1..1
|
||||
float phi = acos(zvalue);
|
||||
// now, generate a random rotation angle for x/y
|
||||
float theta = 2.0 * M_PI * vrot.NextValue();
|
||||
float sin_p = sin(phi);
|
||||
return Vector3D(cos(theta) * sin_p,
|
||||
sin(theta) * sin_p,
|
||||
zvalue);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // halton_h
|
||||
// $Id$
|
||||
|
||||
// halton.h - classes, etc for generating numbers using the Halton pseudo-random sequence. See
|
||||
// http://halton-sequences.wikiverse.org/.
|
||||
//
|
||||
// what this function is useful for is any sort of sampling/integration problem where
|
||||
// you want to solve it by random sampling. Each call the NextValue() generates
|
||||
// a random number between 0 and 1, in an unclumped manner, so that the space can be more
|
||||
// or less evenly sampled with a minimum number of samples.
|
||||
//
|
||||
// It is NOT useful for generating random numbers dynamically, since the outputs aren't
|
||||
// particularly random.
|
||||
//
|
||||
// To generate multidimensional sample values (points in a plane, etc), use two
|
||||
// HaltonSequenceGenerator_t's, with different (primes) bases.
|
||||
|
||||
#ifndef HALTON_H
|
||||
#define HALTON_H
|
||||
|
||||
#include <tier0/platform.h>
|
||||
#include <mathlib/vector.h>
|
||||
|
||||
class HaltonSequenceGenerator_t
|
||||
{
|
||||
int seed;
|
||||
int base;
|
||||
float fbase; //< base as a float
|
||||
|
||||
public:
|
||||
HaltonSequenceGenerator_t(int base); //< base MUST be prime, >=2
|
||||
|
||||
float GetElement(int element);
|
||||
|
||||
inline float NextValue(void)
|
||||
{
|
||||
return GetElement(seed++);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class DirectionalSampler_t //< pseudo-random sphere sampling
|
||||
{
|
||||
HaltonSequenceGenerator_t zdot;
|
||||
HaltonSequenceGenerator_t vrot;
|
||||
public:
|
||||
DirectionalSampler_t(void)
|
||||
: zdot(2),vrot(3)
|
||||
{
|
||||
}
|
||||
|
||||
Vector NextValue(void)
|
||||
{
|
||||
float zvalue=zdot.NextValue();
|
||||
zvalue=2*zvalue-1.0; // map from 0..1 to -1..1
|
||||
float phi=acos(zvalue);
|
||||
// now, generate a random rotation angle for x/y
|
||||
float theta=2.0*M_PI*vrot.NextValue();
|
||||
float sin_p=sin(phi);
|
||||
return Vector(cos(theta)*sin_p,
|
||||
sin(theta)*sin_p,
|
||||
zvalue);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // halton_h
|
283
r5dev/mathlib/math_pfns.h
Normal file
283
r5dev/mathlib/math_pfns.h
Normal file
@ -0,0 +1,283 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef _MATH_PFNS_H_
|
||||
#define _MATH_PFNS_H_
|
||||
|
||||
#include <limits>
|
||||
|
||||
#if defined( _X360 )
|
||||
#include <xboxmath.h>
|
||||
#elif defined(_PS3)
|
||||
|
||||
#ifndef SPU
|
||||
#include <ppu_asm_intrinsics.h>
|
||||
#endif
|
||||
|
||||
// Note that similar defines exist in ssemath.h
|
||||
// Maybe we should consolidate in one place for all platforms.
|
||||
|
||||
#define _VEC_0x7ff (vec_int4){0x7ff,0x7ff,0x7ff,0x7ff}
|
||||
#define _VEC_0x3ff (vec_int4){0x3ff,0x3ff,0x3ff,0x3ff}
|
||||
#define _VEC_22L (vector unsigned int){22,22,22,22}
|
||||
#define _VEC_11L (vector unsigned int){11,11,11,11}
|
||||
#define _VEC_0L (vector unsigned int){0,0,0,0}
|
||||
#define _VEC_255F (vector float){255.0f,255.0f,255.0f,255.0f}
|
||||
#define _VEC_NEGONEF (vector float){-1.0f,-1.0f,-1.0f,-1.0f}
|
||||
#define _VEC_ONEF (vector float){1.0f,1.0f,1.0f,1.0f}
|
||||
#define _VEC_ZEROF (vector float){0.0f,0.0f,0.0f,0.0f}
|
||||
#define _VEC_ZEROxyzONEwF (vector float){0.0f,0.0f,0.0f,1.0f}
|
||||
#define _VEC_HALFF (vector float){0.5f,0.5f,0.5f,0.5f}
|
||||
#define _VEC_HALFxyzZEROwF (vector float){0.5f,0.5f,0.5f,0.0f}
|
||||
#define _VEC_PERMUTE_XYZ0W1 (vector unsigned char){0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x1c,0x1d,0x1e,0x1f}
|
||||
|
||||
#define _VEC_IEEEHACK (vector float){(float)(1 << 23),(float)(1 << 23),(float)(1 << 23),(float)(1 << 23)}
|
||||
#define _VEC_PERMUTE_FASTFTOC (vector unsigned char){0,0,0,0,0,0,0,0,0,0,0,0,0x03,0x07,0x0b,0x0f}
|
||||
|
||||
// AngleQuaternion
|
||||
#define _VEC_PERMUTE_AQsxsxcxcx (vector unsigned char) {0x00,0x01,0x02,0x03,0x00,0x01,0x02,0x03,0x10,0x11,0x12,0x13,0x10,0x11,0x12,0x13}
|
||||
#define _VEC_PERMUTE_AQczszszcz (vector unsigned char) {0x18,0x19,0x1a,0x1b,0x08,0x09,0x0a,0x0b,0x08,0x09,0x0a,0x0b,0x18,0x19,0x1a,0x1b}
|
||||
#define _VEC_PERMUTE_AQcxcxsxsx (vector unsigned char) {0x10,0x11,0x12,0x13,0x10,0x11,0x12,0x13,0x00,0x01,0x02,0x03,0x00,0x01,0x02,0x03}
|
||||
#define _VEC_PERMUTE_AQszczczsz (vector unsigned char) {0x08,0x09,0x0a,0x0b,0x18,0x19,0x1a,0x1b,0x18,0x19,0x1a,0x1b,0x08,0x09,0x0a,0x0b}
|
||||
#define _VEC_PERMUTE_ANGLEQUAT (vector unsigned char) {0x10,0x11,0x12,0x13,0x04,0x05,0x06,0x07,0x18,0x19,0x1a,0x1b,0x0c,0x0d,0x0e,0x0f}
|
||||
|
||||
#define _VEC_EPSILONF (__vector float) {FLT_EPSILON,FLT_EPSILON,FLT_EPSILON,FLT_EPSILON}
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined( PLATFORM_PPC ) || defined(SPU))
|
||||
// If we are not PPC based or SPU based, then assumes it is SSE2. We should make this code cleaner.
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
// These globals are initialized by mathlib and redirected based on available fpu features
|
||||
|
||||
// The following are not declared as macros because they are often used in limiting situations,
|
||||
// and sometimes the compiler simply refuses to inline them for some reason
|
||||
FORCEINLINE float FastSqrt(float x)
|
||||
{
|
||||
__m128 root = _mm_sqrt_ss(_mm_load_ss(&x));
|
||||
return *(reinterpret_cast<float*>(&root));
|
||||
}
|
||||
|
||||
FORCEINLINE float FastRSqrtFast(float x)
|
||||
{
|
||||
// use intrinsics
|
||||
__m128 rroot = _mm_rsqrt_ss(_mm_load_ss(&x));
|
||||
return *(reinterpret_cast<float*>(&rroot));
|
||||
}
|
||||
// Single iteration NewtonRaphson reciprocal square root:
|
||||
// 0.5 * rsqrtps * (3 - x * rsqrtps(x) * rsqrtps(x))
|
||||
// Very low error, and fine to use in place of 1.f / sqrtf(x).
|
||||
FORCEINLINE float FastRSqrt(float x)
|
||||
{
|
||||
float rroot = FastRSqrtFast(x);
|
||||
return (0.5f * rroot) * (3.f - (x * rroot) * rroot);
|
||||
}
|
||||
|
||||
void FastSinCos(float x, float* s, float* c); // any x
|
||||
float FastCos(float x);
|
||||
|
||||
|
||||
|
||||
inline float FastRecip(float x) { return 1.0f / x; }
|
||||
// Simple SSE rsqrt. Usually accurate to around 6 (relative) decimal places
|
||||
// or so, so ok for closed transforms. (ie, computing lighting normals)
|
||||
inline float FastSqrtEst(float x) { return FastRSqrtFast(x) * x; }
|
||||
|
||||
|
||||
#else // !defined( PLATFORM_PPC ) && !defined(_SPU)
|
||||
|
||||
#ifndef SPU
|
||||
// We may not need this for SPU, so let's not bother for now
|
||||
|
||||
FORCEINLINE float _VMX_Sqrt(float x)
|
||||
{
|
||||
return __fsqrts(x);
|
||||
}
|
||||
|
||||
FORCEINLINE double _VMX_RSqrt(double x)
|
||||
{
|
||||
double rroot = __frsqrte(x);
|
||||
|
||||
// Single iteration NewtonRaphson on reciprocal square root estimate
|
||||
return (0.5f * rroot) * (3.0f - (x * rroot) * rroot);
|
||||
}
|
||||
|
||||
FORCEINLINE double _VMX_RSqrtFast(double x)
|
||||
{
|
||||
return __frsqrte(x);
|
||||
}
|
||||
|
||||
#ifdef _X360
|
||||
FORCEINLINE void _VMX_SinCos(float a, float* pS, float* pC)
|
||||
{
|
||||
XMScalarSinCos(pS, pC, a);
|
||||
}
|
||||
|
||||
FORCEINLINE float _VMX_Cos(float a)
|
||||
{
|
||||
return XMScalarCos(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
// the 360 has fixed hw and calls directly
|
||||
#define FastSqrt(x) _VMX_Sqrt(x)
|
||||
#define FastRSqrt(x) _VMX_RSqrt(x)
|
||||
#define FastRSqrtFast(x) _VMX_RSqrtFast(x)
|
||||
#define FastSinCos(x,s,c) _VMX_SinCos(x,s,c)
|
||||
#define FastCos(x) _VMX_Cos(x)
|
||||
|
||||
inline double FastRecip(double x) { return __fres(x); }
|
||||
inline double FastSqrtEst(double x) { return __frsqrte(x) * x; }
|
||||
|
||||
#endif // !defined( PLATFORM_PPC ) && !defined(_SPU)
|
||||
|
||||
// if x is infinite, return FLT_MAX
|
||||
inline float FastClampInfinity(float x)
|
||||
{
|
||||
#ifdef PLATFORM_PPC
|
||||
return fsel(std::numeric_limits<float>::infinity() - x, x, FLT_MAX);
|
||||
#else
|
||||
return (x > FLT_MAX ? FLT_MAX : x);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (_PS3) && !defined(SPU)
|
||||
|
||||
// extern float cosvf(float); /* single precision cosine */
|
||||
// extern float sinvf(float); /* single precision sine */
|
||||
// TODO: need a faster single precision equivalent
|
||||
#define cosvf cosf
|
||||
#define sinvf sinf
|
||||
|
||||
inline int _rotl(int x, int c)
|
||||
{
|
||||
return __rlwimi(x, x, c, 0, 31);
|
||||
}
|
||||
|
||||
inline int64 _rotl64(int64 x, int c)
|
||||
{
|
||||
return __rldicl(x, c, 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Vector Unions
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Floats
|
||||
//-----------------------------------------------------------------
|
||||
typedef union
|
||||
{
|
||||
vector float vf;
|
||||
float f[4];
|
||||
} vector_float_union;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Ints
|
||||
//-----------------------------------------------------------------
|
||||
typedef union
|
||||
{
|
||||
vector int vi;
|
||||
int i[4];
|
||||
} vector_int4_union;
|
||||
|
||||
typedef union
|
||||
{
|
||||
vector unsigned int vui;
|
||||
unsigned int ui[4];
|
||||
} vector_uint4_union;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Shorts
|
||||
//-----------------------------------------------------------------
|
||||
typedef union
|
||||
{
|
||||
vector signed short vs;
|
||||
signed short s[8];
|
||||
} vector_short8_union;
|
||||
|
||||
typedef union
|
||||
{
|
||||
vector unsigned short vus;
|
||||
unsigned short us[8];
|
||||
} vector_ushort8_union;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Chars
|
||||
//-----------------------------------------------------------------
|
||||
typedef union
|
||||
{
|
||||
vector signed char vc;
|
||||
signed char c[16];
|
||||
} vector_char16_union;
|
||||
|
||||
typedef union
|
||||
{
|
||||
vector unsigned char vuc;
|
||||
unsigned char uc[16];
|
||||
} vector_uchar16_union;
|
||||
|
||||
/*
|
||||
FORCEINLINE float _VMX_Sqrt( float x )
|
||||
{
|
||||
vector_float_union vIn, vOut;
|
||||
|
||||
vIn.f[0] = x;
|
||||
|
||||
vOut.vf = sqrtf4(vIn.vf);
|
||||
|
||||
return vOut.f[0];
|
||||
}
|
||||
|
||||
FORCEINLINE float _VMX_RSqrt( float x )
|
||||
{
|
||||
vector_float_union vIn, vOut;
|
||||
|
||||
vIn.f[0] = x;
|
||||
|
||||
vOut.vf = rsqrtf4(vIn.vf);
|
||||
|
||||
return vOut.f[0];
|
||||
}
|
||||
|
||||
FORCEINLINE float _VMX_RSqrtFast( float x )
|
||||
{
|
||||
vector_float_union vIn, vOut;
|
||||
|
||||
vIn.f[0] = x;
|
||||
|
||||
vOut.vf = rsqrtf4fast(vIn.vf);
|
||||
|
||||
return vOut.f[0];
|
||||
}
|
||||
*/
|
||||
|
||||
FORCEINLINE void _VMX_SinCos(float a, float* pS, float* pC)
|
||||
{
|
||||
*pS = sinvf(a);
|
||||
*pC = cosvf(a);
|
||||
}
|
||||
|
||||
FORCEINLINE float _VMX_Cos(float a)
|
||||
{
|
||||
return cosvf(a);
|
||||
}
|
||||
|
||||
|
||||
// the 360 has fixed hw and calls directly
|
||||
/*
|
||||
#define FastSqrt(x) _VMX_Sqrt(x)
|
||||
#define FastRSqrt(x) _VMX_RSqrt(x)
|
||||
#define FastRSqrtFast(x) _VMX_RSqrtFast(x)
|
||||
#define FastSinCos(x,s,c) _VMX_SinCos(x,s,c)
|
||||
#define FastCos(x) _VMX_Cos(x)
|
||||
*/
|
||||
#endif // _PS3
|
||||
#endif // #ifndef SPU
|
||||
|
||||
#endif // _MATH_PFNS_H_
|
2498
r5dev/mathlib/mathlib.h
Normal file
2498
r5dev/mathlib/mathlib.h
Normal file
File diff suppressed because it is too large
Load Diff
4457
r5dev/mathlib/mathlib_base.cpp
Normal file
4457
r5dev/mathlib/mathlib_base.cpp
Normal file
File diff suppressed because it is too large
Load Diff
180
r5dev/mathlib/noisedata.h
Normal file
180
r5dev/mathlib/noisedata.h
Normal file
@ -0,0 +1,180 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: static data for noise() primitives.
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
//
|
||||
// **** DO NOT EDIT THIS FILE. GENERATED BY DATAGEN.PL ****
|
||||
//
|
||||
|
||||
static int perm_a[] = {
|
||||
66,147,106,213,89,115,239,25,171,175,9,114,141,226,118,128,41,208,4,56,
|
||||
180,248,43,82,246,219,94,245,133,131,222,103,160,130,168,145,238,38,23,6,
|
||||
236,67,99,2,70,232,80,209,1,3,68,65,102,210,13,73,55,252,187,170,22,36,
|
||||
52,181,117,163,46,79,166,224,148,75,113,95,156,185,220,164,51,142,161,35,
|
||||
206,251,45,136,197,190,132,32,218,127,63,27,137,93,242,20,189,108,183,
|
||||
122,139,191,249,253,87,98,69,0,144,64,24,214,97,116,158,42,107,15,53,212,
|
||||
83,111,152,240,74,237,62,77,205,149,26,151,178,204,91,176,234,49,154,203,
|
||||
33,221,125,134,165,124,86,39,37,60,150,157,179,109,110,44,159,153,5,100,
|
||||
10,207,40,186,96,215,143,162,230,184,101,54,174,247,76,59,241,223,192,84,
|
||||
104,78,169,146,138,30,48,85,233,19,29,92,126,17,199,250,31,81,188,225,28,
|
||||
112,88,11,182,173,211,129,194,172,14,120,200,167,135,12,177,227,229,155,
|
||||
201,61,105,195,193,244,235,58,8,196,123,254,16,18,50,121,71,243,90,57,
|
||||
202,119,255,47,7,198,228,21,217,216,231,140,72,34
|
||||
};
|
||||
|
||||
static int perm_b[] = {
|
||||
123,108,201,64,40,75,24,221,137,110,191,142,9,69,230,83,7,247,51,54,115,
|
||||
133,180,248,109,116,62,99,251,55,89,253,65,106,228,167,131,132,58,143,
|
||||
97,102,163,202,149,234,12,117,174,94,121,74,32,113,20,60,159,182,204,29,
|
||||
244,118,3,178,255,38,6,114,36,93,30,134,213,90,245,209,88,232,162,125,
|
||||
84,166,70,136,208,231,27,71,157,80,76,0,170,225,203,176,33,161,196,128,
|
||||
252,236,246,2,138,1,250,197,77,243,218,242,19,164,68,212,14,237,144,63,
|
||||
46,103,177,188,85,223,8,160,222,4,216,219,35,15,44,23,126,127,100,226,
|
||||
235,37,168,101,49,22,11,73,61,135,111,183,72,96,185,239,82,18,50,155,
|
||||
186,153,17,233,146,156,107,5,254,10,192,198,148,207,104,13,124,48,95,
|
||||
129,120,206,199,81,249,91,150,210,119,240,122,194,92,34,28,205,175,227,
|
||||
179,220,140,152,79,26,195,47,66,173,169,241,53,184,187,145,112,238,214,
|
||||
147,98,171,229,200,151,25,67,78,189,217,130,224,57,172,59,41,43,16,105,
|
||||
158,165,21,45,56,141,139,215,190,86,42,52,39,87,181,31,154,193,211
|
||||
};
|
||||
|
||||
static int perm_c[] = {
|
||||
97,65,96,25,122,26,219,85,148,251,102,0,140,130,136,213,138,60,236,52,
|
||||
178,131,115,183,144,78,147,168,39,45,169,70,57,146,67,142,252,216,28,54,
|
||||
86,222,194,200,48,5,205,125,214,56,181,255,196,155,37,218,153,208,66,
|
||||
242,73,248,206,61,62,246,177,2,197,107,162,152,89,41,6,160,94,8,201,38,
|
||||
235,228,165,93,111,239,74,231,121,47,166,221,157,64,77,244,29,105,150,
|
||||
123,190,191,225,118,133,42,10,84,185,159,124,132,240,180,44,1,9,19,99,
|
||||
254,12,207,186,71,234,184,11,20,16,193,139,175,98,59,113,27,170,230,91,
|
||||
187,46,156,249,108,195,171,114,14,188,82,192,233,24,32,241,87,164,90,43,
|
||||
163,245,92,40,215,55,226,15,3,112,158,250,172,22,227,137,35,128,145,247,
|
||||
161,119,80,217,189,81,7,63,202,120,223,83,179,4,106,199,229,95,53,50,33,
|
||||
182,72,143,23,243,75,18,173,141,167,198,204,58,174,237,17,129,238,127,
|
||||
31,101,176,36,30,110,209,34,203,135,232,68,149,49,134,126,212,79,76,117,
|
||||
104,210,211,224,253,100,220,109,116,88,13,151,154,69,21,51,103
|
||||
};
|
||||
|
||||
static int perm_d[] = {
|
||||
94,234,145,235,151,166,187,238,4,5,128,115,87,107,229,175,190,108,218,
|
||||
32,17,220,97,90,122,121,71,109,64,227,225,75,81,19,27,162,3,89,139,69,
|
||||
92,26,48,215,116,191,114,2,104,157,66,39,1,127,96,124,30,0,82,233,219,
|
||||
42,131,173,35,201,182,144,14,98,148,244,160,159,179,91,31,68,119,154,
|
||||
205,113,149,167,44,60,18,228,251,245,43,10,80,15,129,67,181,174,6,45,
|
||||
194,237,213,52,99,232,211,212,164,217,57,153,156,102,134,20,249,132,55,
|
||||
204,65,33,231,85,61,37,163,193,189,170,226,63,168,236,165,224,242,195,
|
||||
41,200,40,70,112,100,36,172,130,74,137,252,243,135,230,161,207,16,146,
|
||||
198,118,150,24,29,250,188,25,209,103,23,105,47,7,46,133,83,184,50,79,
|
||||
110,120,53,253,206,214,9,240,101,147,152,183,254,59,126,216,197,171,51,
|
||||
208,248,202,58,176,28,72,177,185,141,12,11,56,222,86,178,155,223,88,111,
|
||||
73,142,210,138,239,221,199,192,84,93,241,125,76,77,255,95,8,78,247,186,
|
||||
123,196,13,140,180,143,54,106,136,34,62,169,38,117,22,21,49,203,158,246
|
||||
};
|
||||
|
||||
static float impulse_xcoords[] = {
|
||||
0.788235,0.541176,0.972549,0.082353,0.352941,0.811765,0.286275,0.752941,
|
||||
0.203922,0.705882,0.537255,0.886275,0.580392,0.137255,0.800000,0.533333,
|
||||
0.117647,0.447059,0.129412,0.925490,0.086275,0.478431,0.666667,0.568627,
|
||||
0.678431,0.313725,0.321569,0.349020,0.988235,0.419608,0.898039,0.219608,
|
||||
0.243137,0.623529,0.501961,0.772549,0.952941,0.517647,0.949020,0.701961,
|
||||
0.454902,0.505882,0.564706,0.960784,0.207843,0.007843,0.831373,0.184314,
|
||||
0.576471,0.462745,0.572549,0.247059,0.262745,0.694118,0.615686,0.121569,
|
||||
0.384314,0.749020,0.145098,0.717647,0.415686,0.607843,0.105882,0.101961,
|
||||
0.200000,0.807843,0.521569,0.780392,0.466667,0.552941,0.996078,0.627451,
|
||||
0.992157,0.529412,0.407843,0.011765,0.709804,0.458824,0.058824,0.819608,
|
||||
0.176471,0.317647,0.392157,0.223529,0.156863,0.490196,0.325490,0.074510,
|
||||
0.239216,0.164706,0.890196,0.603922,0.921569,0.839216,0.854902,0.098039,
|
||||
0.686275,0.843137,0.152941,0.372549,0.062745,0.474510,0.486275,0.227451,
|
||||
0.400000,0.298039,0.309804,0.274510,0.054902,0.815686,0.647059,0.635294,
|
||||
0.662745,0.976471,0.094118,0.509804,0.650980,0.211765,0.180392,0.003922,
|
||||
0.827451,0.278431,0.023529,0.525490,0.450980,0.725490,0.690196,0.941176,
|
||||
0.639216,0.560784,0.196078,0.364706,0.043137,0.494118,0.796078,0.113725,
|
||||
0.760784,0.729412,0.258824,0.290196,0.584314,0.674510,0.823529,0.905882,
|
||||
0.917647,0.070588,0.862745,0.345098,0.913725,0.937255,0.031373,0.215686,
|
||||
0.768627,0.333333,0.411765,0.423529,0.945098,0.721569,0.039216,0.792157,
|
||||
0.956863,0.266667,0.254902,0.047059,0.294118,0.658824,0.250980,1.000000,
|
||||
0.984314,0.756863,0.027451,0.305882,0.835294,0.513725,0.360784,0.776471,
|
||||
0.611765,0.192157,0.866667,0.858824,0.592157,0.803922,0.141176,0.435294,
|
||||
0.588235,0.619608,0.341176,0.109804,0.356863,0.270588,0.737255,0.847059,
|
||||
0.050980,0.764706,0.019608,0.870588,0.933333,0.784314,0.549020,0.337255,
|
||||
0.631373,0.929412,0.231373,0.427451,0.078431,0.498039,0.968627,0.654902,
|
||||
0.125490,0.698039,0.015686,0.878431,0.713725,0.368627,0.431373,0.874510,
|
||||
0.403922,0.556863,0.443137,0.964706,0.909804,0.301961,0.035294,0.850980,
|
||||
0.882353,0.741176,0.380392,0.133333,0.470588,0.643137,0.282353,0.396078,
|
||||
0.980392,0.168627,0.149020,0.235294,0.670588,0.596078,0.733333,0.160784,
|
||||
0.376471,0.682353,0.545098,0.482353,0.745098,0.894118,0.188235,0.329412,
|
||||
0.439216,0.901961,0.000000,0.600000,0.388235,0.172549,0.090196,0.066667
|
||||
};
|
||||
|
||||
static float impulse_ycoords[] = {
|
||||
0.827451,0.337255,0.941176,0.886275,0.878431,0.239216,0.400000,0.164706,
|
||||
0.490196,0.411765,0.964706,0.349020,0.803922,0.317647,0.647059,0.431373,
|
||||
0.933333,0.156863,0.094118,0.219608,0.039216,0.521569,0.498039,0.705882,
|
||||
0.717647,0.047059,0.631373,0.517647,0.984314,0.847059,0.482353,0.439216,
|
||||
0.250980,0.862745,0.690196,0.913725,0.270588,0.070588,0.027451,0.694118,
|
||||
0.811765,0.000000,0.494118,0.823529,0.800000,0.600000,0.003922,0.443137,
|
||||
0.639216,0.376471,0.031373,0.035294,0.552941,0.215686,0.305882,0.133333,
|
||||
0.564706,0.176471,0.211765,0.874510,0.360784,0.654902,0.223529,0.807843,
|
||||
0.372549,0.137255,0.321569,0.015686,0.007843,0.262745,0.125490,0.078431,
|
||||
0.396078,0.976471,0.929412,1.000000,0.937255,0.509804,0.188235,0.850980,
|
||||
0.831373,0.392157,0.741176,0.541176,0.592157,0.286275,0.345098,0.572549,
|
||||
0.537255,0.725490,0.839216,0.184314,0.772549,0.149020,0.505882,0.423529,
|
||||
0.780392,0.011765,0.890196,0.086275,0.427451,0.023529,0.788235,0.050980,
|
||||
0.760784,0.603922,0.066667,0.643137,0.623529,0.960784,0.172549,0.333333,
|
||||
0.082353,0.290196,0.992157,0.709804,0.894118,0.596078,0.243137,0.752941,
|
||||
0.486275,0.670588,0.949020,0.784314,0.145098,0.560784,0.513725,0.180392,
|
||||
0.580392,0.996078,0.380392,0.556863,0.407843,0.945098,0.117647,0.058824,
|
||||
0.678431,0.129412,0.192157,0.105882,0.968627,0.545098,0.462745,0.227451,
|
||||
0.019608,0.866667,0.674510,0.207843,0.627451,0.819608,0.921569,0.356863,
|
||||
0.447059,0.533333,0.435294,0.341176,0.054902,0.529412,0.235294,0.764706,
|
||||
0.615686,0.043137,0.745098,0.266667,0.501961,0.619608,0.776471,0.450980,
|
||||
0.309804,0.325490,0.200000,0.635294,0.247059,0.698039,0.721569,0.168627,
|
||||
0.854902,0.141176,0.611765,0.525490,0.415686,0.298039,0.254902,0.858824,
|
||||
0.568627,0.329412,0.062745,0.843137,0.588235,0.733333,0.607843,0.478431,
|
||||
0.576471,0.662745,0.470588,0.666667,0.980392,0.113725,0.898039,0.203922,
|
||||
0.294118,0.152941,0.098039,0.909804,0.796078,0.768627,0.713725,0.196078,
|
||||
0.368627,0.419608,0.352941,0.090196,0.749020,0.121569,0.882353,0.278431,
|
||||
0.388235,0.917647,0.701961,0.729412,0.835294,0.258824,0.301961,0.101961,
|
||||
0.792157,0.474510,0.686275,0.658824,0.364706,0.682353,0.458824,0.815686,
|
||||
0.282353,0.160784,0.870588,0.988235,0.756863,0.549020,0.274510,0.384314,
|
||||
0.650980,0.737255,0.901961,0.956863,0.972549,0.584314,0.925490,0.403922,
|
||||
0.074510,0.454902,0.952941,0.109804,0.313725,0.905882,0.231373,0.466667
|
||||
};
|
||||
|
||||
static float impulse_zcoords[] = {
|
||||
0.082353,0.643137,0.415686,0.929412,0.568627,0.509804,0.537255,0.815686,
|
||||
0.698039,0.941176,0.776471,0.752941,0.737255,0.525490,0.498039,0.423529,
|
||||
0.792157,0.125490,0.619608,0.164706,0.368627,0.870588,0.137255,0.372549,
|
||||
0.466667,0.486275,0.501961,0.513725,0.709804,0.576471,0.203922,0.258824,
|
||||
0.152941,0.556863,0.223529,0.047059,0.235294,0.474510,0.764706,0.552941,
|
||||
0.847059,0.145098,0.176471,0.937255,0.654902,0.894118,0.729412,0.054902,
|
||||
0.666667,0.749020,0.262745,0.560784,0.431373,0.286275,0.352941,0.239216,
|
||||
0.156863,0.839216,0.427451,0.949020,0.384314,0.227451,0.180392,0.074510,
|
||||
0.172549,0.356863,0.066667,0.517647,0.447059,0.184314,0.062745,0.670588,
|
||||
0.603922,0.219608,0.270588,0.976471,0.505882,0.627451,0.819608,0.854902,
|
||||
0.843137,0.019608,0.713725,0.035294,0.925490,0.349020,0.866667,0.701961,
|
||||
0.909804,0.811765,0.717647,0.141176,0.917647,0.023529,0.098039,0.803922,
|
||||
0.733333,0.658824,0.827451,0.133333,0.858824,0.800000,0.635294,1.000000,
|
||||
0.078431,0.450980,0.835294,0.321569,0.360784,0.529412,0.725490,0.572549,
|
||||
0.639216,0.341176,0.533333,0.094118,0.149020,0.545098,0.101961,0.901961,
|
||||
0.278431,0.694118,0.521569,0.490196,0.454902,0.329412,0.274510,0.027451,
|
||||
0.745098,0.933333,0.443137,0.168627,0.192157,0.988235,0.070588,0.972549,
|
||||
0.768627,0.400000,0.470588,0.207843,0.215686,0.388235,0.439216,0.780392,
|
||||
0.482353,0.121569,0.964706,0.086275,0.890196,0.337255,0.109804,0.305882,
|
||||
0.113725,0.435294,0.721569,0.772549,0.807843,0.741176,0.254902,0.596078,
|
||||
0.494118,0.317647,0.419608,0.000000,0.188235,0.031373,0.376471,0.380392,
|
||||
0.611765,0.945098,0.411765,0.313725,0.874510,0.588235,0.678431,0.160784,
|
||||
0.007843,0.090196,0.850980,0.788235,0.705882,0.266667,0.309804,0.541176,
|
||||
0.231373,0.129412,0.294118,0.243137,0.913725,0.996078,0.117647,0.478431,
|
||||
0.290196,0.549020,0.682353,0.784314,0.396078,0.831373,0.984314,0.584314,
|
||||
0.039216,0.250980,0.600000,0.392157,0.298039,0.050980,0.364706,0.105882,
|
||||
0.623529,0.886275,0.980392,0.325490,0.247059,0.690196,0.674510,0.960784,
|
||||
0.647059,0.211765,0.882353,0.686275,0.823529,0.058824,0.956863,0.043137,
|
||||
0.345098,0.301961,0.592157,0.862745,0.607843,0.458824,0.282353,0.003922,
|
||||
0.580392,0.760784,0.564706,0.011765,0.968627,0.905882,0.756863,0.952941,
|
||||
0.662745,0.015686,0.898039,0.196078,0.333333,0.992157,0.650980,0.407843,
|
||||
0.796078,0.615686,0.878431,0.921569,0.631373,0.200000,0.403922,0.462745
|
||||
};
|
||||
|
97
r5dev/mathlib/powsse.cpp
Normal file
97
r5dev/mathlib/powsse.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "core/stdafx.h"
|
||||
#include "mathlib/ssemath.h"
|
||||
|
||||
// NOTE: This has to be the last file included!
|
||||
//#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
fltx4 Pow_FixedPoint_Exponent_SIMD(const fltx4& x, int exponent)
|
||||
{
|
||||
fltx4 rslt = Four_Ones; // x^0=1.0
|
||||
int xp = abs(exponent);
|
||||
if (xp & 3) // fraction present?
|
||||
{
|
||||
fltx4 sq_rt = SqrtEstSIMD(x);
|
||||
if (xp & 1) // .25?
|
||||
rslt = SqrtEstSIMD(sq_rt); // x^.25
|
||||
if (xp & 2)
|
||||
rslt = MulSIMD(rslt, sq_rt);
|
||||
}
|
||||
xp >>= 2; // strip fraction
|
||||
fltx4 curpower = x; // curpower iterates through x,x^2,x^4,x^8,x^16...
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (xp & 1)
|
||||
rslt = MulSIMD(rslt, curpower);
|
||||
xp >>= 1;
|
||||
if (xp)
|
||||
curpower = MulSIMD(curpower, curpower);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (exponent < 0)
|
||||
return ReciprocalEstSaturateSIMD(rslt); // pow(x,-b)=1/pow(x,b)
|
||||
else
|
||||
return rslt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* (c) Ian Stephenson
|
||||
*
|
||||
* ian@dctsystems.co.uk
|
||||
*
|
||||
* Fast pow() reference implementation
|
||||
*/
|
||||
|
||||
|
||||
static float shift23 = (1 << 23);
|
||||
static float OOshift23 = 1.0 / (1 << 23);
|
||||
|
||||
float FastLog2(float i)
|
||||
{
|
||||
float LogBodge = 0.346607f;
|
||||
float x;
|
||||
float y;
|
||||
x = *(int*)&i;
|
||||
x *= OOshift23; //1/pow(2,23);
|
||||
x = x - 127;
|
||||
|
||||
y = x - floorf(x);
|
||||
y = (y - y * y) * LogBodge;
|
||||
return x + y;
|
||||
}
|
||||
float FastPow2(float i)
|
||||
{
|
||||
float PowBodge = 0.33971f;
|
||||
float x;
|
||||
float y = i - floorf(i);
|
||||
y = (y - y * y) * PowBodge;
|
||||
|
||||
x = i + 127 - y;
|
||||
x *= shift23; //pow(2,23);
|
||||
*(int*)&x = (int)x;
|
||||
return x;
|
||||
}
|
||||
float FastPow(float a, float b)
|
||||
{
|
||||
if (a <= OOshift23)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return FastPow2(b * FastLog2(a));
|
||||
}
|
||||
float FastPow10(float i)
|
||||
{
|
||||
return FastPow2(i * 3.321928f);
|
||||
}
|
||||
|
107
r5dev/mathlib/randsse.cpp
Normal file
107
r5dev/mathlib/randsse.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: generates 4 randum numbers in the range 0..1 quickly, using SIMD
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "core/stdafx.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/basetypes.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/ssemath.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
//#include "tier0/memdbgon.h"
|
||||
|
||||
// see knuth volume 3 for insight.
|
||||
|
||||
class SIMDRandStreamContext
|
||||
{
|
||||
fltx4 m_RandY[55];
|
||||
|
||||
fltx4* m_pRand_J, * m_pRand_K;
|
||||
|
||||
|
||||
public:
|
||||
void Seed(uint32 seed)
|
||||
{
|
||||
m_pRand_J = m_RandY + 23; m_pRand_K = m_RandY + 54;
|
||||
for (int i = 0; i < 55; i++)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
SubFloat(m_RandY[i], j) = (seed >> 16) / 65536.0;
|
||||
seed = (seed + 1) * 3141592621u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fltx4 RandSIMD(void)
|
||||
{
|
||||
// ret= rand[k]+rand[j]
|
||||
fltx4 retval = AddSIMD(*m_pRand_K, *m_pRand_J);
|
||||
|
||||
// if ( ret>=1.0) ret-=1.0
|
||||
fltx4 overflow_mask = CmpGeSIMD(retval, Four_Ones);
|
||||
retval = SubSIMD(retval, AndSIMD(Four_Ones, overflow_mask));
|
||||
|
||||
*m_pRand_K = retval;
|
||||
|
||||
// update pointers w/ wrap-around
|
||||
if (--m_pRand_J < m_RandY)
|
||||
m_pRand_J = m_RandY + 54;
|
||||
if (--m_pRand_K < m_RandY)
|
||||
m_pRand_K = m_RandY + 54;
|
||||
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
#define MAX_SIMULTANEOUS_RANDOM_STREAMS 32
|
||||
|
||||
static SIMDRandStreamContext s_SIMDRandContexts[MAX_SIMULTANEOUS_RANDOM_STREAMS];
|
||||
|
||||
static volatile LONG s_nRandContextsInUse[MAX_SIMULTANEOUS_RANDOM_STREAMS];
|
||||
|
||||
void SeedRandSIMD(uint32 seed)
|
||||
{
|
||||
for (int i = 0; i < MAX_SIMULTANEOUS_RANDOM_STREAMS; i++)
|
||||
s_SIMDRandContexts[i].Seed(seed + i);
|
||||
}
|
||||
|
||||
fltx4 RandSIMD(int nContextIndex)
|
||||
{
|
||||
return s_SIMDRandContexts[nContextIndex].RandSIMD();
|
||||
}
|
||||
|
||||
int GetSIMDRandContext(void)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
for (int i = 0; i < NELEMS(s_SIMDRandContexts); i++)
|
||||
{
|
||||
if (!s_nRandContextsInUse[i]) // available?
|
||||
{
|
||||
// try to take it!
|
||||
if (ThreadInterlockedAssignIf(&(s_nRandContextsInUse[i]), 1, 0))
|
||||
{
|
||||
return i; // done!
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert(0); // why don't we have enough buffers?
|
||||
ThreadSleep(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseSIMDRandContext(int nContext)
|
||||
{
|
||||
s_nRandContextsInUse[nContext] = 0;
|
||||
}
|
||||
|
||||
|
||||
fltx4 RandSIMD(void)
|
||||
{
|
||||
return s_SIMDRandContexts[0].RandSIMD();
|
||||
}
|
1165
r5dev/mathlib/sseconst.cpp
Normal file
1165
r5dev/mathlib/sseconst.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3107
r5dev/mathlib/ssemath.h
Normal file
3107
r5dev/mathlib/ssemath.h
Normal file
File diff suppressed because it is too large
Load Diff
107
r5dev/mathlib/ssenoise.h
Normal file
107
r5dev/mathlib/ssenoise.h
Normal file
@ -0,0 +1,107 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Fast low quality noise suitable for real time use
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "core/stdafx.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/basetypes.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/ssemath.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
//#include "tier0/memdbgon.h"
|
||||
#include "noisedata.h"
|
||||
|
||||
|
||||
#define MAGIC_NUMBER (1<<15) // gives 8 bits of fraction
|
||||
|
||||
static fltx4 Four_MagicNumbers = { MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER };
|
||||
|
||||
|
||||
static ALIGN16 int32 idx_mask[4] = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
|
||||
#define MASK255 (*((fltx4 *)(& idx_mask )))
|
||||
|
||||
// returns 0..1
|
||||
static inline float GetLatticePointValue(int idx_x, int idx_y, int idx_z)
|
||||
{
|
||||
NOTE_UNUSED(perm_d);
|
||||
NOTE_UNUSED(impulse_ycoords);
|
||||
NOTE_UNUSED(impulse_zcoords);
|
||||
|
||||
int ret_idx = perm_a[idx_x & 0xff];
|
||||
ret_idx = perm_b[(idx_y + ret_idx) & 0xff];
|
||||
ret_idx = perm_c[(idx_z + ret_idx) & 0xff];
|
||||
return impulse_xcoords[ret_idx];
|
||||
|
||||
}
|
||||
|
||||
fltx4 NoiseSIMD(const fltx4& x, const fltx4& y, const fltx4& z)
|
||||
{
|
||||
// use magic to convert to integer index
|
||||
fltx4 x_idx = AndSIMD(MASK255, AddSIMD(x, Four_MagicNumbers));
|
||||
fltx4 y_idx = AndSIMD(MASK255, AddSIMD(y, Four_MagicNumbers));
|
||||
fltx4 z_idx = AndSIMD(MASK255, AddSIMD(z, Four_MagicNumbers));
|
||||
|
||||
fltx4 lattice000 = Four_Zeros, lattice001 = Four_Zeros, lattice010 = Four_Zeros, lattice011 = Four_Zeros;
|
||||
fltx4 lattice100 = Four_Zeros, lattice101 = Four_Zeros, lattice110 = Four_Zeros, lattice111 = Four_Zeros;
|
||||
|
||||
// FIXME: Converting the input vectors to int indices will cause load-hit-stores (48 bytes)
|
||||
// Converting the indexed noise values back to vectors will cause more (128 bytes)
|
||||
// The noise table could store vectors if we chunked it into 2x2x2 blocks.
|
||||
fltx4 xfrac = Four_Zeros, yfrac = Four_Zeros, zfrac = Four_Zeros;
|
||||
#define DOPASS(i) \
|
||||
{ unsigned int xi = SubInt( x_idx, i ); \
|
||||
unsigned int yi = SubInt( y_idx, i ); \
|
||||
unsigned int zi = SubInt( z_idx, i ); \
|
||||
SubFloat( xfrac, i ) = (xi & 0xff)*(1.0/256.0); \
|
||||
SubFloat( yfrac, i ) = (yi & 0xff)*(1.0/256.0); \
|
||||
SubFloat( zfrac, i ) = (zi & 0xff)*(1.0/256.0); \
|
||||
xi>>=8; \
|
||||
yi>>=8; \
|
||||
zi>>=8; \
|
||||
\
|
||||
SubFloat( lattice000, i ) = GetLatticePointValue( xi,yi,zi ); \
|
||||
SubFloat( lattice001, i ) = GetLatticePointValue( xi,yi,zi+1 ); \
|
||||
SubFloat( lattice010, i ) = GetLatticePointValue( xi,yi+1,zi ); \
|
||||
SubFloat( lattice011, i ) = GetLatticePointValue( xi,yi+1,zi+1 ); \
|
||||
SubFloat( lattice100, i ) = GetLatticePointValue( xi+1,yi,zi ); \
|
||||
SubFloat( lattice101, i ) = GetLatticePointValue( xi+1,yi,zi+1 ); \
|
||||
SubFloat( lattice110, i ) = GetLatticePointValue( xi+1,yi+1,zi ); \
|
||||
SubFloat( lattice111, i ) = GetLatticePointValue( xi+1,yi+1,zi+1 ); \
|
||||
}
|
||||
|
||||
DOPASS(0);
|
||||
DOPASS(1);
|
||||
DOPASS(2);
|
||||
DOPASS(3);
|
||||
|
||||
// now, we have 8 lattice values for each of four points as m128s, and interpolant values for
|
||||
// each axis in m128 form in [xyz]frac. Perfom the trilinear interpolation as SIMD ops
|
||||
|
||||
// first, do x interpolation
|
||||
fltx4 l2d00 = AddSIMD(lattice000, MulSIMD(xfrac, SubSIMD(lattice100, lattice000)));
|
||||
fltx4 l2d01 = AddSIMD(lattice001, MulSIMD(xfrac, SubSIMD(lattice101, lattice001)));
|
||||
fltx4 l2d10 = AddSIMD(lattice010, MulSIMD(xfrac, SubSIMD(lattice110, lattice010)));
|
||||
fltx4 l2d11 = AddSIMD(lattice011, MulSIMD(xfrac, SubSIMD(lattice111, lattice011)));
|
||||
|
||||
// now, do y interpolation
|
||||
fltx4 l1d0 = AddSIMD(l2d00, MulSIMD(yfrac, SubSIMD(l2d10, l2d00)));
|
||||
fltx4 l1d1 = AddSIMD(l2d01, MulSIMD(yfrac, SubSIMD(l2d11, l2d01)));
|
||||
|
||||
// final z interpolation
|
||||
fltx4 rslt = AddSIMD(l1d0, MulSIMD(zfrac, SubSIMD(l1d1, l1d0)));
|
||||
|
||||
// map to 0..1
|
||||
return MulSIMD(Four_Twos, SubSIMD(rslt, Four_PointFives));
|
||||
|
||||
|
||||
}
|
||||
|
||||
fltx4 NoiseSIMD(FourVectors const& pos)
|
||||
{
|
||||
return NoiseSIMD(pos.x, pos.y, pos.z);
|
||||
}
|
367
r5dev/mathlib/ssequaternion.h
Normal file
367
r5dev/mathlib/ssequaternion.h
Normal file
@ -0,0 +1,367 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: - defines SIMD "structure of arrays" classes and functions.
|
||||
//
|
||||
//===========================================================================//
|
||||
#ifndef SSEQUATMATH_H
|
||||
#define SSEQUATMATH_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "mathlib/ssemath.h"
|
||||
|
||||
// Use this #define to allow SSE versions of Quaternion math
|
||||
// to exist on PC.
|
||||
// On PC, certain horizontal vector operations are not supported.
|
||||
// This causes the SSE implementation of quaternion math to mix the
|
||||
// vector and scalar floating point units, which is extremely
|
||||
// performance negative if you don't compile to native SSE2 (which
|
||||
// we don't as of Sept 1, 2007). So, it's best not to allow these
|
||||
// functions to exist at all. It's not good enough to simply replace
|
||||
// the contents of the functions with scalar math, because each call
|
||||
// to LoadAligned and StoreAligned will result in an unnecssary copy
|
||||
// of the quaternion, and several moves to and from the XMM registers.
|
||||
//
|
||||
// Basically, the problem you run into is that for efficient SIMD code,
|
||||
// you need to load the quaternions and vectors into SIMD registers and
|
||||
// keep them there as long as possible while doing only SIMD math,
|
||||
// whereas for efficient scalar code, each time you copy onto or ever
|
||||
// use a fltx4, it hoses your pipeline. So the difference has to be
|
||||
// in the management of temporary variables in the calling function,
|
||||
// not inside the math functions.
|
||||
//
|
||||
// If you compile assuming the presence of SSE2, the MSVC will abandon
|
||||
// the traditional x87 FPU operations altogether and make everything use
|
||||
// the SSE2 registers, which lessens this problem a little.
|
||||
|
||||
// permitted only on 360, as we've done careful tuning on its Altivec math:
|
||||
#ifdef _X360
|
||||
#define ALLOW_SIMD_QUATERNION_MATH 1 // not on PC!
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Load/store quaternions
|
||||
//---------------------------------------------------------------------
|
||||
#ifndef _X360
|
||||
#if ALLOW_SIMD_QUATERNION_MATH
|
||||
// Using STDC or SSE
|
||||
FORCEINLINE fltx4 LoadAlignedSIMD(const QuaternionAligned& pSIMD)
|
||||
{
|
||||
fltx4 retval = LoadAlignedSIMD(pSIMD.Base());
|
||||
return retval;
|
||||
}
|
||||
|
||||
FORCEINLINE fltx4 LoadAlignedSIMD(const QuaternionAligned* RESTRICT pSIMD)
|
||||
{
|
||||
fltx4 retval = LoadAlignedSIMD(pSIMD);
|
||||
return retval;
|
||||
}
|
||||
|
||||
FORCEINLINE void StoreAlignedSIMD(QuaternionAligned* RESTRICT pSIMD, const fltx4& a)
|
||||
{
|
||||
StoreAlignedSIMD(pSIMD->Base(), a);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
|
||||
// for the transitional class -- load a QuaternionAligned
|
||||
FORCEINLINE fltx4 LoadAlignedSIMD(const QuaternionAligned& pSIMD)
|
||||
{
|
||||
fltx4 retval = XMLoadVector4A(pSIMD.Base());
|
||||
return retval;
|
||||
}
|
||||
|
||||
FORCEINLINE fltx4 LoadAlignedSIMD(const QuaternionAligned* RESTRICT pSIMD)
|
||||
{
|
||||
fltx4 retval = XMLoadVector4A(pSIMD);
|
||||
return retval;
|
||||
}
|
||||
|
||||
FORCEINLINE void StoreAlignedSIMD(QuaternionAligned* RESTRICT pSIMD, const fltx4& a)
|
||||
{
|
||||
XMStoreVector4A(pSIMD->Base(), a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if ALLOW_SIMD_QUATERNION_MATH
|
||||
//---------------------------------------------------------------------
|
||||
// Make sure quaternions are within 180 degrees of one another, if not, reverse q
|
||||
//---------------------------------------------------------------------
|
||||
FORCEINLINE fltx4 QuaternionAlignSIMD(const fltx4& p, const fltx4& q)
|
||||
{
|
||||
// decide if one of the quaternions is backwards
|
||||
fltx4 a = SubSIMD(p, q);
|
||||
fltx4 b = AddSIMD(p, q);
|
||||
a = Dot4SIMD(a, a);
|
||||
b = Dot4SIMD(b, b);
|
||||
fltx4 cmp = CmpGtSIMD(a, b);
|
||||
fltx4 result = MaskedAssign(cmp, NegSIMD(q), q);
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Normalize Quaternion
|
||||
//---------------------------------------------------------------------
|
||||
#if USE_STDC_FOR_SIMD
|
||||
|
||||
FORCEINLINE fltx4 QuaternionNormalizeSIMD(const fltx4& q)
|
||||
{
|
||||
fltx4 radius, result;
|
||||
radius = Dot4SIMD(q, q);
|
||||
|
||||
if (SubFloat(radius, 0)) // > FLT_EPSILON && ((radius < 1.0f - 4*FLT_EPSILON) || (radius > 1.0f + 4*FLT_EPSILON))
|
||||
{
|
||||
float iradius = 1.0f / sqrt(SubFloat(radius, 0));
|
||||
result = ReplicateX4(iradius);
|
||||
result = MulSIMD(result, q);
|
||||
return result;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// SSE + X360 implementation
|
||||
FORCEINLINE fltx4 QuaternionNormalizeSIMD(const fltx4& q)
|
||||
{
|
||||
fltx4 radius, result, mask;
|
||||
radius = Dot4SIMD(q, q);
|
||||
mask = CmpEqSIMD(radius, Four_Zeros); // all ones iff radius = 0
|
||||
result = ReciprocalSqrtSIMD(radius);
|
||||
result = MulSIMD(result, q);
|
||||
return MaskedAssign(mask, q, result); // if radius was 0, just return q
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// 0.0 returns p, 1.0 return q.
|
||||
//---------------------------------------------------------------------
|
||||
FORCEINLINE fltx4 QuaternionBlendNoAlignSIMD(const fltx4& p, const fltx4& q, float t)
|
||||
{
|
||||
fltx4 sclp, sclq, result;
|
||||
sclq = ReplicateX4(t);
|
||||
sclp = SubSIMD(Four_Ones, sclq);
|
||||
result = MulSIMD(sclp, p);
|
||||
result = MaddSIMD(sclq, q, result);
|
||||
return QuaternionNormalizeSIMD(result);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Blend Quaternions
|
||||
//---------------------------------------------------------------------
|
||||
FORCEINLINE fltx4 QuaternionBlendSIMD(const fltx4& p, const fltx4& q, float t)
|
||||
{
|
||||
// decide if one of the quaternions is backwards
|
||||
fltx4 q2, result;
|
||||
q2 = QuaternionAlignSIMD(p, q);
|
||||
result = QuaternionBlendNoAlignSIMD(p, q2, t);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Multiply Quaternions
|
||||
//---------------------------------------------------------------------
|
||||
#ifndef _X360
|
||||
|
||||
// SSE and STDC
|
||||
FORCEINLINE fltx4 QuaternionMultSIMD(const fltx4& p, const fltx4& q)
|
||||
{
|
||||
// decide if one of the quaternions is backwards
|
||||
fltx4 q2, result;
|
||||
q2 = QuaternionAlignSIMD(p, q);
|
||||
SubFloat(result, 0) = SubFloat(p, 0) * SubFloat(q2, 3) + SubFloat(p, 1) * SubFloat(q2, 2) - SubFloat(p, 2) * SubFloat(q2, 1) + SubFloat(p, 3) * SubFloat(q2, 0);
|
||||
SubFloat(result, 1) = -SubFloat(p, 0) * SubFloat(q2, 2) + SubFloat(p, 1) * SubFloat(q2, 3) + SubFloat(p, 2) * SubFloat(q2, 0) + SubFloat(p, 3) * SubFloat(q2, 1);
|
||||
SubFloat(result, 2) = SubFloat(p, 0) * SubFloat(q2, 1) - SubFloat(p, 1) * SubFloat(q2, 0) + SubFloat(p, 2) * SubFloat(q2, 3) + SubFloat(p, 3) * SubFloat(q2, 2);
|
||||
SubFloat(result, 3) = -SubFloat(p, 0) * SubFloat(q2, 0) - SubFloat(p, 1) * SubFloat(q2, 1) - SubFloat(p, 2) * SubFloat(q2, 2) + SubFloat(p, 3) * SubFloat(q2, 3);
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// X360
|
||||
extern const fltx4 g_QuatMultRowSign[4];
|
||||
FORCEINLINE fltx4 QuaternionMultSIMD(const fltx4& p, const fltx4& q)
|
||||
{
|
||||
fltx4 q2, row, result;
|
||||
q2 = QuaternionAlignSIMD(p, q);
|
||||
|
||||
row = XMVectorSwizzle(q2, 3, 2, 1, 0);
|
||||
row = MulSIMD(row, g_QuatMultRowSign[0]);
|
||||
result = Dot4SIMD(row, p);
|
||||
|
||||
row = XMVectorSwizzle(q2, 2, 3, 0, 1);
|
||||
row = MulSIMD(row, g_QuatMultRowSign[1]);
|
||||
row = Dot4SIMD(row, p);
|
||||
result = __vrlimi(result, row, 4, 0);
|
||||
|
||||
row = XMVectorSwizzle(q2, 1, 0, 3, 2);
|
||||
row = MulSIMD(row, g_QuatMultRowSign[2]);
|
||||
row = Dot4SIMD(row, p);
|
||||
result = __vrlimi(result, row, 2, 0);
|
||||
|
||||
row = MulSIMD(q2, g_QuatMultRowSign[3]);
|
||||
row = Dot4SIMD(row, p);
|
||||
result = __vrlimi(result, row, 1, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Quaternion scale
|
||||
//---------------------------------------------------------------------
|
||||
#ifndef _X360
|
||||
|
||||
// SSE and STDC
|
||||
FORCEINLINE fltx4 QuaternionScaleSIMD(const fltx4& p, float t)
|
||||
{
|
||||
float r;
|
||||
fltx4 q;
|
||||
|
||||
// FIXME: nick, this isn't overly sensitive to accuracy, and it may be faster to
|
||||
// use the cos part (w) of the quaternion (sin(omega)*N,cos(omega)) to figure the new scale.
|
||||
float sinom = sqrt(SubFloat(p, 0) * SubFloat(p, 0) + SubFloat(p, 1) * SubFloat(p, 1) + SubFloat(p, 2) * SubFloat(p, 2));
|
||||
sinom = min(sinom, 1.f);
|
||||
|
||||
float sinsom = sin(asin(sinom) * t);
|
||||
|
||||
t = sinsom / (sinom + FLT_EPSILON);
|
||||
SubFloat(q, 0) = t * SubFloat(p, 0);
|
||||
SubFloat(q, 1) = t * SubFloat(p, 1);
|
||||
SubFloat(q, 2) = t * SubFloat(p, 2);
|
||||
|
||||
// rescale rotation
|
||||
r = 1.0f - sinsom * sinsom;
|
||||
|
||||
// Assert( r >= 0 );
|
||||
if (r < 0.0f)
|
||||
r = 0.0f;
|
||||
r = sqrt(r);
|
||||
|
||||
// keep sign of rotation
|
||||
SubFloat(q, 3) = fsel(SubFloat(p, 3), r, -r);
|
||||
return q;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// X360
|
||||
FORCEINLINE fltx4 QuaternionScaleSIMD(const fltx4& p, float t)
|
||||
{
|
||||
fltx4 sinom = Dot3SIMD(p, p);
|
||||
sinom = SqrtSIMD(sinom);
|
||||
sinom = MinSIMD(sinom, Four_Ones);
|
||||
fltx4 sinsom = ArcSinSIMD(sinom);
|
||||
fltx4 t4 = ReplicateX4(t);
|
||||
sinsom = MulSIMD(sinsom, t4);
|
||||
sinsom = SinSIMD(sinsom);
|
||||
sinom = AddSIMD(sinom, Four_Epsilons);
|
||||
sinom = ReciprocalSIMD(sinom);
|
||||
t4 = MulSIMD(sinsom, sinom);
|
||||
fltx4 result = MulSIMD(p, t4);
|
||||
|
||||
// rescale rotation
|
||||
sinsom = MulSIMD(sinsom, sinsom);
|
||||
fltx4 r = SubSIMD(Four_Ones, sinsom);
|
||||
r = MaxSIMD(r, Four_Zeros);
|
||||
r = SqrtSIMD(r);
|
||||
|
||||
// keep sign of rotation
|
||||
fltx4 cmp = CmpGeSIMD(p, Four_Zeros);
|
||||
r = MaskedAssign(cmp, r, NegSIMD(r));
|
||||
|
||||
result = __vrlimi(result, r, 1, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Quaternion sphereical linear interpolation
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef _X360
|
||||
|
||||
// SSE and STDC
|
||||
FORCEINLINE fltx4 QuaternionSlerpNoAlignSIMD(const fltx4& p, const fltx4& q, float t)
|
||||
{
|
||||
float omega, cosom, sinom, sclp, sclq;
|
||||
|
||||
fltx4 result;
|
||||
|
||||
// 0.0 returns p, 1.0 return q.
|
||||
cosom = SubFloat(p, 0) * SubFloat(q, 0) + SubFloat(p, 1) * SubFloat(q, 1) +
|
||||
SubFloat(p, 2) * SubFloat(q, 2) + SubFloat(p, 3) * SubFloat(q, 3);
|
||||
|
||||
if ((1.0f + cosom) > 0.000001f)
|
||||
{
|
||||
if ((1.0f - cosom) > 0.000001f)
|
||||
{
|
||||
omega = acos(cosom);
|
||||
sinom = sin(omega);
|
||||
sclp = sin((1.0f - t) * omega) / sinom;
|
||||
sclq = sin(t * omega) / sinom;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: add short circuit for cosom == 1.0f?
|
||||
sclp = 1.0f - t;
|
||||
sclq = t;
|
||||
}
|
||||
SubFloat(result, 0) = sclp * SubFloat(p, 0) + sclq * SubFloat(q, 0);
|
||||
SubFloat(result, 1) = sclp * SubFloat(p, 1) + sclq * SubFloat(q, 1);
|
||||
SubFloat(result, 2) = sclp * SubFloat(p, 2) + sclq * SubFloat(q, 2);
|
||||
SubFloat(result, 3) = sclp * SubFloat(p, 3) + sclq * SubFloat(q, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
SubFloat(result, 0) = -SubFloat(q, 1);
|
||||
SubFloat(result, 1) = SubFloat(q, 0);
|
||||
SubFloat(result, 2) = -SubFloat(q, 3);
|
||||
SubFloat(result, 3) = SubFloat(q, 2);
|
||||
sclp = sin((1.0f - t) * (0.5f * M_PI));
|
||||
sclq = sin(t * (0.5f * M_PI));
|
||||
SubFloat(result, 0) = sclp * SubFloat(p, 0) + sclq * SubFloat(result, 0);
|
||||
SubFloat(result, 1) = sclp * SubFloat(p, 1) + sclq * SubFloat(result, 1);
|
||||
SubFloat(result, 2) = sclp * SubFloat(p, 2) + sclq * SubFloat(result, 2);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// X360
|
||||
FORCEINLINE fltx4 QuaternionSlerpNoAlignSIMD(const fltx4& p, const fltx4& q, float t)
|
||||
{
|
||||
return XMQuaternionSlerp(p, q, t);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
FORCEINLINE fltx4 QuaternionSlerpSIMD(const fltx4& p, const fltx4& q, float t)
|
||||
{
|
||||
fltx4 q2, result;
|
||||
q2 = QuaternionAlignSIMD(p, q);
|
||||
result = QuaternionSlerpNoAlignSIMD(p, q2, t);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endif // ALLOW_SIMD_QUATERNION_MATH
|
||||
|
||||
#endif // SSEQUATMATH_H
|
||||
|
File diff suppressed because it is too large
Load Diff
671
r5dev/mathlib/vector2d.h
Normal file
671
r5dev/mathlib/vector2d.h
Normal file
@ -0,0 +1,671 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef VECTOR2D_H
|
||||
#define VECTOR2D_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
// For vec_t, put this somewhere else?
|
||||
#include "tier0/basetypes.h"
|
||||
|
||||
// For rand(). We really need a library!
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/bits.h"
|
||||
#include "mathlib/math_pfns.h"
|
||||
|
||||
//=========================================================
|
||||
// 2D Vector2D
|
||||
//=========================================================
|
||||
|
||||
class Vector2D
|
||||
{
|
||||
public:
|
||||
// Members
|
||||
vec_t x, y;
|
||||
|
||||
// Construction/destruction
|
||||
Vector2D(void);
|
||||
Vector2D(vec_t X, vec_t Y);
|
||||
Vector2D(const float* pFloat);
|
||||
|
||||
// Initialization
|
||||
void Init(vec_t ix = 0.0f, vec_t iy = 0.0f);
|
||||
|
||||
// Got any nasty NAN's?
|
||||
bool IsValid() const;
|
||||
|
||||
// array access...
|
||||
vec_t operator[](int i) const;
|
||||
vec_t& operator[](int i);
|
||||
|
||||
// Base address...
|
||||
vec_t* Base();
|
||||
vec_t const* Base() const;
|
||||
|
||||
// Initialization methods
|
||||
void Random(float minVal, float maxVal);
|
||||
|
||||
// equality
|
||||
bool operator==(const Vector2D& v) const;
|
||||
bool operator!=(const Vector2D& v) const;
|
||||
|
||||
// arithmetic operations
|
||||
Vector2D& operator+=(const Vector2D& v);
|
||||
Vector2D& operator-=(const Vector2D& v);
|
||||
Vector2D& operator*=(const Vector2D& v);
|
||||
Vector2D& operator*=(float s);
|
||||
Vector2D& operator/=(const Vector2D& v);
|
||||
Vector2D& operator/=(float s);
|
||||
|
||||
// negate the Vector2D components
|
||||
void Negate();
|
||||
|
||||
// Get the Vector2D's magnitude.
|
||||
vec_t Length() const;
|
||||
|
||||
// Get the Vector2D's magnitude squared.
|
||||
vec_t LengthSqr(void) const;
|
||||
|
||||
// return true if this vector is (0,0) within tolerance
|
||||
bool IsZero(float tolerance = 0.01f) const
|
||||
{
|
||||
return (x > -tolerance && x < tolerance&&
|
||||
y > -tolerance && y < tolerance);
|
||||
}
|
||||
|
||||
// Normalize in place and return the old length.
|
||||
vec_t NormalizeInPlace();
|
||||
|
||||
// Compare length.
|
||||
bool IsLengthGreaterThan(float val) const;
|
||||
bool IsLengthLessThan(float val) const;
|
||||
|
||||
// Get the distance from this Vector2D to the other one.
|
||||
vec_t DistTo(const Vector2D& vOther) const;
|
||||
|
||||
// Get the distance from this Vector2D to the other one squared.
|
||||
vec_t DistToSqr(const Vector2D& vOther) const;
|
||||
|
||||
// Copy
|
||||
void CopyToArray(float* rgfl) const;
|
||||
|
||||
// Multiply, add, and assign to this (ie: *this = a + b * scalar). This
|
||||
// is about 12% faster than the actual Vector2D equation (because it's done per-component
|
||||
// rather than per-Vector2D).
|
||||
void MulAdd(const Vector2D& a, const Vector2D& b, float scalar);
|
||||
|
||||
// Dot product.
|
||||
vec_t Dot(const Vector2D& vOther) const;
|
||||
|
||||
// assignment
|
||||
Vector2D& operator=(const Vector2D& vOther);
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
// copy constructors
|
||||
Vector2D(const Vector2D& vOther);
|
||||
|
||||
// arithmetic operations
|
||||
Vector2D operator-(void) const;
|
||||
|
||||
Vector2D operator+(const Vector2D& v) const;
|
||||
Vector2D operator-(const Vector2D& v) const;
|
||||
Vector2D operator*(const Vector2D& v) const;
|
||||
Vector2D operator/(const Vector2D& v) const;
|
||||
Vector2D operator*(float fl) const;
|
||||
Vector2D operator/(float fl) const;
|
||||
|
||||
// Cross product between two vectors.
|
||||
Vector2D Cross(const Vector2D& vOther) const;
|
||||
|
||||
// Returns a Vector2D with the min or max in X, Y, and Z.
|
||||
Vector2D Min(const Vector2D& vOther) const;
|
||||
Vector2D Max(const Vector2D& vOther) const;
|
||||
|
||||
#else
|
||||
|
||||
private:
|
||||
// No copy constructors allowed if we're in optimal mode
|
||||
Vector2D(const Vector2D& vOther);
|
||||
#endif
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const Vector2D vec2_origin(0, 0);
|
||||
const Vector2D vec2_invalid(FLT_MAX, FLT_MAX);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Vector2D related operations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Vector2D clear
|
||||
void Vector2DClear(Vector2D& a);
|
||||
|
||||
// Copy
|
||||
void Vector2DCopy(const Vector2D& src, Vector2D& dst);
|
||||
|
||||
// Vector2D arithmetic
|
||||
void Vector2DAdd(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
||||
void Vector2DSubtract(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
||||
void Vector2DMultiply(const Vector2D& a, vec_t b, Vector2D& result);
|
||||
void Vector2DMultiply(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
||||
void Vector2DDivide(const Vector2D& a, vec_t b, Vector2D& result);
|
||||
void Vector2DDivide(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
||||
void Vector2DMA(const Vector2D& start, float s, const Vector2D& dir, Vector2D& result);
|
||||
|
||||
// Store the min or max of each of x, y, and z into the result.
|
||||
void Vector2DMin(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
||||
void Vector2DMax(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
||||
|
||||
#define Vector2DExpand( v ) (v).x, (v).y
|
||||
|
||||
// Normalization
|
||||
vec_t Vector2DNormalize(Vector2D& v);
|
||||
|
||||
// Length
|
||||
vec_t Vector2DLength(const Vector2D& v);
|
||||
|
||||
// Dot Product
|
||||
vec_t DotProduct2D(const Vector2D& a, const Vector2D& b);
|
||||
|
||||
// Linearly interpolate between two vectors
|
||||
void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, vec_t t, Vector2D& dest);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Inlined Vector2D methods
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector2D::Vector2D(void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
// Initialize to NAN to catch errors
|
||||
x = y = VEC_T_NAN;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline Vector2D::Vector2D(vec_t X, vec_t Y)
|
||||
{
|
||||
x = X; y = Y;
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
inline Vector2D::Vector2D(const float* pFloat)
|
||||
{
|
||||
Assert(pFloat);
|
||||
x = pFloat[0]; y = pFloat[1];
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// copy constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector2D::Vector2D(const Vector2D& vOther)
|
||||
{
|
||||
Assert(vOther.IsValid());
|
||||
x = vOther.x; y = vOther.y;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// initialization
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void Vector2D::Init(vec_t ix, vec_t iy)
|
||||
{
|
||||
x = ix; y = iy;
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
inline void Vector2D::Random(float minVal, float maxVal)
|
||||
{
|
||||
x = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
|
||||
y = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
|
||||
}
|
||||
|
||||
inline void Vector2DClear(Vector2D& a)
|
||||
{
|
||||
a.x = a.y = 0.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// assignment
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector2D& Vector2D::operator=(const Vector2D& vOther)
|
||||
{
|
||||
Assert(vOther.IsValid());
|
||||
x = vOther.x; y = vOther.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Array access
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline vec_t& Vector2D::operator[](int i)
|
||||
{
|
||||
Assert((i >= 0) && (i < 2));
|
||||
return ((vec_t*)this)[i];
|
||||
}
|
||||
|
||||
inline vec_t Vector2D::operator[](int i) const
|
||||
{
|
||||
Assert((i >= 0) && (i < 2));
|
||||
return ((vec_t*)this)[i];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Base address...
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline vec_t* Vector2D::Base()
|
||||
{
|
||||
return (vec_t*)this;
|
||||
}
|
||||
|
||||
inline vec_t const* Vector2D::Base() const
|
||||
{
|
||||
return (vec_t const*)this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// IsValid?
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector2D::IsValid() const
|
||||
{
|
||||
return IsFinite(x) && IsFinite(y);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// comparison
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector2D::operator==(const Vector2D& src) const
|
||||
{
|
||||
Assert(src.IsValid() && IsValid());
|
||||
return (src.x == x) && (src.y == y);
|
||||
}
|
||||
|
||||
inline bool Vector2D::operator!=(const Vector2D& src) const
|
||||
{
|
||||
Assert(src.IsValid() && IsValid());
|
||||
return (src.x != x) || (src.y != y);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copy
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void Vector2DCopy(const Vector2D& src, Vector2D& dst)
|
||||
{
|
||||
Assert(src.IsValid());
|
||||
dst.x = src.x;
|
||||
dst.y = src.y;
|
||||
}
|
||||
|
||||
inline void Vector2D::CopyToArray(float* rgfl) const
|
||||
{
|
||||
Assert(IsValid());
|
||||
Assert(rgfl);
|
||||
rgfl[0] = x; rgfl[1] = y;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// standard math operations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void Vector2D::Negate()
|
||||
{
|
||||
Assert(IsValid());
|
||||
x = -x; y = -y;
|
||||
}
|
||||
|
||||
inline Vector2D& Vector2D::operator+=(const Vector2D& v)
|
||||
{
|
||||
Assert(IsValid() && v.IsValid());
|
||||
x += v.x; y += v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2D& Vector2D::operator-=(const Vector2D& v)
|
||||
{
|
||||
Assert(IsValid() && v.IsValid());
|
||||
x -= v.x; y -= v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2D& Vector2D::operator*=(float fl)
|
||||
{
|
||||
x *= fl;
|
||||
y *= fl;
|
||||
Assert(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2D& Vector2D::operator*=(const Vector2D& v)
|
||||
{
|
||||
x *= v.x;
|
||||
y *= v.y;
|
||||
Assert(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2D& Vector2D::operator/=(float fl)
|
||||
{
|
||||
Assert(fl != 0.0f);
|
||||
float oofl = 1.0f / fl;
|
||||
x *= oofl;
|
||||
y *= oofl;
|
||||
Assert(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2D& Vector2D::operator/=(const Vector2D& v)
|
||||
{
|
||||
Assert(v.x != 0.0f && v.y != 0.0f);
|
||||
x /= v.x;
|
||||
y /= v.y;
|
||||
Assert(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void Vector2DAdd(const Vector2D& a, const Vector2D& b, Vector2D& c)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
c.x = a.x + b.x;
|
||||
c.y = a.y + b.y;
|
||||
}
|
||||
|
||||
inline void Vector2DSubtract(const Vector2D& a, const Vector2D& b, Vector2D& c)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
c.x = a.x - b.x;
|
||||
c.y = a.y - b.y;
|
||||
}
|
||||
|
||||
inline void Vector2DMultiply(const Vector2D& a, vec_t b, Vector2D& c)
|
||||
{
|
||||
Assert(a.IsValid() && IsFinite(b));
|
||||
c.x = a.x * b;
|
||||
c.y = a.y * b;
|
||||
}
|
||||
|
||||
inline void Vector2DMultiply(const Vector2D& a, const Vector2D& b, Vector2D& c)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
c.x = a.x * b.x;
|
||||
c.y = a.y * b.y;
|
||||
}
|
||||
|
||||
|
||||
inline void Vector2DDivide(const Vector2D& a, vec_t b, Vector2D& c)
|
||||
{
|
||||
Assert(a.IsValid());
|
||||
Assert(b != 0.0f);
|
||||
vec_t oob = 1.0f / b;
|
||||
c.x = a.x * oob;
|
||||
c.y = a.y * oob;
|
||||
}
|
||||
|
||||
inline void Vector2DDivide(const Vector2D& a, const Vector2D& b, Vector2D& c)
|
||||
{
|
||||
Assert(a.IsValid());
|
||||
Assert((b.x != 0.0f) && (b.y != 0.0f));
|
||||
c.x = a.x / b.x;
|
||||
c.y = a.y / b.y;
|
||||
}
|
||||
|
||||
inline void Vector2DMA(const Vector2D& start, float s, const Vector2D& dir, Vector2D& result)
|
||||
{
|
||||
Assert(start.IsValid() && IsFinite(s) && dir.IsValid());
|
||||
result.x = start.x + s * dir.x;
|
||||
result.y = start.y + s * dir.y;
|
||||
}
|
||||
|
||||
// FIXME: Remove
|
||||
// For backwards compatability
|
||||
inline void Vector2D::MulAdd(const Vector2D& a, const Vector2D& b, float scalar)
|
||||
{
|
||||
x = a.x + b.x * scalar;
|
||||
y = a.y + b.y * scalar;
|
||||
}
|
||||
|
||||
inline void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, vec_t t, Vector2D& dest)
|
||||
{
|
||||
dest[0] = src1[0] + (src2[0] - src1[0]) * t;
|
||||
dest[1] = src1[1] + (src2[1] - src1[1]) * t;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// dot, cross
|
||||
//-----------------------------------------------------------------------------
|
||||
inline vec_t DotProduct2D(const Vector2D& a, const Vector2D& b)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
return(a.x * b.x + a.y * b.y);
|
||||
}
|
||||
|
||||
// for backwards compatability
|
||||
inline vec_t Vector2D::Dot(const Vector2D& vOther) const
|
||||
{
|
||||
return DotProduct2D(*this, vOther);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// length
|
||||
//-----------------------------------------------------------------------------
|
||||
inline vec_t Vector2DLength(const Vector2D& v)
|
||||
{
|
||||
Assert(v.IsValid());
|
||||
return (vec_t)FastSqrt(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
inline vec_t Vector2D::LengthSqr(void) const
|
||||
{
|
||||
Assert(IsValid());
|
||||
return (x * x + y * y);
|
||||
}
|
||||
|
||||
inline vec_t Vector2D::NormalizeInPlace()
|
||||
{
|
||||
return Vector2DNormalize(*this);
|
||||
}
|
||||
|
||||
inline bool Vector2D::IsLengthGreaterThan(float val) const
|
||||
{
|
||||
return LengthSqr() > val * val;
|
||||
}
|
||||
|
||||
inline bool Vector2D::IsLengthLessThan(float val) const
|
||||
{
|
||||
return LengthSqr() < val * val;
|
||||
}
|
||||
|
||||
inline vec_t Vector2D::Length(void) const
|
||||
{
|
||||
return Vector2DLength(*this);
|
||||
}
|
||||
|
||||
|
||||
inline void Vector2DMin(const Vector2D& a, const Vector2D& b, Vector2D& result)
|
||||
{
|
||||
result.x = (a.x < b.x) ? a.x : b.x;
|
||||
result.y = (a.y < b.y) ? a.y : b.y;
|
||||
}
|
||||
|
||||
|
||||
inline void Vector2DMax(const Vector2D& a, const Vector2D& b, Vector2D& result)
|
||||
{
|
||||
result.x = (a.x > b.x) ? a.x : b.x;
|
||||
result.y = (a.y > b.y) ? a.y : b.y;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Normalization
|
||||
//-----------------------------------------------------------------------------
|
||||
inline vec_t Vector2DNormalize(Vector2D& v)
|
||||
{
|
||||
Assert(v.IsValid());
|
||||
vec_t l = v.Length();
|
||||
if (l != 0.0f)
|
||||
{
|
||||
v /= l;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.x = v.y = 0.0f;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get the distance from this Vector2D to the other one
|
||||
//-----------------------------------------------------------------------------
|
||||
inline vec_t Vector2D::DistTo(const Vector2D& vOther) const
|
||||
{
|
||||
Vector2D delta;
|
||||
Vector2DSubtract(*this, vOther, delta);
|
||||
return delta.Length();
|
||||
}
|
||||
|
||||
inline vec_t Vector2D::DistToSqr(const Vector2D& vOther) const
|
||||
{
|
||||
Vector2D delta;
|
||||
Vector2DSubtract(*this, vOther, delta);
|
||||
return delta.LengthSqr();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Computes the closest point to vecTarget no farther than flMaxDist from vecStart
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void ComputeClosestPoint2D(const Vector2D& vecStart, float flMaxDist, const Vector2D& vecTarget, Vector2D* pResult)
|
||||
{
|
||||
Vector2D vecDelta;
|
||||
Vector2DSubtract(vecTarget, vecStart, vecDelta);
|
||||
float flDistSqr = vecDelta.LengthSqr();
|
||||
if (flDistSqr <= flMaxDist * flMaxDist)
|
||||
{
|
||||
*pResult = vecTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
vecDelta /= FastSqrt(flDistSqr);
|
||||
Vector2DMA(vecStart, flMaxDist, vecDelta, *pResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Slow methods
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns a Vector2D with the min or max in X, Y, and Z.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector2D Vector2D::Min(const Vector2D& vOther) const
|
||||
{
|
||||
return Vector2D(x < vOther.x ? x : vOther.x,
|
||||
y < vOther.y ? y : vOther.y);
|
||||
}
|
||||
|
||||
inline Vector2D Vector2D::Max(const Vector2D& vOther) const
|
||||
{
|
||||
return Vector2D(x > vOther.x ? x : vOther.x,
|
||||
y > vOther.y ? y : vOther.y);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// arithmetic operations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector2D Vector2D::operator-(void) const
|
||||
{
|
||||
return Vector2D(-x, -y);
|
||||
}
|
||||
|
||||
inline Vector2D Vector2D::operator+(const Vector2D& v) const
|
||||
{
|
||||
Vector2D res;
|
||||
Vector2DAdd(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector2D Vector2D::operator-(const Vector2D& v) const
|
||||
{
|
||||
Vector2D res;
|
||||
Vector2DSubtract(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector2D Vector2D::operator*(float fl) const
|
||||
{
|
||||
Vector2D res;
|
||||
Vector2DMultiply(*this, fl, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector2D Vector2D::operator*(const Vector2D& v) const
|
||||
{
|
||||
Vector2D res;
|
||||
Vector2DMultiply(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector2D Vector2D::operator/(float fl) const
|
||||
{
|
||||
Vector2D res;
|
||||
Vector2DDivide(*this, fl, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector2D Vector2D::operator/(const Vector2D& v) const
|
||||
{
|
||||
Vector2D res;
|
||||
Vector2DDivide(*this, v, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Vector2D operator*(float fl, const Vector2D& v)
|
||||
{
|
||||
return v * fl;
|
||||
}
|
||||
|
||||
#endif //slow
|
||||
|
||||
#endif // VECTOR2D_H
|
||||
|
687
r5dev/mathlib/vector4d.h
Normal file
687
r5dev/mathlib/vector4d.h
Normal file
@ -0,0 +1,687 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef VECTOR4D_H
|
||||
#define VECTOR4D_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h> // For rand(). We really need a library!
|
||||
#include <float.h>
|
||||
#if !defined( _X360 )
|
||||
#include <xmmintrin.h> // For SSE
|
||||
#endif
|
||||
#include "tier0/basetypes.h" // For vec_t, put this somewhere else?
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/bits.h"
|
||||
#include "mathlib/math_pfns.h"
|
||||
|
||||
// forward declarations
|
||||
class Vector3D;
|
||||
class Vector2D;
|
||||
|
||||
//=========================================================
|
||||
// 4D Vector4D
|
||||
//=========================================================
|
||||
|
||||
class Vector4D
|
||||
{
|
||||
public:
|
||||
// Members
|
||||
vec_t x, y, z, w;
|
||||
|
||||
// Construction/destruction
|
||||
Vector4D(void);
|
||||
Vector4D(vec_t X, vec_t Y, vec_t Z, vec_t W);
|
||||
Vector4D(const float* pFloat);
|
||||
|
||||
// Initialization
|
||||
void Init(vec_t ix = 0.0f, vec_t iy = 0.0f, vec_t iz = 0.0f, vec_t iw = 0.0f);
|
||||
|
||||
// Got any nasty NAN's?
|
||||
bool IsValid() const;
|
||||
|
||||
// array access...
|
||||
vec_t operator[](int i) const;
|
||||
vec_t& operator[](int i);
|
||||
|
||||
// Base address...
|
||||
inline vec_t* Base();
|
||||
inline vec_t const* Base() const;
|
||||
|
||||
// Cast to Vector and Vector2D...
|
||||
Vector3D& AsVector3D();
|
||||
Vector3D const& AsVector3D() const;
|
||||
|
||||
Vector2D& AsVector2D();
|
||||
Vector2D const& AsVector2D() const;
|
||||
|
||||
// Initialization methods
|
||||
void Random(vec_t minVal, vec_t maxVal);
|
||||
|
||||
// equality
|
||||
bool operator==(const Vector4D& v) const;
|
||||
bool operator!=(const Vector4D& v) const;
|
||||
|
||||
// arithmetic operations
|
||||
Vector4D& operator+=(const Vector4D& v);
|
||||
Vector4D& operator-=(const Vector4D& v);
|
||||
Vector4D& operator*=(const Vector4D& v);
|
||||
Vector4D& operator*=(float s);
|
||||
Vector4D& operator/=(const Vector4D& v);
|
||||
Vector4D& operator/=(float s);
|
||||
|
||||
// negate the Vector4D components
|
||||
void Negate();
|
||||
|
||||
// Get the Vector4D's magnitude.
|
||||
vec_t Length() const;
|
||||
|
||||
// Get the Vector4D's magnitude squared.
|
||||
vec_t LengthSqr(void) const;
|
||||
|
||||
// return true if this vector is (0,0,0,0) within tolerance
|
||||
bool IsZero(float tolerance = 0.01f) const
|
||||
{
|
||||
return (x > -tolerance && x < tolerance&&
|
||||
y > -tolerance && y < tolerance&&
|
||||
z > -tolerance && z < tolerance&&
|
||||
w > -tolerance && w < tolerance);
|
||||
}
|
||||
|
||||
// Get the distance from this Vector4D to the other one.
|
||||
vec_t DistTo(const Vector4D& vOther) const;
|
||||
|
||||
// Get the distance from this Vector4D to the other one squared.
|
||||
vec_t DistToSqr(const Vector4D& vOther) const;
|
||||
|
||||
// Copy
|
||||
void CopyToArray(float* rgfl) const;
|
||||
|
||||
// Multiply, add, and assign to this (ie: *this = a + b * scalar). This
|
||||
// is about 12% faster than the actual Vector4D equation (because it's done per-component
|
||||
// rather than per-Vector4D).
|
||||
void MulAdd(Vector4D const& a, Vector4D const& b, float scalar);
|
||||
|
||||
// Dot product.
|
||||
vec_t Dot(Vector4D const& vOther) const;
|
||||
|
||||
// No copy constructors allowed if we're in optimal mode
|
||||
#ifdef VECTOR_NO_SLOW_OPERATIONS
|
||||
private:
|
||||
#else
|
||||
public:
|
||||
#endif
|
||||
Vector4D(Vector4D const& vOther);
|
||||
|
||||
// No assignment operators either...
|
||||
Vector4D& operator=(Vector4D const& src);
|
||||
};
|
||||
|
||||
const Vector4D vec4_origin(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
const Vector4D vec4_invalid(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SSE optimized routines
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class ALIGN16 Vector4DAligned : public Vector4D
|
||||
{
|
||||
public:
|
||||
Vector4DAligned(void) {}
|
||||
Vector4DAligned(vec_t X, vec_t Y, vec_t Z, vec_t W);
|
||||
|
||||
inline void Set(vec_t X, vec_t Y, vec_t Z, vec_t W);
|
||||
inline void InitZero(void);
|
||||
|
||||
inline __m128& AsM128() { return *(__m128*) & x; }
|
||||
inline const __m128& AsM128() const { return *(const __m128*) & x; }
|
||||
|
||||
private:
|
||||
// No copy constructors allowed if we're in optimal mode
|
||||
Vector4DAligned(Vector4DAligned const& vOther);
|
||||
|
||||
// No assignment operators either...
|
||||
Vector4DAligned& operator=(Vector4DAligned const& src);
|
||||
} ALIGN16_POST;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Vector4D related operations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Vector4D clear
|
||||
void Vector4DClear(Vector4D& a);
|
||||
|
||||
// Copy
|
||||
void Vector4DCopy(Vector4D const& src, Vector4D& dst);
|
||||
|
||||
// Vector4D arithmetic
|
||||
void Vector4DAdd(Vector4D const& a, Vector4D const& b, Vector4D& result);
|
||||
void Vector4DSubtract(Vector4D const& a, Vector4D const& b, Vector4D& result);
|
||||
void Vector4DMultiply(Vector4D const& a, vec_t b, Vector4D& result);
|
||||
void Vector4DMultiply(Vector4D const& a, Vector4D const& b, Vector4D& result);
|
||||
void Vector4DDivide(Vector4D const& a, vec_t b, Vector4D& result);
|
||||
void Vector4DDivide(Vector4D const& a, Vector4D const& b, Vector4D& result);
|
||||
void Vector4DMA(Vector4D const& start, float s, Vector4D const& dir, Vector4D& result);
|
||||
|
||||
// Vector4DAligned arithmetic
|
||||
void Vector4DMultiplyAligned(Vector4DAligned const& a, vec_t b, Vector4DAligned& result);
|
||||
|
||||
|
||||
#define Vector4DExpand( v ) (v).x, (v).y, (v).z, (v).w
|
||||
|
||||
// Normalization
|
||||
vec_t Vector4DNormalize(Vector4D& v);
|
||||
|
||||
// Length
|
||||
vec_t Vector4DLength(Vector4D const& v);
|
||||
|
||||
// Dot Product
|
||||
vec_t DotProduct4D(Vector4D const& a, Vector4D const& b);
|
||||
|
||||
// Linearly interpolate between two vectors
|
||||
void Vector4DLerp(Vector4D const& src1, Vector4D const& src2, vec_t t, Vector4D& dest);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Inlined Vector4D methods
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector4D::Vector4D(void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
// Initialize to NAN to catch errors
|
||||
x = y = z = w = VEC_T_NAN;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline Vector4D::Vector4D(vec_t X, vec_t Y, vec_t Z, vec_t W)
|
||||
{
|
||||
x = X; y = Y; z = Z; w = W;
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
inline Vector4D::Vector4D(const float* pFloat)
|
||||
{
|
||||
Assert(pFloat);
|
||||
x = pFloat[0]; y = pFloat[1]; z = pFloat[2]; w = pFloat[3];
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// copy constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector4D::Vector4D(const Vector4D& vOther)
|
||||
{
|
||||
Assert(vOther.IsValid());
|
||||
x = vOther.x; y = vOther.y; z = vOther.z; w = vOther.w;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// initialization
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void Vector4D::Init(vec_t ix, vec_t iy, vec_t iz, vec_t iw)
|
||||
{
|
||||
x = ix; y = iy; z = iz; w = iw;
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
inline void Vector4D::Random(vec_t minVal, vec_t maxVal)
|
||||
{
|
||||
x = minVal + ((vec_t)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
|
||||
y = minVal + ((vec_t)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
|
||||
z = minVal + ((vec_t)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
|
||||
w = minVal + ((vec_t)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
|
||||
}
|
||||
|
||||
inline void Vector4DClear(Vector4D& a)
|
||||
{
|
||||
a.x = a.y = a.z = a.w = 0.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// assignment
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector4D& Vector4D::operator=(const Vector4D& vOther)
|
||||
{
|
||||
Assert(vOther.IsValid());
|
||||
x = vOther.x; y = vOther.y; z = vOther.z; w = vOther.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Array access
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline vec_t& Vector4D::operator[](int i)
|
||||
{
|
||||
Assert((i >= 0) && (i < 4));
|
||||
return ((vec_t*)this)[i];
|
||||
}
|
||||
|
||||
inline vec_t Vector4D::operator[](int i) const
|
||||
{
|
||||
Assert((i >= 0) && (i < 4));
|
||||
return ((vec_t*)this)[i];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Cast to Vector and Vector2D...
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector3D& Vector4D::AsVector3D()
|
||||
{
|
||||
return *(Vector3D*)this;
|
||||
}
|
||||
|
||||
inline Vector3D const& Vector4D::AsVector3D() const
|
||||
{
|
||||
return *(Vector3D const*)this;
|
||||
}
|
||||
|
||||
inline Vector2D& Vector4D::AsVector2D()
|
||||
{
|
||||
return *(Vector2D*)this;
|
||||
}
|
||||
|
||||
inline Vector2D const& Vector4D::AsVector2D() const
|
||||
{
|
||||
return *(Vector2D const*)this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Base address...
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline vec_t* Vector4D::Base()
|
||||
{
|
||||
return (vec_t*)this;
|
||||
}
|
||||
|
||||
inline vec_t const* Vector4D::Base() const
|
||||
{
|
||||
return (vec_t const*)this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// IsValid?
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector4D::IsValid() const
|
||||
{
|
||||
return IsFinite(x) && IsFinite(y) && IsFinite(z) && IsFinite(w);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// comparison
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector4D::operator==(Vector4D const& src) const
|
||||
{
|
||||
Assert(src.IsValid() && IsValid());
|
||||
return (src.x == x) && (src.y == y) && (src.z == z) && (src.w == w);
|
||||
}
|
||||
|
||||
inline bool Vector4D::operator!=(Vector4D const& src) const
|
||||
{
|
||||
Assert(src.IsValid() && IsValid());
|
||||
return (src.x != x) || (src.y != y) || (src.z != z) || (src.w != w);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copy
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void Vector4DCopy(Vector4D const& src, Vector4D& dst)
|
||||
{
|
||||
Assert(src.IsValid());
|
||||
dst.x = src.x;
|
||||
dst.y = src.y;
|
||||
dst.z = src.z;
|
||||
dst.w = src.w;
|
||||
}
|
||||
|
||||
inline void Vector4D::CopyToArray(float* rgfl) const
|
||||
{
|
||||
Assert(IsValid());
|
||||
Assert(rgfl);
|
||||
rgfl[0] = x; rgfl[1] = y; rgfl[2] = z; rgfl[3] = w;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// standard math operations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void Vector4D::Negate()
|
||||
{
|
||||
Assert(IsValid());
|
||||
x = -x; y = -y; z = -z; w = -w;
|
||||
}
|
||||
|
||||
inline Vector4D& Vector4D::operator+=(const Vector4D& v)
|
||||
{
|
||||
Assert(IsValid() && v.IsValid());
|
||||
x += v.x; y += v.y; z += v.z; w += v.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector4D& Vector4D::operator-=(const Vector4D& v)
|
||||
{
|
||||
Assert(IsValid() && v.IsValid());
|
||||
x -= v.x; y -= v.y; z -= v.z; w -= v.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector4D& Vector4D::operator*=(float fl)
|
||||
{
|
||||
x *= fl;
|
||||
y *= fl;
|
||||
z *= fl;
|
||||
w *= fl;
|
||||
Assert(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector4D& Vector4D::operator*=(Vector4D const& v)
|
||||
{
|
||||
x *= v.x;
|
||||
y *= v.y;
|
||||
z *= v.z;
|
||||
w *= v.w;
|
||||
Assert(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector4D& Vector4D::operator/=(float fl)
|
||||
{
|
||||
Assert(fl != 0.0f);
|
||||
float oofl = 1.0f / fl;
|
||||
x *= oofl;
|
||||
y *= oofl;
|
||||
z *= oofl;
|
||||
w *= oofl;
|
||||
Assert(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector4D& Vector4D::operator/=(Vector4D const& v)
|
||||
{
|
||||
Assert(v.x != 0.0f && v.y != 0.0f && v.z != 0.0f && v.w != 0.0f);
|
||||
x /= v.x;
|
||||
y /= v.y;
|
||||
z /= v.z;
|
||||
w /= v.w;
|
||||
Assert(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void Vector4DAdd(Vector4D const& a, Vector4D const& b, Vector4D& c)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
c.x = a.x + b.x;
|
||||
c.y = a.y + b.y;
|
||||
c.z = a.z + b.z;
|
||||
c.w = a.w + b.w;
|
||||
}
|
||||
|
||||
inline void Vector4DSubtract(Vector4D const& a, Vector4D const& b, Vector4D& c)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
c.x = a.x - b.x;
|
||||
c.y = a.y - b.y;
|
||||
c.z = a.z - b.z;
|
||||
c.w = a.w - b.w;
|
||||
}
|
||||
|
||||
inline void Vector4DMultiply(Vector4D const& a, vec_t b, Vector4D& c)
|
||||
{
|
||||
Assert(a.IsValid() && IsFinite(b));
|
||||
c.x = a.x * b;
|
||||
c.y = a.y * b;
|
||||
c.z = a.z * b;
|
||||
c.w = a.w * b;
|
||||
}
|
||||
|
||||
inline void Vector4DMultiply(Vector4D const& a, Vector4D const& b, Vector4D& c)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
c.x = a.x * b.x;
|
||||
c.y = a.y * b.y;
|
||||
c.z = a.z * b.z;
|
||||
c.w = a.w * b.w;
|
||||
}
|
||||
|
||||
inline void Vector4DDivide(Vector4D const& a, vec_t b, Vector4D& c)
|
||||
{
|
||||
Assert(a.IsValid());
|
||||
Assert(b != 0.0f);
|
||||
vec_t oob = 1.0f / b;
|
||||
c.x = a.x * oob;
|
||||
c.y = a.y * oob;
|
||||
c.z = a.z * oob;
|
||||
c.w = a.w * oob;
|
||||
}
|
||||
|
||||
inline void Vector4DDivide(Vector4D const& a, Vector4D const& b, Vector4D& c)
|
||||
{
|
||||
Assert(a.IsValid());
|
||||
Assert((b.x != 0.0f) && (b.y != 0.0f) && (b.z != 0.0f) && (b.w != 0.0f));
|
||||
c.x = a.x / b.x;
|
||||
c.y = a.y / b.y;
|
||||
c.z = a.z / b.z;
|
||||
c.w = a.w / b.w;
|
||||
}
|
||||
|
||||
inline void Vector4DMA(Vector4D const& start, float s, Vector4D const& dir, Vector4D& result)
|
||||
{
|
||||
Assert(start.IsValid() && IsFinite(s) && dir.IsValid());
|
||||
result.x = start.x + s * dir.x;
|
||||
result.y = start.y + s * dir.y;
|
||||
result.z = start.z + s * dir.z;
|
||||
result.w = start.w + s * dir.w;
|
||||
}
|
||||
|
||||
// FIXME: Remove
|
||||
// For backwards compatability
|
||||
inline void Vector4D::MulAdd(Vector4D const& a, Vector4D const& b, float scalar)
|
||||
{
|
||||
x = a.x + b.x * scalar;
|
||||
y = a.y + b.y * scalar;
|
||||
z = a.z + b.z * scalar;
|
||||
w = a.w + b.w * scalar;
|
||||
}
|
||||
|
||||
inline void Vector4DLerp(const Vector4D& src1, const Vector4D& src2, vec_t t, Vector4D& dest)
|
||||
{
|
||||
dest[0] = src1[0] + (src2[0] - src1[0]) * t;
|
||||
dest[1] = src1[1] + (src2[1] - src1[1]) * t;
|
||||
dest[2] = src1[2] + (src2[2] - src1[2]) * t;
|
||||
dest[3] = src1[3] + (src2[3] - src1[3]) * t;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// dot, cross
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline vec_t DotProduct4D(const Vector4D& a, const Vector4D& b)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
return(a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w);
|
||||
}
|
||||
|
||||
// for backwards compatability
|
||||
inline vec_t Vector4D::Dot(Vector4D const& vOther) const
|
||||
{
|
||||
return DotProduct4D(*this, vOther);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// length
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline vec_t Vector4DLength(Vector4D const& v)
|
||||
{
|
||||
Assert(v.IsValid());
|
||||
return (vec_t)FastSqrt(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
|
||||
}
|
||||
|
||||
inline vec_t Vector4D::LengthSqr(void) const
|
||||
{
|
||||
Assert(IsValid());
|
||||
return (x * x + y * y + z * z + w * w);
|
||||
}
|
||||
|
||||
inline vec_t Vector4D::Length(void) const
|
||||
{
|
||||
return Vector4DLength(*this);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Normalization
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// FIXME: Can't use until we're un-macroed in mathlib.h
|
||||
inline vec_t Vector4DNormalize(Vector4D& v)
|
||||
{
|
||||
Assert(v.IsValid());
|
||||
vec_t l = v.Length();
|
||||
if (l != 0.0f)
|
||||
{
|
||||
v /= l;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.x = v.y = v.z = v.w = 0.0f;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get the distance from this Vector4D to the other one
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline vec_t Vector4D::DistTo(const Vector4D& vOther) const
|
||||
{
|
||||
Vector4D delta;
|
||||
Vector4DSubtract(*this, vOther, delta);
|
||||
return delta.Length();
|
||||
}
|
||||
|
||||
inline vec_t Vector4D::DistToSqr(const Vector4D& vOther) const
|
||||
{
|
||||
Vector4D delta;
|
||||
Vector4DSubtract(*this, vOther, delta);
|
||||
return delta.LengthSqr();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Vector4DAligned routines
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline Vector4DAligned::Vector4DAligned(vec_t X, vec_t Y, vec_t Z, vec_t W)
|
||||
{
|
||||
x = X; y = Y; z = Z; w = W;
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
inline void Vector4DAligned::Set(vec_t X, vec_t Y, vec_t Z, vec_t W)
|
||||
{
|
||||
x = X; y = Y; z = Z; w = W;
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
inline void Vector4DAligned::InitZero(void)
|
||||
{
|
||||
#if !defined( _X360 )
|
||||
this->AsM128() = _mm_set1_ps(0.0f);
|
||||
#else
|
||||
this->AsM128() = __vspltisw(0);
|
||||
#endif
|
||||
Assert(IsValid());
|
||||
}
|
||||
|
||||
inline void Vector4DMultiplyAligned(Vector4DAligned const& a, Vector4DAligned const& b, Vector4DAligned& c)
|
||||
{
|
||||
Assert(a.IsValid() && b.IsValid());
|
||||
#if !defined( _X360 )
|
||||
c.x = a.x * b.x;
|
||||
c.y = a.y * b.y;
|
||||
c.z = a.z * b.z;
|
||||
c.w = a.w * b.w;
|
||||
#else
|
||||
c.AsM128() = __vmulfp(a.AsM128(), b.AsM128());
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void Vector4DWeightMAD(vec_t w, Vector4DAligned const& vInA, Vector4DAligned& vOutA, Vector4DAligned const& vInB, Vector4DAligned& vOutB)
|
||||
{
|
||||
Assert(vInA.IsValid() && vInB.IsValid() && IsFinite(w));
|
||||
|
||||
#if !defined( _X360 )
|
||||
vOutA.x += vInA.x * w;
|
||||
vOutA.y += vInA.y * w;
|
||||
vOutA.z += vInA.z * w;
|
||||
vOutA.w += vInA.w * w;
|
||||
|
||||
vOutB.x += vInB.x * w;
|
||||
vOutB.y += vInB.y * w;
|
||||
vOutB.z += vInB.z * w;
|
||||
vOutB.w += vInB.w * w;
|
||||
#else
|
||||
__vector4 temp;
|
||||
|
||||
temp = __lvlx(&w, 0);
|
||||
temp = __vspltw(temp, 0);
|
||||
|
||||
vOutA.AsM128() = __vmaddfp(vInA.AsM128(), temp, vOutA.AsM128());
|
||||
vOutB.AsM128() = __vmaddfp(vInB.AsM128(), temp, vOutB.AsM128());
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void Vector4DWeightMADSSE(vec_t w, Vector4DAligned const& vInA, Vector4DAligned& vOutA, Vector4DAligned const& vInB, Vector4DAligned& vOutB)
|
||||
{
|
||||
Assert(vInA.IsValid() && vInB.IsValid() && IsFinite(w));
|
||||
|
||||
#if !defined( _X360 )
|
||||
// Replicate scalar float out to 4 components
|
||||
__m128 packed = _mm_set1_ps(w);
|
||||
|
||||
// 4D SSE Vector MAD
|
||||
vOutA.AsM128() = _mm_add_ps(vOutA.AsM128(), _mm_mul_ps(vInA.AsM128(), packed));
|
||||
vOutB.AsM128() = _mm_add_ps(vOutB.AsM128(), _mm_mul_ps(vInB.AsM128(), packed));
|
||||
#else
|
||||
__vector4 temp;
|
||||
|
||||
temp = __lvlx(&w, 0);
|
||||
temp = __vspltw(temp, 0);
|
||||
|
||||
vOutA.AsM128() = __vmaddfp(vInA.AsM128(), temp, vOutA.AsM128());
|
||||
vOutB.AsM128() = __vmaddfp(vInB.AsM128(), temp, vOutB.AsM128());
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // VECTOR4D_H
|
||||
|
1292
r5dev/mathlib/vmatrix.cpp
Normal file
1292
r5dev/mathlib/vmatrix.cpp
Normal file
File diff suppressed because it is too large
Load Diff
947
r5dev/mathlib/vmatrix.h
Normal file
947
r5dev/mathlib/vmatrix.h
Normal file
@ -0,0 +1,947 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
//
|
||||
// VMatrix always postmultiply vectors as in Ax = b.
|
||||
// Given a set of basis vectors ((F)orward, (L)eft, (U)p), and a (T)ranslation,
|
||||
// a matrix to transform a vector into that space looks like this:
|
||||
// Fx Lx Ux Tx
|
||||
// Fy Ly Uy Ty
|
||||
// Fz Lz Uz Tz
|
||||
// 0 0 0 1
|
||||
|
||||
// Note that concatenating matrices needs to multiply them in reverse order.
|
||||
// ie: if I want to apply matrix A, B, then C, the equation needs to look like this:
|
||||
// C * B * A * v
|
||||
// ie:
|
||||
// v = A * v;
|
||||
// v = B * v;
|
||||
// v = C * v;
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VMATRIX_H
|
||||
#define VMATRIX_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/vplane.h"
|
||||
#include "mathlib/vector4d.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
struct cplane_t;
|
||||
|
||||
|
||||
class VMatrix
|
||||
{
|
||||
public:
|
||||
|
||||
VMatrix();
|
||||
VMatrix(
|
||||
vec_t m00, vec_t m01, vec_t m02, vec_t m03,
|
||||
vec_t m10, vec_t m11, vec_t m12, vec_t m13,
|
||||
vec_t m20, vec_t m21, vec_t m22, vec_t m23,
|
||||
vec_t m30, vec_t m31, vec_t m32, vec_t m33
|
||||
);
|
||||
|
||||
// Creates a matrix where the X axis = forward
|
||||
// the Y axis = left, and the Z axis = up
|
||||
VMatrix(const Vector3D& forward, const Vector3D& left, const Vector3D& up);
|
||||
VMatrix(const Vector3D& forward, const Vector3D& left, const Vector3D& up, const Vector3D& translation);
|
||||
|
||||
// Construct from a 3x4 matrix
|
||||
VMatrix(const matrix3x4_t& matrix3x4);
|
||||
|
||||
// Set the values in the matrix.
|
||||
void Init(
|
||||
vec_t m00, vec_t m01, vec_t m02, vec_t m03,
|
||||
vec_t m10, vec_t m11, vec_t m12, vec_t m13,
|
||||
vec_t m20, vec_t m21, vec_t m22, vec_t m23,
|
||||
vec_t m30, vec_t m31, vec_t m32, vec_t m33
|
||||
);
|
||||
|
||||
|
||||
// Initialize from a 3x4
|
||||
void Init(const matrix3x4_t& matrix3x4);
|
||||
|
||||
// array access
|
||||
inline float* operator[](int i)
|
||||
{
|
||||
return m[i];
|
||||
}
|
||||
|
||||
inline const float* operator[](int i) const
|
||||
{
|
||||
return m[i];
|
||||
}
|
||||
|
||||
// Get a pointer to m[0][0]
|
||||
inline float* Base()
|
||||
{
|
||||
return &m[0][0];
|
||||
}
|
||||
|
||||
inline const float* Base() const
|
||||
{
|
||||
return &m[0][0];
|
||||
}
|
||||
|
||||
void SetLeft(const Vector3D& vLeft);
|
||||
void SetUp(const Vector3D& vUp);
|
||||
void SetForward(const Vector3D& vForward);
|
||||
|
||||
void GetBasisVectors(Vector3D& vForward, Vector3D& vLeft, Vector3D& vUp) const;
|
||||
void SetBasisVectors(const Vector3D& vForward, const Vector3D& vLeft, const Vector3D& vUp);
|
||||
|
||||
// Get/set the translation.
|
||||
Vector3D& GetTranslation(Vector3D& vTrans) const;
|
||||
void SetTranslation(const Vector3D& vTrans);
|
||||
|
||||
void PreTranslate(const Vector3D& vTrans);
|
||||
void PostTranslate(const Vector3D& vTrans);
|
||||
|
||||
const matrix3x4_t& As3x4() const;
|
||||
void CopyFrom3x4(const matrix3x4_t& m3x4);
|
||||
void Set3x4(matrix3x4_t& matrix3x4) const;
|
||||
|
||||
bool operator==(const VMatrix& src) const;
|
||||
bool operator!=(const VMatrix& src) const { return !(*this == src); }
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
// Access the basis vectors.
|
||||
Vector3D GetLeft() const;
|
||||
Vector3D GetUp() const;
|
||||
Vector3D GetForward() const;
|
||||
Vector3D GetTranslation() const;
|
||||
#endif
|
||||
|
||||
|
||||
// Matrix->vector operations.
|
||||
public:
|
||||
// Multiply by a 3D vector (same as operator*).
|
||||
void V3Mul(const Vector3D& vIn, Vector3D& vOut) const;
|
||||
|
||||
// Multiply by a 4D vector.
|
||||
void V4Mul(const Vector4D& vIn, Vector4D& vOut) const;
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
// Applies the rotation (ignores translation in the matrix). (This just calls VMul3x3).
|
||||
Vector3D ApplyRotation(const Vector3D& vVec) const;
|
||||
|
||||
// Multiply by a vector (divides by w, assumes input w is 1).
|
||||
Vector3D operator*(const Vector3D& vVec) const;
|
||||
|
||||
// Multiply by the upper 3x3 part of the matrix (ie: only apply rotation).
|
||||
Vector3D VMul3x3(const Vector3D& vVec) const;
|
||||
|
||||
// Apply the inverse (transposed) rotation (only works on pure rotation matrix)
|
||||
Vector3D VMul3x3Transpose(const Vector3D& vVec) const;
|
||||
|
||||
// Multiply by the upper 3 rows.
|
||||
Vector3D VMul4x3(const Vector3D& vVec) const;
|
||||
|
||||
// Apply the inverse (transposed) transformation (only works on pure rotation/translation)
|
||||
Vector3D VMul4x3Transpose(const Vector3D& vVec) const;
|
||||
#endif
|
||||
|
||||
|
||||
// Matrix->plane operations.
|
||||
public:
|
||||
// Transform the plane. The matrix can only contain translation and rotation.
|
||||
void TransformPlane(const VPlane& inPlane, VPlane& outPlane) const;
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
// Just calls TransformPlane and returns the result.
|
||||
VPlane operator*(const VPlane& thePlane) const;
|
||||
#endif
|
||||
|
||||
// Matrix->matrix operations.
|
||||
public:
|
||||
|
||||
VMatrix& operator=(const VMatrix& mOther);
|
||||
|
||||
// Multiply two matrices (out = this * vm).
|
||||
void MatrixMul(const VMatrix& vm, VMatrix& out) const;
|
||||
|
||||
// Add two matrices.
|
||||
const VMatrix& operator+=(const VMatrix& other);
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
// Just calls MatrixMul and returns the result.
|
||||
VMatrix operator*(const VMatrix& mOther) const;
|
||||
|
||||
// Add/Subtract two matrices.
|
||||
VMatrix operator+(const VMatrix& other) const;
|
||||
VMatrix operator-(const VMatrix& other) const;
|
||||
|
||||
// Negation.
|
||||
VMatrix operator-() const;
|
||||
|
||||
// Return inverse matrix. Be careful because the results are undefined
|
||||
// if the matrix doesn't have an inverse (ie: InverseGeneral returns false).
|
||||
VMatrix operator~() const;
|
||||
#endif
|
||||
|
||||
// Matrix operations.
|
||||
public:
|
||||
// Set to identity.
|
||||
void Identity();
|
||||
|
||||
bool IsIdentity() const;
|
||||
|
||||
// Setup a matrix for origin and angles.
|
||||
void SetupMatrixOrgAngles(const Vector3D& origin, const QAngle& vAngles);
|
||||
|
||||
// Setup a matrix for angles and no translation.
|
||||
void SetupMatrixAngles(const QAngle& vAngles);
|
||||
|
||||
// General inverse. This may fail so check the return!
|
||||
bool InverseGeneral(VMatrix& vInverse) const;
|
||||
|
||||
// Does a fast inverse, assuming the matrix only contains translation and rotation.
|
||||
void InverseTR(VMatrix& mRet) const;
|
||||
|
||||
// Usually used for debug checks. Returns true if the upper 3x3 contains
|
||||
// unit vectors and they are all orthogonal.
|
||||
bool IsRotationMatrix() const;
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
// This calls the other InverseTR and returns the result.
|
||||
VMatrix InverseTR() const;
|
||||
|
||||
// Get the scale of the matrix's basis vectors.
|
||||
Vector3D GetScale() const;
|
||||
|
||||
// (Fast) multiply by a scaling matrix setup from vScale.
|
||||
VMatrix Scale(const Vector3D& vScale);
|
||||
|
||||
// Normalize the basis vectors.
|
||||
VMatrix NormalizeBasisVectors() const;
|
||||
|
||||
// Transpose.
|
||||
VMatrix Transpose() const;
|
||||
|
||||
// Transpose upper-left 3x3.
|
||||
VMatrix Transpose3x3() const;
|
||||
#endif
|
||||
|
||||
public:
|
||||
// The matrix.
|
||||
vec_t m[4][4];
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helper functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
// Setup an identity matrix.
|
||||
VMatrix SetupMatrixIdentity();
|
||||
|
||||
// Setup as a scaling matrix.
|
||||
VMatrix SetupMatrixScale(const Vector3D& vScale);
|
||||
|
||||
// Setup a translation matrix.
|
||||
VMatrix SetupMatrixTranslation(const Vector3D& vTranslation);
|
||||
|
||||
// Setup a matrix to reflect around the plane.
|
||||
VMatrix SetupMatrixReflection(const VPlane& thePlane);
|
||||
|
||||
// Setup a matrix to project from vOrigin onto thePlane.
|
||||
VMatrix SetupMatrixProjection(const Vector3D& vOrigin, const VPlane& thePlane);
|
||||
|
||||
// Setup a matrix to rotate the specified amount around the specified axis.
|
||||
VMatrix SetupMatrixAxisRot(const Vector3D& vAxis, vec_t fDegrees);
|
||||
|
||||
// Setup a matrix from euler angles. Just sets identity and calls MatrixAngles.
|
||||
VMatrix SetupMatrixAngles(const QAngle& vAngles);
|
||||
|
||||
// Setup a matrix for origin and angles.
|
||||
VMatrix SetupMatrixOrgAngles(const Vector3D& origin, const QAngle& vAngles);
|
||||
|
||||
#endif
|
||||
|
||||
#define VMatToString(mat) (static_cast<const char *>(CFmtStr("[ (%f, %f, %f), (%f, %f, %f), (%f, %f, %f), (%f, %f, %f) ]", mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3], mat.m[1][0], mat.m[1][1], mat.m[1][2], mat.m[1][3], mat.m[2][0], mat.m[2][1], mat.m[2][2], mat.m[2][3], mat.m[3][0], mat.m[3][1], mat.m[3][2], mat.m[3][3] ))) // ** Note: this generates a temporary, don't hold reference!
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the point at the intersection on the 3 planes.
|
||||
// Returns false if it can't be solved (2 or more planes are parallel).
|
||||
//-----------------------------------------------------------------------------
|
||||
bool PlaneIntersection(const VPlane& vp1, const VPlane& vp2, const VPlane& vp3, Vector3D& vOut);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// These methods are faster. Use them if you want faster code
|
||||
//-----------------------------------------------------------------------------
|
||||
void MatrixSetIdentity(VMatrix& dst);
|
||||
void MatrixTranspose(const VMatrix& src, VMatrix& dst);
|
||||
void MatrixCopy(const VMatrix& src, VMatrix& dst);
|
||||
void MatrixMultiply(const VMatrix& src1, const VMatrix& src2, VMatrix& dst);
|
||||
|
||||
// Accessors
|
||||
void MatrixGetColumn(const VMatrix& src, int nCol, Vector3D* pColumn);
|
||||
void MatrixSetColumn(VMatrix& src, int nCol, const Vector3D& column);
|
||||
void MatrixGetRow(const VMatrix& src, int nCol, Vector3D* pColumn);
|
||||
void MatrixSetRow(VMatrix& src, int nCol, const Vector3D& column);
|
||||
|
||||
// Vector3DMultiply treats src2 as if it's a direction vector
|
||||
void Vector3DMultiply(const VMatrix& src1, const Vector3D& src2, Vector3D& dst);
|
||||
|
||||
// Vector3DMultiplyPosition treats src2 as if it's a point (adds the translation)
|
||||
inline void Vector3DMultiplyPosition(const VMatrix& src1, const VectorByValue src2, Vector3D& dst);
|
||||
|
||||
// Vector3DMultiplyPositionProjective treats src2 as if it's a point
|
||||
// and does the perspective divide at the end
|
||||
void Vector3DMultiplyPositionProjective(const VMatrix& src1, const Vector3D& src2, Vector3D& dst);
|
||||
|
||||
// Vector3DMultiplyPosition treats src2 as if it's a direction
|
||||
// and does the perspective divide at the end
|
||||
// NOTE: src1 had better be an inverse transpose to use this correctly
|
||||
void Vector3DMultiplyProjective(const VMatrix& src1, const Vector3D& src2, Vector3D& dst);
|
||||
|
||||
void Vector4DMultiply(const VMatrix& src1, const Vector4D& src2, Vector4D& dst);
|
||||
|
||||
// Same as Vector4DMultiply except that src2 has an implicit W of 1
|
||||
void Vector4DMultiplyPosition(const VMatrix& src1, const Vector3D& src2, Vector4D& dst);
|
||||
|
||||
// Multiplies the vector by the transpose of the matrix
|
||||
void Vector3DMultiplyTranspose(const VMatrix& src1, const Vector3D& src2, Vector3D& dst);
|
||||
void Vector4DMultiplyTranspose(const VMatrix& src1, const Vector4D& src2, Vector4D& dst);
|
||||
|
||||
// Transform a plane
|
||||
void MatrixTransformPlane(const VMatrix& src, const cplane_t& inPlane, cplane_t& outPlane);
|
||||
|
||||
// Transform a plane that has an axis-aligned normal
|
||||
void MatrixTransformAxisAlignedPlane(const VMatrix& src, int nDim, float flSign, float flDist, cplane_t& outPlane);
|
||||
|
||||
void MatrixBuildTranslation(VMatrix& dst, float x, float y, float z);
|
||||
void MatrixBuildTranslation(VMatrix& dst, const Vector3D& translation);
|
||||
|
||||
inline void MatrixTranslate(VMatrix& dst, const Vector3D& translation)
|
||||
{
|
||||
VMatrix matTranslation, temp;
|
||||
MatrixBuildTranslation(matTranslation, translation);
|
||||
MatrixMultiply(dst, matTranslation, temp);
|
||||
dst = temp;
|
||||
}
|
||||
|
||||
|
||||
void MatrixBuildRotationAboutAxis(VMatrix& dst, const Vector3D& vAxisOfRot, float angleDegrees);
|
||||
void MatrixBuildRotateZ(VMatrix& dst, float angleDegrees);
|
||||
|
||||
inline void MatrixRotate(VMatrix& dst, const Vector3D& vAxisOfRot, float angleDegrees)
|
||||
{
|
||||
VMatrix rotation, temp;
|
||||
MatrixBuildRotationAboutAxis(rotation, vAxisOfRot, angleDegrees);
|
||||
MatrixMultiply(dst, rotation, temp);
|
||||
dst = temp;
|
||||
}
|
||||
|
||||
// Builds a rotation matrix that rotates one direction vector into another
|
||||
void MatrixBuildRotation(VMatrix& dst, const Vector3D& initialDirection, const Vector3D& finalDirection);
|
||||
|
||||
// Builds a scale matrix
|
||||
void MatrixBuildScale(VMatrix& dst, float x, float y, float z);
|
||||
void MatrixBuildScale(VMatrix& dst, const Vector3D& scale);
|
||||
|
||||
// Build a perspective matrix.
|
||||
// zNear and zFar are assumed to be positive.
|
||||
// You end up looking down positive Z, X is to the right, Y is up.
|
||||
// X range: [0..1]
|
||||
// Y range: [0..1]
|
||||
// Z range: [0..1]
|
||||
void MatrixBuildPerspective(VMatrix& dst, float fovX, float fovY, float zNear, float zFar);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Given a projection matrix, take the extremes of the space in transformed into world space and
|
||||
// get a bounding box.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CalculateAABBFromProjectionMatrix(const VMatrix& worldToVolume, Vector3D* pMins, Vector3D* pMaxs);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Given a projection matrix, take the extremes of the space in transformed into world space and
|
||||
// get a bounding sphere.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CalculateSphereFromProjectionMatrix(const VMatrix& worldToVolume, Vector3D* pCenter, float* pflRadius);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Given an inverse projection matrix, take the extremes of the space in transformed into world space and
|
||||
// get a bounding box.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CalculateAABBFromProjectionMatrixInverse(const VMatrix& volumeToWorld, Vector3D* pMins, Vector3D* pMaxs);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Given an inverse projection matrix, take the extremes of the space in transformed into world space and
|
||||
// get a bounding sphere.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CalculateSphereFromProjectionMatrixInverse(const VMatrix& volumeToWorld, Vector3D* pCenter, float* pflRadius);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Calculate frustum planes given a clip->world space transform.
|
||||
//-----------------------------------------------------------------------------
|
||||
void FrustumPlanesFromMatrix(const VMatrix& clipToWorld, Frustum_t& frustum);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Setup a matrix from euler angles.
|
||||
//-----------------------------------------------------------------------------
|
||||
void MatrixFromAngles(const QAngle& vAngles, VMatrix& dst);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates euler angles from a matrix
|
||||
//-----------------------------------------------------------------------------
|
||||
void MatrixToAngles(const VMatrix& src, QAngle& vAngles);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Does a fast inverse, assuming the matrix only contains translation and rotation.
|
||||
//-----------------------------------------------------------------------------
|
||||
void MatrixInverseTR(const VMatrix& src, VMatrix& dst);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inverts any matrix at all
|
||||
//-----------------------------------------------------------------------------
|
||||
bool MatrixInverseGeneral(const VMatrix& src, VMatrix& dst);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Computes the inverse transpose
|
||||
//-----------------------------------------------------------------------------
|
||||
void MatrixInverseTranspose(const VMatrix& src, VMatrix& dst);
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// VMatrix inlines.
|
||||
//-----------------------------------------------------------------------------
|
||||
inline VMatrix::VMatrix()
|
||||
{
|
||||
}
|
||||
|
||||
inline VMatrix::VMatrix(
|
||||
vec_t m00, vec_t m01, vec_t m02, vec_t m03,
|
||||
vec_t m10, vec_t m11, vec_t m12, vec_t m13,
|
||||
vec_t m20, vec_t m21, vec_t m22, vec_t m23,
|
||||
vec_t m30, vec_t m31, vec_t m32, vec_t m33)
|
||||
{
|
||||
Init(
|
||||
m00, m01, m02, m03,
|
||||
m10, m11, m12, m13,
|
||||
m20, m21, m22, m23,
|
||||
m30, m31, m32, m33
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline VMatrix::VMatrix(const matrix3x4_t& matrix3x4)
|
||||
{
|
||||
Init(matrix3x4);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates a matrix where the X axis = forward
|
||||
// the Y axis = left, and the Z axis = up
|
||||
//-----------------------------------------------------------------------------
|
||||
inline VMatrix::VMatrix(const Vector3D& xAxis, const Vector3D& yAxis, const Vector3D& zAxis)
|
||||
{
|
||||
Init(
|
||||
xAxis.x, yAxis.x, zAxis.x, 0.0f,
|
||||
xAxis.y, yAxis.y, zAxis.y, 0.0f,
|
||||
xAxis.z, yAxis.z, zAxis.z, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
);
|
||||
}
|
||||
|
||||
inline VMatrix::VMatrix(const Vector3D& xAxis, const Vector3D& yAxis, const Vector3D& zAxis, const Vector3D& translation)
|
||||
{
|
||||
Init(
|
||||
xAxis.x, yAxis.x, zAxis.x, translation.x,
|
||||
xAxis.y, yAxis.y, zAxis.y, translation.y,
|
||||
xAxis.z, yAxis.z, zAxis.z, translation.z,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline void VMatrix::Init(
|
||||
vec_t m00, vec_t m01, vec_t m02, vec_t m03,
|
||||
vec_t m10, vec_t m11, vec_t m12, vec_t m13,
|
||||
vec_t m20, vec_t m21, vec_t m22, vec_t m23,
|
||||
vec_t m30, vec_t m31, vec_t m32, vec_t m33
|
||||
)
|
||||
{
|
||||
m[0][0] = m00;
|
||||
m[0][1] = m01;
|
||||
m[0][2] = m02;
|
||||
m[0][3] = m03;
|
||||
|
||||
m[1][0] = m10;
|
||||
m[1][1] = m11;
|
||||
m[1][2] = m12;
|
||||
m[1][3] = m13;
|
||||
|
||||
m[2][0] = m20;
|
||||
m[2][1] = m21;
|
||||
m[2][2] = m22;
|
||||
m[2][3] = m23;
|
||||
|
||||
m[3][0] = m30;
|
||||
m[3][1] = m31;
|
||||
m[3][2] = m32;
|
||||
m[3][3] = m33;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Initialize from a 3x4
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void VMatrix::Init(const matrix3x4_t& matrix3x4)
|
||||
{
|
||||
memcpy(m, matrix3x4.Base(), sizeof(matrix3x4_t));
|
||||
|
||||
m[3][0] = 0.0f;
|
||||
m[3][1] = 0.0f;
|
||||
m[3][2] = 0.0f;
|
||||
m[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Methods related to the basis vectors of the matrix
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
inline Vector3D VMatrix::GetForward() const
|
||||
{
|
||||
return Vector3D(m[0][0], m[1][0], m[2][0]);
|
||||
}
|
||||
|
||||
inline Vector3D VMatrix::GetLeft() const
|
||||
{
|
||||
return Vector3D(m[0][1], m[1][1], m[2][1]);
|
||||
}
|
||||
|
||||
inline Vector3D VMatrix::GetUp() const
|
||||
{
|
||||
return Vector3D(m[0][2], m[1][2], m[2][2]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void VMatrix::SetForward(const Vector3D& vForward)
|
||||
{
|
||||
m[0][0] = vForward.x;
|
||||
m[1][0] = vForward.y;
|
||||
m[2][0] = vForward.z;
|
||||
}
|
||||
|
||||
inline void VMatrix::SetLeft(const Vector3D& vLeft)
|
||||
{
|
||||
m[0][1] = vLeft.x;
|
||||
m[1][1] = vLeft.y;
|
||||
m[2][1] = vLeft.z;
|
||||
}
|
||||
|
||||
inline void VMatrix::SetUp(const Vector3D& vUp)
|
||||
{
|
||||
m[0][2] = vUp.x;
|
||||
m[1][2] = vUp.y;
|
||||
m[2][2] = vUp.z;
|
||||
}
|
||||
|
||||
inline void VMatrix::GetBasisVectors(Vector3D& vForward, Vector3D& vLeft, Vector3D& vUp) const
|
||||
{
|
||||
vForward.Init(m[0][0], m[1][0], m[2][0]);
|
||||
vLeft.Init(m[0][1], m[1][1], m[2][1]);
|
||||
vUp.Init(m[0][2], m[1][2], m[2][2]);
|
||||
}
|
||||
|
||||
inline void VMatrix::SetBasisVectors(const Vector3D& vForward, const Vector3D& vLeft, const Vector3D& vUp)
|
||||
{
|
||||
SetForward(vForward);
|
||||
SetLeft(vLeft);
|
||||
SetUp(vUp);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Methods related to the translation component of the matrix
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
inline Vector3D VMatrix::GetTranslation() const
|
||||
{
|
||||
return Vector3D(m[0][3], m[1][3], m[2][3]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline Vector3D& VMatrix::GetTranslation(Vector3D& vTrans) const
|
||||
{
|
||||
vTrans.x = m[0][3];
|
||||
vTrans.y = m[1][3];
|
||||
vTrans.z = m[2][3];
|
||||
return vTrans;
|
||||
}
|
||||
|
||||
inline void VMatrix::SetTranslation(const Vector3D& vTrans)
|
||||
{
|
||||
m[0][3] = vTrans.x;
|
||||
m[1][3] = vTrans.y;
|
||||
m[2][3] = vTrans.z;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// appply translation to this matrix in the input space
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void VMatrix::PreTranslate(const Vector3D& vTrans)
|
||||
{
|
||||
Vector3D tmp;
|
||||
Vector3DMultiplyPosition(*this, vTrans, tmp);
|
||||
m[0][3] = tmp.x;
|
||||
m[1][3] = tmp.y;
|
||||
m[2][3] = tmp.z;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// appply translation to this matrix in the output space
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void VMatrix::PostTranslate(const Vector3D& vTrans)
|
||||
{
|
||||
m[0][3] += vTrans.x;
|
||||
m[1][3] += vTrans.y;
|
||||
m[2][3] += vTrans.z;
|
||||
}
|
||||
|
||||
inline const matrix3x4_t& VMatrix::As3x4() const
|
||||
{
|
||||
return *((const matrix3x4_t*)this);
|
||||
}
|
||||
|
||||
inline void VMatrix::CopyFrom3x4(const matrix3x4_t& m3x4)
|
||||
{
|
||||
memcpy(m, m3x4.Base(), sizeof(matrix3x4_t));
|
||||
m[3][0] = m[3][1] = m[3][2] = 0;
|
||||
m[3][3] = 1;
|
||||
}
|
||||
|
||||
inline void VMatrix::Set3x4(matrix3x4_t& matrix3x4) const
|
||||
{
|
||||
memcpy(matrix3x4.Base(), m, sizeof(matrix3x4_t));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Matrix math operations
|
||||
//-----------------------------------------------------------------------------
|
||||
inline const VMatrix& VMatrix::operator+=(const VMatrix& other)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
m[i][j] += other.m[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
inline VMatrix VMatrix::operator+(const VMatrix& other) const
|
||||
{
|
||||
VMatrix ret;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
((float*)ret.m)[i] = ((float*)m)[i] + ((float*)other.m)[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline VMatrix VMatrix::operator-(const VMatrix& other) const
|
||||
{
|
||||
VMatrix ret;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
ret.m[i][j] = m[i][j] - other.m[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline VMatrix VMatrix::operator-() const
|
||||
{
|
||||
VMatrix ret;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
((float*)ret.m)[i] = ((float*)m)[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Vector transformation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
inline Vector3D VMatrix::operator*(const Vector3D& vVec) const
|
||||
{
|
||||
Vector3D vRet;
|
||||
vRet.x = m[0][0] * vVec.x + m[0][1] * vVec.y + m[0][2] * vVec.z + m[0][3];
|
||||
vRet.y = m[1][0] * vVec.x + m[1][1] * vVec.y + m[1][2] * vVec.z + m[1][3];
|
||||
vRet.z = m[2][0] * vVec.x + m[2][1] * vVec.y + m[2][2] * vVec.z + m[2][3];
|
||||
|
||||
return vRet;
|
||||
}
|
||||
|
||||
inline Vector3D VMatrix::VMul4x3(const Vector3D& vVec) const
|
||||
{
|
||||
Vector3D vResult;
|
||||
Vector3DMultiplyPosition(*this, vVec, vResult);
|
||||
return vResult;
|
||||
}
|
||||
|
||||
|
||||
inline Vector3D VMatrix::VMul4x3Transpose(const Vector3D& vVec) const
|
||||
{
|
||||
Vector3D tmp = vVec;
|
||||
tmp.x -= m[0][3];
|
||||
tmp.y -= m[1][3];
|
||||
tmp.z -= m[2][3];
|
||||
|
||||
return Vector3D(
|
||||
m[0][0] * tmp.x + m[1][0] * tmp.y + m[2][0] * tmp.z,
|
||||
m[0][1] * tmp.x + m[1][1] * tmp.y + m[2][1] * tmp.z,
|
||||
m[0][2] * tmp.x + m[1][2] * tmp.y + m[2][2] * tmp.z
|
||||
);
|
||||
}
|
||||
|
||||
inline Vector3D VMatrix::VMul3x3(const Vector3D& vVec) const
|
||||
{
|
||||
return Vector3D(
|
||||
m[0][0] * vVec.x + m[0][1] * vVec.y + m[0][2] * vVec.z,
|
||||
m[1][0] * vVec.x + m[1][1] * vVec.y + m[1][2] * vVec.z,
|
||||
m[2][0] * vVec.x + m[2][1] * vVec.y + m[2][2] * vVec.z
|
||||
);
|
||||
}
|
||||
|
||||
inline Vector3D VMatrix::VMul3x3Transpose(const Vector3D& vVec) const
|
||||
{
|
||||
return Vector3D(
|
||||
m[0][0] * vVec.x + m[1][0] * vVec.y + m[2][0] * vVec.z,
|
||||
m[0][1] * vVec.x + m[1][1] * vVec.y + m[2][1] * vVec.z,
|
||||
m[0][2] * vVec.x + m[1][2] * vVec.y + m[2][2] * vVec.z
|
||||
);
|
||||
}
|
||||
|
||||
#endif // VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
|
||||
inline void VMatrix::V3Mul(const Vector3D& vIn, Vector3D& vOut) const
|
||||
{
|
||||
vec_t rw;
|
||||
|
||||
rw = 1.0f / (m[3][0] * vIn.x + m[3][1] * vIn.y + m[3][2] * vIn.z + m[3][3]);
|
||||
vOut.x = (m[0][0] * vIn.x + m[0][1] * vIn.y + m[0][2] * vIn.z + m[0][3]) * rw;
|
||||
vOut.y = (m[1][0] * vIn.x + m[1][1] * vIn.y + m[1][2] * vIn.z + m[1][3]) * rw;
|
||||
vOut.z = (m[2][0] * vIn.x + m[2][1] * vIn.y + m[2][2] * vIn.z + m[2][3]) * rw;
|
||||
}
|
||||
|
||||
inline void VMatrix::V4Mul(const Vector4D& vIn, Vector4D& vOut) const
|
||||
{
|
||||
vOut[0] = m[0][0] * vIn[0] + m[0][1] * vIn[1] + m[0][2] * vIn[2] + m[0][3] * vIn[3];
|
||||
vOut[1] = m[1][0] * vIn[0] + m[1][1] * vIn[1] + m[1][2] * vIn[2] + m[1][3] * vIn[3];
|
||||
vOut[2] = m[2][0] * vIn[0] + m[2][1] * vIn[1] + m[2][2] * vIn[2] + m[2][3] * vIn[3];
|
||||
vOut[3] = m[3][0] * vIn[0] + m[3][1] * vIn[1] + m[3][2] * vIn[2] + m[3][3] * vIn[3];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Plane transformation
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void VMatrix::TransformPlane(const VPlane& inPlane, VPlane& outPlane) const
|
||||
{
|
||||
Vector3D vTrans;
|
||||
Vector3DMultiply(*this, inPlane.m_Normal, outPlane.m_Normal);
|
||||
outPlane.m_Dist = inPlane.m_Dist * DotProduct(outPlane.m_Normal, outPlane.m_Normal);
|
||||
outPlane.m_Dist += DotProduct(outPlane.m_Normal, GetTranslation(vTrans));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Other random stuff
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void VMatrix::Identity()
|
||||
{
|
||||
MatrixSetIdentity(*this);
|
||||
}
|
||||
|
||||
|
||||
inline bool VMatrix::IsIdentity() const
|
||||
{
|
||||
return
|
||||
m[0][0] == 1.0f && m[0][1] == 0.0f && m[0][2] == 0.0f && m[0][3] == 0.0f &&
|
||||
m[1][0] == 0.0f && m[1][1] == 1.0f && m[1][2] == 0.0f && m[1][3] == 0.0f &&
|
||||
m[2][0] == 0.0f && m[2][1] == 0.0f && m[2][2] == 1.0f && m[2][3] == 0.0f &&
|
||||
m[3][0] == 0.0f && m[3][1] == 0.0f && m[3][2] == 0.0f && m[3][3] == 1.0f;
|
||||
}
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
inline Vector3D VMatrix::ApplyRotation(const Vector3D& vVec) const
|
||||
{
|
||||
return VMul3x3(vVec);
|
||||
}
|
||||
|
||||
inline VMatrix VMatrix::operator~() const
|
||||
{
|
||||
VMatrix mRet;
|
||||
InverseGeneral(mRet);
|
||||
return mRet;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Accessors
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void MatrixGetColumn(const VMatrix& src, int nCol, Vector3D* pColumn)
|
||||
{
|
||||
Assert((nCol >= 0) && (nCol <= 3));
|
||||
|
||||
pColumn->x = src[0][nCol];
|
||||
pColumn->y = src[1][nCol];
|
||||
pColumn->z = src[2][nCol];
|
||||
}
|
||||
|
||||
inline void MatrixSetColumn(VMatrix& src, int nCol, const Vector3D& column)
|
||||
{
|
||||
Assert((nCol >= 0) && (nCol <= 3));
|
||||
|
||||
src.m[0][nCol] = column.x;
|
||||
src.m[1][nCol] = column.y;
|
||||
src.m[2][nCol] = column.z;
|
||||
}
|
||||
|
||||
inline void MatrixGetRow(const VMatrix& src, int nRow, Vector3D* pRow)
|
||||
{
|
||||
Assert((nRow >= 0) && (nRow <= 3));
|
||||
*pRow = *(Vector3D*)src[nRow];
|
||||
}
|
||||
|
||||
inline void MatrixSetRow(VMatrix& dst, int nRow, const Vector3D& row)
|
||||
{
|
||||
Assert((nRow >= 0) && (nRow <= 3));
|
||||
*(Vector3D*)dst[nRow] = row;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Vector3DMultiplyPosition treats src2 as if it's a point (adds the translation)
|
||||
//-----------------------------------------------------------------------------
|
||||
// NJS: src2 is passed in as a full vector rather than a reference to prevent the need
|
||||
// for 2 branches and a potential copy in the body. (ie, handling the case when the src2
|
||||
// reference is the same as the dst reference ).
|
||||
inline void Vector3DMultiplyPosition(const VMatrix& src1, const VectorByValue src2, Vector3D& dst)
|
||||
{
|
||||
dst[0] = src1[0][0] * src2.x + src1[0][1] * src2.y + src1[0][2] * src2.z + src1[0][3];
|
||||
dst[1] = src1[1][0] * src2.x + src1[1][1] * src2.y + src1[1][2] * src2.z + src1[1][3];
|
||||
dst[2] = src1[2][0] * src2.x + src1[2][1] * src2.y + src1[2][2] * src2.z + src1[2][3];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Transform a plane that has an axis-aligned normal
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void MatrixTransformAxisAlignedPlane(const VMatrix& src, int nDim, float flSign, float flDist, cplane_t& outPlane)
|
||||
{
|
||||
// See MatrixTransformPlane in the .cpp file for an explanation of the algorithm.
|
||||
MatrixGetColumn(src, nDim, &outPlane.normal);
|
||||
outPlane.normal *= flSign;
|
||||
outPlane.dist = flDist * DotProduct(outPlane.normal, outPlane.normal);
|
||||
|
||||
// NOTE: Writing this out by hand because it doesn't inline (inline depth isn't large enough)
|
||||
// This should read outPlane.dist += DotProduct( outPlane.normal, src.GetTranslation );
|
||||
outPlane.dist += outPlane.normal.x * src.m[0][3] + outPlane.normal.y * src.m[1][3] + outPlane.normal.z * src.m[2][3];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Matrix equality test
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool MatricesAreEqual(const VMatrix& src1, const VMatrix& src2, float flTolerance)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
if (fabs(src1[i][j] - src2[i][j]) > flTolerance)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void MatrixBuildOrtho(VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar);
|
||||
void MatrixBuildPerspectiveX(VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar);
|
||||
void MatrixBuildPerspectiveOffCenterX(VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right);
|
||||
void MatrixBuildPerspectiveZRange(VMatrix& dst, double flZNear, double flZFar);
|
||||
|
||||
inline void MatrixOrtho(VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar)
|
||||
{
|
||||
VMatrix mat;
|
||||
MatrixBuildOrtho(mat, left, top, right, bottom, zNear, zFar);
|
||||
|
||||
VMatrix temp;
|
||||
MatrixMultiply(dst, mat, temp);
|
||||
dst = temp;
|
||||
}
|
||||
|
||||
inline void MatrixPerspectiveX(VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar)
|
||||
{
|
||||
VMatrix mat;
|
||||
MatrixBuildPerspectiveX(mat, flFovX, flAspect, flZNear, flZFar);
|
||||
|
||||
VMatrix temp;
|
||||
MatrixMultiply(dst, mat, temp);
|
||||
dst = temp;
|
||||
}
|
||||
|
||||
inline void MatrixPerspectiveOffCenterX(VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right)
|
||||
{
|
||||
VMatrix mat;
|
||||
MatrixBuildPerspectiveOffCenterX(mat, flFovX, flAspect, flZNear, flZFar, bottom, top, left, right);
|
||||
|
||||
VMatrix temp;
|
||||
MatrixMultiply(dst, mat, temp);
|
||||
dst = temp;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
182
r5dev/mathlib/vplane.h
Normal file
182
r5dev/mathlib/vplane.h
Normal file
@ -0,0 +1,182 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef VPLANE_H
|
||||
#define VPLANE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "mathlib/vector.h"
|
||||
|
||||
typedef int SideType;
|
||||
|
||||
// Used to represent sides of things like planes.
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
|
||||
#define VP_EPSILON 0.01f
|
||||
|
||||
|
||||
class VPlane
|
||||
{
|
||||
public:
|
||||
VPlane();
|
||||
VPlane(const Vector3D& vNormal, vec_t dist);
|
||||
|
||||
void Init(const Vector3D& vNormal, vec_t dist);
|
||||
|
||||
// Return the distance from the point to the plane.
|
||||
vec_t DistTo(const Vector3D& vVec) const;
|
||||
|
||||
// Copy.
|
||||
VPlane& operator=(const VPlane& thePlane);
|
||||
|
||||
// Returns SIDE_ON, SIDE_FRONT, or SIDE_BACK.
|
||||
// The epsilon for SIDE_ON can be passed in.
|
||||
SideType GetPointSide(const Vector3D& vPoint, vec_t sideEpsilon = VP_EPSILON) const;
|
||||
|
||||
// Returns SIDE_FRONT or SIDE_BACK.
|
||||
SideType GetPointSideExact(const Vector3D& vPoint) const;
|
||||
|
||||
// Classify the box with respect to the plane.
|
||||
// Returns SIDE_ON, SIDE_FRONT, or SIDE_BACK
|
||||
SideType BoxOnPlaneSide(const Vector3D& vMin, const Vector3D& vMax) const;
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
// Flip the plane.
|
||||
VPlane Flip();
|
||||
|
||||
// Get a point on the plane (normal*dist).
|
||||
Vector3D GetPointOnPlane() const;
|
||||
|
||||
// Snap the specified point to the plane (along the plane's normal).
|
||||
Vector3D SnapPointToPlane(const Vector3D& vPoint) const;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Vector3D m_Normal;
|
||||
vec_t m_Dist;
|
||||
|
||||
#ifdef VECTOR_NO_SLOW_OPERATIONS
|
||||
private:
|
||||
// No copy constructors allowed if we're in optimal mode
|
||||
VPlane(const VPlane& vOther);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inlines.
|
||||
//-----------------------------------------------------------------------------
|
||||
inline VPlane::VPlane()
|
||||
{
|
||||
}
|
||||
|
||||
inline VPlane::VPlane(const Vector3D& vNormal, vec_t dist)
|
||||
{
|
||||
m_Normal = vNormal;
|
||||
m_Dist = dist;
|
||||
}
|
||||
|
||||
inline void VPlane::Init(const Vector3D& vNormal, vec_t dist)
|
||||
{
|
||||
m_Normal = vNormal;
|
||||
m_Dist = dist;
|
||||
}
|
||||
|
||||
inline vec_t VPlane::DistTo(const Vector3D& vVec) const
|
||||
{
|
||||
return vVec.Dot(m_Normal) - m_Dist;
|
||||
}
|
||||
|
||||
inline VPlane& VPlane::operator=(const VPlane& thePlane)
|
||||
{
|
||||
m_Normal = thePlane.m_Normal;
|
||||
m_Dist = thePlane.m_Dist;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
||||
|
||||
inline VPlane VPlane::Flip()
|
||||
{
|
||||
return VPlane(-m_Normal, -m_Dist);
|
||||
}
|
||||
|
||||
inline Vector3D VPlane::GetPointOnPlane() const
|
||||
{
|
||||
return m_Normal * m_Dist;
|
||||
}
|
||||
|
||||
inline Vector3D VPlane::SnapPointToPlane(const Vector3D& vPoint) const
|
||||
{
|
||||
return vPoint - m_Normal * DistTo(vPoint);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline SideType VPlane::GetPointSide(const Vector3D& vPoint, vec_t sideEpsilon) const
|
||||
{
|
||||
vec_t fDist;
|
||||
|
||||
fDist = DistTo(vPoint);
|
||||
if (fDist >= sideEpsilon)
|
||||
return SIDE_FRONT;
|
||||
else if (fDist <= -sideEpsilon)
|
||||
return SIDE_BACK;
|
||||
else
|
||||
return SIDE_ON;
|
||||
}
|
||||
|
||||
inline SideType VPlane::GetPointSideExact(const Vector3D& vPoint) const
|
||||
{
|
||||
return DistTo(vPoint) > 0.0f ? SIDE_FRONT : SIDE_BACK;
|
||||
}
|
||||
|
||||
|
||||
// BUGBUG: This should either simply use the implementation in mathlib or cease to exist.
|
||||
// mathlib implementation is much more efficient. Check to see that VPlane isn't used in
|
||||
// performance critical code.
|
||||
inline SideType VPlane::BoxOnPlaneSide(const Vector3D& vMin, const Vector3D& vMax) const
|
||||
{
|
||||
int i, firstSide, side;
|
||||
TableVector vPoints[8] =
|
||||
{
|
||||
{ vMin.x, vMin.y, vMin.z },
|
||||
{ vMin.x, vMin.y, vMax.z },
|
||||
{ vMin.x, vMax.y, vMax.z },
|
||||
{ vMin.x, vMax.y, vMin.z },
|
||||
|
||||
{ vMax.x, vMin.y, vMin.z },
|
||||
{ vMax.x, vMin.y, vMax.z },
|
||||
{ vMax.x, vMax.y, vMax.z },
|
||||
{ vMax.x, vMax.y, vMin.z },
|
||||
};
|
||||
|
||||
firstSide = GetPointSideExact(vPoints[0]);
|
||||
for (i = 1; i < 8; i++)
|
||||
{
|
||||
side = GetPointSideExact(vPoints[i]);
|
||||
|
||||
// Does the box cross the plane?
|
||||
if (side != firstSide)
|
||||
return SIDE_ON;
|
||||
}
|
||||
|
||||
// Ok, they're all on the same side, return that.
|
||||
return firstSide;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // VPLANE_H
|
@ -131,12 +131,12 @@ struct studiohdr_t
|
||||
|
||||
int length; // size of data
|
||||
|
||||
Vector3 eyeposition; // ideal eye position
|
||||
Vector3 illumposition; // illumination center
|
||||
Vector3 hull_min; // ideal movement hull size
|
||||
Vector3 hull_max;
|
||||
Vector3 view_bbmin; // clipping bounding box
|
||||
Vector3 view_bbmax;
|
||||
Vector3D eyeposition; // ideal eye position
|
||||
Vector3D illumposition; // illumination center
|
||||
Vector3D hull_min; // ideal movement hull size
|
||||
Vector3D hull_max;
|
||||
Vector3D view_bbmin; // clipping bounding box
|
||||
Vector3D view_bbmax;
|
||||
|
||||
int flags;
|
||||
|
||||
|
@ -154,12 +154,34 @@
|
||||
#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
|
||||
#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
|
||||
|
||||
#define FORWARD_DECLARE_HANDLE(name) typedef struct name##__ *name
|
||||
|
||||
#ifndef NOTE_UNUSED
|
||||
#define NOTE_UNUSED(x) (void)(x) // for pesky compiler / lint warnings
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
||||
#endif
|
||||
|
||||
#define M_PI_F ((float)(M_PI)) // Shouldn't collide with anything.
|
||||
|
||||
// NJS: Inlined to prevent floats from being autopromoted to doubles, as with the old system.
|
||||
#ifndef RAD2DEG
|
||||
#define RAD2DEG( x ) ( (float)(x) * (float)(180.f / M_PI_F) )
|
||||
#endif
|
||||
|
||||
#ifndef DEG2RAD
|
||||
#define DEG2RAD( x ) ( (float)(x) * (float)(M_PI_F / 180.f) )
|
||||
#endif
|
||||
|
||||
typedef int qboolean;
|
||||
|
||||
typedef float vec_t;
|
||||
typedef float vec3_t[3];
|
||||
|
||||
|
@ -23,6 +23,19 @@
|
||||
#endif
|
||||
std::mutex s_LogMutex;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// True if -hushasserts was passed on command line.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HushAsserts()
|
||||
{
|
||||
#ifdef DBGFLAG_ASSERT
|
||||
static bool s_bHushAsserts = !!CommandLine()->FindParm("-hushasserts");
|
||||
return s_bHushAsserts;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Templates to assist in validating pointers:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define Assert assert
|
||||
#include "tier0/dbgflag.h"
|
||||
|
||||
bool HushAsserts();
|
||||
//-----------------------------------------------------------------------------
|
||||
enum class eDLL_T : int
|
||||
{
|
||||
|
@ -32,6 +32,8 @@
|
||||
#define IsPlatformWindowsPC64() 1
|
||||
#define IsPlatformWindowsPC32() 0
|
||||
#define PLATFORM_WINDOWS_PC64 1
|
||||
|
||||
#define COMPILER_MSVC64 1
|
||||
#else
|
||||
#define IsPlatformWindowsPC64() 0
|
||||
#define IsPlatformWindowsPC32() 1
|
||||
@ -141,6 +143,59 @@
|
||||
|
||||
#endif // CROSS_PLATFORM_VERSION < 2
|
||||
|
||||
#if defined( GNUC ) && !defined( COMPILER_PS3 ) // use pre-align on PS3
|
||||
// gnuc has the align decoration at the end
|
||||
#define ALIGN4
|
||||
#define ALIGN8
|
||||
#define ALIGN16
|
||||
#define ALIGN32
|
||||
#define ALIGN128
|
||||
|
||||
#undef ALIGN16_POST
|
||||
#define ALIGN4_POST DECL_ALIGN(4)
|
||||
#define ALIGN8_POST DECL_ALIGN(8)
|
||||
#define ALIGN16_POST DECL_ALIGN(16)
|
||||
#define ALIGN32_POST DECL_ALIGN(32)
|
||||
#define ALIGN128_POST DECL_ALIGN(128)
|
||||
#else
|
||||
// MSVC has the align at the start of the struct
|
||||
// PS3 SNC supports both
|
||||
#define ALIGN4 DECL_ALIGN(4)
|
||||
#define ALIGN8 DECL_ALIGN(8)
|
||||
#define ALIGN16 DECL_ALIGN(16)
|
||||
#define ALIGN32 DECL_ALIGN(32)
|
||||
#define ALIGN128 DECL_ALIGN(128)
|
||||
|
||||
#define ALIGN4_POST
|
||||
#define ALIGN8_POST
|
||||
#define ALIGN16_POST
|
||||
#define ALIGN32_POST
|
||||
#define ALIGN128_POST
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Generally useful platform-independent macros (move to another file?)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// need macro for constant expression
|
||||
#define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) )
|
||||
|
||||
// Force a function call site -not- to inlined. (useful for profiling)
|
||||
#define DONT_INLINE(a) (((int)(a)+1)?(a):(a))
|
||||
|
||||
// Marks the codepath from here until the next branch entry point as unreachable,
|
||||
// and asserts if any attempt is made to execute it.
|
||||
#define UNREACHABLE() { Assert(0); HINT(0); }
|
||||
|
||||
// In cases where no default is present or appropriate, this causes MSVC to generate
|
||||
// as little code as possible, and throw an assertion in debug.
|
||||
#define NO_DEFAULT default: UNREACHABLE();
|
||||
|
||||
// Defines MAX_PATH
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 260
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Time stamp counter
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1,5 +1,43 @@
|
||||
#ifndef THREADTOOLS_H
|
||||
#define THREADTOOLS_H
|
||||
|
||||
inline bool ThreadInterlockedAssignIf(LONG volatile* p, int32 value, int32 comperand)
|
||||
{
|
||||
Assert((size_t)p % 4 == 0);
|
||||
return _InterlockedCompareExchange(p, comperand, value);
|
||||
}
|
||||
inline void ThreadSleep(unsigned nMilliseconds)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef PLATFORM_WINDOWS_PC // This is performed by the game module!
|
||||
//static bool bInitialized = false;
|
||||
//if (!bInitialized)
|
||||
//{
|
||||
// bInitialized = true;
|
||||
// // Set the timer resolution to 1 ms (default is 10.0, 15.6, 2.5, 1.0 or
|
||||
// // some other value depending on hardware and software) so that we can
|
||||
// // use Sleep( 1 ) to avoid wasting CPU time without missing our frame
|
||||
// // rate.
|
||||
// timeBeginPeriod(1);
|
||||
//}
|
||||
#endif
|
||||
|
||||
Sleep(nMilliseconds);
|
||||
#elif PLATFORM_PS3
|
||||
if (nMilliseconds == 0)
|
||||
{
|
||||
// sys_ppu_thread_yield doesn't seem to function properly, so sleep instead.
|
||||
sys_timer_usleep(60);
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_timer_usleep(nMilliseconds * 1000);
|
||||
}
|
||||
#elif defined(POSIX)
|
||||
usleep(nMilliseconds * 1000);
|
||||
#endif
|
||||
}
|
||||
//=============================================================================
|
||||
class CThreadFastMutex;
|
||||
|
||||
|
50
r5dev/vphysics/physics_collide.cpp
Normal file
50
r5dev/vphysics/physics_collide.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "core/stdafx.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Calculate the volume of a tetrahedron with these vertices
|
||||
// Input : p0 - points of tetrahedron
|
||||
// p1 -
|
||||
// p2 -
|
||||
// p3 -
|
||||
// Output : float (volume in units^3)
|
||||
//-----------------------------------------------------------------------------
|
||||
static float TetrahedronVolume(const Vector3D& p0, const Vector3D& p1, const Vector3D& p2, const Vector3D& p3)
|
||||
{
|
||||
Vector3D a, b, c, cross;
|
||||
float volume = 1.0f / 6.0f;
|
||||
|
||||
a = p1 - p0;
|
||||
b = p2 - p0;
|
||||
c = p3 - p0;
|
||||
cross = CrossProduct(b, c);
|
||||
|
||||
volume *= DotProduct(a, cross);
|
||||
if (volume < 0)
|
||||
return -volume;
|
||||
return volume;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Calculate a triangle area with these vertices
|
||||
// Input : p0 - points of tetrahedron
|
||||
// p1 -
|
||||
// p2 -
|
||||
// Output : float (area)
|
||||
//-----------------------------------------------------------------------------
|
||||
static float TriangleArea(const Vector3D& p0, const Vector3D& p1, const Vector3D& p2)
|
||||
{
|
||||
Vector3D e0 = p1 - p0;
|
||||
Vector3D e1 = p2 - p0;
|
||||
Vector3D cross;
|
||||
|
||||
CrossProduct(e0, e1, cross);
|
||||
return 0.5 * cross.Length();
|
||||
}
|
@ -58,11 +58,19 @@
|
||||
<ClCompile Include="..\materialsystem\cmaterialglue.cpp" />
|
||||
<ClCompile Include="..\materialsystem\cmaterialsystem.cpp" />
|
||||
<ClCompile Include="..\mathlib\adler32.cpp" />
|
||||
<ClCompile Include="..\mathlib\almostequal.cpp" />
|
||||
<ClCompile Include="..\mathlib\bits.cpp" />
|
||||
<ClCompile Include="..\mathlib\color_conversion.cpp" />
|
||||
<ClCompile Include="..\mathlib\crc32.cpp" />
|
||||
<ClCompile Include="..\mathlib\halton.cpp" />
|
||||
<ClCompile Include="..\mathlib\IceKey.cpp" />
|
||||
<ClCompile Include="..\mathlib\mathlib_base.cpp" />
|
||||
<ClCompile Include="..\mathlib\powsse.cpp" />
|
||||
<ClCompile Include="..\mathlib\randsse.cpp" />
|
||||
<ClCompile Include="..\mathlib\sha1.cpp" />
|
||||
<ClCompile Include="..\mathlib\sha256.cpp" />
|
||||
<ClCompile Include="..\mathlib\sseconst.cpp" />
|
||||
<ClCompile Include="..\mathlib\vmatrix.cpp" />
|
||||
<ClCompile Include="..\networksystem\pylon.cpp" />
|
||||
<ClCompile Include="..\protoc\cl_rcon.pb.cc">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
@ -109,11 +117,13 @@
|
||||
<ClCompile Include="..\vpc\IAppSystem.cpp" />
|
||||
<ClCompile Include="..\vpc\interfaces.cpp" />
|
||||
<ClCompile Include="..\vpc\keyvalues.cpp" />
|
||||
<ClCompile Include="..\vphysics\physics_collide.cpp" />
|
||||
<ClCompile Include="..\vphysics\QHull.cpp" />
|
||||
<ClCompile Include="..\vpklib\packedstore.cpp" />
|
||||
<ClCompile Include="..\vstdlib\callback.cpp" />
|
||||
<ClCompile Include="..\vstdlib\completion.cpp" />
|
||||
<ClCompile Include="..\vstdlib\keyvaluessystem.cpp" />
|
||||
<ClCompile Include="..\vstdlib\random.cpp" />
|
||||
<ClCompile Include="..\windows\console.cpp" />
|
||||
<ClCompile Include="..\windows\id3dx.cpp" />
|
||||
<ClCompile Include="..\windows\input.cpp" />
|
||||
@ -189,12 +199,23 @@
|
||||
<ClInclude Include="..\mathlib\bits.h" />
|
||||
<ClInclude Include="..\mathlib\color.h" />
|
||||
<ClInclude Include="..\mathlib\crc32.h" />
|
||||
<ClInclude Include="..\mathlib\halton.h" />
|
||||
<ClInclude Include="..\mathlib\IceKey.H" />
|
||||
<ClInclude Include="..\mathlib\mathlib.h" />
|
||||
<ClInclude Include="..\mathlib\math_pfns.h" />
|
||||
<ClInclude Include="..\mathlib\noisedata.h" />
|
||||
<ClInclude Include="..\mathlib\parallel_for.h" />
|
||||
<ClInclude Include="..\mathlib\sha1.h" />
|
||||
<ClInclude Include="..\mathlib\sha256.h" />
|
||||
<ClInclude Include="..\mathlib\ssemath.h" />
|
||||
<ClInclude Include="..\mathlib\ssenoise.h" />
|
||||
<ClInclude Include="..\mathlib\ssequaternion.h" />
|
||||
<ClInclude Include="..\mathlib\swap.h" />
|
||||
<ClInclude Include="..\mathlib\vector.h" />
|
||||
<ClInclude Include="..\mathlib\vector2d.h" />
|
||||
<ClInclude Include="..\mathlib\vector4d.h" />
|
||||
<ClInclude Include="..\mathlib\vmatrix.h" />
|
||||
<ClInclude Include="..\mathlib\vplane.h" />
|
||||
<ClInclude Include="..\milessdk\win64_rrthreads.h" />
|
||||
<ClInclude Include="..\networksystem\pylon.h" />
|
||||
<ClInclude Include="..\networksystem\serverlisting.h" />
|
||||
@ -452,6 +473,7 @@
|
||||
<ClInclude Include="..\vstdlib\callback.h" />
|
||||
<ClInclude Include="..\vstdlib\completion.h" />
|
||||
<ClInclude Include="..\vstdlib\keyvaluessystem.h" />
|
||||
<ClInclude Include="..\vstdlib\random.h" />
|
||||
<ClInclude Include="..\windows\console.h" />
|
||||
<ClInclude Include="..\windows\id3dx.h" />
|
||||
<ClInclude Include="..\windows\input.h" />
|
||||
|
@ -510,6 +510,36 @@
|
||||
<ClCompile Include="..\tier0\platform.cpp">
|
||||
<Filter>sdk\tier0</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\mathlib_base.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\powsse.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\randsse.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\sseconst.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\vmatrix.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\almostequal.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\color_conversion.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\halton.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\vphysics\physics_collide.cpp">
|
||||
<Filter>sdk\vphysics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\vstdlib\random.cpp">
|
||||
<Filter>sdk\vstdlib</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\client\cdll_engine_int.h">
|
||||
@ -1520,6 +1550,42 @@
|
||||
<ClInclude Include="..\public\include\icommandline.h">
|
||||
<Filter>sdk\public\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\mathlib.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\noisedata.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssemath.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssenoise.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssequaternion.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vector2d.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vector4d.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vmatrix.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vplane.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\halton.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\math_pfns.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\vstdlib\random.h">
|
||||
<Filter>sdk\vstdlib</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\shared\resource\lockedserver.png">
|
||||
|
@ -188,12 +188,23 @@
|
||||
<ClInclude Include="..\mathlib\bits.h" />
|
||||
<ClInclude Include="..\mathlib\color.h" />
|
||||
<ClInclude Include="..\mathlib\crc32.h" />
|
||||
<ClInclude Include="..\mathlib\halton.h" />
|
||||
<ClInclude Include="..\mathlib\IceKey.H" />
|
||||
<ClInclude Include="..\mathlib\mathlib.h" />
|
||||
<ClInclude Include="..\mathlib\math_pfns.h" />
|
||||
<ClInclude Include="..\mathlib\noisedata.h" />
|
||||
<ClInclude Include="..\mathlib\parallel_for.h" />
|
||||
<ClInclude Include="..\mathlib\sha1.h" />
|
||||
<ClInclude Include="..\mathlib\sha256.h" />
|
||||
<ClInclude Include="..\mathlib\ssemath.h" />
|
||||
<ClInclude Include="..\mathlib\ssenoise.h" />
|
||||
<ClInclude Include="..\mathlib\ssequaternion.h" />
|
||||
<ClInclude Include="..\mathlib\swap.h" />
|
||||
<ClInclude Include="..\mathlib\vector.h" />
|
||||
<ClInclude Include="..\mathlib\vector2d.h" />
|
||||
<ClInclude Include="..\mathlib\vector4d.h" />
|
||||
<ClInclude Include="..\mathlib\vmatrix.h" />
|
||||
<ClInclude Include="..\mathlib\vplane.h" />
|
||||
<ClInclude Include="..\networksystem\pylon.h" />
|
||||
<ClInclude Include="..\networksystem\serverlisting.h" />
|
||||
<ClInclude Include="..\networksystem\sm_protocol.h" />
|
||||
@ -432,6 +443,7 @@
|
||||
<ClInclude Include="..\vstdlib\callback.h" />
|
||||
<ClInclude Include="..\vstdlib\completion.h" />
|
||||
<ClInclude Include="..\vstdlib\keyvaluessystem.h" />
|
||||
<ClInclude Include="..\vstdlib\random.h" />
|
||||
<ClInclude Include="..\windows\console.h" />
|
||||
<ClInclude Include="..\windows\system.h" />
|
||||
</ItemGroup>
|
||||
@ -477,11 +489,19 @@
|
||||
<ClCompile Include="..\launcher\launcher.cpp" />
|
||||
<ClCompile Include="..\launcher\prx.cpp" />
|
||||
<ClCompile Include="..\mathlib\adler32.cpp" />
|
||||
<ClCompile Include="..\mathlib\almostequal.cpp" />
|
||||
<ClCompile Include="..\mathlib\bits.cpp" />
|
||||
<ClCompile Include="..\mathlib\color_conversion.cpp" />
|
||||
<ClCompile Include="..\mathlib\crc32.cpp" />
|
||||
<ClCompile Include="..\mathlib\halton.cpp" />
|
||||
<ClCompile Include="..\mathlib\IceKey.cpp" />
|
||||
<ClCompile Include="..\mathlib\mathlib_base.cpp" />
|
||||
<ClCompile Include="..\mathlib\powsse.cpp" />
|
||||
<ClCompile Include="..\mathlib\randsse.cpp" />
|
||||
<ClCompile Include="..\mathlib\sha1.cpp" />
|
||||
<ClCompile Include="..\mathlib\sha256.cpp" />
|
||||
<ClCompile Include="..\mathlib\sseconst.cpp" />
|
||||
<ClCompile Include="..\mathlib\vmatrix.cpp" />
|
||||
<ClCompile Include="..\networksystem\pylon.cpp" />
|
||||
<ClCompile Include="..\protoc\cl_rcon.pb.cc">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
@ -523,11 +543,13 @@
|
||||
<ClCompile Include="..\vpc\IAppSystem.cpp" />
|
||||
<ClCompile Include="..\vpc\interfaces.cpp" />
|
||||
<ClCompile Include="..\vpc\keyvalues.cpp" />
|
||||
<ClCompile Include="..\vphysics\physics_collide.cpp" />
|
||||
<ClCompile Include="..\vphysics\QHull.cpp" />
|
||||
<ClCompile Include="..\vpklib\packedstore.cpp" />
|
||||
<ClCompile Include="..\vstdlib\callback.cpp" />
|
||||
<ClCompile Include="..\vstdlib\completion.cpp" />
|
||||
<ClCompile Include="..\vstdlib\keyvaluessystem.cpp" />
|
||||
<ClCompile Include="..\vstdlib\random.cpp" />
|
||||
<ClCompile Include="..\windows\console.cpp" />
|
||||
<ClCompile Include="..\windows\system.cpp" />
|
||||
</ItemGroup>
|
||||
|
@ -1125,6 +1125,42 @@
|
||||
<ClInclude Include="..\public\include\icommandline.h">
|
||||
<Filter>sdk\public\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\noisedata.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssemath.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssenoise.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssequaternion.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vector2d.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vector4d.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vmatrix.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vplane.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\halton.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\math_pfns.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\mathlib.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\vstdlib\random.h">
|
||||
<Filter>sdk\vstdlib</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\common\opcodes.cpp">
|
||||
@ -1382,6 +1418,36 @@
|
||||
<ClCompile Include="..\tier0\platform.cpp">
|
||||
<Filter>sdk\tier0</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\mathlib_base.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\powsse.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\randsse.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\sseconst.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\vmatrix.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\almostequal.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\color_conversion.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\halton.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\vphysics\physics_collide.cpp">
|
||||
<Filter>sdk\vphysics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\vstdlib\random.cpp">
|
||||
<Filter>sdk\vstdlib</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\Dedicated.def" />
|
||||
|
@ -66,10 +66,17 @@
|
||||
<ClCompile Include="..\materialsystem\cshaderglue.cpp" />
|
||||
<ClCompile Include="..\mathlib\adler32.cpp" />
|
||||
<ClCompile Include="..\mathlib\bits.cpp" />
|
||||
<ClCompile Include="..\mathlib\color_conversion.cpp" />
|
||||
<ClCompile Include="..\mathlib\crc32.cpp" />
|
||||
<ClCompile Include="..\mathlib\halton.cpp" />
|
||||
<ClCompile Include="..\mathlib\IceKey.cpp" />
|
||||
<ClCompile Include="..\mathlib\mathlib_base.cpp" />
|
||||
<ClCompile Include="..\mathlib\powsse.cpp" />
|
||||
<ClCompile Include="..\mathlib\randsse.cpp" />
|
||||
<ClCompile Include="..\mathlib\sha1.cpp" />
|
||||
<ClCompile Include="..\mathlib\sha256.cpp" />
|
||||
<ClCompile Include="..\mathlib\sseconst.cpp" />
|
||||
<ClCompile Include="..\mathlib\vmatrix.cpp" />
|
||||
<ClCompile Include="..\networksystem\pylon.cpp" />
|
||||
<ClCompile Include="..\protoc\cl_rcon.pb.cc">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
@ -117,11 +124,13 @@
|
||||
<ClCompile Include="..\vpc\IAppSystem.cpp" />
|
||||
<ClCompile Include="..\vpc\interfaces.cpp" />
|
||||
<ClCompile Include="..\vpc\keyvalues.cpp" />
|
||||
<ClCompile Include="..\vphysics\physics_collide.cpp" />
|
||||
<ClCompile Include="..\vphysics\QHull.cpp" />
|
||||
<ClCompile Include="..\vpklib\packedstore.cpp" />
|
||||
<ClCompile Include="..\vstdlib\callback.cpp" />
|
||||
<ClCompile Include="..\vstdlib\completion.cpp" />
|
||||
<ClCompile Include="..\vstdlib\keyvaluessystem.cpp" />
|
||||
<ClCompile Include="..\vstdlib\random.cpp" />
|
||||
<ClCompile Include="..\windows\console.cpp" />
|
||||
<ClCompile Include="..\windows\id3dx.cpp" />
|
||||
<ClCompile Include="..\windows\input.cpp" />
|
||||
@ -204,15 +213,27 @@
|
||||
<ClInclude Include="..\materialsystem\cmaterialsystem.h" />
|
||||
<ClInclude Include="..\materialsystem\cshaderglue.h" />
|
||||
<ClInclude Include="..\mathlib\adler32.h" />
|
||||
<ClInclude Include="..\mathlib\almostequal.cpp" />
|
||||
<ClInclude Include="..\mathlib\bits.h" />
|
||||
<ClInclude Include="..\mathlib\color.h" />
|
||||
<ClInclude Include="..\mathlib\crc32.h" />
|
||||
<ClInclude Include="..\mathlib\halton.h" />
|
||||
<ClInclude Include="..\mathlib\IceKey.H" />
|
||||
<ClInclude Include="..\mathlib\mathlib.h" />
|
||||
<ClInclude Include="..\mathlib\math_pfns.h" />
|
||||
<ClInclude Include="..\mathlib\noisedata.h" />
|
||||
<ClInclude Include="..\mathlib\parallel_for.h" />
|
||||
<ClInclude Include="..\mathlib\sha1.h" />
|
||||
<ClInclude Include="..\mathlib\sha256.h" />
|
||||
<ClInclude Include="..\mathlib\ssemath.h" />
|
||||
<ClInclude Include="..\mathlib\ssenoise.h" />
|
||||
<ClInclude Include="..\mathlib\ssequaternion.h" />
|
||||
<ClInclude Include="..\mathlib\swap.h" />
|
||||
<ClInclude Include="..\mathlib\vector.h" />
|
||||
<ClInclude Include="..\mathlib\vector2d.h" />
|
||||
<ClInclude Include="..\mathlib\vector4d.h" />
|
||||
<ClInclude Include="..\mathlib\vmatrix.h" />
|
||||
<ClInclude Include="..\mathlib\vplane.h" />
|
||||
<ClInclude Include="..\milessdk\win64_rrthreads.h" />
|
||||
<ClInclude Include="..\networksystem\pylon.h" />
|
||||
<ClInclude Include="..\networksystem\serverlisting.h" />
|
||||
@ -472,6 +493,7 @@
|
||||
<ClInclude Include="..\vstdlib\callback.h" />
|
||||
<ClInclude Include="..\vstdlib\completion.h" />
|
||||
<ClInclude Include="..\vstdlib\keyvaluessystem.h" />
|
||||
<ClInclude Include="..\vstdlib\random.h" />
|
||||
<ClInclude Include="..\windows\console.h" />
|
||||
<ClInclude Include="..\windows\id3dx.h" />
|
||||
<ClInclude Include="..\windows\input.h" />
|
||||
|
@ -543,6 +543,33 @@
|
||||
<ClCompile Include="..\materialsystem\cshaderglue.cpp">
|
||||
<Filter>sdk\materialsystem</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\mathlib_base.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\vstdlib\random.cpp">
|
||||
<Filter>sdk\vstdlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\powsse.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\randsse.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\vmatrix.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\vphysics\physics_collide.cpp">
|
||||
<Filter>sdk\vphysics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\halton.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\sseconst.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\mathlib\color_conversion.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\client\cdll_engine_int.h">
|
||||
@ -1589,6 +1616,45 @@
|
||||
<ClInclude Include="..\materialsystem\cshaderglue.h">
|
||||
<Filter>sdk\materialsystem</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\mathlib.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vector2d.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\math_pfns.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\vstdlib\random.h">
|
||||
<Filter>sdk\vstdlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssemath.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssenoise.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\noisedata.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vmatrix.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vector4d.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\vplane.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\almostequal.cpp">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\halton.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\mathlib\ssequaternion.h">
|
||||
<Filter>sdk\mathlib</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\shared\resource\lockedserver.png">
|
||||
|
261
r5dev/vstdlib/random.cpp
Normal file
261
r5dev/vstdlib/random.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: Random number generator
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "core/stdafx.h"
|
||||
#include "vstdlib/random.h"
|
||||
#include <math.h>
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
#define IA 16807
|
||||
#define IM 2147483647
|
||||
#define IQ 127773
|
||||
#define IR 2836
|
||||
#define NDIV (1+(IM-1)/NTAB)
|
||||
#define MAX_RANDOM_RANGE 0x7FFFFFFFUL
|
||||
|
||||
// fran1 -- return a random floating-point number on the interval [0,1)
|
||||
//
|
||||
#define AM (1.0/IM)
|
||||
#define EPS 1.2e-7
|
||||
#define RNMX (1.0-EPS)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// globals
|
||||
//-----------------------------------------------------------------------------
|
||||
static CUniformRandomStream s_UniformStream;
|
||||
static CGaussianRandomStream s_GaussianStream;
|
||||
static IUniformRandomStream* s_pUniformStream = &s_UniformStream;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Installs a global random number generator, which will affect the Random functions above
|
||||
//-----------------------------------------------------------------------------
|
||||
void InstallUniformRandomStream(IUniformRandomStream* pStream)
|
||||
{
|
||||
s_pUniformStream = pStream ? pStream : &s_UniformStream;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A couple of convenience functions to access the library's global uniform stream
|
||||
//-----------------------------------------------------------------------------
|
||||
void RandomSeed(int iSeed)
|
||||
{
|
||||
s_pUniformStream->SetSeed(iSeed);
|
||||
}
|
||||
|
||||
float RandomFloat(float flMinVal, float flMaxVal)
|
||||
{
|
||||
return s_pUniformStream->RandomFloat(flMinVal, flMaxVal);
|
||||
}
|
||||
|
||||
float RandomFloatExp(float flMinVal, float flMaxVal, float flExponent)
|
||||
{
|
||||
return s_pUniformStream->RandomFloatExp(flMinVal, flMaxVal, flExponent);
|
||||
}
|
||||
|
||||
int RandomInt(int iMinVal, int iMaxVal)
|
||||
{
|
||||
return s_pUniformStream->RandomInt(iMinVal, iMaxVal);
|
||||
}
|
||||
|
||||
float RandomGaussianFloat(float flMean, float flStdDev)
|
||||
{
|
||||
return s_GaussianStream.RandomFloat(flMean, flStdDev);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Implementation of the uniform random number stream
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
CUniformRandomStream::CUniformRandomStream()
|
||||
{
|
||||
SetSeed(0);
|
||||
}
|
||||
|
||||
void CUniformRandomStream::SetSeed(int iSeed)
|
||||
{
|
||||
m_mutex.lock();
|
||||
m_idum = ((iSeed < 0) ? iSeed : -iSeed);
|
||||
m_iy = 0;
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
int CUniformRandomStream::GenerateRandomNumber()
|
||||
{
|
||||
m_mutex.lock();
|
||||
int j;
|
||||
int k;
|
||||
|
||||
if (m_idum <= 0 || !m_iy)
|
||||
{
|
||||
if (-(m_idum) < 1)
|
||||
m_idum = 1;
|
||||
else
|
||||
m_idum = -(m_idum);
|
||||
|
||||
for (j = NTAB + 7; j >= 0; j--)
|
||||
{
|
||||
k = (m_idum) / IQ;
|
||||
m_idum = IA * (m_idum - k * IQ) - IR * k;
|
||||
if (m_idum < 0)
|
||||
m_idum += IM;
|
||||
if (j < NTAB)
|
||||
m_iv[j] = m_idum;
|
||||
}
|
||||
m_iy = m_iv[0];
|
||||
}
|
||||
k = (m_idum) / IQ;
|
||||
m_idum = IA * (m_idum - k * IQ) - IR * k;
|
||||
if (m_idum < 0)
|
||||
m_idum += IM;
|
||||
j = m_iy / NDIV;
|
||||
|
||||
// We're seeing some strange memory corruption in the contents of s_pUniformStream.
|
||||
// Perhaps it's being caused by something writing past the end of this array?
|
||||
// Bounds-check in release to see if that's the case.
|
||||
if (j >= NTAB || j < 0)
|
||||
{
|
||||
//DebuggerBreakIfDebugging();
|
||||
//Warning("CUniformRandomStream had an array overrun: tried to write to element %d of 0..31. Contact Tom or Elan.\n", j);
|
||||
j = (j % NTAB) & 0x7fffffff;
|
||||
}
|
||||
|
||||
m_iy = m_iv[j];
|
||||
m_iv[j] = m_idum;
|
||||
|
||||
m_mutex.unlock();
|
||||
return m_iy;
|
||||
}
|
||||
|
||||
float CUniformRandomStream::RandomFloat(float flLow, float flHigh)
|
||||
{
|
||||
// float in [0,1)
|
||||
float fl = AM * GenerateRandomNumber();
|
||||
if (fl > RNMX)
|
||||
{
|
||||
fl = RNMX;
|
||||
}
|
||||
return (fl * (flHigh - flLow)) + flLow; // float in [low,high)
|
||||
}
|
||||
|
||||
float CUniformRandomStream::RandomFloatExp(float flMinVal, float flMaxVal, float flExponent)
|
||||
{
|
||||
// float in [0,1)
|
||||
float fl = AM * GenerateRandomNumber();
|
||||
if (fl > RNMX)
|
||||
{
|
||||
fl = RNMX;
|
||||
}
|
||||
if (flExponent != 1.0f)
|
||||
{
|
||||
fl = powf(fl, flExponent);
|
||||
}
|
||||
return (fl * (flMaxVal - flMinVal)) + flMinVal; // float in [low,high)
|
||||
}
|
||||
|
||||
int CUniformRandomStream::RandomInt(int iLow, int iHigh)
|
||||
{
|
||||
//ASSERT(lLow <= lHigh);
|
||||
unsigned int maxAcceptable;
|
||||
unsigned int x = iHigh - iLow + 1;
|
||||
unsigned int n;
|
||||
if (x <= 1 || MAX_RANDOM_RANGE < x - 1)
|
||||
{
|
||||
return iLow;
|
||||
}
|
||||
|
||||
// The following maps a uniform distribution on the interval [0,MAX_RANDOM_RANGE]
|
||||
// to a smaller, client-specified range of [0,x-1] in a way that doesn't bias
|
||||
// the uniform distribution unfavorably. Even for a worst case x, the loop is
|
||||
// guaranteed to be taken no more than half the time, so for that worst case x,
|
||||
// the average number of times through the loop is 2. For cases where x is
|
||||
// much smaller than MAX_RANDOM_RANGE, the average number of times through the
|
||||
// loop is very close to 1.
|
||||
//
|
||||
maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE + 1) % x);
|
||||
do
|
||||
{
|
||||
n = GenerateRandomNumber();
|
||||
} while (n > maxAcceptable);
|
||||
|
||||
return iLow + (n % x);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Implementation of the gaussian random number stream
|
||||
// We're gonna use the Box-Muller method (which actually generates 2
|
||||
// gaussian-distributed numbers at once)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
CGaussianRandomStream::CGaussianRandomStream(IUniformRandomStream* pUniformStream)
|
||||
{
|
||||
AttachToStream(pUniformStream);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Attaches to a random uniform stream
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGaussianRandomStream::AttachToStream(IUniformRandomStream* pUniformStream)
|
||||
{
|
||||
m_mutex.lock();
|
||||
m_pUniformStream = pUniformStream;
|
||||
m_bHaveValue = false;
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Generates random numbers
|
||||
//-----------------------------------------------------------------------------
|
||||
float CGaussianRandomStream::RandomFloat(float flMean, float flStdDev)
|
||||
{
|
||||
m_mutex.lock();
|
||||
IUniformRandomStream* pUniformStream = m_pUniformStream ? m_pUniformStream : s_pUniformStream;
|
||||
float fac, rsq, v1, v2;
|
||||
|
||||
if (!m_bHaveValue)
|
||||
{
|
||||
// Pick 2 random #s from -1 to 1
|
||||
// Make sure they lie inside the unit circle. If they don't, try again
|
||||
do
|
||||
{
|
||||
v1 = 2.0f * pUniformStream->RandomFloat() - 1.0f;
|
||||
v2 = 2.0f * pUniformStream->RandomFloat() - 1.0f;
|
||||
rsq = v1 * v1 + v2 * v2;
|
||||
} while ((rsq > 1.0f) || (rsq == 0.0f));
|
||||
|
||||
// The box-muller transformation to get the two gaussian numbers
|
||||
fac = sqrtf(-2.0f * log(rsq) / rsq);
|
||||
|
||||
// Store off one value for later use
|
||||
m_flRandomValue = v1 * fac;
|
||||
m_bHaveValue = true;
|
||||
|
||||
m_mutex.unlock();
|
||||
return flStdDev * (v2 * fac) + flMean;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bHaveValue = false;
|
||||
|
||||
m_mutex.unlock();
|
||||
return flStdDev * m_flRandomValue + flMean;
|
||||
}
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates a histogram (for testing)
|
||||
//-----------------------------------------------------------------------------
|
106
r5dev/vstdlib/random.h
Normal file
106
r5dev/vstdlib/random.h
Normal file
@ -0,0 +1,106 @@
|
||||
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: Random number generator
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef VSTDLIB_RANDOM_H
|
||||
#define VSTDLIB_RANDOM_H
|
||||
|
||||
#include "tier0/basetypes.h"
|
||||
#include "tier0/threadtools.h"
|
||||
|
||||
#define NTAB 32
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning( disable:4251 )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A generator of uniformly distributed random numbers
|
||||
//-----------------------------------------------------------------------------
|
||||
class IUniformRandomStream
|
||||
{
|
||||
public:
|
||||
// Sets the seed of the random number generator
|
||||
virtual void SetSeed(int iSeed) = 0;
|
||||
|
||||
// Generates random numbers
|
||||
virtual float RandomFloat(float flMinVal = 0.0f, float flMaxVal = 1.0f) = 0;
|
||||
virtual int RandomInt(int iMinVal, int iMaxVal) = 0;
|
||||
virtual float RandomFloatExp(float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f) = 0;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The standard generator of uniformly distributed random numbers
|
||||
//-----------------------------------------------------------------------------
|
||||
class CUniformRandomStream : public IUniformRandomStream
|
||||
{
|
||||
public:
|
||||
CUniformRandomStream();
|
||||
|
||||
// Sets the seed of the random number generator
|
||||
virtual void SetSeed(int iSeed);
|
||||
|
||||
// Generates random numbers
|
||||
virtual float RandomFloat(float flMinVal = 0.0f, float flMaxVal = 1.0f);
|
||||
virtual int RandomInt(int iMinVal, int iMaxVal);
|
||||
virtual float RandomFloatExp(float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f);
|
||||
|
||||
private:
|
||||
int GenerateRandomNumber();
|
||||
|
||||
int m_idum;
|
||||
int m_iy;
|
||||
int m_iv[NTAB];
|
||||
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A generator of gaussian distributed random numbers
|
||||
//-----------------------------------------------------------------------------
|
||||
class CGaussianRandomStream
|
||||
{
|
||||
public:
|
||||
// Passing in NULL will cause the gaussian stream to use the
|
||||
// installed global random number generator
|
||||
CGaussianRandomStream(IUniformRandomStream* pUniformStream = NULL);
|
||||
|
||||
// Attaches to a random uniform stream
|
||||
void AttachToStream(IUniformRandomStream* pUniformStream = NULL);
|
||||
|
||||
// Generates random numbers
|
||||
float RandomFloat(float flMean = 0.0f, float flStdDev = 1.0f);
|
||||
|
||||
private:
|
||||
IUniformRandomStream* m_pUniformStream;
|
||||
bool m_bHaveValue;
|
||||
float m_flRandomValue;
|
||||
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A couple of convenience functions to access the library's global uniform stream
|
||||
//-----------------------------------------------------------------------------
|
||||
void RandomSeed(int iSeed);
|
||||
float RandomFloat(float flMinVal = 0.0f, float flMaxVal = 1.0f);
|
||||
float RandomFloatExp(float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f);
|
||||
int RandomInt(int iMinVal, int iMaxVal);
|
||||
float RandomGaussianFloat(float flMean = 0.0f, float flStdDev = 1.0f);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Installs a global random number generator, which will affect the Random functions above
|
||||
//-----------------------------------------------------------------------------
|
||||
void InstallUniformRandomStream(IUniformRandomStream* pStream);
|
||||
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif // VSTDLIB_RANDOM_H
|
Loading…
x
Reference in New Issue
Block a user