225 lines
5.7 KiB
C++
225 lines
5.7 KiB
C++
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
|
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
|
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
|
|
|
#ifndef CM_RANDOM_H
|
|
#define CM_RANDOM_H
|
|
|
|
#include "foundation/PxQuat.h"
|
|
#include "foundation/PxVec3.h"
|
|
#define TEST_MAX_RAND 0xffff
|
|
|
|
namespace physx
|
|
{
|
|
namespace Cm
|
|
{
|
|
class BasicRandom
|
|
{
|
|
public:
|
|
BasicRandom(PxU32 seed = 0) : mRnd(seed) {}
|
|
~BasicRandom() {}
|
|
|
|
PX_FORCE_INLINE void setSeed(PxU32 seed) { mRnd = seed; }
|
|
PX_FORCE_INLINE PxU32 getCurrentValue() const { return mRnd; }
|
|
PxU32 randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; }
|
|
|
|
PX_FORCE_INLINE PxU32 rand() { return randomize() & 0xffff; }
|
|
PX_FORCE_INLINE PxU32 rand32() { return randomize() & 0xffffffff; }
|
|
|
|
PxF32 rand(PxF32 a, PxF32 b)
|
|
{
|
|
const PxF32 r = rand32() / (static_cast<PxF32>(0xffffffff));
|
|
return r * (b - a) + a;
|
|
}
|
|
|
|
PxI32 rand(PxI32 a, PxI32 b)
|
|
{
|
|
return a + static_cast<PxI32>(rand32() % (b - a));
|
|
}
|
|
|
|
PxF32 randomFloat()
|
|
{
|
|
return rand() / (static_cast<PxF32>(0xffff)) - 0.5f;
|
|
}
|
|
PxF32 randomFloat32()
|
|
{
|
|
return rand32() / (static_cast<PxF32>(0xffffffff)) - 0.5f;
|
|
}
|
|
|
|
PxF32 randomFloat32(PxReal a, PxReal b) { return rand32() / PxF32(0xffffffff)*(b - a) + a; }
|
|
void unitRandomPt(physx::PxVec3& v)
|
|
{
|
|
v = unitRandomPt();
|
|
}
|
|
|
|
void unitRandomQuat(physx::PxQuat& v)
|
|
{
|
|
v = unitRandomQuat();
|
|
}
|
|
|
|
PxVec3 unitRandomPt()
|
|
{
|
|
PxVec3 v;
|
|
do
|
|
{
|
|
v.x = randomFloat();
|
|
v.y = randomFloat();
|
|
v.z = randomFloat();
|
|
} while (v.normalize() < 1e-6f);
|
|
return v;
|
|
}
|
|
|
|
PxQuat unitRandomQuat()
|
|
{
|
|
PxQuat v;
|
|
do
|
|
{
|
|
v.x = randomFloat();
|
|
v.y = randomFloat();
|
|
v.z = randomFloat();
|
|
v.w = randomFloat();
|
|
} while (v.normalize() < 1e-6f);
|
|
|
|
return v;
|
|
}
|
|
|
|
private:
|
|
PxU32 mRnd;
|
|
};
|
|
|
|
//--------------------------------------
|
|
// Fast, very good random numbers
|
|
//
|
|
// Period = 2^249
|
|
//
|
|
// Kirkpatrick, S., and E. Stoll, 1981; A Very Fast Shift-Register
|
|
// Sequence Random Number Generator, Journal of Computational Physics,
|
|
// V. 40.
|
|
//
|
|
// Maier, W.L., 1991; A Fast Pseudo Random Number Generator,
|
|
// Dr. Dobb's Journal, May, pp. 152 - 157
|
|
|
|
class RandomR250
|
|
{
|
|
public:
|
|
RandomR250(PxI32 s)
|
|
{
|
|
setSeed(s);
|
|
}
|
|
|
|
void setSeed(PxI32 s)
|
|
{
|
|
BasicRandom lcg(s);
|
|
mIndex = 0;
|
|
|
|
PxI32 j;
|
|
for (j = 0; j < 250; j++) // fill r250 buffer with bit values
|
|
mBuffer[j] = lcg.randomize();
|
|
|
|
for (j = 0; j < 250; j++) // set some MSBs to 1
|
|
if (lcg.randomize() > 0x40000000L)
|
|
mBuffer[j] |= 0x80000000L;
|
|
|
|
PxU32 msb = 0x80000000; // turn on diagonal bit
|
|
PxU32 mask = 0xffffffff; // turn off the leftmost bits
|
|
|
|
for (j = 0; j < 32; j++)
|
|
{
|
|
const PxI32 k = 7 * j + 3; // select a word to operate on
|
|
mBuffer[k] &= mask; // turn off bits left of the diagonal
|
|
mBuffer[k] |= msb; // turn on the diagonal bit
|
|
mask >>= 1;
|
|
msb >>= 1;
|
|
}
|
|
}
|
|
|
|
PxU32 randI()
|
|
{
|
|
PxI32 j;
|
|
|
|
// wrap pointer around
|
|
if (mIndex >= 147) j = mIndex - 147;
|
|
else j = mIndex + 103;
|
|
|
|
const PxU32 new_rand = mBuffer[mIndex] ^ mBuffer[j];
|
|
mBuffer[mIndex] = new_rand;
|
|
|
|
// increment pointer for next time
|
|
if (mIndex >= 249) mIndex = 0;
|
|
else mIndex++;
|
|
|
|
return new_rand >> 1;
|
|
}
|
|
|
|
PxReal randUnit()
|
|
{
|
|
PxU32 mask = (1 << 23) - 1;
|
|
return PxF32(randI()&(mask)) / PxF32(mask);
|
|
}
|
|
|
|
PxReal rand(PxReal lower, PxReal upper)
|
|
{
|
|
return lower + randUnit() * (upper - lower);
|
|
}
|
|
|
|
private:
|
|
PxU32 mBuffer[250];
|
|
PxI32 mIndex;
|
|
};
|
|
|
|
static RandomR250 gRandomR250(0x95d6739b);
|
|
|
|
PX_FORCE_INLINE PxU32 Rand()
|
|
{
|
|
return gRandomR250.randI() & TEST_MAX_RAND;
|
|
}
|
|
|
|
PX_FORCE_INLINE PxF32 Rand(PxF32 a, PxF32 b)
|
|
{
|
|
const PxF32 r = static_cast<PxF32>(Rand()) / (static_cast<PxF32>(TEST_MAX_RAND));
|
|
return r * (b - a) + a;
|
|
}
|
|
PX_FORCE_INLINE PxF32 RandLegacy(PxF32 a, PxF32 b)
|
|
{
|
|
const PxF32 r = static_cast<PxF32>(Rand()) / (static_cast<PxF32>(0x7fff) + 1.0f);
|
|
return r * (b - a) + a;
|
|
}
|
|
//returns numbers from [a, b-1]
|
|
PX_FORCE_INLINE PxI32 Rand(PxI32 a, PxI32 b)
|
|
{
|
|
return a + static_cast<PxI32>(Rand() % (b - a));
|
|
}
|
|
|
|
PX_FORCE_INLINE void SetSeed(PxU32 seed)
|
|
{
|
|
gRandomR250.setSeed(seed);
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|