tResponseCurve.h
Engine/source/math/util/tResponseCurve.h
Classes:
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24// Notice: 25// Some of this code originates from an article in AI Game Programming Wisdom 26// by Dave Mark. 27 28#ifndef _TRESPONSECURVE_H_ 29#define _TRESPONSECURVE_H_ 30 31#ifndef _TVECTOR_H_ 32#include "core/util/tVector.h" 33#endif 34 35#ifndef _MMATHFN_H_ 36#include "math/mMathFn.h" 37#endif 38 39#ifndef _SIMOBJECT_H_ 40#include "console/simObject.h" 41#endif 42 43 44// ------------------------------- 45// Represents a sigmoid function 46// Note: not used by ResponseCurve 47// ------------------------------- 48 49class Sigmoid 50{ 51public: 52 Sigmoid( F32 s, F32 m) { _s = s; _m = m; } 53 ~Sigmoid() {}; 54 55 inline F32 get( F32 x ) 56 { 57 F32 pow = -2.0f * ( ( x - _m ) / _s ); 58 F32 y = 1.0f / mPow( 1 + M_CONST_E_F, pow ); 59 return y; 60 } 61 62 F32 _s; 63 F32 _m; 64}; 65 66// ----------------------------------------------------------------------------- 67// Represents a response curve, can query values 68// ----------------------------------------------------------------------------- 69 70template< class T > 71class ResponseCurve 72{ 73public: 74 75 struct Sample 76 { 77 Sample() :mF(0) { dMemset(&mVal, 0, sizeof(mVal)); } 78 Sample( F32 f, const T &val ) : mF(f), mVal(val) {} 79 80 F32 mF; 81 T mVal; 82 }; 83 84 typedef Vector< Sample> SampleList; 85 SampleList mSamples; 86 87 const SampleList& getSamples() { return mSamples; } 88 89 ResponseCurve() {} 90 ResponseCurve( U32 numSamples ) { mSamples.reserve(numSamples); } 91 92 void clear() { mSamples.clear(); } 93 void addPoint( F32 f, const T &val ); 94 //void addPoints( U32 count, F32 f[], const T &val[] ); 95 T getVal( F32 f ) const; 96 S32 setPoint( S32 idx, F32 f, const T &val ); 97 void removePoint( S32 idx ); 98 S32 getSampleCount() const { return mSamples.size(); } 99}; 100 101//----------------------------------------------------------------------------- 102// Adds a new value to the Response Curve, at the position f 103//----------------------------------------------------------------------------- 104template< class T > 105inline void ResponseCurve<T>::addPoint( F32 f, const T &val ) 106{ 107 typename SampleList::iterator iter = mSamples.begin(); 108 for ( ; iter != mSamples.end(); iter++ ) 109 { 110 if ( iter->mF == f ) 111 { 112 Con::warnf( "Warn: ResponseCurve<T>::AddPoint, Duplicate values are not allowed." ); 113 return; 114 } 115 116 if ( iter->mF > f ) 117 break; 118 } 119 120 mSamples.insert( iter, Sample( f, val ) ); 121} 122 123//----------------------------------------------------------------------------- 124// Finds the right value at position f, interpolating between the previous 125// and the following values 126//----------------------------------------------------------------------------- 127template< class T > 128inline T ResponseCurve<T>::getVal( F32 f ) const 129{ 130 T retVal; 131 132 if ( mSamples.empty() ) 133 { 134 retVal = T(); 135 } 136 else 137 { 138 U32 nSamples = mSamples.size(); 139 if ( nSamples == 1 || f <= mSamples[0].mF ) 140 { 141 retVal = mSamples[0].mVal; 142 } 143 else if ( f >= mSamples[nSamples-1].mF ) 144 { 145 retVal = mSamples[nSamples-1].mVal; 146 } 147 else 148 { 149 U32 i = 1; 150 while ( i < (nSamples-1) && mSamples[i].mF < f ) 151 ++i; 152 153 // Interpolate between m_Samples[i-1] and m_Samples[i] 154 F32 fSampleMin = mSamples[i-1].mF; 155 F32 fSampleMax = mSamples[i].mF; 156 AssertWarn(fSampleMin != fSampleMax, "fSampleMin should not equal fSampleMax" ); 157 158 F32 t = (f - fSampleMin) / (fSampleMax - fSampleMin); 159 retVal = mSamples[i-1].mVal + ( mSamples[i].mVal - mSamples[i-1].mVal) * t; 160 } 161 } 162 163 return retVal; 164} 165 166template< class T > 167inline S32 ResponseCurve< T >::setPoint( S32 idx, F32 f, const T &val ) 168{ 169 mSamples.erase( idx ); 170 171 typename SampleList::iterator iter = mSamples.begin(); 172 for ( ; iter != mSamples.end(); iter++ ) 173 { 174 if ( iter->mF == f ) 175 { 176 Con::warnf( "Warn: ResponseCurve<T>::AddPoint, Duplicate values are not allowed." ); 177 return -1; 178 } 179 180 if ( iter->mF > f ) 181 break; 182 } 183 184 mSamples.insert( iter, Sample( f, val ) ); 185 186 return (S32)( iter - mSamples.begin() ); 187} 188 189 190class FloatCurve : public ResponseCurve<F32> 191{ 192public: 193 FloatCurve() {} 194}; 195 196 197// ----------------------------------------------- 198// A ResponseCurve<F32> wrapped as a SimObject 199// ----------------------------------------------- 200 201class SimResponseCurve : public SimObject 202{ 203 typedef SimObject Parent; 204 205public: 206 207 SimResponseCurve(); 208 //~SimResponseCurve(); 209 210 DECLARE_CONOBJECT( SimResponseCurve ); 211 212 virtual bool onAdd(); 213 virtual void onRemove(); 214 215 void addPoint( F32 value, F32 time ); 216 F32 getValue( F32 time ); 217 void clear(); 218 219 ResponseCurve<F32> mCurve; 220}; 221 222 223// A networked-datablock version of ResponseCurve 224/* 225class ResponseCurveData : public SimDataBlock 226{ 227 typedef SimDataBlock Parent; 228 229public: 230 231 ResponseCurveData(); 232 //~ResponseCurveData(); 233 234 DECLARE_CONOBJECT( ResponseCurveData ); 235 236 virtual bool onAdd(); 237 virtual void onRemove(); 238 239 240 void addPoint( F32 value, F32 time ); 241 F32 getValue( F32 time ); 242 void clear(); 243 244 ResponseCurve<F32> mCurve; 245}; 246*/ 247 248#endif 249