Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / nel / src / misc / mouse_smoother.cpp
bloba92cbca6ee4f6cec5adc85ede1ffdb22114b708b
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdmisc.h"
18 #include "nel/misc/mouse_smoother.h"
20 #ifdef DEBUG_NEW
21 #define new DEBUG_NEW
22 #endif
24 namespace NLMISC
27 // *******************************************************************************************
28 /// build some hermite spline value, with the given points and tangents
29 static inline void BuildHermiteVector(const NLMISC::CVector2f &P0,
30 const NLMISC::CVector2f &P1,
31 const NLMISC::CVector2f &T0,
32 const NLMISC::CVector2f &T1,
33 NLMISC::CVector2f &dest,
34 float lambda
37 const float lambda2 = lambda * lambda;
38 const float lambda3 = lambda2 * lambda;
39 const float h1 = 2 * lambda3 - 3 * lambda2 + 1;
40 const float h2 = - 2 * lambda3 + 3 * lambda2;
41 const float h3 = lambda3 - 2 * lambda2 + lambda;
42 const float h4 = lambda3 - lambda2;
43 /// just avoid some ctor calls here...
44 dest.set(h1 * P0.x + h2 * P1.x + h3 * T0.x + h4 * T1.x,
45 h1 * P0.y + h2 * P1.y + h3 * T0.y + h4 * T1.y);
48 // *******************************************************************************************
49 CMouseSmoother::CMouseSmoother(double samplingPeriod /*=0.2f*/)
51 nlassert(samplingPeriod > 0);
52 _SamplingPeriod = samplingPeriod;
53 _Init = false;
57 // *******************************************************************************************
58 void CMouseSmoother::setSamplingPeriod(double period)
60 if (period == _SamplingPeriod) return;
61 reset();
62 nlassert(_SamplingPeriod > 0);
63 _SamplingPeriod = period;
67 // *******************************************************************************************
68 NLMISC::CVector2f CMouseSmoother::samplePos(const CVector2f &wantedPos, double date)
70 if (!_Init)
72 _Sample[0] = _Sample[1] = _Sample[2] = _Sample[3] = CSample(date, wantedPos);
73 _Init = true;
75 else
77 // see if enough time has elapsed since last sample
78 if (date - _Sample[3].Date >= _SamplingPeriod)
80 uint numSamples = (uint) floor((date - _Sample[3].Date) / _SamplingPeriod);
81 numSamples = std::min(numSamples, (uint) 4);
82 for(uint k = 0; k < numSamples; ++k)
84 // add a new sample
85 _Sample[0] = _Sample[1];
86 _Sample[1] = _Sample[2];
87 _Sample[2] = _Sample[3];
88 _Sample[3] = CSample(date, wantedPos);
91 else if (date == _Sample[3].Date)
93 // update cur pos
94 _Sample[3] = CSample(date, wantedPos);
97 if (_Sample[1].Pos.x == _Sample[2].Pos.x &&
98 _Sample[1].Pos.y == _Sample[2].Pos.y
101 // special case : if pointer hasn't moved, allow a discontinuity of speed
102 return _Sample[2].Pos;
104 double evalDate = date - 2 * _SamplingPeriod;
105 clamp(evalDate, _Sample[1].Date, _Sample[2].Date);
106 CVector2f t0;
107 double dt = _Sample[2].Date - _Sample[1].Date;
108 if (_Sample[2].Date != _Sample[0].Date)
110 t0 = (float) dt * (_Sample[2].Pos - _Sample[0].Pos) / (float) (_Sample[2].Date - _Sample[0].Date);
112 else
114 t0= NLMISC::CVector::Null;
116 CVector2f t1;
117 if (_Sample[3].Date != _Sample[1].Date)
119 t1 = (float) dt * (_Sample[3].Pos - _Sample[1].Pos) / (float) (_Sample[3].Date - _Sample[1].Date);
121 else
123 t1= NLMISC::CVector::Null;
125 NLMISC::CVector2f result;
126 if (dt == 0) return _Sample[2].Pos;
127 BuildHermiteVector(_Sample[1].Pos, _Sample[2].Pos, t0, t1, result, (float) ((evalDate - _Sample[1].Date) / dt));
128 return result;
131 // *******************************************************************************************
132 void CMouseSmoother::reset()
134 _Init = false;
137 } // NLMISC