Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGParticles.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 //---------------------------------------------------------------------------
00040 //  Includes
00041 //---------------------------------------------------------------------------
00042 
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 
00046 #include <OSGConfig.h>
00047 #include <OSGAction.h>
00048 #include <OSGDrawAction.h>
00049 #include <OSGRenderAction.h>
00050 #include <OSGMaterial.h>
00051 #include <OSGGeoPropPtrs.h>
00052 #include <OSGCamera.h>
00053 
00054 #include "OSGParticles.h"
00055 
00056 #include <algorithm>
00057 
00058 OSG_USING_NAMESPACE
00059 
00060 /***************************************************************************\
00061  *                            Description                                  *
00062 \***************************************************************************/
00063 
00071 /***************************************************************************\
00072  *                           Class methods                                 *
00073 \***************************************************************************/
00074 
00075 void Particles::initMethod (void)
00076 {
00077     DrawAction::registerEnterDefault( getClassType(),
00078         osgTypedMethodFunctor2BaseCPtrRef<Action::ResultE,
00079                                           ParticlesPtr  ,
00080                                           CNodePtr      ,
00081                                           Action       *>
00082                                        (&MaterialDrawable::drawActionHandler));
00083 
00084     RenderAction::registerEnterDefault( getClassType(),
00085         osgTypedMethodFunctor2BaseCPtrRef<Action::ResultE,
00086                                           ParticlesPtr  ,
00087                                           CNodePtr      ,
00088                                           Action       *>
00089                                        (&MaterialDrawable::renderActionHandler));
00090 }
00091 
00092 /***************************************************************************\
00093  *                           Instance methods                              *
00094 \***************************************************************************/
00095 
00096 /*-------------------------------------------------------------------------*\
00097  -  private                                                                 -
00098 \*-------------------------------------------------------------------------*/
00099 
00100 Particles::Particles(void) :
00101     Inherited()
00102 {
00103 }
00104 
00105 Particles::Particles(const Particles &source) :
00106     Inherited(source)
00107 {
00108 }
00109 
00110 Particles::~Particles(void)
00111 {
00112     ParticlesPtr thisP(*this);
00113 
00114     if(_sfPositions.getValue() != NullFC)
00115     {
00116         beginEditCP(_sfPositions.getValue(), Attachment::ParentsFieldMask);
00117         {
00118             _sfPositions.getValue()->subParent(thisP);
00119         }
00120         endEditCP(_sfPositions.getValue(), Attachment::ParentsFieldMask);
00121 
00122         subRefCP(_sfPositions.getValue());
00123     }
00124 
00125     if(_sfSecPositions.getValue() != NullFC)
00126     {
00127         beginEditCP(_sfSecPositions.getValue(), Attachment::ParentsFieldMask);
00128         {
00129             _sfSecPositions.getValue()->subParent(thisP);
00130         }
00131         endEditCP(_sfSecPositions.getValue(), Attachment::ParentsFieldMask);
00132 
00133         subRefCP(_sfSecPositions.getValue());
00134     }
00135 
00136     if(_sfColors.getValue() != NullFC)
00137     {
00138         beginEditCP(_sfColors.getValue(), Attachment::ParentsFieldMask);
00139         {
00140             _sfColors.getValue()->subParent(thisP);
00141         }
00142         endEditCP(_sfColors.getValue(), Attachment::ParentsFieldMask);
00143 
00144         subRefCP(_sfColors.getValue());
00145     }
00146 
00147     if(_sfNormals.getValue() != NullFC)
00148     {
00149         beginEditCP(_sfNormals.getValue(), Attachment::ParentsFieldMask);
00150         {
00151             _sfNormals.getValue()->subParent(thisP);
00152         }
00153         endEditCP(_sfNormals.getValue(), Attachment::ParentsFieldMask);
00154 
00155         subRefCP(_sfNormals.getValue());
00156     }
00157 
00158     subRefCP(_sfMaterial.getValue());
00159 }
00160 
00161 /*------------------------------- Sync -----------------------------------*/
00162 
00163 void Particles::changed(BitVector whichField, UInt32 origin)
00164 {
00165     if(whichField & PositionsFieldMask)
00166     {
00167         for(UInt32 i = 0; i < _parents.size(); i++)
00168         {
00169             _parents[i]->invalidateVolume();
00170         }
00171         getBsp().destroy();
00172 
00173         if(origin & ChangedOrigin::Abstract)
00174         {
00175             if(origin & ChangedOrigin::AbstrCheckValid)
00176             {
00177                 ParticlesPtr thisP(*this);
00178 
00179                 if(_sfPositions.getValue()                    != NullFC &&
00180                    _sfPositions.getValue()->findParent(thisP) ==     -1 )
00181                 {
00182                     GeoPositionsPtr pPos = _sfPositions.getValue();
00183 
00184                     _sfPositions.setValue(NullFC);
00185 
00186                     setPositions(pPos);
00187                 }
00188             }
00189             else if(origin & ChangedOrigin::AbstrIncRefCount)
00190             {
00191                 addRefCP(_sfPositions.getValue());
00192             }
00193             else
00194             {
00195                 GeoPositionsPtr pPos = _sfPositions.getValue();
00196 
00197                 _sfPositions.setValue(NullFC);
00198 
00199                 setPositions(pPos);
00200             }
00201         }
00202     }
00203 
00204     if(whichField & SecPositionsFieldMask)
00205     {
00206         if(origin & ChangedOrigin::Abstract)
00207         {
00208             if(origin & ChangedOrigin::AbstrCheckValid)
00209             {
00210                 ParticlesPtr thisP(*this);
00211 
00212                 if(_sfSecPositions.getValue()                    != NullFC &&
00213                    _sfSecPositions.getValue()->findParent(thisP) ==     -1 )
00214                 {
00215                     GeoPositionsPtr pPos = _sfSecPositions.getValue();
00216 
00217                     _sfSecPositions.setValue(NullFC);
00218 
00219                     setSecPositions(pPos);
00220                 }
00221             }
00222             else if(origin & ChangedOrigin::AbstrIncRefCount)
00223             {
00224                 addRefCP(_sfSecPositions.getValue());
00225             }
00226             else
00227             {
00228                 GeoPositionsPtr pPos = _sfSecPositions.getValue();
00229 
00230                 _sfSecPositions.setValue(NullFC);
00231 
00232                 setSecPositions(pPos);
00233             }
00234         }
00235     }
00236 
00237     if(whichField & ColorsFieldMask)
00238     {
00239         if(origin & ChangedOrigin::Abstract)
00240         {
00241             if(origin & ChangedOrigin::AbstrCheckValid)
00242             {
00243                 ParticlesPtr thisP(*this);
00244 
00245                 if(_sfColors.getValue()                    != NullFC &&
00246                    _sfColors.getValue()->findParent(thisP) ==     -1 )
00247                 {
00248                     GeoColorsPtr pCol = _sfColors.getValue();
00249 
00250                     _sfColors.setValue(NullFC);
00251 
00252                     setColors(pCol);
00253                 }
00254             }
00255             else if(origin & ChangedOrigin::AbstrIncRefCount)
00256             {
00257                 addRefCP(_sfColors.getValue());
00258             }
00259             else
00260             {
00261                 GeoColorsPtr pCol = _sfColors.getValue();
00262 
00263                 _sfColors.setValue(NullFC);
00264 
00265                 setColors(pCol);
00266             }
00267         }
00268     }
00269 
00270     if(whichField & NormalsFieldMask)
00271     {
00272         if(origin & ChangedOrigin::Abstract)
00273         {
00274             if(origin & ChangedOrigin::AbstrCheckValid)
00275             {
00276                 ParticlesPtr thisP(*this);
00277 
00278                 if(_sfNormals.getValue()                    != NullFC &&
00279                    _sfNormals.getValue()->findParent(thisP) ==     -1 )
00280                 {
00281                     GeoNormalsPtr pNorm = _sfNormals.getValue();
00282 
00283                     _sfNormals.setValue(NullFC);
00284 
00285                     setNormals(pNorm);
00286                 }
00287             }
00288             else if(origin & ChangedOrigin::AbstrIncRefCount)
00289             {
00290                 addRefCP(_sfNormals.getValue());
00291             }
00292             else
00293             {
00294                 GeoNormalsPtr pNorm = _sfNormals.getValue();
00295 
00296                 _sfNormals.setValue(NullFC);
00297 
00298                 setNormals(pNorm);
00299             }
00300         }
00301     }
00302 
00303     if(whichField & MaterialFieldMask)
00304     {
00305         if(origin & ChangedOrigin::Abstract)
00306         {
00307             if(origin & ChangedOrigin::AbstrIncRefCount)
00308             {
00309                 addRefCP(_sfMaterial.getValue());
00310             }
00311             else
00312             {
00313                 MaterialPtr pMat = _sfMaterial.getValue();
00314                 
00315                 _sfMaterial.setValue(NullFC);
00316                 
00317                 setMaterial(pMat);
00318             }
00319         }
00320     }
00321 
00322     Inherited::changed(whichField, origin);
00323 }
00324 
00325 /*------------------------------ Output ----------------------------------*/
00326 
00327 void Particles::dump(      UInt32    ,
00328                          const BitVector ) const
00329 {
00330     SLOG << "Dump Particles NI" << std::endl;
00331 }
00332 
00333 
00334 void Particles::adjustVolume( Volume & volume )
00335 {
00336     GeoPositionsPtr pos = getPositions();
00337 
00338     if ( pos == NullFC )
00339         return;                 // Node has no particles, no volume
00340 
00341     volume.setValid();
00342     volume.setEmpty();
00343 
00344     MFVec3f *sizes = getMFSizes();
00345 
00346     if(sizes->size() == pos->size())
00347     {
00348         Vec3f p;
00349         Real32 s;
00350 
00351         for(UInt32 i = 0; i < pos->size(); i++)
00352         {
00353             pos->getValue(p, i);
00354             // make the size bigger to accomodate rotations
00355             s=(*sizes)[i][0]*Sqrt2;
00356 
00357             p[0]+=s/2;
00358             p[1]+=s/2;
00359             p[2]+=s/2;
00360             volume.extendBy(p);
00361             p[0]-=s;
00362             volume.extendBy(p);
00363             p[1]-=s;
00364             volume.extendBy(p);
00365             p[0]+=s;
00366             volume.extendBy(p);
00367             p[2]-=s;
00368             volume.extendBy(p);
00369             p[0]-=s;
00370             volume.extendBy(p);
00371             p[1]+=s;
00372             volume.extendBy(p);
00373             p[0]+=s;
00374             volume.extendBy(p);
00375         }
00376 
00377     }
00378     else if(sizes->size() == 1)
00379     {
00380         Vec3f p;
00381         Real32 s,s2;
00382         // make the size bigger to accomodate rotations
00383         s=(*sizes)[0][0]*Sqrt2;
00384         s2=s/2;
00385 
00386         for(UInt32 i = 0; i < pos->size(); i++)
00387         {
00388             pos->getValue(p, i);
00389 
00390             p[0]+=s2;
00391             p[1]+=s2;
00392             p[2]+=s2;
00393             volume.extendBy(p);
00394             p[0]-=s;
00395             volume.extendBy(p);
00396             p[1]-=s;
00397             volume.extendBy(p);
00398             p[0]+=s;
00399             volume.extendBy(p);
00400             p[2]-=s;
00401             volume.extendBy(p);
00402             p[0]-=s;
00403             volume.extendBy(p);
00404             p[1]+=s;
00405             volume.extendBy(p);
00406             p[0]+=s;
00407             volume.extendBy(p);
00408         }
00409 
00410     }
00411     else
00412     {
00413         Vec3f p;
00414 
00415         for(UInt32 i = 0; i < pos->getSize(); i++)
00416         {
00417             pos->getValue(p, i);
00418 
00419             volume.extendBy(p);
00420         }
00421     }
00422 }
00423 
00424 #if !defined(OSG_DO_DOC) || OSG_DOC_LEVEL > 1  // remove from user docu
00425 
00426 /*---------------------------- pumps -----------------------------------*/
00427 
00441 class ParticleTraits
00442 {
00443 };
00444 
00447 struct ColTraitBase : public ParticleTraits
00448 {
00449     typedef void (OSG_APIENTRY *pumpFunc)( GLubyte * data );
00450     static const int formatBase;
00451     enum { numFormats = GL_DOUBLE - GL_BYTE + 1 };
00452 
00453     static char *formatNames[];
00454 
00455     static pumpFunc ColorFuncs[numFormats][4]; 
00456 };
00457 
00460 const int ColTraitBase::formatBase = GL_BYTE;
00461 
00464 char *ColTraitBase::formatNames[] = 
00465 {   "GL_BYTE", "GL_UNSIGNED_BYTE", "GL_SHORT", "GL_UNSIGNED_SHORT", 
00466     "GL_INT", "GL_UNSIGNED_INT", "GL_FLOAT", "GL_2_BYTES", 
00467     "GL_3_BYTES", "GL_4_BYTES", "GL_DOUBLE"
00468 };
00469 
00472 ColTraitBase::pumpFunc 
00473 ColTraitBase::ColorFuncs[ColTraitBase::numFormats][4] = {
00474     { NULL, NULL, 
00475       (pumpFunc)glColor3bv, (pumpFunc)glColor4bv },   // GL_BYTE
00476     { NULL, NULL, 
00477       (pumpFunc)glColor3ubv,(pumpFunc)glColor4ubv },  // GL_UNSIGNED_BYTE
00478     { NULL, NULL, 
00479       (pumpFunc)glColor3sv, (pumpFunc)glColor4sv },   // GL_SHORT
00480     { NULL, NULL,  
00481       (pumpFunc)glColor3usv,(pumpFunc)glColor4usv },  // GL_UNSIGNED_SHORT
00482     { NULL, NULL,  
00483       (pumpFunc)glColor3iv, (pumpFunc)glColor4iv },   // GL_INT
00484     { NULL, NULL,  
00485       (pumpFunc)glColor3uiv,(pumpFunc)glColor4uiv },  // GL_UNSIGNED_INT
00486     { NULL, NULL,  
00487       (pumpFunc)glColor3fv, (pumpFunc)glColor4fv },   // GL_FLOAT
00488     { NULL, NULL, NULL, NULL },                       // GL_2_BYTES
00489     { NULL, NULL, NULL, NULL },                       // GL_3_BYTES
00490     { NULL, NULL, NULL, NULL },                       // GL_4_BYTES
00491     { NULL, NULL,  
00492       (pumpFunc)glColor3dv, (pumpFunc)glColor4dv },   // GL_DOUBLE
00493 };
00494 
00495 struct ColTraitNone : public ColTraitBase
00496 {
00497     typedef UInt8 dataType; // no data needed, but can't instantiate void
00498     
00499     static inline void init(Particles *, DrawActionBase *, dataType &)
00500     {
00501     }
00502     
00503     static inline bool particle(dataType &, UInt32)
00504     {
00505         return false;
00506     }
00507     
00508     static inline void vertex(dataType &, UInt32, UInt32)
00509     {
00510     }
00511 };
00512 
00513 struct ColTraitSingle : public ColTraitBase
00514 {
00515     typedef UInt8 dataType; // no data needed, but can't instantiate void
00516     
00517     static inline void init(Particles *part, DrawActionBase *, dataType &)
00518     {
00519         GeoColorsPtr col = part->getColors();
00520  
00521         if(col != NullFC)
00522         {
00523             pumpFunc col_func;
00524 
00525             col_func = ColorFuncs[ col->getFormat() - formatBase ]
00526                                  [ col->getDimension() - 1 ];
00527 
00528             if(col_func == NULL)
00529             {
00530                 SWARNING << "Particles " << part << "have illegal "
00531                          << "colors: " << col->getDimension()
00532                          << "D " << formatNames[col->getFormat() - formatBase]
00533                          << "!" << std::endl;
00534                 return;
00535             }
00536             else
00537             {
00538                 col_func((GLubyte*) col->getData());
00539             }
00540         }
00541     }
00542     
00543     static inline bool particle(dataType &, UInt32)
00544     {
00545         return false;
00546     }
00547 
00548     static inline void vertex(dataType &, UInt32, UInt32)
00549     {
00550     }
00551 };
00552 
00553 struct ColTraitParticle : public ColTraitBase
00554 {
00555     typedef struct
00556     {
00557         UInt8    *data;
00558         UInt32    stride;
00559         pumpFunc  func;
00560     } 
00561     dataType;
00562     
00563     static inline void init(Particles *part, DrawActionBase *, dataType &data)
00564     {
00565         GeoColorsPtr col = part->getColors();
00566 
00567         data.data = col->getData();
00568         if((data.stride = col->getStride()) == 0)
00569             data.stride = col->getFormatSize() * col->getDimension();
00570         
00571         data.func = ColorFuncs[ col->getFormat() - formatBase ]
00572                               [ col->getDimension() - 1 ];
00573                              
00574         if(data.func == NULL)
00575         {
00576             SWARNING << "Particles " << part << "have illegal "
00577                      << "colors: " << col->getDimension()
00578                      << "D " << formatNames[ col->getFormat() - formatBase ]
00579                      << "!" << std::endl;
00580             return;
00581         }
00582     }
00583     
00584     static inline bool particle(dataType &data, UInt32 particle)
00585     {   
00586         data.func((GLubyte*)(data.data + particle * data.stride));
00587         return false;
00588     }
00589     
00590     static inline void vertex(dataType &, UInt32, UInt32)
00591     {
00592     }
00593 };
00594 
00595 struct ColTraitGeneric : public ColTraitBase
00596 {
00597     typedef struct
00598     {
00599         UInt8    *data;
00600         UInt32    stride;
00601         pumpFunc  func;
00602         bool      perParticle;
00603     } 
00604     dataType;
00605     
00606     static inline void init(Particles *part, DrawActionBase *, dataType &data)
00607     {
00608         GeoColorsPtr col = part->getColors();
00609         
00610         data.perParticle = false;
00611         
00612         if(col != NullFC)
00613         {
00614             data.data = col->getData();
00615             if((data.stride = col->getStride()) == 0)
00616                 data.stride = col->getFormatSize() * col->getDimension();
00617 
00618             data.func = ColorFuncs[ col->getFormat() - formatBase ]
00619                                   [ col->getDimension() - 1 ];
00620 
00621             if(data.func == NULL)
00622             {
00623                 SWARNING << "Particles " << part << "have illegal "
00624                          << "colors: " << col->getDimension()
00625                          << "D " << formatNames[ col->getFormat() - formatBase ]
00626                          << "!" << std::endl;
00627                 return;
00628             }
00629             
00630             if(col->getSize() == 1)
00631             {
00632                 data.func((GLubyte*) col->getData());
00633             }
00634             else if(col->getSize() == part->getPositions()->getSize())
00635             {
00636                 data.perParticle = true;
00637             }
00638         }
00639     }
00640     
00641     static inline bool particle(dataType &data, UInt32 particle)
00642     {   
00643         if(data.perParticle == true)
00644             data.func((GLubyte*)(data.data + particle * data.stride));
00645         return false;
00646     }
00647         
00648     static inline void vertex(dataType &, UInt32, UInt32)
00649     {
00650     }
00651 };
00652 
00655 struct PosTraitGeneric : public ParticleTraits
00656 {
00657     typedef struct
00658     {
00659         GeoPositionsPtr pos;
00660         Pnt3f p;
00661     }
00662     dataType;
00663     
00664     static inline void init(Particles *, DrawActionBase *, dataType &data,
00665         GeoPositionsPtr &pos)
00666     {
00667         data.pos = pos;
00668     }
00669     
00670     static inline bool particle(dataType &data, UInt32 particle)
00671     {
00672         data.pos->getValue(data.p, particle);
00673              
00674         return false;
00675     }
00676     
00677     static inline Pnt3f &position(dataType &data)
00678     {
00679         return data.p;
00680     }
00681     
00682     static inline void vertex(dataType &data, UInt32 , Vec4f &dir, 
00683                               Real32 s)
00684     {
00685         glVertex3f( data.p[0] + dir[0] * s, 
00686                     data.p[1] + dir[1] * s, 
00687                     data.p[2] + dir[2] * s);             
00688     }
00689     
00690     static inline void vertex(dataType &data)
00691     {
00692         glVertex3fv( (GLfloat*) data.p.getValues() );             
00693     }
00694 };
00695 
00696 struct PosTrait3f : public ParticleTraits
00697 {
00698     typedef struct
00699     {
00700         MFPnt3f *pos;
00701         Pnt3f   *p;
00702     }
00703     dataType;
00704     
00705     static inline void init(Particles *, DrawActionBase *, dataType &data,
00706         GeoPositionsPtr &pos)
00707     {
00708         GeoPositions3fPtr pos3f = GeoPositions3fPtr::dcast(pos);
00709  
00710         data.pos  = pos3f->getFieldPtr();
00711     }
00712     
00713     static inline bool particle(dataType &data, UInt32 particle)
00714     {
00715         data.p = & (*(data.pos))[particle];
00716         return false;
00717     }
00718     
00719     static inline Pnt3f &position(dataType &data)
00720     {
00721         return *data.p;
00722     }
00723     
00724     static inline void vertex(dataType &data, UInt32 , Vec4f &dir, Real32 s)
00725     {
00726         glVertex3f( (*data.p)[0] + dir[0] * s, 
00727                     (*data.p)[1] + dir[1] * s, 
00728                     (*data.p)[2] + dir[2] * s);             
00729     }
00730     
00731     static inline void vertex(dataType &data)
00732     {
00733         glVertex3fv( (GLfloat*) (*data.p).getValues() );             
00734     }
00735 };
00736 
00739 struct SizeTraitGeneric : public ParticleTraits
00740 {
00741     typedef struct
00742     {
00743         MFVec3f *sizes;
00744         Vec3f    s;
00745         bool     perParticle;
00746     }
00747     dataType;
00748     
00749     static inline void init(Particles *part, DrawActionBase *, dataType &data)
00750     {
00751         data.sizes = part->getMFSizes();
00752         
00753         if(data.sizes != NULL)
00754         {
00755             if(data.sizes->size() == 1)
00756             {
00757                 data.s = (*(data.sizes))[0];
00758                 data.perParticle = false;
00759             }
00760             else if(data.sizes->size() == part->getPositions()->size())
00761             {
00762                 data.perParticle = true;
00763             }
00764             else
00765             {
00766                 data.s.setValues(1,1,1);
00767                 data.perParticle = false;
00768             }           
00769         }
00770         else
00771         {
00772             data.s.setValues(1,1,1);
00773             data.perParticle = false;
00774         }           
00775     }
00776    
00777     static inline bool particle(dataType &, UInt32)
00778     {
00779         return false;
00780     }
00781     
00782     static inline Vec3f &size(dataType &data, UInt32 particle)
00783     {
00784         if(data.perParticle)
00785                 return (*(data.sizes))[particle];
00786         return data.s;
00787     }
00788 };
00789 
00790 struct SizeTraitSingle : public ParticleTraits
00791 {
00792     typedef struct
00793     {
00794         Vec3f    s;
00795     }
00796     dataType;
00797     
00798     static inline void init(Particles *part, DrawActionBase *, dataType &data)
00799     {
00800         data.s = part->getSizes()[0];
00801     }
00802     
00803     static inline bool particle(dataType &, UInt32)
00804     {
00805         return false;
00806     }
00807     
00808     static inline Vec3f &size(dataType &data, UInt32)
00809     {
00810         return data.s;
00811     }
00812 };
00813 
00814 struct SizeTraitParticle : public ParticleTraits
00815 {
00816     typedef struct
00817     {
00818         MFVec3f *sizes;
00819         Vec3f    s;
00820     }
00821     dataType;
00822     
00823     static inline void init(Particles *part, DrawActionBase *, dataType &data)
00824     {
00825         data.sizes = part->getMFSizes();
00826     }
00827     
00828     static inline bool particle(dataType &, UInt32)
00829     {
00830         return false;
00831     }
00832     
00833     static inline Vec3f &size(dataType &data, UInt32 particle)
00834     {
00835         return (*(data.sizes))[particle];
00836     }
00837 };
00838 
00839 struct SizeTraitNone : public ParticleTraits
00840 {
00841     typedef UInt8 dataType;
00842     
00843     static inline void init(Particles *, DrawActionBase *, dataType &)
00844     {
00845     }
00846     
00847     static inline bool particle(dataType &, UInt32)
00848     {
00849         return false;
00850     }
00851     
00852     static inline Vec3f &size(dataType &, UInt32 )
00853     {
00854         static Vec3f s(1,1,1);
00855         return s;
00856     }
00857 };
00858 
00861 struct TexTraitGeneric : public ParticleTraits
00862 {
00863     typedef struct
00864     {
00865         MFReal32 *texzs;
00866         Real32    z;
00867         bool      perParticle;
00868     }
00869     dataType;
00870     
00871     static inline void init(Particles *part, DrawActionBase *, dataType &data)
00872     {
00873         data.texzs = part->getMFTextureZs();
00874         
00875         data.perParticle = false;
00876         
00877         if(data.texzs != NULL)
00878         {
00879             if(data.texzs->size() == 1)
00880             {
00881                 data.z = (*(data.texzs))[0];
00882              }
00883             else if(data.texzs->size() == part->getPositions()->size())
00884             {
00885                 data.perParticle = true;
00886             }
00887             else
00888             {
00889                 data.z = 0;
00890             }           
00891         }
00892         else
00893         {
00894             data.z = 0;
00895         }
00896     }
00897     
00898     static inline bool particle(dataType &data, UInt32 particle)
00899     {       
00900         if(data.perParticle)
00901         {
00902             data.z = (*(data.texzs))[particle];
00903         }
00904         return false;
00905     }
00906     
00907     static inline void vertex(dataType &data)
00908     {
00909         glTexCoord1f(data.z);
00910     }
00911     
00912     static inline void vertex(dataType &data, UInt32 , Real32 u,
00913                                 Real32 v)
00914     {
00915         glTexCoord3f(u, v, data.z);
00916     }
00917 };
00918 
00919 struct TexTraitParticle : public ParticleTraits
00920 {
00921     typedef struct
00922     {
00923         MFReal32 *texzs;
00924         Real32    z;
00925     }
00926     dataType;
00927     
00928     static inline void init(Particles *part, DrawActionBase *, dataType &data)
00929     {
00930         data.texzs = part->getMFTextureZs();
00931     }
00932     
00933     static inline bool particle(dataType &data, UInt32 particle)
00934     {       
00935         data.z = (*(data.texzs))[particle];
00936         return false;
00937     }
00938     
00939     static inline void vertex(dataType &data)
00940     {
00941         glTexCoord1f(data.z);
00942     }
00943     
00944     static inline void vertex(dataType &data, UInt32 , Real32 u,
00945                                 Real32 v)
00946     {
00947         glTexCoord3f(u, v, data.z);
00948     }
00949 };
00950 
00951 struct TexTraitSingle : public ParticleTraits
00952 {
00953     typedef struct
00954     {
00955         Real32    z;
00956     }
00957     dataType;
00958     
00959     static inline void init(Particles *part, DrawActionBase *, dataType &data)
00960     {
00961         data.z = (*(part->getMFTextureZs()))[0];
00962     }
00963     
00964     static inline bool particle(dataType &, UInt32)
00965     {
00966         return false;
00967     }
00968     
00969     static inline void vertex(dataType &data)
00970     {
00971         glTexCoord1f(data.z);
00972     }
00973     
00974     static inline void vertex(dataType &data, UInt32 , Real32 u,
00975                                 Real32 v)
00976     {
00977         glTexCoord3f(u, v, data.z);
00978     }
00979 };
00980 
00981 struct TexTraitNone : public ParticleTraits
00982 {
00983     typedef UInt8 dataType;
00984     
00985     static inline void init(Particles *, DrawActionBase *, dataType &)
00986     {
00987     }
00988     
00989     static inline bool particle(dataType &, UInt32)
00990     {
00991         return false;
00992     }
00993     
00994     static inline void vertex(dataType &, UInt32 )
00995     {
00996         glTexCoord1f(0);
00997     }
00998    
00999     static inline void vertex(dataType &, UInt32, Real32 u, Real32 v)
01000     {
01001         glTexCoord2f(u, v);
01002     }
01003 };
01004 
01005 
01008 struct NormalTraitGeneric : public ParticleTraits
01009 {
01010     typedef struct
01011     {
01012         GeoNormalsPtr norms;
01013         Vec3f         n;
01014         bool          perParticle;
01015     }
01016     dataType;
01017     
01018     static inline void init(Particles *part, DrawActionBase *, dataType &data)
01019     {
01020         data.norms = part->getNormals();
01021         
01022         data.perParticle = false;
01023         
01024         if(data.norms != NullFC)
01025         {
01026             if(data.norms->size() == 1)
01027             {
01028                 data.n = data.norms->getValue(0);
01029             }
01030             else if(data.norms->getSize() == part->getPositions()->getSize())
01031             {
01032                 data.perParticle = true;
01033             }
01034             else
01035             {
01036                 data.n.setValues(0,1,0);
01037             }           
01038         }
01039         else
01040         {
01041             data.n.setValues(0,1,0);
01042         }
01043     }
01044     
01045     static inline bool particle(dataType &data, UInt32 particle)
01046     {
01047         if(data.perParticle)
01048             data.norms->getValue(data.n, particle);
01049              
01050         return false;
01051     }
01052     
01053     static inline Vec3f &normal(dataType &data)
01054     {
01055         return data.n;
01056     }
01057     
01058     static inline void normal(dataType &data, UInt32 )
01059     {
01060         glNormal3fv( (GLfloat*) data.n.getValues() );            
01061     }
01062 };
01063 
01064 struct NormalTraitGeneric3f : public ParticleTraits
01065 {
01066     typedef struct
01067     {
01068         MFVec3f *norms;
01069         Vec3f   *n;
01070         bool     perParticle;
01071         Vec3f    const_n;