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/>.
19 #include "nel/3d/ps_float.h"
20 #include "nel/3d/ps_register_float_attribs.h"
21 #include "nel/misc/fast_floor.h"
30 /////////////////////////////////////
31 // CPSFloatGradient implementation //
32 /////////////////////////////////////
34 CPSFloatGradient::CPSFloatGradient(const float *floatTab
, uint32 nbValues
, uint32 nbStages
, float nbCycles
)
35 : CPSValueGradient
<float>(nbCycles
)
37 _F
.setValues(floatTab
, nbValues
, nbStages
) ;
41 ////////////////////////////////////////////
42 // CPSFloatBezierCurve implementation //
43 ////////////////////////////////////////////
45 CPSFloatCurveFunctor::CPSFloatCurveFunctor() : _NumSamples(0), _Smoothing(true)
48 _CtrlPoints.push_back(CCtrlPoint(0, 0.5f));
49 _CtrlPoints.push_back(CCtrlPoint(1, 0.5f));
54 ///=======================================================================================
55 void CPSFloatCurveFunctor::sortPoints(void)
57 std::sort(_CtrlPoints
.begin(), _CtrlPoints
.end());
60 ///=======================================================================================
61 void CPSFloatCurveFunctor::addControlPoint(const CCtrlPoint
&ctrlPoint
)
63 _CtrlPoints
.push_back(ctrlPoint
);
68 ///=======================================================================================
69 const CPSFloatCurveFunctor::CCtrlPoint
&CPSFloatCurveFunctor::getControlPoint(uint index
) const
71 return _CtrlPoints
[index
];
74 ///=======================================================================================
75 void CPSFloatCurveFunctor::setCtrlPoint(uint index
, const CCtrlPoint
&ctrlPoint
)
77 nlassert(ctrlPoint
.Date
>= 0 && ctrlPoint
.Date
<= 1);
78 _CtrlPoints
[index
] = ctrlPoint
;
83 ///=======================================================================================
84 void CPSFloatCurveFunctor::removeCtrlPoint(uint index
)
86 nlassert(_CtrlPoints
.size() > 1);
87 _CtrlPoints
.erase(_CtrlPoints
.begin() + index
);
91 ///=======================================================================================
92 void CPSFloatCurveFunctor::setNumSamples(uint32 numSamples
)
94 nlassert(numSamples
> 0);
95 _NumSamples
= numSamples
;
99 ///=======================================================================================
100 float CPSFloatCurveFunctor::getValue(float date
) const
102 if (_CtrlPoints
.empty()) return 0.f
;
103 NLMISC::clamp(date
, 0, 1);
104 // find a key that has a higher value
105 CPSVector
<CCtrlPoint
>::V::const_iterator it
= _CtrlPoints
.begin();
106 while ( it
!= _CtrlPoints
.end() && it
->Date
<= date
) ++it
;
108 if (it
== _CtrlPoints
.begin()) return _CtrlPoints
[0].Value
;
109 if (it
== _CtrlPoints
.end()) return _CtrlPoints
[_CtrlPoints
.size() - 1].Value
;
110 CPSVector
<CCtrlPoint
>::V::const_iterator precIt
= it
- 1;
111 if (precIt
->Date
== it
->Date
) return 0.5f
* (precIt
->Value
+ it
->Value
);
112 const float lambda
= (date
- precIt
->Date
) / (it
->Date
- precIt
->Date
);
113 if (!_Smoothing
) // linear interpolation
115 return lambda
* it
->Value
+ (1.f
- lambda
) * precIt
->Value
;
117 else // hermite interpolation
119 float width
= it
->Date
- precIt
->Date
;
120 uint index
= (uint
)(precIt
- _CtrlPoints
.begin());
121 float t1
= getSlope(index
) * width
, t2
= getSlope(index
+ 1) * width
;
122 const float lambda2
= NLMISC::sqr(lambda
);
123 const float lambda3
= lambda2
* lambda
;
124 const float h1
= 2 * lambda3
- 3 * lambda2
+ 1;
125 const float h2
= - 2 * lambda3
+ 3 * lambda2
;
126 const float h3
= lambda3
- 2 * lambda2
+ lambda
;
127 const float h4
= lambda3
- lambda2
;
129 return h1
* precIt
->Value
+ h2
* it
->Value
+ h3
* t1
+ h4
* t2
;
133 ///=======================================================================================
134 void CPSFloatCurveFunctor::updateTab(void)
136 float step
= 1.f
/ _NumSamples
;
138 _Tab
.resize(_NumSamples
+ 1);
140 for (k
= 0; k
<= _NumSamples
; ++k
)
142 _Tab
[k
] = getValue(d
);
145 _MinValue
= _MaxValue
= _Tab
[0];
146 for (k
= 1; k
<= _NumSamples
; ++k
)
148 _MinValue
= std::min(_MinValue
, _Tab
[k
]);
149 _MaxValue
= std::max(_MaxValue
, _Tab
[k
]);
153 ///=======================================================================================
154 void CPSFloatCurveFunctor::serial(NLMISC::IStream
&f
)
157 f
.serial(_NumSamples
, _Smoothing
);
158 f
.serialCont(_CtrlPoints
);
165 ///=======================================================================================
166 float CPSFloatCurveFunctor::getSlope(uint index
) const
168 // tangent for first point
171 return _CtrlPoints
[1].Date
!= _CtrlPoints
[0].Date
? (_CtrlPoints
[1].Value
- _CtrlPoints
[0].Value
)
172 / (_CtrlPoints
[1].Date
- _CtrlPoints
[0].Date
)
176 // tangent for last point
177 if (index
== _CtrlPoints
.size() - 1)
179 return _CtrlPoints
[index
].Date
!= _CtrlPoints
[index
- 1].Date
? (_CtrlPoints
[index
].Value
- _CtrlPoints
[index
- 1].Value
)
180 / (_CtrlPoints
[index
].Date
- _CtrlPoints
[index
- 1].Date
)
184 // tangent for other points
185 return _CtrlPoints
[index
+ 1].Date
!= _CtrlPoints
[index
- 1].Date
? (_CtrlPoints
[index
+ 1].Value
- _CtrlPoints
[index
- 1].Value
)
186 / (_CtrlPoints
[index
+ 1].Date
- _CtrlPoints
[index
- 1].Date
)
190 ///=======================================================================================
191 void CPSFloatCurveFunctor::enableSmoothing(bool enable
/* = true*/)
197 ///=======================================================================================
198 void PSRegisterFloatAttribs()
200 NLMISC_REGISTER_CLASS(CPSFloatBlender
);
201 NLMISC_REGISTER_CLASS(CPSFloatGradient
);
202 NLMISC_REGISTER_CLASS(CPSFloatMemory
);
203 NLMISC_REGISTER_CLASS(CPSFloatBinOp
);
204 NLMISC_REGISTER_CLASS(CPSFloatCurve
);