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 <cstdlib>
00044 #include <cstdio>
00045
00046 #include "OSGConfig.h"
00047 #include "OSGGLEXT.h"
00048 #include "OSGAction.h"
00049 #include "OSGRenderAction.h"
00050 #include "OSGMaterial.h"
00051 //#include "OSGGeoPropPtrs.h"
00052 #include "OSGCamera.h"
00053 #include "OSGWindow.h"
00054 #include "OSGDrawEnv.h"
00055
00056 #include "OSGParticles.h"
00057 #include "OSGDrawableStatsAttachment.h"
00058
00059 #include <algorithm>
00060
00061
00062 OSG_USING_NAMESPACE
00063
00064 // Documentation for this class is emited in the
00065 // OSGParticlesBase.cpp file.
00066 // To modify it, please change the .fcd file (OSGParticles.fcd) and
00067 // regenerate the base file.
00068
00069 /***************************************************************************\
00070  *                           File variables                                *
00071 \***************************************************************************/
00072
00073 static UInt32 _extMultitexture           = Window::invalidExtensionID;
00074
00075 static UInt32 _funcglMultiTexCoord3fvARB = Window::invalidFunctionID;
00076
00077 /***************************************************************************\
00078  *                           Class methods                                 *
00079 \***************************************************************************/
00080
00081 void Particles::initMethod(InitPhase ePhase)
00082 {
00083     Inherited::initMethod(ePhase);
00084
00085     if(ePhase == TypeObject::SystemPost)
00086     {
00087         RenderAction::registerEnterDefault(
00088             Particles::getClassType(),
00089             reinterpret_cast<Action::Callback>(
00090                 &MaterialDrawable::renderActionEnterHandler));
00091
00092         RenderAction::registerLeaveDefault(
00093             Particles::getClassType(),
00094             reinterpret_cast<Action::Callback>(
00095                 &MaterialDrawable::renderActionLeaveHandler));
00096
00097         _extMultitexture            =
00098             Window::registerExtension("GL_ARB_multitexture");
00099
00100         _funcglMultiTexCoord3fvARB =
00101             Window::registerFunction(
00102                 OSG_DLSYM_UNDERSCORE"glMultiTexCoord3fvARB", _extMultitexture);
00103     }
00104 }
00105
00106 /***************************************************************************\
00107  *                           Instance methods                              *
00108 \***************************************************************************/
00109
00110 /*-------------------------------------------------------------------------*\
00111  -  private                                                                 -
00112 \*-------------------------------------------------------------------------*/
00113
00114 Particles::Particles(void) :
00115     Inherited()
00116 {
00117 }
00118
00119 Particles::Particles(const Particles &source) :
00120     Inherited(source)
00121 {
00122 }
00123
00124 Particles::~Particles(void)
00125 {
00126 }
00127
00128 /*------------------------------- Sync -----------------------------------*/
00129
00130 void Particles::changed(ConstFieldMaskArg whichField,
00131                         UInt32            origin,
00132                         BitVector         details)
00133 {
00134     if(whichField & PositionsFieldMask)
00135     {
00136         for(UInt32 i = 0; i < _mfParents.size(); i++)
00137         {
00138             _mfParents[i]->invalidateVolume();
00139         }
00140
00141         editBsp().destroy();
00142     }
00143
00144     Inherited::changed(whichField, origin, details);
00145 }
00146
00147 /*------------------------------ Output ----------------------------------*/
00148
00149 void Particles::dump(      UInt32    ,
00150                      const BitVector ) const
00151 {
00152     SLOG << "Dump Particles NI" << std::endl;
00153 }
00154
00155
00156 void Particles::adjustVolume( Volume & volume )
00157 {
00158     GeoVectorProperty *pos = getPositions();
00159
00160     if ( pos == NULL )
00161         return;                 // Node has no particles, no volume
00162
00163     volume.setValid();
00164     volume.setEmpty();
00165
00166     const MFVec3f *sizes = getMFSizes();
00167
00168     if(sizes->size() == pos->size())
00169     {
00170         Vec3f p;
00171         Real32 s;
00172
00173         for(UInt32 i = 0; i < pos->size(); i++)
00174         {
00175             pos->getValue(p, i);
00176             // make the size bigger to accomodate rotations
00177             s=(*sizes)[i][0]*Sqrt2;
00178
00179             p[0]+=s/2;
00180             p[1]+=s/2;
00181             p[2]+=s/2;
00182             volume.extendBy(p);
00183             p[0]-=s;
00184             volume.extendBy(p);
00185             p[1]-=s;
00186             volume.extendBy(p);
00187             p[0]+=s;
00188             volume.extendBy(p);
00189             p[2]-=s;
00190             volume.extendBy(p);
00191             p[0]-=s;
00192             volume.extendBy(p);
00193             p[1]+=s;
00194             volume.extendBy(p);
00195             p[0]+=s;
00196             volume.extendBy(p);
00197         }
00198
00199     }
00200     else if(sizes->size() == 1)
00201     {
00202         Vec3f p;
00203         Real32 s,s2;
00204         // make the size bigger to accomodate rotations
00205         s=(*sizes)[0][0]*Sqrt2;
00206         s2=s/2;
00207
00208         for(UInt32 i = 0; i < pos->size(); i++)
00209         {
00210             pos->getValue(p, i);
00211
00212             p[0]+=s2;
00213             p[1]+=s2;
00214             p[2]+=s2;
00215             volume.extendBy(p);
00216             p[0]-=s;
00217             volume.extendBy(p);
00218             p[1]-=s;
00219             volume.extendBy(p);
00220             p[0]+=s;
00221             volume.extendBy(p);
00222             p[2]-=s;
00223             volume.extendBy(p);
00224             p[0]-=s;
00225             volume.extendBy(p);
00226             p[1]+=s;
00227             volume.extendBy(p);
00228             p[0]+=s;
00229             volume.extendBy(p);
00230         }
00231
00232     }
00233     else
00234     {
00235         Vec3f p;
00236
00237         for(UInt32 i = 0; i < pos->getSize(); i++)
00238         {
00239             pos->getValue(p, i);
00240
00241             volume.extendBy(p);
00242         }
00243     }
00244 }
00245
00246 void Particles::fill(DrawableStatsAttachment *pStat)
00247 {
00248     if(pStat == NULL)
00249     {
00250         FINFO(("Particles::fill(DrawableStatsAttachment *): "
00251                 "No attachment given.\n"));
00252         return;
00253     }
00254
00255     const GeoVectorProperty *positions = getPositions();
00256     const MFInt32           *indices   = getMFIndices();
00257
00258     if(positions == NULL)
00259     {
00260         FINFO(("Particles::fill(DrawableStatsAttachment *): "
00261                "No positions.\n"));
00262         return;
00263     }
00264
00265     UInt32 verts     = 0;
00266     UInt32 points    = 0;
00267     UInt32 lines     = 0;
00268     UInt32 triangles = 0;
00269
00270     if(indices->size() > 0)
00271     {
00272         verts += indices->size();
00273     }
00274     else
00275     {
00276         verts += positions->size();
00277     }
00278
00279     switch(getMode())
00280     {
00281     case Points:
00282     {
00283         points += verts;
00284         break;
00285     }
00286
00287     case Lines:
00288     {
00289         lines += verts;
00290         break;
00291     }
00292
00293     case ViewDirQuads:
00294     case ViewerQuads:
00295     case Rectangles:
00296     case ShaderQuads:
00297     {
00298         triangles += verts * 2;
00299         break;
00300     }
00301
00302     case Arrows:
00303     case ViewerArrows:
00304     {
00305         triangles += verts * 5;
00306         break;
00307     }
00308
00309     case ShaderStrips:
00310     {
00311         triangles += verts - 2;
00312         break;
00313     }
00314
00315     default:
00316     {
00317         FWARNING(("Particles::fill(DrawableStatsAttachment *): "
00318                   "Invalid sfMode value.\n"));
00319         break;
00320     }
00321     }
00322
00323     pStat->setVertices (verts    );
00324     pStat->setPoints   (points   );
00325     pStat->setLines    (lines    );
00326     pStat->setTriangles(triangles);
00327 }
00328
00329 #if !defined(OSG_DO_DOC) || OSG_DOC_LEVEL > 1  // remove from user docu
00330 
00331 /*---------------------------- pumps -----------------------------------*/
00332
00346 class ParticleTraits
00347 {
00348 };
00349
00352 struct ColTraitBase : public ParticleTraits
00353 {
00354     typedef void (OSG_APIENTRY *pumpFunc)( GLubyte * data );
00355     static const int formatBase;
00356     enum { numFormats = GL_DOUBLE - GL_BYTE + 1 };
00357
00358     static const char *formatNames[];
00359
00360     static pumpFunc ColorFuncs[numFormats][4];
00361 };
00362
00365 const int ColTraitBase::formatBase = GL_BYTE;
00366
00369 const char *ColTraitBase::formatNames[] =
00370 {   "GL_BYTE", "GL_UNSIGNED_BYTE", "GL_SHORT", "GL_UNSIGNED_SHORT",
00371     "GL_INT", "GL_UNSIGNED_INT", "GL_FLOAT", "GL_2_BYTES",
00372     "GL_3_BYTES", "GL_4_BYTES", "GL_DOUBLE"
00373 };
00374
00377 ColTraitBase::pumpFunc
00378 ColTraitBase::ColorFuncs[ColTraitBase::numFormats][4] = {
00379     { NULL,
00380       NULL,
00381       reinterpret_cast<pumpFunc>(glColor3bv),
00382       reinterpret_cast<pumpFunc>(glColor4bv) },   // GL_BYTE
00383     { NULL,
00384       NULL,
00385       reinterpret_cast<pumpFunc>(glColor3ubv),
00386       reinterpret_cast<pumpFunc>(glColor4ubv) },  // GL_UNSIGNED_BYTE
00387     { NULL,
00388       NULL,
00389       reinterpret_cast<pumpFunc>(glColor3sv),
00390       reinterpret_cast<pumpFunc>(glColor4sv) },   // GL_SHORT
00391     { NULL,
00392       NULL,
00393       reinterpret_cast<pumpFunc>(glColor3usv),
00394       reinterpret_cast<pumpFunc>(glColor4usv) },  // GL_UNSIGNED_SHORT
00395     { NULL,
00396       NULL,
00397       reinterpret_cast<pumpFunc>(glColor3iv),
00398       reinterpret_cast<pumpFunc>(glColor4iv) },   // GL_INT
00399     { NULL,
00400       NULL,
00401       reinterpret_cast<pumpFunc>(glColor3uiv),
00402       reinterpret_cast<pumpFunc>(glColor4uiv) },  // GL_UNSIGNED_INT
00403     { NULL,
00404       NULL,
00405       reinterpret_cast<pumpFunc>(glColor3fv),
00406       reinterpret_cast<pumpFunc>(glColor4fv) },   // GL_FLOAT
00407     { NULL, NULL, NULL, NULL },                   // GL_2_BYTES
00408     { NULL, NULL, NULL, NULL },                   // GL_3_BYTES
00409     { NULL, NULL, NULL, NULL },                   // GL_4_BYTES
00410     { NULL, NULL,
00411       reinterpret_cast<pumpFunc>(glColor3dv),
00412       reinterpret_cast<pumpFunc>(glColor4dv) },   // GL_DOUBLE
00413 };
00414
00415 struct ColTraitNone : public ColTraitBase
00416 {
00417     typedef UInt8 dataType; // no data needed, but can't instantiate void
00418
00419     static inline void init(Particles *, DrawEnv *, dataType &)
00420     {
00421     }
00422
00423     static inline bool particle(dataType &, UInt32)
00424     {
00425         return false;
00426     }
00427
00428     static inline void vertex(dataType &, UInt32, UInt32)
00429     {
00430     }
00431 };
00432
00433 struct ColTraitSingle : public ColTraitBase
00434 {
00435     typedef UInt8 dataType; // no data needed, but can't instantiate void
00436
00437     static inline void init(Particles *part, DrawEnv *, dataType &)
00438     {
00439         GeoVectorProperty *col = part->getColors();
00440
00441         if(col != NULL)
00442         {
00443             pumpFunc col_func;
00444
00445             col_func = ColorFuncs[ col->getFormat() - formatBase ]
00446                                  [ col->getDimension() - 1 ];
00447
00448             if(col_func == NULL)
00449             {
00450                 SWARNING << "Particles " << part << "have illegal "
00451                          << "colors: " << col->getDimension()
00452                          << "D " << formatNames[col->getFormat() - formatBase]
00453                          << "!" << std::endl;
00454                 return;
00455             }
00456             else
00457             {
00458                 col_func(const_cast<GLubyte*>(col->getData()));
00459             }
00460         }
00461     }
00462
00463     static inline bool particle(dataType &, UInt32)
00464     {
00465         return false;
00466     }
00467
00468     static inline void vertex(dataType &, UInt32, UInt32)
00469     {
00470     }
00471 };
00472
00473 struct ColTraitParticle : public ColTraitBase
00474 {
00475     typedef struct
00476     {
00477         const UInt8    *data;
00478               UInt32    stride;
00479               pumpFunc  func;
00480     }
00481     dataType;
00482
00483     static inline void init(Particles *part, DrawEnv *, dataType &data)
00484     {
00485         GeoVectorProperty *col = part->getColors();
00486
00487         data.data = col->getData();
00488         if((data.stride = col->getStride()) == 0)
00489             data.stride = col->getFormatSize() * col->getDimension();
00490
00491         data.func = ColorFuncs[ col->getFormat() - formatBase ]
00492                               [ col->getDimension() - 1 ];
00493
00494         if(data.func == NULL)
00495         {
00496             SWARNING << "Particles " << part << "have illegal "
00497                      << "colors: " << col->getDimension()
00498                      << "D " << formatNames[ col->getFormat() - formatBase ]
00499                      << "!" << std::endl;
00500             return;
00501         }
00502     }
00503
00504     static inline bool particle(dataType &data, UInt32 particle)
00505     {
00506         data.func(const_cast<GLubyte *>(data.data + particle * data.stride));
00507
00508         return false;
00509     }
00510
00511     static inline void vertex(dataType &, UInt32, UInt32)
00512     {
00513     }
00514 };
00515
00516 struct ColTraitGeneric : public ColTraitBase
00517 {
00518     struct dataType
00519     {
00520         const UInt8    *data;
00521               UInt32    stride;
00522               pumpFunc  func;
00523               bool      perParticle;
00524     };
00525
00526     static inline void init(Particles *part, DrawEnv *, dataType &data)
00527     {
00528         GeoVectorProperty *col = part->getColors();
00529
00530         data.perParticle = false;
00531
00532         if(col != NULL)
00533         {
00534             data.data = col->getData();
00535             if((data.stride = col->getStride()) == 0)
00536                 data.stride = col->getFormatSize() * col->getDimension();
00537
00538             data.func = ColorFuncs[ col->getFormat() - formatBase ]
00539                                   [ col->getDimension() - 1 ];
00540
00541             if(data.func == NULL)
00542             {
00543                 SWARNING << "Particles " << part << "have illegal "
00544                          << "colors: " << col->getDimension()
00545                          << "D " << formatNames[ col->getFormat() - formatBase ]
00546                          << "!" << std::endl;
00547                 return;
00548             }
00549
00550             if(col->getSize() == 1)
00551             {
00552                 data.func(const_cast<GLubyte *>(col->getData()));
00553             }
00554             else if(col->getSize() == part->getPositions()->getSize())
00555             {
00556                 data.perParticle = true;
00557             }
00558         }
00559     }
00560
00561     static inline bool particle(dataType &data, UInt32 particle)
00562     {
00563         if(data.perParticle == true)
00564         {
00565             data.func(
00566                 const_cast<GLubyte *>(data.data + particle * data.stride));
00567         }
00568         return false;
00569     }
00570
00571     static inline void vertex(dataType &, UInt32, UInt32)
00572     {
00573     }
00574 };
00575
00578 struct PosTraitNone : public ParticleTraits
00579 {
00580     typedef struct
00581     {
00582     }
00583     dataType;
00584
00585     static inline void init(Particles *, DrawEnv *, dataType &data,
00586         GeoVectorProperty *pos)
00587     {
00588     }
00589
00590     static inline bool particle(dataType &data, UInt32 particle)
00591     {
00592         return false;
00593     }
00594
00595     static inline Pnt3f &position(dataType &data)
00596     {
00597         static Pnt3f null(0,0,0);
00598         return null;
00599     }
00600
00601     static inline void vertex(dataType &data, UInt32 , Vec4f &dir,
00602                               Real32 s)
00603     {
00604     }
00605
00606     static inline void vertex(dataType &data)
00607     {
00608     }
00609 };
00610
00611 struct PosTraitGeneric : public ParticleTraits
00612 {
00613     typedef struct
00614     {
00615         GeoVectorProperty *pos;
00616         Pnt3f              p;
00617     }
00618     dataType;
00619
00620     static inline void init(Particles *, DrawEnv *, dataType &data,
00621         GeoVectorProperty *pos)
00622     {
00623         data.pos = pos;
00624     }
00625
00626     static inline bool particle(dataType &data, UInt32 particle)
00627     {
00628         data.pos->getValue(data.p, particle);
00629
00630         return false;
00631     }
00632
00633     static inline Pnt3f &position(dataType &data)
00634     {
00635         return data.p;
00636     }
00637
00638     static inline void vertex(dataType &data, UInt32 , Vec4f &dir,
00639                               Real32 s)
00640     {
00641         glVertex3f( data.p[0] + dir[0] * s,
00642                     data.p[1] + dir[1] * s,
00643                     data.p[2] + dir[2] * s);
00644     }
00645
00646     static inline void vertex(dataType &data)
00647     {
00648         glVertex3fv(static_cast<GLfloat *>(data.p.getValues()));
00649     }
00650 };
00651
00652 struct PosTrait3f : public ParticleTraits
00653 {
00654     struct dataType
00655     {
00656         const MFPnt3f *pos;
00657         const Pnt3f   *p;
00658     };
00659
00660     static inline void init(Particles         *,
00661                             DrawEnv           *,
00662                             dataType          &data,
00663                             GeoVectorProperty *pos)
00664     {
00665         GeoPnt3fProperty *pos3f = dynamic_cast<GeoPnt3fProperty *>(pos);
00666
00667         data.pos  = pos3f->getFieldPtr();
00668     }
00669
00670     static inline bool particle(dataType &data, UInt32 particle)
00671     {
00672         data.p = & (*(data.pos))[particle];
00673         return false;
00674     }
00675
00676     static inline const Pnt3f &position(dataType &data)
00677     {
00678         return *data.p;
00679     }
00680
00681     static inline void vertex(dataType &data, UInt32 , Vec4f &dir, Real32 s)
00682     {
00683         glVertex3f( (*data.p)[0] + dir[0] * s,
00684                     (*data.p)[1] + dir[1] * s,
00685                     (*data.p)[2] + dir[2] * s);
00686     }
00687
00688     static inline void vertex(dataType &data)
00689     {
00690         glVertex3fv(static_cast<const GLfloat *>((*data.p).getValues()));
00691     }
00692 };
00693
00696 struct SizeTraitGeneric : public ParticleTraits
00697 {
00698     struct dataType
00699     {
00700         const MFVec3f *sizes;
00701               Vec3f    s;
00702               bool     perParticle;
00703     };
00704
00705     static inline void init(Particles *part, DrawEnv *, dataType &data)
00706     {
00707         data.sizes = part->getMFSizes();
00708
00709         if(data.sizes != NULL)
00710         {
00711             if(data.sizes->size() == 1)
00712             {
00713                 data.s = (*(data.sizes))[0];
00714                 data.perParticle = false;
00715             }
00716             else if(data.sizes->size() == part->getPositions()->size())
00717             {
00718                 data.perParticle = true;
00719             }
00720             else
00721             {
00722                 data.s.setValues(1,1,1);
00723                 data.perParticle = false;
00724             }
00725         }
00726         else
00727         {
00728             data.s.setValues(1,1,1);
00729             data.perParticle = false;
00730         }
00731     }
00732
00733     static inline bool particle(dataType &, UInt32)
00734     {
00735         return false;
00736     }
00737
00738     static inline const Vec3f &size(dataType &data, UInt32 particle)
00739     {
00740         if(data.perParticle)
00741                 return (*(data.sizes))[particle];
00742         return data.s;
00743     }
00744 };
00745
00746 struct SizeTraitSingle : public ParticleTraits
00747 {
00748     typedef struct
00749     {
00750         Vec3f    s;
00751     }
00752     dataType;
00753
00754     static inline void init(Particles *part, DrawEnv *, dataType &data)
00755     {
00756         data.s = (*part->getMFSizes())[0];
00757     }
00758
00759     static inline bool particle(dataType &, UInt32)
00760     {
00761         return false;
00762     }
00763
00764     static inline Vec3f &size(dataType &data, UInt32)
00765     {
00766         return data.s;
00767     }
00768 };
00769
00770 struct SizeTraitParticle : public ParticleTraits
00771 {
00772     struct dataType
00773     {
00774         const MFVec3f *sizes;
00775               Vec3f    s;
00776     };
00777
00778     static inline void init(Particles *part, DrawEnv *, dataType &data)
00779     {
00780         data.sizes = part->getMFSizes();
00781     }
00782
00783     static inline bool particle(dataType &, UInt32)
00784     {
00785         return false;
00786     }
00787
00788     static inline const Vec3f &size(dataType &data, UInt32 particle)
00789     {
00790         return (*(data.sizes))[particle];
00791     }
00792 };
00793
00794 struct SizeTraitNone : public ParticleTraits
00795 {
00796     typedef UInt8 dataType;
00797
00798     static inline void init(Particles *, DrawEnv *, dataType &)
00799     {
00800     }
00801
00802     static inline bool particle(dataType &, UInt32)
00803     {
00804         return false;
00805     }
00806
00807     static inline Vec3f &size(dataType &, UInt32 )
00808     {
00809         static Vec3f s(1,1,1);
00810         return s;
00811     }
00812 };
00813
00816 struct TexTraitGeneric : public ParticleTraits
00817 {
00818     struct dataType
00819     {
00820         const MFReal32 *texzs;
00821               Real32    z;
00822               bool      perParticle;
00823     };
00824
00825     static inline void init(Particles *part, DrawEnv *, dataType &data)
00826     {
00827         data.texzs = part->getMFTextureZs();
00828
00829         data.perParticle = false;
00830
00831         if(data.texzs != NULL)
00832         {
00833             if(data.texzs->size() == 1)
00834             {
00835                 data.z = (*(data.texzs))[0];
00836             }
00837             else if(data.texzs->size() == part->getPositions()->size())
00838             {
00839                 data.perParticle = true;
00840                 data.z = 0;
00841             }
00842             else
00843             {
00844                 data.z = 0;
00845             }
00846         }
00847         else
00848         {
00849             data.z = 0;
00850         }
00851     }
00852
00853     static inline bool particle(dataType &data, UInt32 particle)
00854     {
00855         if(data.perParticle)
00856         {
00857             data.z = (*(data.texzs))[particle];
00858         }
00859         return false;
00860     }
00861
00862     static inline void vertex(dataType &data)
00863     {
00864         glTexCoord1f(data.z);
00865     }
00866
00867     static inline void vertex(dataType &data, UInt32 , Real32 u,
00868                                 Real32 v)
00869     {
00870         glTexCoord3f(u, v, data.z);
00871     }
00872 };
00873
00874 struct TexTraitParticle : public ParticleTraits
00875 {
00876     struct dataType
00877     {
00878         const MFReal32 *texzs;
00879               Real32    z;
00880     };
00881
00882     static inline void init(Particles *part, DrawEnv *, dataType &data)
00883     {
00884         data.texzs = part->getMFTextureZs();
00885     }
00886
00887     static inline bool particle(dataType &data, UInt32 particle)
00888     {
00889         data.z = (*(data.texzs))[particle];
00890         return false;
00891     }
00892
00893     static inline void vertex(dataType &data)
00894     {
00895         glTexCoord1f(data.z);
00896     }
00897
00898     static inline void vertex(dataType &data, UInt32 , Real32 u,
00899                                 Real32 v)
00900     {
00901         glTexCoord3f(u, v, data.z);
00902     }
00903 };
00904
00905 struct TexTraitSingle : public ParticleTraits
00906 {
00907     typedef struct
00908     {
00909         Real32    z;
00910     }
00911     dataType;
00912
00913     static inline void init(Particles *part, DrawEnv *, dataType &data)
00914     {
00915         data.z = (*(part->getMFTextureZs()))[0];
00916     }
00917
00918     static inline bool particle(dataType &, UInt32)
00919     {
00920         return false;
00921     }
00922
00923     static inline void vertex(dataType &data)
00924     {
00925         glTexCoord1f(data.z);
00926     }
00927
00928     static inline void vertex(dataType &data, UInt32 , Real32 u,
00929                                 Real32 v)
00930     {
00931         glTexCoord3f(u, v, data.z);
00932     }
00933 };
00934
00935 struct TexTraitNone : public ParticleTraits
00936 {
00937     typedef UInt8 dataType;
00938
00939     static inline void init(Particles *, DrawEnv *, dataType &)
00940     {
00941     }
00942
00943     static inline bool particle(dataType &, UInt32)
00944     {
00945         return false;
00946     }
00947
00948     static inline void vertex(dataType &, UInt32 )
00949     {
00950         glTexCoord1f(0);
00951     }
00952
00953     static inline void vertex(dataType &, UInt32, Real32 u, Real32 v)
00954     {
00955         glTexCoord2f(u, v);
00956     }
00957 };
00958
00959
00962 struct NormalTraitGeneric : public ParticleTraits
00963 {
00964     typedef struct
00965     {
00966         GeoVectorProperty *norms;
00967         Vec3f              n;
00968         bool               perParticle;
00969     }
00970     dataType;
00971
00972     static inline void init(Particles *part, DrawEnv *, dataType &data)
00973     {
00974         data.norms = part->getNormals();
00975
00976         data.perParticle = false;
00977
00978         if(data.norms != NULL)
00979         {
00980             if(data.norms->size() == 1)
00981             {
00982                 data.norms->getValue(data.n, 0);
00983             }
00984             else if(data.norms->getSize() == part->getPositions()->getSize())
00985             {
00986                 data.perParticle = true;
00987             }
00988             else
00989             {
00990                 data.n.setValues(0,1,0);
00991             }
00992         }
00993         else
00994         {
00995             data.n.setValues(0,1,0);
00996         }
00997     }
00998
00999     static inline bool particle(dataType &data, UInt32 particle)
01000     {
01001         if(data.perParticle)
01002             data.norms->getValue(data.n, particle);
01003
01004         return false;
01005     }
01006
01007     static inline Vec3f &normal(dataType &data)
01008     {
01009         return data.n;
01010     }
01011
01012     static inline void normal(dataType &data, UInt32 )
01013     {
01014         glNormal3fv(static_cast<GLfloat *>(data.n.getValues()));
01015     }
01016 };
01017
01018 struct NormalTraitGeneric3f : public ParticleTraits
01019 {
01020     struct dataType
01021     {
01022         const MFVec3f *norms;
01023         const Vec3f   *n;
01024               bool     perParticle;
01025               Vec3f    const_n;
01026     };
01027
01028     static inline void init(Particles *part, DrawEnv *, dataType &data)
01029     {
01030         GeoVec3fProperty *norms3f =
01031             dynamic_cast<GeoVec3fProperty *>(part->getNormals());
01032
01033         data.norms = norms3f->getFieldPtr();
01034
01035         data.perParticle = false;
01036
01037         if(norms3f != NULL)
01038         {
01039             if(norms3f->getSize() == 1)
01040             {
01041                 data.n = &(*(data.norms))[0];
01042             }
01043             else if(data.norms->size() == part->getPositions()->size())
01044             {
01045                 data.perParticle = true;
01046             }
01047             else
01048             {
01049                 data.const_n.setValues(0,1,0);
01050                 data.n = &data.const_n;
01051             }
01052         }
01053         else
01054         {
01055             data.const_n.setValues(0,1,0);
01056             data.n = &data.const_n;
01057         }
01058     }
01059
01060     static inline bool particle(dataType &data, UInt32 particle)
01061     {
01062         if(data.perParticle)
01063             data.n = &(*(data.norms))[particle];
01064
01065         return false;
01066     }
01067
01068     static inline const Vec3f &normal(dataType &data)
01069     {
01070         return *data.n;
01071     }
01072
01073     static inline void normal(dataType &data, UInt32 )
01074     {
01075         glNormal3fv(static_cast<const GLfloat *>(data.n->getValues()));
01076     }
01077 };
01078
01079 /* ParticlesDrawer base classes, define the common interface(s) */
01080
01081 struct OSG::ParticlesDrawer
01082 {
01083     virtual void draw(Particles *part,
01084                       DrawEnv   *pEnv,
01085                       UInt32 length) = 0;
01086
01087     virtual void drawIndexed(      Particles *part,
01088                                    DrawEnv   *pEnv,
01089                              const Int32     *index,
01090                                    UInt32     length) = 0;
01091
01092     virtual ~ParticlesDrawer()
01093     {
01094     }
01095 };
01096
01097 /* View-Dir aligned, indexed quad rendering */
01098
01099 template <class posTrait, class colTrait, class texTrait, class sizeTrait>
01100 struct drawViewDirQuads : public ParticlesDrawer
01101 {
01102     virtual void drawIndexed(      Particles *part,
01103                                    DrawEnv   *pEnv,
01104                              const Int32     *index,
01105                                    UInt32     length)
01106     {
01107         // get ModelView matrix to define the direction vectors
01108         Matrix camera  = pEnv->getCameraToWorld();
01109         Matrix toworld = pEnv->getObjectToWorld();
01110
01111
01112 /*
01113         DrawActionBase *action = pEnv->getOldAction();
01114 
01115         RenderAction *ra = dynamic_cast<RenderAction *>(action);
01116 
01117         if(ra != NULL)
01118         {
01119             toworld = ra->top_matrix();
01120         }
01121         else
01122         {
01123             action->getActNode()->getToWorld(toworld);
01124         }
01125  */
01126
01127         // normalize them, we don't want to neutralize scales in toworld
01128         toworld[0].normalize();
01129         toworld[1].normalize();
01130         toworld[2].normalize();
01131         toworld.transpose();
01132         camera.multLeft(toworld);
01133
01134         // Direction vectors
01135         Vec4f  d1, d2, d3, d4;
01136
01137         d1 = -1.0f * camera[0] + -1.0f * camera[1];
01138         d2 =  1.0f * camera[0] + -1.0f * camera[1];
01139         d3 =  1.0f * camera[0] +  1.0f * camera[1];
01140         d4 = -1.0f * camera[0] +  1.0f * camera[1];
01141
01142         // some variables for faster access
01143         GeoVectorProperty *pos  = part->getPositions();
01144
01145         // init traits
01146         typename colTrait::dataType colData;
01147         colTrait::init(part, pEnv, colData);
01148
01149         typename texTrait::dataType texData;
01150         texTrait::init(part, pEnv, texData);
01151
01152         typename sizeTrait::dataType sizeData;
01153         sizeTrait::init(part, pEnv, sizeData);
01154
01155         typename posTrait::dataType posData;
01156         posTrait::init(part, pEnv, posData, part->getPositions());
01157
01158         glBegin(GL_QUADS);
01159
01160         Int32 i;
01161
01162         for(UInt32 ii = 0; ii < length; ++ii)
01163         {
01164             i = index[ii];
01165
01166             if(i < 0 || i > Int32(pos->getSize()))
01167                 continue;
01168
01169             if(colTrait::particle (colData,  i))
01170                 continue;
01171
01172             if(texTrait::particle (texData,  i))
01173                 continue;
01174
01175             if(sizeTrait::particle(sizeData, i))
01176                 continue;
01177
01178             if(posTrait::particle(posData, i))
01179                 continue;
01180
01181             Real32 s = sizeTrait::size(sizeData, i)[0] / 2.f;
01182
01183             if(s == 0)
01184                 continue;
01185
01186             colTrait::vertex(colData, i, 0);
01187             texTrait::vertex(texData, 0, 0, 0);
01188             posTrait::vertex(posData, 0, d1, s);
01189
01190             colTrait::vertex(colData, i, 1);
01191             texTrait::vertex(texData, 1, 1, 0);
01192             posTrait::vertex(posData, 1, d2, s);
01193
01194             colTrait::vertex(colData, i, 2);
01195             texTrait::vertex(texData, 2, 1, 1);
01196             posTrait::vertex(posData, 2, d3, s);
01197
01198             colTrait::vertex(colData, i, 3);
01199             texTrait::vertex(texData, 3, 0, 1);
01200             posTrait::vertex(posData, 3, d4, s);
01201         }
01202
01203         glEnd();
01204     }
01205
01206     virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
01207     {
01208         // get ModelView matrix to define the direction vectors
01209
01210         Matrix camera  = pEnv->getCameraToWorld();
01211         Matrix toworld = pEnv->getObjectToWorld();
01212
01213 /*
01214         DrawActionBase *action = pEnv->getOldAction();
01215 
01216         RenderAction *ra = dynamic_cast<RenderAction *>(action);
01217 
01218         if(ra != NULL)
01219         {
01220             toworld = ra->top_matrix();
01221         }
01222         else
01223         {
01224             action->getActNode()->getToWorld(toworld);
01225         }
01226  */
01227
01228         // normalize them, we don't want to neutralize scales in toworld
01229         toworld[0].normalize();
01230         toworld[1].normalize();
01231         toworld[2].normalize();
01232         toworld.transpose();
01233         camera.multLeft(toworld);
01234
01235         // Direction vectors
01236         Vec4f  d1, d2, d3, d4;
01237
01238         d1 = -1.0f * camera[0] + -1.0f * camera[1];
01239         d2 =  1.0f * camera[0] + -1.0f * camera[1];
01240         d3 =  1.0f * camera[0] +  1.0f * camera[1];
01241         d4 = -1.0f * camera[0] +  1.0f * camera[1];
01242
01243         // some variables for faster access
01244
01245         // init traits
01246         typename colTrait::dataType colData;
01247         colTrait::init(part, pEnv, colData);
01248
01249         typename texTrait::dataType texData;
01250         texTrait::init(part, pEnv, texData);
01251
01252         typename sizeTrait::dataType sizeData;
01253         sizeTrait::init(part, pEnv, sizeData);
01254
01255         typename posTrait::dataType posData;
01256         posTrait::init(part, pEnv, posData, part->getPositions());
01257
01258         glBegin(GL_QUADS);
01259
01260         for(UInt32 i = 0; i < length; ++i)
01261         {
01262             if(colTrait::particle (colData,  i))
01263                 continue;
01264
01265             if(texTrait::particle (texData,  i))
01266                 continue;
01267
01268             if(sizeTrait::particle(sizeData, i))
01269                 continue;
01270
01271             if(posTrait::particle(posData, i))
01272                 continue;
01273
01274             Real32 s = sizeTrait::size(sizeData, i)[0] / 2.f;
01275
01276             if(s == 0)
01277                 continue;
01278
01279             colTrait::vertex(colData, i, 0);
01280             texTrait::vertex(texData, 0, 0, 0);
01281             posTrait::vertex(posData, 0, d1, s);
01282
01283             colTrait::vertex(colData, i, 1);
01284             texTrait::vertex(texData, 1, 1, 0);
01285             posTrait::vertex(posData, 1, d2, s);
01286
01287             colTrait::vertex(colData, i, 2);
01288             texTrait::vertex(texData, 2, 1, 1);
01289             posTrait::vertex(posData, 2, d3, s);
01290
01291             colTrait::vertex(colData, i, 3);
01292             texTrait::vertex(texData, 3, 0, 1);
01293             posTrait::vertex(posData, 3, d4, s);
01294         }
01295
01296         glEnd();
01297     }
01298 };
01299
01300
01301 /* Viewer aligned, indexed quad rendering */
01302
01303 template <class posTrait, class colTrait, class texTrait, class sizeTrait>
01304 struct drawViewerQuads : public ParticlesDrawer
01305 {
01306     virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
01307                              const Int32 *index, UInt32 length)
01308     {
01309         // get ModelView matrix to define the direction vectors
01310 //        Matrix camera,toworld;
01311
01312         Matrix camera  = pEnv->getCameraToWorld();
01313         Matrix toworld = pEnv->getObjectToWorld();
01314
01315 /*
01316         DrawActionBase *action = pEnv->getOldAction();
01317 
01318         RenderAction *ra = dynamic_cast<RenderAction *>(action);
01319 
01320         if(ra != NULL)
01321         {
01322             toworld = ra->top_matrix();
01323         }
01324         else
01325         {
01326             action->getActNode()->getToWorld(toworld);
01327         }
01328  */
01329
01330         // normalize them, we don't want to neutralize scales in toworld
01331         toworld[0].normalize();
01332         toworld[1].normalize();
01333         toworld[2].normalize();
01334         toworld.invert();
01335         camera.multLeft(toworld);
01336
01337         // Viewer position & up
01338         Pnt3f  vpos(camera[3]);
01339         Vec3f  vup (camera[1]);
01340         vup.normalize();
01341         Vec3f  vdir,vnorm;
01342
01343         // direction vector
01344         Vec4f d;
01345
01346         // some variables for faster access
01347         GeoVectorProperty *pos  = part->getPositions();
01348
01349         // init traits
01350         typename colTrait::dataType colData;
01351         colTrait::init(part, pEnv, colData);
01352
01353         typename texTrait::dataType texData;
01354         texTrait::init(part, pEnv, texData);
01355
01356         typename sizeTrait::dataType sizeData;
01357         sizeTrait::init(part, pEnv, sizeData);
01358
01359         typename posTrait::dataType posData;
01360         posTrait::init(part, pEnv, posData, part->getPositions());
01361
01362         glBegin(GL_QUADS);
01363
01364         Int32 i;
01365
01366         for(UInt32 ii = 0; ii < length; ++ii)
01367         {
01368             i = index[ii];
01369
01370             if(i < 0 || i > Int32(pos->getSize()))
01371                 continue;
01372
01373             if(colTrait::particle (colData,  i))
01374                 continue;
01375
01376             if(texTrait::particle (texData,  i))
01377                 continue;
01378
01379             if(sizeTrait::particle(sizeData, i))
01380                 continue;
01381
01382             if(posTrait::particle(posData, i))
01383                 continue;
01384
01385             Real32 s = sizeTrait::size(sizeData, i)[0] / 2.f;
01386
01387             if(s == 0)
01388                 continue;
01389
01390             // calc viewer-relative coord system
01391
01392             Pnt3f p = pos->getValue<Pnt3f>(i);
01393             vdir = vpos - p;
01394             vdir.normalize();
01395             vnorm = vup.cross(vdir);
01396
01397             d.setValues( -vnorm[0] - vup[0],
01398                          -vnorm[1] - vup[1],
01399                          -vnorm[2] - vup[2],
01400                          1 );
01401             colTrait::vertex(colData, i, 0);
01402             texTrait::vertex(texData, 0, 0, 0);
01403             posTrait::vertex(posData, 0, d, s);
01404
01405             d.setValues(  vnorm[0] - vup[0],
01406                           vnorm[1] - vup[1],
01407                           vnorm[2] - vup[2],
01408                          1 );
01409             colTrait::vertex(colData, i, 1);
01410             texTrait::vertex(texData, 1, 1, 0);
01411             posTrait::vertex(posData, 1, d, s);
01412
01413             d.setValues(  vnorm[0] + vup[0],
01414                           vnorm[1] + vup[1],
01415                           vnorm[2] + vup[2],
01416                          1 );
01417             colTrait::vertex(colData, i, 2);
01418             texTrait::vertex(texData, 2, 1, 1);
01419             posTrait::vertex(posData, 2, d, s);
01420
01421             d.setValues( -vnorm[0] + vup[0],
01422                          -vnorm[1] + vup[1],
01423                          -vnorm[2] + vup[2],
01424                          1 );
01425             colTrait::vertex(colData, i, 3);
01426             texTrait::vertex(texData, 3, 0, 1);
01427             posTrait::vertex(posData, 3, d, s);
01428         }
01429
01430         glEnd();
01431     }
01432
01433     virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
01434     {
01435         // get ModelView matrix to define the direction vectors
01436
01437         Matrix camera  = pEnv->getCameraToWorld();
01438         Matrix toworld = pEnv->getObjectToWorld();
01439
01440 /*
01441         DrawActionBase *action = pEnv->getOldAction();
01442 
01443         RenderAction *ra = dynamic_cast<RenderAction *>(action);
01444 
01445         if(ra != NULL)
01446         {
01447             toworld = ra->top_matrix();
01448         }
01449         else
01450         {
01451             action->getActNode()->getToWorld(toworld);
01452         }
01453  */
01454
01455         // normalize them, we don't want to neutralize scales in toworld
01456         toworld[0].normalize();
01457         toworld[1].normalize();
01458         toworld[2].normalize();
01459         toworld.invert();
01460         camera.multLeft(toworld);
01461
01462         // Viewer position & up
01463         Pnt3f  vpos(camera[3]);
01464         Vec3f  vup (camera[1]);
01465         vup.normalize();
01466         Vec3f  vdir,vnorm;
01467
01468         // direction vector
01469         Vec4f d;
01470
01471         // some variables for faster access
01472         GeoVectorProperty *pos = part->getPositions();
01473
01474         // init traits
01475         typename colTrait::dataType colData;
01476         colTrait::init(part, pEnv, colData);
01477
01478         typename texTrait::dataType texData;
01479         texTrait::init(part, pEnv, texData);
01480
01481         typename sizeTrait::dataType sizeData;
01482         sizeTrait::init(part, pEnv, sizeData);
01483
01484         typename posTrait::dataType posData;
01485         posTrait::init(part, pEnv, posData, part->getPositions());
01486
01487         glBegin(GL_QUADS);
01488
01489         for(UInt32 i = 0; i < length; ++i)
01490         {
01491             if(colTrait::particle (colData,  i))
01492                 continue;
01493
01494             if(texTrait::particle (texData,  i))
01495                 continue;
01496
01497             if(sizeTrait::particle(sizeData, i))
01498                 continue;
01499
01500             if(posTrait::particle(posData, i))
01501                 continue;
01502
01503             Real32 s = sizeTrait::size(sizeData, i)[0] / 2.f;
01504
01505             if(s == 0)
01506                 continue;
01507
01508             // calc viewer-relative coord system
01509
01510             Pnt3f p = pos->getValue<Pnt3f>(i);
01511             vdir = vpos - p;
01512             vdir.normalize();
01513             vnorm = vup.cross(vdir);
01514
01515             d.setValues( -vnorm[0] - vup[0],
01516                          -vnorm[1] - vup[1],
01517                          -vnorm[2] - vup[2],
01518                          1 );
01519             colTrait::vertex(colData, i, 0);
01520             texTrait::vertex(texData, 0, 0, 0);
01521             posTrait::vertex(posData, 0, d, s);
01522
01523             d.setValues(  vnorm[0] - vup[0],
01524                           vnorm[1] - vup[1],
01525                           vnorm[2] - vup[2],
01526                          1 );
01527             colTrait::vertex(colData, i, 1);
01528             texTrait::vertex(texData, 1, 1, 0);
01529             posTrait::vertex(posData, 1, d, s);
01530
01531             d.setValues(  vnorm[0] + vup[0],
01532                           vnorm[1] + vup[1],
01533                           vnorm[2] + vup[2],
01534                          1 );
01535             colTrait::vertex(colData, i, 2);
01536             texTrait::vertex(texData, 2, 1, 1);
01537             posTrait::vertex(posData, 2, d, s);
01538
01539             d.setValues( -vnorm[0] + vup[0],
01540                          -vnorm[1] + vup[1],
01541                          -vnorm[2] + vup[2],
01542                          1 );
01543             colTrait::vertex(colData, i, 3);
01544             texTrait::vertex(texData, 3, 0, 1);
01545             posTrait::vertex(posData, 3, d, s);
01546         }
01547
01548         glEnd();
01549     }
01550 };
01551
01552
01553
01554 /* Single color lines between secPos and pos */
01555
01556 template <class posTrait, class colTrait, class texTrait, class sizeTrait>
01557 struct drawLines : public ParticlesDrawer
01558 {
01559     virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
01560     {
01561         // some variables for faster access
01562
01563         // init traits
01564         typename colTrait::dataType colData;
01565         colTrait::init(part, pEnv, colData);
01566
01567         typename texTrait::dataType texData;
01568         texTrait::init(part, pEnv, texData);
01569
01570         typename sizeTrait::dataType sizeData;
01571         sizeTrait::init(part, pEnv, sizeData);
01572
01573         typename posTrait::dataType posData;
01574         posTrait::init(part, pEnv, posData, part->getPositions());
01575
01576         typename posTrait::dataType secPosData;
01577         posTrait::init(part, pEnv, secPosData, part->getSecPositions());
01578
01579         Real32 s = sizeTrait::size(sizeData, 0)[0];
01580
01581         glPushAttrib(GL_LINE_BIT);
01582         glLineWidth(s);
01583
01584         glBegin(GL_LINES);
01585
01586         for(UInt32 i = 0; i < length; ++i)
01587         {
01588             if(colTrait::particle (colData,  i))
01589                 continue;
01590
01591             if(texTrait::particle (texData,  i))
01592                 continue;
01593
01594             if(sizeTrait::particle(sizeData, i))
01595                 continue;
01596
01597             if(posTrait::particle(posData, i))
01598                 continue;
01599
01600             if(posTrait::particle(secPosData, i))
01601                 continue;
01602
01603             posTrait::vertex(posData);
01604             posTrait::vertex(secPosData);
01605         }
01606
01607         glEnd();
01608
01609         glPopAttrib();
01610     }
01611
01612     virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
01613                              const Int32 *index, UInt32 length)
01614     {
01615         // some variables for faster access
01616         GeoVectorProperty *pos  = part->getPositions();
01617
01618         // init traits
01619         typename colTrait::dataType colData;
01620         colTrait::init(part, pEnv, colData);
01621
01622         typename texTrait::dataType texData;
01623         texTrait::init(part, pEnv, texData);
01624
01625         typename sizeTrait::dataType sizeData;
01626         sizeTrait::init(part, pEnv, sizeData);
01627
01628         typename posTrait::dataType posData;
01629         posTrait::init(part, pEnv, posData, part->getPositions());
01630
01631         typename posTrait::dataType secPosData;
01632         posTrait::init(part, pEnv, secPosData, part->getSecPositions());
01633
01634         Real32 s = sizeTrait::size(sizeData, 0)[0];
01635
01636         glPushAttrib(GL_LINE_BIT);
01637         glLineWidth(s);
01638
01639         glBegin(GL_LINES);
01640
01641         Int32 i;
01642
01643         for(UInt32 ii = 0; ii < length; ++ii)
01644         {
01645             i = index[ii];
01646
01647             if(i < 0 || i > Int32(pos->getSize()))
01648                 continue;
01649
01650             if(colTrait::particle (colData,  i))
01651                 continue;
01652
01653             if(texTrait::particle (texData,  i))
01654                 continue;
01655
01656             if(sizeTrait::particle(sizeData, i))
01657                 continue;
01658
01659             if(posTrait::particle(posData, i))
01660                 continue;
01661
01662             if(posTrait::particle(secPosData, i))
01663                 continue;
01664
01665             posTrait::vertex(posData);
01666             posTrait::vertex(secPosData);
01667         }
01668
01669         glEnd();
01670
01671         glPopAttrib();
01672     }
01673 };
01674
01675 /*  Points at pos */
01676
01677 template <class posTrait, class colTrait, class texTrait, class sizeTrait>
01678 struct drawPoints : public ParticlesDrawer
01679 {
01680     virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
01681     {
01682         // some variables for faster access
01683         // init traits
01684         typename posTrait::dataType posData;
01685         posTrait::init(part, pEnv, posData, part->getPositions());
01686
01687         typename colTrait::dataType colData;
01688         colTrait::init(part, pEnv, colData);
01689
01690         typename sizeTrait::dataType sizeData;
01691         sizeTrait::init(part, pEnv, sizeData);
01692
01693         typename texTrait::dataType texData;
01694         texTrait::init(part, pEnv, texData);
01695
01696         sizeTrait::particle(sizeData, 0);
01697         Real32 s = sizeTrait::size(sizeData, 0)[0];
01698
01699         glPushAttrib(GL_POINT_BIT);
01700         glPointSize(s);
01701
01702         glBegin(GL_POINTS);
01703
01704         for(UInt32 i = 0; i < length; ++i)
01705         {
01706             if(colTrait::particle(colData, i))
01707                 continue;
01708
01709             if(posTrait::particle(posData, i))
01710                 continue;
01711
01712             if(texTrait::particle(texData, i))
01713                 continue;
01714
01715             texTrait::vertex(texData);
01716             posTrait::vertex(posData);
01717         }
01718
01719         glEnd();
01720
01721         glPopAttrib();
01722     }
01723
01724     virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
01725                              const Int32 *index, UInt32 length)
01726     {
01727         // some variables for faster access
01728         GeoVectorProperty *pos  = part->getPositions();
01729
01730         // init traits
01731         typename posTrait::dataType posData;
01732         posTrait::init(part, pEnv, posData, part->getPositions());
01733
01734         typename colTrait::dataType colData;
01735         colTrait::init(part, pEnv, colData);
01736
01737         typename sizeTrait::dataType sizeData;
01738         sizeTrait::init(part, pEnv, sizeData);
01739
01740         sizeTrait::particle(sizeData, 0);
01741         Real32 s = sizeTrait::size(sizeData, 0)[0];
01742
01743         glPushAttrib(GL_POINT_BIT);
01744         glPointSize(s);
01745
01746         glBegin(GL_POINTS);
01747
01748         Int32 i;
01749
01750         for(UInt32 ii = 0; ii < length; ++ii)
01751         {
01752             i = index[ii];
01753
01754             if(i < 0 || i > Int32(pos->getSize()))
01755                 continue;
01756
01757             if(colTrait::particle(colData, i))
01758                 continue;
01759
01760             if(posTrait::particle(posData, i))
01761                 continue;
01762
01763             posTrait::vertex(posData);
01764         }
01765
01766         glEnd();
01767
01768         glPopAttrib();
01769     }
01770 };
01771
01772 /* Geometry traits for drawing objects */
01773
01774 struct GeoTraitArrow : public ParticleTraits
01775 {
01776     typedef UInt8 dataType;
01777
01778     static inline void init(Particles *, DrawEnv *, dataType &)
01779     {
01780     }
01781
01782     static inline void exit(Particles *, DrawEnv *, dataType &)
01783     {
01784     }
01785
01786     static inline bool particle(dataType &, UInt32)
01787     {
01788         return false;
01789     }
01790
01791     static inline void draw(      dataType &,
01792                             const Pnt3f    &p,
01793                             const Pnt3f    &,
01794                                   Vec3f    &dx,
01795                                   Vec3f    &dy,
01796                                   Vec3f    &dz,
01797                             const Vec3f    &s)
01798     {
01799         dz*=s[2];
01800         dx*=s[0];
01801
01802         glNormal3fv(static_cast<GLfloat *>(dy.getValues()));
01803
01804         glBegin(GL_TRIANGLE_FAN);
01805
01806         glVertex3fv(static_cast<const GLfloat *>(p.getValues()));
01807
01808         glVertex3f(p[0] + dz[0] * .5f + dx[0]      ,
01809                    p[1] + dz[1] * .5f + dx[1]      ,
01810                    p[2] + dz[2] * .5f + dx[2]      );
01811
01812         glVertex3f(p[0] + dz[0] * .5f + dx[0] * .5f ,
01813                    p[1] + dz[1] * .5f + dx[1] * .5f ,
01814                    p[2] + dz[2] * .5f + dx[2] * .5f );
01815
01816         glVertex3f(p[0] + dz[0]       + dx[0] * .5f ,
01817                    p[1] + dz[1]       + dx[1] * .5f ,
01818                    p[2] + dz[2]       + dx[2] * .5f );
01819
01820         glVertex3f(p[0] + dz[0]       - dx[0] * .5f ,
01821                    p[1] + dz[1]       - dx[1] * .5f ,
01822                    p[2] + dz[2]       - dx[2] * .5f );
01823
01824         glVertex3f(p[0] + dz[0] * .5f - dx[0] * .5f ,
01825                    p[1] + dz[1] * .5f - dx[1] * .5f ,
01826                    p[2] + dz[2] * .5f - dx[2] * .5f );
01827
01828         glVertex3f(p[0] + dz[0] * .5f - dx[0]      ,
01829                    p[1] + dz[1] * .5f - dx[1]      ,
01830                    p[2] + dz[2] * .5f - dx[2]      );
01831
01832         glEnd();
01833     }
01834 };
01835
01836
01837 /* Geometry traits for drawing rectangles */
01838
01839 struct GeoTraitRectangle : public ParticleTraits
01840 {
01841     typedef UInt8 dataType;
01842
01843     static inline void init(Particles *, DrawEnv *, dataType &)
01844     {
01845         glBegin(GL_QUADS);
01846     }
01847
01848     static inline void exit(Particles *, DrawEnv *, dataType &)
01849     {
01850         glEnd();
01851     }
01852
01853     static inline bool particle(dataType &, UInt32)
01854     {
01855         return false;
01856     }
01857
01858     static inline void draw(      dataType &,
01859                             const Pnt3f    &p,
01860                             const Pnt3f    &sp,
01861                                   Vec3f    &dx,
01862                                   Vec3f    &dy,
01863                                   Vec3f    &,
01864                             const Vec3f    &s)
01865     {
01866         dx *= s[0] * .5f;
01867
01868         glNormal3fv(static_cast<GLfloat *>(dy.getValues()));
01869
01870         glVertex3f( p[0] - dx[0],
01871                     p[1] - dx[1],
01872                     p[2] - dx[2]);
01873
01874         glVertex3f( p[0] + dx[0],
01875                     p[1] + dx[1],
01876                     p[2] + dx[2]);
01877
01878         glVertex3f(sp[0] + dx[0],
01879                    sp[1] + dx[1],
01880                    sp[2] + dx[2]);
01881
01882         glVertex3f(sp[0] - dx[0],
01883                    sp[1] - dx[1],
01884                    sp[2] - dx[2]);
01885     }
01886 };
01887
01888
01889
01890 /* Objects using the pos/secpos/normal coordinate system for rendering */
01891
01892 template <class posTrait, class colTrait, class sizeTrait, class normalTrait,
01893           class geoTrait>
01894 struct drawObjects : public ParticlesDrawer
01895 {
01896     virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
01897     {
01898         // some variables for faster access
01899
01900         // init traits
01901         typename geoTrait::dataType geoData;
01902         geoTrait::init(part, pEnv, geoData);
01903
01904         typename colTrait::dataType colData;
01905         colTrait::init(part, pEnv, colData);
01906
01907         typename sizeTrait::dataType sizeData;
01908         sizeTrait::init(part, pEnv, sizeData);
01909
01910         typename normalTrait::dataType normalData;
01911         normalTrait::init(part, pEnv, normalData);
01912
01913         typename posTrait::dataType posData, secPosData;
01914         posTrait::init(part, pEnv, posData   , part->getPositions());
01915         posTrait::init(part, pEnv, secPosData, part->getSecPositions());
01916
01917         for(UInt32 i = 0; i < length; ++i)
01918         {
01919             if(geoTrait::particle (geoData,  i))
01920                 continue;
01921
01922             if(colTrait::particle (colData,  i))
01923                 continue;
01924
01925             if(sizeTrait::particle(sizeData, i))
01926                 continue;
01927
01928             if(normalTrait::particle(normalData, i))
01929                 continue;
01930
01931             if(posTrait::particle (posData,  i))
01932                 continue;
01933
01934             if(posTrait::particle (secPosData,  i))
01935                 continue;
01936
01937             // calc the coordinate system
01938
01939             Pnt3f &p  = posTrait   ::position(posData   );
01940             Pnt3f &sp = posTrait   ::position(secPosData);
01941             Vec3f &n  = normalTrait::normal  (normalData);
01942
01943             Vec3f dz(sp - p);
01944             dz.normalize();
01945
01946             Vec3f dx(n.cross(dz));
01947             if(dx.isZero())
01948             {
01949                 dx=Vec3f(1,0,0).cross(dz);
01950                 if(dx.isZero())
01951                 {
01952                     dx=Vec3f(0,1,0).cross(dz);
01953                     if(dx.isZero())
01954                     {
01955                         dx=Vec3f(0,0,1).cross(dz);
01956                     }
01957                     else
01958                     {
01959                         dx.setValues(0,0,0);
01960                     }
01961                 }
01962             }
01963             dx.normalize();
01964
01965             Vec3f dy(dx.cross(dz));
01966
01967             // now draw the geometry;
01968             geoTrait::draw(geoData, p, sp, dx, dy, dz,
01969                            sizeTrait::size(sizeData, i));
01970         }
01971
01972         geoTrait::exit(part, pEnv, geoData);
01973     }
01974
01975     virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
01976                              const Int32 *index, UInt32 length)
01977     {
01978         // some variables for faster access
01979         GeoVectorProperty *pos = part->getPositions();
01980
01981         // init traits
01982         typename geoTrait::dataType geoData;
01983         geoTrait::init(part, pEnv, geoData);
01984
01985         typename colTrait::dataType colData;
01986         colTrait::init(part, pEnv, colData);
01987
01988         typename sizeTrait::dataType sizeData;
01989         sizeTrait::init(part, pEnv, sizeData);
01990
01991         typename normalTrait::dataType normalData;
01992         normalTrait::init(part, pEnv, normalData);
01993
01994         typename posTrait::dataType posData, secPosData;
01995         posTrait::init(part, pEnv, posData   , part->getPositions());
01996         posTrait::init(part, pEnv, secPosData, part->getSecPositions());
01997
01998         Int32 i;
01999
02000         for(UInt32 ii = 0; ii < length; ++ii)
02001         {
02002             i = index[ii];
02003
02004             if(i < 0 || i > Int32(pos->getSize()))
02005                 continue;
02006
02007             if(geoTrait::particle (geoData,  i))
02008                 continue;
02009
02010             if(colTrait::particle (colData,  i))
02011                 continue;
02012
02013             if(sizeTrait::particle(sizeData, i))
02014                 continue;
02015
02016             if(normalTrait::particle(normalData, i))
02017                 continue;
02018
02019             if(posTrait::particle (posData,  i))
02020                 continue;
02021
02022             if(posTrait::particle (secPosData,  i))
02023                 continue;
02024
02025             // calc the coordinate system
02026
02027             Pnt3f &p  = posTrait   ::position(posData   );
02028             Pnt3f &sp = posTrait   ::position(secPosData);
02029             Vec3f &n  = normalTrait::normal  (normalData);
02030
02031             Vec3f dz(sp - p);
02032             dz.normalize();
02033
02034             Vec3f dx(n.cross(dz));
02035             if(dx.isZero())
02036             {
02037                 dx=Vec3f(1,0,0).cross(dz);
02038                 if(dx.isZero())
02039                 {
02040                     dx=Vec3f(0,1,0).cross(dz);
02041                     if(dx.isZero())
02042                     {
02043                         dx=Vec3f(0,0,1).cross(dz);
02044                     }
02045                     else
02046                     {
02047                         dx.setValues(0,0,0);
02048                     }
02049                 }
02050             }
02051             dx.normalize();
02052
02053             Vec3f dy(dx.cross(dz));
02054
02055             // now draw the geometry;
02056             geoTrait::draw(geoData, p, sp, dx, dy, dz,
02057                            sizeTrait::size(sizeData, i));
02058         }
02059
02060         geoTrait::exit(part, pEnv, geoData);
02061     }
02062 };
02063
02064
02065 /* Objects using the pos/secpos and viewer-directed coordinate system for
02066    rendering */
02067
02068 template <class posTrait, class colTrait, class sizeTrait,
02069           class geoTrait>
02070 struct drawViewerObjects : public ParticlesDrawer
02071 {
02072     virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
02073     {
02074         Matrix camera  = pEnv->getCameraToWorld();
02075         Matrix toworld = pEnv->getObjectToWorld();
02076
02077 //        DrawActionBase *action = pEnv->getOldAction();
02078         // get ModelView matrix to define the direction vectors
02079 //        Matrix camera,toworld;
02080 //        action->getCamera()->getBeacon()->getToWorld(camera);
02081 //        action->getActNode()->getToWorld(toworld);
02082         // normalize them, we don't want to neutralize scales in toworld
02083         toworld[0].normalize();
02084         toworld[1].normalize();
02085         toworld[2].normalize();
02086         toworld.invert();
02087         camera.multLeft(toworld);
02088
02089         // Viewer position & up
02090         Pnt3f  vpos(camera[3]);
02091
02092         // some variables for faster access
02093
02094         // init traits
02095         typename geoTrait::dataType geoData;
02096         geoTrait::init(part, pEnv, geoData);
02097
02098         typename colTrait::dataType colData;
02099         colTrait::init(part, pEnv, colData);
02100
02101         typename sizeTrait::dataType sizeData;
02102         sizeTrait::init(part, pEnv, sizeData);
02103
02104         typename posTrait::dataType posData, secPosData;
02105         posTrait::init(part, pEnv, posData   , part->getPositions());
02106         posTrait::init(part, pEnv, secPosData, part->getSecPositions());
02107
02108         for(UInt32 i = 0; i < length; ++i)
02109         {
02110             if(geoTrait::particle (geoData,  i))
02111                 continue;
02112
02113             if(colTrait::particle (colData,  i))
02114                 continue;
02115
02116             if(sizeTrait::particle(sizeData, i))
02117                 continue;
02118
02119             if(posTrait::particle (posData,  i))
02120                 continue;
02121
02122             if(posTrait::particle (secPosData,  i))
02123                 continue;
02124
02125             // calc the coordinate system
02126
02127             Pnt3f &p  = posTrait::position(posData   );
02128             Pnt3f &sp = posTrait::position(secPosData);
02129             Vec3f  n  = vpos - p;
02130
02131             Vec3f dz(sp - p);
02132             dz.normalize();
02133
02134             Vec3f dx(n.cross(dz));
02135             if(dx.isZero())
02136             {
02137                 dx=Vec3f(1,0,0).cross(dz);
02138                 if(dx.isZero())
02139                 {
02140                     dx=Vec3f(0,1,0).cross(dz);
02141                     if(dx.isZero())
02142                     {
02143                         dx=Vec3f(0,0,1).cross(dz);
02144                     }
02145                     else
02146                     {
02147                         dx.setValues(0,0,0);
02148                     }
02149                 }
02150             }
02151             dx.normalize();
02152
02153             Vec3f dy(dx.cross(dz));
02154
02155             // now draw the geometry;
02156             geoTrait::draw(geoData, p, sp, dx, dy, dz,
02157                            sizeTrait::size(sizeData, i));
02158         }
02159
02160         geoTrait::exit(part, pEnv, geoData);
02161    }
02162
02163     virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
02164                              const Int32 *index, UInt32 length)
02165     {
02166         Matrix camera  = pEnv->getCameraToWorld();
02167         Matrix toworld = pEnv->getObjectToWorld();
02168
02169 //        DrawActionBase *action = pEnv->getOldAction();
02170         // get ModelView matrix to define the direction vectors
02171 //        Matrix camera,toworld;
02172 //        action->getCamera()->getBeacon()->getToWorld(camera);
02173 //        action->getActNode()->getToWorld(toworld);
02174         // normalize them, we don't want to neutralize scales in toworld
02175         toworld[0].normalize();
02176         toworld[1].normalize();
02177         toworld[2].normalize();
02178         toworld.invert();
02179         camera.multLeft(toworld);
02180
02181         // Viewer position & up
02182         Pnt3f  vpos(camera[3]);
02183
02184         // some variables for faster access
02185         GeoVectorProperty *pos = part->getPositions();
02186
02187         // init traits
02188         typename geoTrait::dataType geoData;
02189         geoTrait::init(part, pEnv, geoData);
02190
02191         typename colTrait::dataType colData;
02192         colTrait::init(part, pEnv, colData);
02193
02194         typename sizeTrait::dataType sizeData;
02195         sizeTrait::init(part, pEnv, sizeData);
02196
02197         typename posTrait::dataType posData, secPosData;
02198         posTrait::init(part, pEnv, posData   , part->getPositions());
02199         posTrait::init(part, pEnv, secPosData, part->getSecPositions());
02200
02201         Int32 i;
02202
02203         for(UInt32 ii = 0; ii < length; ++ii)
02204         {
02205             i = index[ii];
02206
02207             if(i < 0 || i > Int32(pos->getSize()))
02208                 continue;
02209
02210             if(geoTrait::particle (geoData,  i))
02211                 continue;
02212
02213             if(colTrait::particle (colData,  i))
02214                 continue;
02215
02216             if(sizeTrait::particle(sizeData, i))
02217                 continue;
02218
02219             if(posTrait::particle (posData,  i))
02220                 continue;
02221
02222             if(posTrait::particle (secPosData,  i))
02223                 continue;
02224
02225             // calc the coordinate system
02226
02227             Pnt3f &p  = posTrait   ::position(posData   );
02228             Pnt3f &sp = posTrait   ::position(secPosData);
02229             Vec3f  n  = vpos - p;
02230
02231             Vec3f dz(sp - p);
02232             dz.normalize();
02233
02234             Vec3f dx(n.cross(dz));
02235             if(dx.isZero())
02236             {
02237                 dx=Vec3f(1,0,0).cross(dz);
02238                 if(dx.isZero())
02239                 {
02240                     dx=Vec3f(0,1,0).cross(dz);
02241                     if(dx.isZero())
02242                     {
02243                         dx=Vec3f(0,0,1).cross(dz);
02244                     }
02245                     else
02246                     {
02247                         dx.setValues(0,0,0);
02248                     }
02249                 }
02250             }
02251             dx.normalize();
02252
02253             Vec3f dy(dx.cross(dz));
02254
02255             // now draw the geometry;
02256             geoTrait::draw(geoData, p, sp, dx, dy, dz,
02257                            sizeTrait::size(sizeData, i));
02258         }
02259
02260         geoTrait::exit(part, pEnv, geoData);
02261     }
02262 };
02263
02264
02265 /* Static coordinates quad, pass all parameters to shader */
02266
02267 template <class posTrait, class secPosTrait, class colTrait, class texTrait,
02268           class sizeTrait, class normalTrait>
02269 struct drawShaderQuads : public ParticlesDrawer
02270 {
02271     virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
02272                              const Int32 *index, UInt32 length)
02273     {
02274         Window *win = pEnv->getWindow();
02275
02276         void (OSG_APIENTRY*_glMultiTexCoord3fvARB)(GLenum which,
02277                                                    GLubyte * data)=
02278             reinterpret_cast<void (OSG_APIENTRY*) (GLenum which,
02279                                                    GLubyte * data)>(
02280                 win->getFunction(_funcglMultiTexCoord3fvARB));
02281
02282         // init traits
02283         typename colTrait::dataType colData;
02284         colTrait::init(part, pEnv, colData);
02285
02286         typename texTrait::dataType texData;
02287         texTrait::init(part, pEnv, texData);
02288
02289         typename sizeTrait::dataType sizeData;
02290         sizeTrait::init(part, pEnv, sizeData);
02291
02292         typename normalTrait::dataType normalData;
02293         normalTrait::init(part, pEnv, normalData);
02294
02295         typename posTrait::dataType posData;
02296         posTrait::init(part, pEnv, posData, part->getPositions());
02297
02298         typename secPosTrait::dataType secPosData;
02299         secPosTrait::init(part, pEnv, secPosData, part->getSecPositions());
02300
02301         GeoVectorProperty *pos = part->getPositions();
02302
02303         glBegin(GL_QUADS);
02304
02305         Int32 i;
02306
02307         for(UInt32 ii = 0; ii < length; ++ii)
02308         {
02309             i = index[ii];
02310
02311             if(i < 0 || i > Int32(pos->getSize()))
02312                 continue;
02313
02314             if(colTrait::particle (colData,  i))
02315                 continue;
02316
02317             if(texTrait::particle(texData, i))
02318                 continue;
02319
02320             if(sizeTrait::particle(sizeData, i))
02321                 continue;
02322
02323             if(normalTrait::particle(normalData, i))
02324                 continue;
02325
02326             if(posTrait::particle(posData, i))
02327                 continue;
02328
02329             if(secPosTrait::particle(secPosData, i))
02330                 continue;
02331
02332
02333             Vec3f s = sizeTrait::size(sizeData, i);
02334
02335             if(s[0] == 0)
02336                 continue;
02337
02338             normalTrait::normal(normalData, 0);
02339
02340             _glMultiTexCoord3fvARB(
02341                 GL_TEXTURE1_ARB,
02342                 reinterpret_cast<GLubyte *>(
02343                     posTrait::position(posData).getValues()));
02344
02345             _glMultiTexCoord3fvARB(
02346                 GL_TEXTURE2_ARB,
02347                 reinterpret_cast<GLubyte *>(
02348                     secPosTrait::position(secPosData).getValues()));
02349
02350             _glMultiTexCoord3fvARB(GL_TEXTURE3_ARB,
02351                                    reinterpret_cast<GLubyte *>(s.getValues()));
02352
02353             texTrait::vertex(texData, 0, 0, 0);
02354             glVertex2f      (-.5f, -.5f);
02355             texTrait::vertex(texData, 0, 1, 0);
02356             glVertex2f      ( .5f, -.5f);
02357             texTrait::vertex(texData, 0, 1, 1);
02358             glVertex2f      ( .5f,  .5f);
02359             texTrait::vertex(texData, 0, 0, 1);
02360             glVertex2f      (-.5f,  .5f);
02361         }
02362
02363         glEnd();
02364     }
02365
02366     virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
02367     {
02368         Window *win = pEnv->getWindow();
02369
02370         void (OSG_APIENTRY*_glMultiTexCoord3fvARB)(GLenum which,
02371                                                    GLubyte * data)=
02372             reinterpret_cast<void (OSG_APIENTRY*) (GLenum which,
02373                                                    GLubyte * data)>(
02374                 win->getFunction(_funcglMultiTexCoord3fvARB));
02375
02376         // init traits
02377         typename colTrait::dataType colData;
02378         colTrait::init(part, pEnv, colData);
02379
02380         typename texTrait::dataType texData;
02381         texTrait::init(part, pEnv, texData);
02382
02383         typename sizeTrait::dataType sizeData;
02384         sizeTrait::init(part, pEnv, sizeData);
02385
02386         typename normalTrait::dataType normalData;
02387         normalTrait::init(part, pEnv, normalData);
02388
02389         typename posTrait::dataType posData;
02390         posTrait::init(part, pEnv, posData, part->getPositions());
02391
02392         typename secPosTrait::dataType secPosData;
02393         secPosTrait::init(part, pEnv, secPosData, part->getSecPositions());
02394
02395         glBegin(GL_QUADS);
02396
02397         for(UInt32 i = 0; i < length; ++i)
02398         {
02399             if(colTrait::particle (colData,  i))
02400                 continue;
02401
02402             if(texTrait::particle(texData, i))
02403                 continue;
02404
02405             if(sizeTrait::particle(sizeData, i))
02406                 continue;
02407
02408             if(normalTrait::particle(normalData, i))
02409                 continue;
02410
02411             if(posTrait::particle(posData, i))
02412                 continue;
02413
02414             if(secPosTrait::particle(secPosData, i))
02415                 continue;
02416
02417
02418             Vec3f s = sizeTrait::size(sizeData, i);
02419
02420             if(s[0] == 0)
02421                 continue;
02422
02423             normalTrait::normal(normalData, 0);
02424
02425             _glMultiTexCoord3fvARB(
02426                 GL_TEXTURE1_ARB,
02427                 reinterpret_cast<GLubyte *>(
02428                     posTrait::position(posData).getValues()));
02429
02430             _glMultiTexCoord3fvARB(
02431                 GL_TEXTURE2_ARB,
02432                 reinterpret_cast<GLubyte *>(
02433                     secPosTrait::position(secPosData).getValues()));
02434
02435             _glMultiTexCoord3fvARB(GL_TEXTURE3_ARB,
02436                                    reinterpret_cast<GLubyte *>(s.getValues()));
02437
02438             texTrait::vertex(texData, 0, 0, 0);
02439             glVertex2f      (-.5f, -.5f);
02440             texTrait::vertex(texData, 0, 1, 0);
02441             glVertex2f      ( .5f, -.5f);
02442             texTrait::vertex(texData, 0, 1, 1);
02443             glVertex2f      ( .5f,  .5f);
02444             texTrait::vertex(texData, 0, 0, 1);
02445             glVertex2f      (-.5f,  .5f);
02446         }
02447
02448         glEnd();
02449     }
02450 };
02451
02452
02453 /* Static coordinates strips with y coordinates between -.5 and .5, split
02454    into size[2] parts, pass all parameters to shader */
02455
02456 template <class posTrait, class secPosTrait, class colTrait, class texTrait,
02457           class sizeTrait, class normalTrait>
02458 struct drawShaderStrips : public ParticlesDrawer
02459 {
02460     virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
02461                              const Int32 *index, UInt32 length)
02462     {
02463         Window *win = pEnv->getWindow();
02464
02465         void (OSG_APIENTRY*_glMultiTexCoord3fvARB)(GLenum which,
02466                                                    GLubyte * data)=
02467             reinterpret_cast<void (OSG_APIENTRY*) (GLenum which,
02468                                                    GLubyte * data)>(
02469                 win->getFunction(_funcglMultiTexCoord3fvARB));
02470
02471         // init traits
02472         typename colTrait::dataType colData;
02473         colTrait::init(part, pEnv, colData);
02474
02475         typename texTrait::dataType texData;
02476         texTrait::init(part, pEnv, texData);
02477
02478         typename sizeTrait::dataType sizeData;
02479         sizeTrait::init(part, pEnv, sizeData);
02480
02481         typename normalTrait::dataType normalData;
02482         normalTrait::init(part, pEnv, normalData);
02483
02484         typename posTrait::dataType posData;
02485         posTrait::init(part, pEnv, posData, part->getPositions());
02486
02487         typename secPosTrait::dataType secPosData;
02488         secPosTrait::init(part, pEnv, secPosData, part->getSecPositions());
02489
02490         GeoVectorProperty *pos = part->getPositions();
02491
02492         Int32 i;
02493
02494         for(UInt32 ii = 0; ii < length; ++ii)
02495         {
02496             i = index[ii];
02497
02498             if(i < 0 || i > Int32(pos->getSize()))
02499                 continue;
02500
02501             if(colTrait::particle (colData,  i))
02502                 continue;
02503
02504             if(texTrait::particle(texData, i))
02505                 continue;
02506
02507             if(sizeTrait::particle(sizeData, i))
02508                 continue;
02509
02510             if(normalTrait::particle(normalData, i))
02511                 continue;
02512
02513             if(posTrait::particle(posData, i))
02514                 continue;
02515
02516             if(secPosTrait::particle(secPosData, i))
02517                 continue;
02518
02519
02520             Vec3f s = sizeTrait::size(sizeData, i);
02521
02522             if(s[0] == 0)
02523                 continue;
02524
02525             normalTrait::normal(normalData, 0);
02526
02527             _glMultiTexCoord3fvARB(
02528                 GL_TEXTURE1_ARB,
02529                 reinterpret_cast<GLubyte *>(
02530                     posTrait::position(posData).getValues()));
02531
02532             _glMultiTexCoord3fvARB(
02533                 GL_TEXTURE2_ARB,
02534                 reinterpret_cast<GLubyte *>(
02535                     secPosTrait::position(secPosData).getValues()));
02536
02537             _glMultiTexCoord3fvARB(GL_TEXTURE3_ARB,
02538                                    reinterpret_cast<GLubyte *>(s.getValues()));
02539
02540             glBegin(GL_QUAD_STRIP);
02541
02542             UInt32 n = static_cast<UInt32>(s[2]);
02543             Real32 step = 1.f / (n-1);
02544             Real32 v = 0.f;
02545             for(UInt32 y = 0; y < n; ++y, v += step)
02546             {
02547                 texTrait::vertex(texData, 0, 0, v);
02548                 glVertex2f  (-.5f, v-.5f);
02549                 texTrait::vertex(texData, 0, 1, v);
02550                 glVertex2f  ( .5f, v-.5f);
02551             }
02552
02553             glEnd();
02554         }
02555
02556     }
02557
02558     virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
02559     {
02560         Window *win = pEnv->getWindow();
02561
02562         void (OSG_APIENTRY*_glMultiTexCoord3fvARB) (GLenum which,
02563                                                     GLubyte * data)=
02564             reinterpret_cast<void (OSG_APIENTRY*) (GLenum which,
02565                                                    GLubyte * data)>(
02566                 win->getFunction(_funcglMultiTexCoord3fvARB));
02567
02568         // init traits
02569         typename colTrait::dataType colData;
02570         colTrait::init(part, pEnv, colData);
02571
02572         typename texTrait::dataType texData;
02573         texTrait::init(part, pEnv, texData);
02574
02575         typename sizeTrait::dataType sizeData;
02576         sizeTrait::init(part, pEnv, sizeData);
02577
02578         typename normalTrait::dataType normalData;
02579         normalTrait::init(part, pEnv, normalData);
02580
02581         typename posTrait::dataType posData;
02582         posTrait::init(part, pEnv, posData, part->getPositions());
02583
02584         typename secPosTrait::dataType secPosData;
02585         secPosTrait::init(part, pEnv, secPosData, part->getSecPositions());
02586
02587         for(UInt32 i = 0; i < length; ++i)
02588         {
02589             if(colTrait::particle (colData,  i))
02590                 continue;
02591
02592             if(texTrait::particle(texData, i))
02593                 continue;
02594
02595             if(sizeTrait::particle(sizeData, i))
02596                 continue;
02597
02598             if(normalTrait::particle(normalData, i))
02599                 continue;
02600
02601             if(posTrait::particle(posData, i))
02602                 continue;
02603
02604             if(secPosTrait::particle(secPosData, i))
02605                 continue;
02606
02607
02608             Vec3f s = sizeTrait::size(sizeData, i);
02609
02610             if(s[0] == 0)
02611                 continue;
02612
02613             normalTrait::normal(normalData, 0);
02614
02615             _glMultiTexCoord3fvARB(
02616                 GL_TEXTURE1_ARB,
02617                 reinterpret_cast<GLubyte *>(
02618                     posTrait::position(posData).getValues()));
02619
02620             _glMultiTexCoord3fvARB(
02621                 GL_TEXTURE2_ARB,
02622                 reinterpret_cast<GLubyte *>(
02623                     secPosTrait::position(secPosData).getValues()));
02624
02625             _glMultiTexCoord3fvARB(GL_TEXTURE3_ARB,
02626                                    reinterpret_cast<GLubyte *>(s.getValues()));
02627
02628             glBegin(GL_QUAD_STRIP);
02629
02630             UInt32 n = static_cast<UInt32>(s[2]);
02631             Real32 step = 1.f / (n-1);
02632             Real32 v = 0.f;
02633             for(UInt32 y = 0; y < n; ++y, v += step)
02634             {
02635                 texTrait::vertex(texData, 0, 0, v);
02636                 glVertex2f  (-.5f, v-.5f);
02637                 texTrait::vertex(texData, 0, 1, v);
02638                 glVertex2f  ( .5f, v-.5f);
02639             }
02640
02641             glEnd();
02642         }
02643     }
02644 };
02645
02646
02647
02648
02649 /* Sorting functions */
02650
02651
02652 struct sorter
02653 {
02654     sorter() {}
02655
02656     sorter(Real32 value, Int32 index)
02657     {
02658         _value=value;
02659         _index=index;
02660     }
02661
02662     bool operator<(const sorter &a) const
02663     {
02664         if(_value < a._value)
02665             return true;
02666
02667         return false;
02668     }
02669
02670     bool operator<=(const sorter &a) const
02671     {
02672         if(_value <= a._value)
02673             return true;
02674
02675         return false;
02676     }
02677
02678     bool operator>(const sorter &a) const
02679     {
02680         return ! (a < *this);
02681     }
02682
02683     bool operator>=(const sorter &a) const
02684     {
02685         return ! (a <= *this);
02686     }
02687
02688     Real32 _value;
02689     Int32  _index;
02690 };
02691
02692 Int32 *Particles::calcIndex(DrawEnv *pEnv,
02693                             UInt32  &len,
02694                             Int32   *index)
02695 {
02696     // some variables for faster access
02697           GeoVectorProperty *pos     = getPositions();
02698     const MFInt32           *indices = getMFIndices();
02699
02700     // get ModelView matrix to define the direction vectors
02701 //    Matrix camera,toworld;
02702
02703     Matrix camera  = pEnv->getCameraToWorld();
02704     Matrix toworld = pEnv->getObjectToWorld();
02705
02706 /*
02707     RenderAction *ra = dynamic_cast<RenderAction *>(pEnv->getOldAction());
02708 
02709     if(ra != NULL)
02710     {
02711         toworld = ra->top_matrix();
02712     }
02713  */
02714
02715     toworld.invert();
02716     camera.multLeft(toworld);
02717
02718     Pnt3f refpoint(camera[3].getValues());
02719
02720     if(getMode() == ViewDirQuads)
02721         camera.invert();
02722
02723     Pnt3f p,q;
02724     UInt32 size;
02725
02726     if(indices->size() > 0)
02727     {
02728         if(getNumParticles() == -1)
02729         {
02730             size = indices->size();
02731         }
02732         else
02733         {
02734             size = getNumParticles();
02735         }
02736     }
02737     else
02738     {
02739         if(getNumParticles() == -1)
02740         {
02741             size = pos->size();
02742         }
02743         else
02744         {
02745             size = getNumParticles();
02746         }
02747     }
02748
02749     std::vector<sorter> sorterList(size);
02750
02751     len = 0;
02752     UInt32 i;
02753
02754     if(getMode() == ViewDirQuads)
02755     {
02756         if(indices->size() > 0)
02757         {
02758             for(i = 0; i < size; i++)
02759             {
02760                 if((*(indices))[i] < 0 ||
02761                    (*(indices))[i] > Int32(pos->size()))
02762                     continue;
02763
02764                 sorterList[len]._index = (*(indices))[i];
02765
02766                 pos->getValue(p,i);
02767                 camera.mult(p, p);
02768                 sorterList[len]._value = p[2];
02769
02770                 len++;
02771             }
02772         }
02773         else
02774         {
02775             for(i = 0; i < size; i++)
02776             {
02777                 sorterList[len]._index = i;
02778
02779                 pos->getValue(p,i);
02780                 camera.mult(p, p);
02781                 sorterList[len]._value = p[2];
02782
02783                 len++;
02784             }
02785         }
02786     }
02787     else
02788     {
02789         if(indices->size() > 0)
02790         {
02791             for(i = 0; i < size; i++)
02792             {
02793                 if((*(indices))[i] < 0 ||
02794                    (*(indices))[i] > Int32(pos->size()))
02795                     continue;
02796
02797                 sorterList[len]._index = (*(indices))[i];
02798
02799                 pos->getValue(p,i);
02800                 sorterList[len]._value = - refpoint.dist2(p);
02801
02802                 len++;
02803             }
02804         }
02805         else
02806         {
02807             for(i = 0; i < size; i++)
02808             {
02809                 sorterList[len]._index = i;
02810
02811                 pos->getValue(p,i);
02812                 sorterList[len]._value = - refpoint.dist2(p);
02813
02814                 len++;
02815             }
02816         }
02817     }
02818
02819     std::sort(sorterList.begin(), sorterList.begin() + len);
02820
02821     if(index == NULL)
02822         index=new Int32[len];
02823
02824     if(getDrawOrder() == FrontToBack)
02825     {
02826         for(i = 0; i<len; i++)
02827         {
02828             index[i] = sorterList[len - 1 - i]._index;
02829         }
02830     }
02831     else
02832     {
02833         for(i = 0; i<len; i++)
02834         {
02835             index[i] = sorterList[i]._index;
02836         }
02837     }
02838
02839     return index;
02840 }
02841
02844 #endif // remove from user docu
02845 
02848 Action::ResultE Particles::drawPrimitives(DrawEnv *pEnv)
02849 {
02850     // some variables for faster access
02851           GeoVectorProperty *pos  = getPositions();
02852           GeoVectorProperty *col  = getColors();
02853           GeoVectorProperty *norm = getNormals();
02854     const MFVec3f           *size = getMFSizes();
02855
02856     if((size   ->size() > 1 && size   ->size() != pos->getSize())  ||
02857        (col  != NULL && col->getSize()  != 1 &&
02858                         col->getSize()  != pos->getSize())       ||
02859        (norm != NULL && norm->getSize() != 1 &&
02860                         norm->getSize() != pos->getSize())
02861       )
02862     {
02863         FWARNING(("Particles::draw: inconsistent attributes "
02864                     "(p:%d s:%d c:%d)!\n",
02865                     pos->getSize(), size->size(),
02866                   (col != NULL)? int(col->getSize()) : -1));
02867         return Action::Continue;
02868     }
02869
02870     ParticlesDrawer *drawer = findDrawer();
02871
02872     if(drawer == NULL)
02873     {
02874         FWARNING(("Particles 0x%p: couldn't find drawer!\n", this));
02875         return Action::Continue;;
02876     }
02877
02878     const Int32 *index = NULL;
02879     UInt32 length = 0;
02880     bool freeIndex = false;
02881
02882     if(_sfDrawOrder.getValue() != Particles::Any)
02883     {
02884         if(getDynamic())
02885         {
02886             index = calcIndex(pEnv,length);
02887         }
02888         else
02889         {
02890             if(!getBsp().created())
02891             {
02892                 editBsp().build(this);
02893             }
02894
02895 //            Matrix modelview,toworld;
02896
02897             Matrix modelview = pEnv->getCameraToWorld();
02898             Matrix toworld   = pEnv->getObjectToWorld();
02899
02900 /*
02901             RenderAction *ra = dynamic_cast<RenderAction *>(
02902                 pEnv->getOldAction());
02903 
02904             if(ra != NULL)
02905             {
02906                 toworld = ra->top_matrix();
02907             }
02908             else
02909             {
02910                 pEnv->getOldAction()->getActNode()->getToWorld(toworld);
02911             }
02912  */
02913 //            action->getCamera()->getBeacon()->getToWorld(modelview);
02914 //            action->getActNode()->getToWorld(toworld);
02915
02916             toworld.invert();
02917             modelview.mult(toworld);
02918
02919             Pnt3f ref(modelview[3][0],modelview[3][1],
02920                       modelview[3][2]);
02921             Vec3f refvec(  modelview[2][0],modelview[2][1],
02922                       modelview[2][2]);
02923
02924             index = getBsp().traverse(ref,length);
02925         }
02926         freeIndex = true;
02927     }
02928     else if (getMFIndices()->size() > 0)
02929     {
02930         index  = &(getMFIndices()->getValues()[0]);
02931         if(getNumParticles() == -1)
02932         {
02933             length = getMFIndices()->size();
02934         }
02935         else
02936         {
02937             length = getNumParticles();
02938         }
02939     }
02940
02941     if(index != NULL)
02942     {
02943         if(length > 0)
02944             drawer->drawIndexed(this,pEnv,index,length);
02945     }
02946     else
02947     {
02948         if(getNumParticles() == -1)
02949         {
02950             drawer->draw(this,pEnv,pos->getSize());
02951         }
02952         else if(getNumParticles() > 0)
02953         {
02954             drawer->draw(this,pEnv,getNumParticles());
02955         }
02956     }
02957
02958     if(freeIndex)
02959         delete [] index;
02960
02961     return Action::Continue;
02962 }
02963
02966 ParticlesDrawer *Particles::findDrawer(void)
02967 {
02968     if(getPositions() == NULL)
02969         return NULL;
02970
02971     UInt8 mode;
02972     enum { part = 0, sing, none } size,normal,color,tex,secpos;
02973
02974     mode = getMode();
02975
02976     // find the parameters' use
02977
02978     size =   (getMFSizes()->size()      == getPositions()->getSize()) ? part :
02979              (getMFSizes()->size()      == 1                        ) ? sing :
02980                                                                         none;
02981     normal = (getNormals() != NULL &&
02982               getNormals()->getSize()   == getPositions()->getSize()) ? part :
02983              (getNormals() != NULL &&
02984               getNormals()->getSize()   == 1                        ) ? sing :
02985                                                                         none;
02986     secpos = (getSecPositions() != NULL &&
02987               getSecPositions()->getSize()== getPositions()->getSize())?part :
02988              (getSecPositions() != NULL &&
02989               getSecPositions()->getSize()== 1                        )?sing :
02990                                                                         none;
02991     color =  (getColors() != NULL &&
02992               getColors()->getSize()    == getPositions()->getSize()) ? part :
02993              (getColors() != NULL &&
02994               getColors()->getSize()    == 1                        ) ? sing :
02995                                                                         none;
02996     tex =    (getMFTextureZs()->size()  == getPositions()->getSize()) ? part :
02997              (getMFTextureZs()->size()  == 1                        ) ? sing :
02998                                                                         none;
02999
03000     // check if the used types are common cases
03001
03002 /*
03003     bool normalIs3f = (getNormals()   != NULL &&
03004                        getNormals()->getFormat()      == GL_FLOAT);
03005 
03006     bool colorIs3f  = (getColors()    != NULL &&
03007                        getColors()->getFormat()       == GL_FLOAT &&
03008                        getColors()->getDimension()    == 3);
03009  */
03010
03011     bool posIs3f    = (getPositions() != NULL &&
03012                        getPositions()->getFormat()    == GL_FLOAT &&
03013                        getPositions()->getDimension() == 3);
03014
03015     // now find the drawer
03016
03017     // main difference: mode, as only a subset of the attributes is used
03018     // in the different modes
03019
03020     // this is where to add fast pathes...
03021     // don't go overboard, as every path adds code, and code bloat is
03022     // easily obtained here.
03023
03024     switch(mode)
03025     {
03026     case Points:
03027     {
03028         static ParticlesDrawer *fallback =
03029                     new drawPoints<PosTraitGeneric,ColTraitGeneric,
03030                                    TexTraitGeneric,SizeTraitGeneric>;
03031
03032         return fallback;
03033     }
03034
03035     case Lines:
03036     {
03037         if(secpos == none)
03038         {
03039             FWARNING(("Particles::findDrawer: Need secondary positions for "
03040                       "type Lines!\n"));
03041             return NULL;
03042         }
03043
03044         static ParticlesDrawer *fallback =
03045                     new drawLines<PosTraitGeneric,ColTraitGeneric,
03046                                   TexTraitGeneric,SizeTraitGeneric>;
03047
03048         return fallback;
03049     }
03050
03051     case ViewDirQuads:
03052     {
03053         static ParticlesDrawer *fallback =
03054                     new drawViewDirQuads<PosTraitGeneric,ColTraitGeneric,
03055                                          TexTraitGeneric,SizeTraitGeneric>;
03056
03057         if(posIs3f && tex == none && size != none)
03058         {
03059             static ParticlesDrawer *pumps[] = {
03060               new drawViewDirQuads<PosTrait3f,ColTraitParticle,
03061                                    TexTraitNone,SizeTraitParticle>,
03062               new drawViewDirQuads<PosTrait3f,ColTraitSingle,
03063                                    TexTraitNone,SizeTraitParticle>,
03064               new drawViewDirQuads<PosTrait3f,ColTraitNone,
03065                                    TexTraitNone,SizeTraitParticle>,
03066
03067               new drawViewDirQuads<PosTrait3f,ColTraitParticle,
03068                                    TexTraitNone,SizeTraitSingle>,
03069               new drawViewDirQuads<PosTrait3f,ColTraitSingle,
03070                                    TexTraitNone,SizeTraitSingle>,
03071               new drawViewDirQuads<PosTrait3f,ColTraitNone,
03072                                    TexTraitNone,SizeTraitSingle>,
03073               };
03074
03075               return pumps[size * 3 + color];
03076         }
03077
03078         return fallback;
03079     }
03080
03081     case ViewerQuads:
03082     {
03083         static ParticlesDrawer *fallback =
03084                     new drawViewerQuads<PosTraitGeneric,ColTraitGeneric,
03085                                          TexTraitGeneric,SizeTraitGeneric>;
03086
03087         if(posIs3f && tex == none && size != none)
03088         {
03089             static ParticlesDrawer *pumps[] = {
03090               new drawViewerQuads<PosTrait3f,ColTraitParticle,
03091                                   TexTraitNone,SizeTraitParticle>,
03092               new drawViewerQuads<PosTrait3f,ColTraitSingle,
03093                                   TexTraitNone,SizeTraitParticle>,
03094               new drawViewerQuads<PosTrait3f,ColTraitNone,
03095                                   TexTraitNone,SizeTraitParticle>,
03096
03097               new drawViewerQuads<PosTrait3f,ColTraitParticle,
03098                                   TexTraitNone,SizeTraitSingle>,
03099               new drawViewerQuads<PosTrait3f,ColTraitSingle,
03100                                   TexTraitNone,SizeTraitSingle>,
03101               new drawViewerQuads<PosTrait3f,ColTraitNone,
03102                                   TexTraitNone,SizeTraitSingle>,
03103               };
03104
03105               return pumps[size * 3 + color];
03106         }
03107
03108         return fallback;
03109     }
03110
03111     case Arrows:
03112     {
03113         if(secpos == none)
03114         {
03115             FWARNING(("Particles::findDrawer: Need secondary positions for "
03116                       "type Arrows!\n"));
03117             return NULL;
03118         }
03119
03120         if(normal == none)
03121         {
03122             FWARNING(("Particles::findDrawer: Need normals for "
03123                       "type Arrows!\n"));
03124             return NULL;
03125         }
03126
03127         static ParticlesDrawer *fallback =
03128                     new drawObjects<PosTraitGeneric,ColTraitGeneric,
03129                                     SizeTraitGeneric,NormalTraitGeneric,
03130                                     GeoTraitArrow>;
03131
03132         return fallback;
03133     }
03134
03135     case ViewerArrows:
03136     {
03137         if(secpos == none)
03138         {
03139             FWARNING(("Particles::findDrawer: Need secondary positions for "
03140                       "type ViewerArrows!\n"));
03141             return NULL;
03142         }
03143
03144         if(normal == none)
03145         {
03146             FWARNING(("Particles::findDrawer: Need normals for "
03147                       "type ViewerArrows!\n"));
03148             return NULL;
03149         }
03150
03151         static ParticlesDrawer *fallback =
03152                     new drawViewerObjects<PosTraitGeneric,ColTraitGeneric,
03153                                           SizeTraitGeneric,GeoTraitArrow>;
03154
03155         return fallback;
03156     }
03157
03158     case Rectangles:
03159     {
03160         if(secpos == none)
03161         {
03162             FWARNING(("Particles::findDrawer: Need secondary positions for "
03163                       "type Rectangles!\n"));
03164             return NULL;
03165         }
03166
03167         if(normal == none)
03168         {
03169             FWARNING(("Particles::findDrawer: Need normals for "
03170                       "type Rectangles!\n"));
03171             return NULL;
03172         }
03173
03174         static ParticlesDrawer *fallback =
03175                     new drawObjects<PosTraitGeneric,ColTraitGeneric,
03176                                     SizeTraitGeneric,NormalTraitGeneric,
03177                                     GeoTraitRectangle>;
03178
03179         return fallback;
03180     }
03181
03182     case ShaderQuads:
03183     {
03184         static ParticlesDrawer *fallback =
03185                     new drawShaderQuads<PosTraitGeneric,PosTraitGeneric,
03186                                         ColTraitGeneric, TexTraitGeneric,
03187                                         SizeTraitGeneric,NormalTraitGeneric>,
03188                                *nosecfallback =
03189                     new drawShaderQuads<PosTraitGeneric,PosTraitNone,
03190                                         ColTraitGeneric, TexTraitGeneric,
03191                                         SizeTraitGeneric,NormalTraitGeneric>;
03192
03193         if(secpos == none)
03194         {
03195             return nosecfallback;
03196         }
03197         else
03198         {
03199             return fallback;
03200         }
03201     }
03202
03203     case ShaderStrips:
03204     {
03205         static ParticlesDrawer *fallback =
03206                     new drawShaderStrips<PosTraitGeneric,PosTraitGeneric,
03207                                          ColTraitGeneric, TexTraitGeneric,
03208                                          SizeTraitGeneric,NormalTraitGeneric>,
03209                                *nosecfallback =
03210                     new drawShaderStrips<PosTraitGeneric,PosTraitNone,
03211                                          ColTraitGeneric, TexTraitGeneric,
03212                                          SizeTraitGeneric,NormalTraitGeneric>;
03213
03214         if(secpos == none)
03215         {
03216             return nosecfallback;
03217         }
03218         else
03219         {
03220             return fallback;
03221         }
03222     }
03223
03224     };
03225
03226
03227     if (normal) return NULL; // make picky compilers happy
03228     return NULL;
03229 }
03230