1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
18 #include "nel/misc/mouse_smoother.h"
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
,
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
;
57 // *******************************************************************************************
58 void CMouseSmoother::setSamplingPeriod(double period
)
60 if (period
== _SamplingPeriod
) return;
62 nlassert(_SamplingPeriod
> 0);
63 _SamplingPeriod
= period
;
67 // *******************************************************************************************
68 NLMISC::CVector2f
CMouseSmoother::samplePos(const CVector2f
&wantedPos
, double date
)
72 _Sample
[0] = _Sample
[1] = _Sample
[2] = _Sample
[3] = CSample(date
, wantedPos
);
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
)
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
)
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
);
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
);
114 t0
= NLMISC::CVector::Null
;
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
);
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
));
131 // *******************************************************************************************
132 void CMouseSmoother::reset()