00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_PS_ATTRIB_MAKER_TEMPLATE_H
00027 #define NL_PS_ATTRIB_MAKER_TEMPLATE_H
00028
00029 #include "nel/misc/types_nl.h"
00030 #include "3d/ps_attrib_maker_helper.h"
00031 #include "3d/ps_plane_basis.h"
00032 #include "3d/fast_floor.h"
00033
00034 namespace NL3D {
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00050 template <typename T>
00051 inline T PSValueBlend(const T &t1, const T &t2, float alpha)
00052 {
00053 return T(alpha * t2 + (1.f - alpha) * t1);
00054 }
00055
00056
00058 template <>
00059 inline NLMISC::CRGBA PSValueBlend(const NLMISC::CRGBA &t1, const NLMISC::CRGBA &t2, float alpha)
00060 {
00061 NLMISC::CRGBA result;
00062 result.blendFromui(t1, t2, OptFastFloor(255.0f * alpha));
00063 return result;
00064 }
00065
00066
00068 template <>
00069 inline CPlaneBasis PSValueBlend(const CPlaneBasis &t1, const CPlaneBasis &t2, float alpha)
00070 {
00071 return CPlaneBasis(PSValueBlend(t1.getNormal(), t2.getNormal(), alpha));
00072 }
00073
00074
00076 template <typename T> struct CPSValueBlendFuncBase
00077 {
00078 virtual void getValues(T &startValue, T &endValue) const = 0;
00079 virtual void setValues(T startValue, T endValue) = 0;
00080 };
00081
00082
00083
00093 template <typename T> class CPSValueBlendFunc : public CPSValueBlendFuncBase<T>
00094 {
00095 public:
00097
00098
00099 CPSValueBlendFunc() {}
00100
00102 void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00103 {
00104 f.serialVersion(1);
00105 f.serial(_StartValue, _EndValue);
00106 }
00108
00110 #ifdef NL_OS_WINDOWS
00111 __forceinline
00112 #endif
00113 T operator()(TAnimationTime time) const
00114 {
00115
00116 return PSValueBlend(_StartValue, _EndValue, time);
00117
00118 }
00119
00121
00122
00123 virtual void getValues(T &startValue, T &endValue) const
00124 {
00125 startValue = (*this)(0);
00126 endValue = (*this)(1);
00127 }
00128
00130 virtual void setValues(T startValue, T endValue)
00131 {
00132 _StartValue = startValue;
00133 _EndValue = endValue;
00134 }
00135
00137 T getMaxValue(void) const
00138 {
00139 return std::max((*this)(0), (*this)(1));
00140 }
00142
00143 protected:
00144 T _StartValue, _EndValue;
00145 };
00146
00147
00158 template <typename T> class CPSValueBlender : public CPSAttribMakerT<T, CPSValueBlendFunc<T> >
00159 {
00160 public:
00165 CPSValueBlender(float nbCycles) : CPSAttribMakerT<T, CPSValueBlendFunc<T> >(nbCycles)
00166 {
00167 }
00168
00169 virtual T getMaxValue(void) const { return _F.getMaxValue(); }
00170
00171
00172 };
00173
00174
00175
00176
00188 template <typename T, const uint n> class CPSValueBlendSampleFunc : public CPSValueBlendFuncBase<T>
00189 {
00190 public:
00192 #ifdef NL_OS_WINDOWS
00193 __forceinline
00194 #endif
00195 T operator()(TAnimationTime time) const
00196 {
00197
00198 return _Values[OptFastFloor(time * n)];
00199 }
00200
00202
00203 virtual void getValues(T &startValue, T &endValue) const
00204 {
00205 startValue = _Values[0];
00206 endValue = _Values[n];
00207 }
00208
00210
00211 virtual void setValues(T startValue, T endValue)
00212 {
00213 float step = 1.f / n;
00214 float alpha = 0.0f;
00215 for (uint k = 0; k < n; ++k)
00216 {
00217 _Values[k] = PSValueBlend(startValue, endValue, alpha);
00218 alpha += step;
00219 }
00220 _Values[n] = endValue;
00221 }
00222
00224 CPSValueBlendSampleFunc() {}
00225
00227 void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00228 {
00229 f.serialVersion(1);
00230 if (f.isReading())
00231 {
00232 T t1, t2;
00233 f.serial(t1, t2);
00234 setValues(t1, t2);
00235 }
00236 else
00237 {
00238 f.serial(_Values[0], _Values[n]);
00239 }
00240 }
00241
00242 T getMaxValue(void) const
00243 {
00244 return std::max((*this)(0), (*this)(1));
00245 }
00246
00247 protected:
00248 T _Values[n + 1];
00249 };
00250
00251
00252
00253
00259 template <typename T, const uint n> class CPSValueBlenderSample : public CPSAttribMakerT<T, CPSValueBlendSampleFunc<T, n> >
00260 {
00261 public:
00262
00267 CPSValueBlenderSample(float nbCycles) : CPSAttribMakerT<T, CPSValueBlendSampleFunc<T, n> >(nbCycles)
00268 {
00269 }
00270 virtual T getMaxValue(void) const { return _F.getMaxValue(); }
00271 };
00272
00273
00274
00275
00283 template <typename T> class CPSValueGradientFunc
00284 {
00285 public:
00287 #ifdef NL_OS_WINDOWS
00288 __forceinline
00289 #endif
00290 T operator()(TAnimationTime time) const
00291 {
00292 return _Tab[OptFastFloor(time * _NbValues)];
00293 }
00294
00296 void getValues(T *tab) const
00297 {
00298 nlassert(tab);
00299 T *pt = tab;
00300 uint32 src = 0;
00301 for (uint32 k = 0; k <= (_NbValues / _NbStages); ++k, src = src + _NbStages)
00302 {
00303 *pt++ =_Tab[src];
00304 }
00305 }
00306
00308 T getValue(uint index) const
00309 {
00310 nlassert(index < getNumValues());
00311 return _Tab[index * _NbStages];
00312 }
00313
00314
00315
00316
00317 uint32 getNumValues(void) const { return (_NbValues / _NbStages) + 1; }
00318
00327 inline void setValues(const T *ValueTab, uint32 numValues, uint32 nbStages);
00328
00330 uint32 getNumStages(void) const { return _NbStages; }
00331
00333 void setNumStages(uint32 numStages)
00334 {
00335 std::vector<T> v;
00336 v.resize(getNumValues());
00337 getValues(&v[0]);
00338 setValues(&v[0], getNumValues(), numStages);
00339 }
00340
00342 virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00343
00344
00345 T getMaxValue(void) const
00346 {
00347 return _MaxValue;
00348 }
00349
00351 CPSValueGradientFunc() : _NbStages(0), _NbValues(0)
00352 {
00353 }
00355 virtual ~CPSValueGradientFunc() {}
00356
00357
00358
00359 protected:
00360
00361 std::vector<T> _Tab;
00362
00363
00364
00365 uint32 _NbStages;
00366
00367
00368 uint32 _NbValues;
00369
00370
00371
00372 T _MaxValue;
00373 };
00374
00375
00376
00377
00383 template <typename T> class CPSValueGradient : public CPSAttribMakerT<T, CPSValueGradientFunc<T> >
00384 {
00385 public:
00386
00391 CPSValueGradient(float nbCycles) : CPSAttribMakerT<T, CPSValueGradientFunc<T> >(nbCycles)
00392 {
00393 }
00394 virtual T getMaxValue(void) const { return _F.getMaxValue(); }
00395 };
00396
00397
00398
00399
00401
00403
00404
00405
00406
00407 template <typename T>
00408 inline void CPSValueGradientFunc<T>::setValues(const T *valueTab, uint32 numValues, uint32 nbStages)
00409 {
00410 nlassert(numValues > 1);
00411 nlassert(nbStages > 0);
00412
00413 _NbStages = nbStages;
00414 _MaxValue = valueTab[0];
00415 _NbValues = (numValues - 1) * nbStages;
00416 _Tab.resize(_NbValues + 1);
00417
00418
00419 float step = 1.0f / float(nbStages);
00420 float alpha;
00421
00422 std::vector<T>::iterator dest = _Tab.begin();
00423
00424 for (uint32 k = 0; k < (numValues - 1); ++k)
00425 {
00426 if (!(valueTab[k] < _MaxValue))
00427 {
00428 _MaxValue = valueTab[k];
00429 }
00430
00431 alpha = 0;
00432
00433 for(uint32 l = 0; l < nbStages; ++l)
00434 {
00435
00436
00437 *dest++ = PSValueBlend(valueTab[k], valueTab[k + 1], alpha);
00438 alpha += step;
00439 }
00440 }
00441 *dest++ = valueTab[numValues - 1];
00442 }
00443
00444
00445
00446
00447
00448 template <typename T>
00449 void CPSValueGradientFunc<T>::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00450 {
00451 f.serialVersion(1);
00452 f.serial(_NbStages);
00453 if (f.isReading())
00454 {
00455
00456
00457
00458 uint32 numVal;
00459 f.serial(numVal);
00460 _NbValues = (numVal - 1) * _NbStages;
00461
00462
00463 if (numVal < 256)
00464 {
00465 T tab[256];
00466 for (uint32 k = 0; k < numVal; ++k)
00467 {
00468 f.serial(tab[k]);
00469 }
00470 setValues(tab, numVal, _NbStages);
00471 }
00472 else
00473 {
00474 std::vector<T> tab(numVal);
00475 for (uint32 k = 0; k < numVal; ++k)
00476 {
00477 f.serial(tab[k]);
00478 }
00479 setValues(&tab[0], numVal, _NbStages);
00480 }
00481 }
00482 else
00483 {
00484
00485 uint32 numKeyValues = getNumValues();
00486 f.serial(numKeyValues);
00487
00488
00489
00490 for (uint32 k = 0; k < numKeyValues; ++k)
00491 {
00492 f.serial(_Tab[k * _NbStages]);
00493 }
00494 }
00495 }
00496
00497 }
00498
00499
00500 #endif // NL_PS_ATTRIB_MAKER_TEMPLATE_H
00501
00502