# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

ps_attrib_maker_template.h

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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  *      In this file, we define several template that helps to create attributes maker such as gradient (of float, int, vector etc) 
00038  * attributes maker are used in the particle system to generate values, such as size, color etc. see ps_attrib_maker.h
00039  * for more informations
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);      // a cast to T is necessary, because 
00117                                                                                                                 // the specialization couls be done with integer
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         // serialization is done by CPSAttribMakerT
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         // a table of Values that interpolate the values given
00361         std::vector<T> _Tab;
00362 
00363 
00364         // number of interpolated value between each 'key'
00365         uint32 _NbStages;
00366 
00367         // total number of value in the tab
00368         uint32 _NbValues;
00369 
00370 
00371         // the max value
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 // methods implementations //
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         // copy the tab performing linear interpolation between values given in parameter
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                         // use the right version of the template function PSValueBlend
00436                         // to do the job
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                 // reload the number of keys 
00457 
00458                 uint32 numVal;
00459                 f.serial(numVal);               
00460                 _NbValues = (numVal - 1) * _NbStages;
00461 
00462                 // create the table on the stack for small gradient
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                 // saves the number of keys
00485                 uint32 numKeyValues = getNumValues();
00486                 f.serial(numKeyValues);
00487 
00488 
00489                 // save each key                
00490                 for (uint32 k = 0; k < numKeyValues; ++k)
00491                 {
00492                         f.serial(_Tab[k * _NbStages]);                  
00493                 }
00494         }
00495 }
00496 
00497 } // NL3D
00498 
00499 
00500 #endif // NL_PS_ATTRIB_MAKER_TEMPLATE_H
00501 
00502 /* End of ps_attrib_maker_template.h */