238 lines
7.3 KiB
C++
238 lines
7.3 KiB
C++
|
/*
|
||
|
-----------------------------------------------------------------------------
|
||
|
This source file is part of OGRE
|
||
|
(Object-oriented Graphics Rendering Engine)
|
||
|
For the latest info, see http://www.ogre3d.org/
|
||
|
|
||
|
Copyright (c) 2000-2009 Torus Knot Software Ltd
|
||
|
|
||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
of this software and associated documentation files (the "Software"), to deal
|
||
|
in the Software without restriction, including without limitation the rights
|
||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
copies of the Software, and to permit persons to whom the Software is
|
||
|
furnished to do so, subject to the following conditions:
|
||
|
|
||
|
The above copyright notice and this permission notice shall be included in
|
||
|
all copies or substantial portions of the Software.
|
||
|
|
||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
THE SOFTWARE.
|
||
|
-----------------------------------------------------------------------------
|
||
|
*/
|
||
|
#include "stdneb.h"
|
||
|
#include "memory/memory.h"
|
||
|
#include "OgreMath.h"
|
||
|
#include "asm_math.h"
|
||
|
#include "OgreVector3.h"
|
||
|
#include "OgreVector4.h"
|
||
|
|
||
|
|
||
|
namespace Ogre
|
||
|
{
|
||
|
|
||
|
const Real Math::POS_INFINITY = std::numeric_limits<Real>::infinity();
|
||
|
const Real Math::NEG_INFINITY = -std::numeric_limits<Real>::infinity();
|
||
|
const Real Math::OGRE_PI = Real( 4.0 * atan( 1.0 ) );
|
||
|
const Real Math::TWO_PI = Real( 2.0 * OGRE_PI );
|
||
|
const Real Math::HALF_PI = Real( 0.5 * OGRE_PI );
|
||
|
const Real Math::fDeg2Rad = OGRE_PI / Real(180.0);
|
||
|
const Real Math::fRad2Deg = Real(180.0) / OGRE_PI;
|
||
|
const Real Math::LOG2 = log(Real(2.0));
|
||
|
|
||
|
int Math::mTrigTableSize;
|
||
|
Math::AngleUnit Math::msAngleUnit;
|
||
|
|
||
|
Real Math::mTrigTableFactor;
|
||
|
Real *Math::mSinTable = NULL;
|
||
|
Real *Math::mTanTable = NULL;
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
Math::Math( unsigned int trigTableSize )
|
||
|
{
|
||
|
msAngleUnit = AU_DEGREE;
|
||
|
|
||
|
mTrigTableSize = trigTableSize;
|
||
|
mTrigTableFactor = mTrigTableSize / Math::TWO_PI;
|
||
|
|
||
|
mSinTable = n_new_array(float, mTrigTableSize);
|
||
|
mTanTable = n_new_array(float, mTrigTableSize);
|
||
|
|
||
|
buildTrigTables();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
Math::~Math()
|
||
|
{
|
||
|
n_delete_array(mSinTable);
|
||
|
n_delete_array(mTanTable);
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
void Math::buildTrigTables(void)
|
||
|
{
|
||
|
// Build trig lookup tables
|
||
|
// Could get away with building only PI sized Sin table but simpler this
|
||
|
// way. Who cares, it'll ony use an extra 8k of memory anyway and I like
|
||
|
// simplicity.
|
||
|
Real angle;
|
||
|
for (int i = 0; i < mTrigTableSize; ++i)
|
||
|
{
|
||
|
angle = Math::TWO_PI * i / mTrigTableSize;
|
||
|
mSinTable[i] = sin(angle);
|
||
|
mTanTable[i] = tan(angle);
|
||
|
}
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::SinTable (Real fValue)
|
||
|
{
|
||
|
// Convert range to index values, wrap if required
|
||
|
int idx;
|
||
|
if (fValue >= 0)
|
||
|
{
|
||
|
idx = int(fValue * mTrigTableFactor) % mTrigTableSize;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
idx = mTrigTableSize - (int(-fValue * mTrigTableFactor) % mTrigTableSize) - 1;
|
||
|
}
|
||
|
|
||
|
return mSinTable[idx];
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::TanTable (Real fValue)
|
||
|
{
|
||
|
// Convert range to index values, wrap if required
|
||
|
int idx = int(fValue *= mTrigTableFactor) % mTrigTableSize;
|
||
|
return mTanTable[idx];
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
int Math::ISign (int iValue)
|
||
|
{
|
||
|
return ( iValue > 0 ? +1 : ( iValue < 0 ? -1 : 0 ) );
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Radian Math::ACos (Real fValue)
|
||
|
{
|
||
|
if ( -1.0 < fValue )
|
||
|
{
|
||
|
if ( fValue < 1.0 )
|
||
|
return Radian(acos(fValue));
|
||
|
else
|
||
|
return Radian(0.0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return Radian(OGRE_PI);
|
||
|
}
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Radian Math::ASin (Real fValue)
|
||
|
{
|
||
|
if ( -1.0 < fValue )
|
||
|
{
|
||
|
if ( fValue < 1.0 )
|
||
|
return Radian(asin(fValue));
|
||
|
else
|
||
|
return Radian(HALF_PI);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return Radian(-HALF_PI);
|
||
|
}
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::Sign (Real fValue)
|
||
|
{
|
||
|
if ( fValue > 0.0 )
|
||
|
return 1.0;
|
||
|
|
||
|
if ( fValue < 0.0 )
|
||
|
return -1.0;
|
||
|
|
||
|
return 0.0;
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::InvSqrt(Real fValue)
|
||
|
{
|
||
|
return Real(asm_rsq(fValue));
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::UnitRandom ()
|
||
|
{
|
||
|
return asm_rand() / asm_rand_max();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::RangeRandom (Real fLow, Real fHigh)
|
||
|
{
|
||
|
return (fHigh-fLow)*UnitRandom() + fLow;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::SymmetricRandom ()
|
||
|
{
|
||
|
return 2.0f * UnitRandom() - 1.0f;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
void Math::setAngleUnit(Math::AngleUnit unit)
|
||
|
{
|
||
|
msAngleUnit = unit;
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Math::AngleUnit Math::getAngleUnit(void)
|
||
|
{
|
||
|
return msAngleUnit;
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::AngleUnitsToRadians(Real angleunits)
|
||
|
{
|
||
|
if (msAngleUnit == AU_DEGREE)
|
||
|
return angleunits * fDeg2Rad;
|
||
|
else
|
||
|
return angleunits;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::RadiansToAngleUnits(Real radians)
|
||
|
{
|
||
|
if (msAngleUnit == AU_DEGREE)
|
||
|
return radians * fRad2Deg;
|
||
|
else
|
||
|
return radians;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::AngleUnitsToDegrees(Real angleunits)
|
||
|
{
|
||
|
if (msAngleUnit == AU_RADIAN)
|
||
|
return angleunits * fRad2Deg;
|
||
|
else
|
||
|
return angleunits;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
Real Math::DegreesToAngleUnits(Real degrees)
|
||
|
{
|
||
|
if (msAngleUnit == AU_RADIAN)
|
||
|
return degrees * fDeg2Rad;
|
||
|
else
|
||
|
return degrees;
|
||
|
}
|
||
|
//-----------------------------------------------------------------------
|
||
|
bool Math::RealEqual( Real a, Real b, Real tolerance )
|
||
|
{
|
||
|
if (fabs(b-a) <= tolerance)
|
||
|
return true;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
}
|