fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / NodeCores / Drawables / Particles / OSGParticles.cpp
blob4cff459c7cdf5825fff578f2dfea0d4e9ef46dd0
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
47 #include "OSGGLEXT.h"
48 #include "OSGAction.h"
49 #include "OSGRenderAction.h"
50 #include "OSGMaterial.h"
51 //#include "OSGGeoPropPtrs.h"
52 #include "OSGCamera.h"
53 #include "OSGWindow.h"
54 #include "OSGDrawEnv.h"
56 #include "OSGParticles.h"
57 #include "OSGDrawableStatsAttachment.h"
59 #include "OSGGLFuncProtos.h"
60 #include "OSGConceptPropertyChecks.h"
62 #include <algorithm>
64 OSG_BEGIN_NAMESPACE
66 // Documentation for this class is emited in the
67 // OSGParticlesBase.cpp file.
68 // To modify it, please change the .fcd file (OSGParticles.fcd) and
69 // regenerate the base file.
71 /***************************************************************************\
72 * File variables *
73 \***************************************************************************/
75 static UInt32 _extMultitexture = Window::invalidExtensionID;
77 static UInt32 _funcglMultiTexCoord3fvARB = Window::invalidFunctionID;
79 /***************************************************************************\
80 * Class methods *
81 \***************************************************************************/
83 void Particles::initMethod(InitPhase ePhase)
85 Inherited::initMethod(ePhase);
87 if(ePhase == TypeObject::SystemPost)
89 RenderAction::registerEnterDefault(
90 Particles::getClassType(),
91 reinterpret_cast<Action::Callback>(
92 &MaterialDrawable::renderEnter));
94 RenderAction::registerLeaveDefault(
95 Particles::getClassType(),
96 reinterpret_cast<Action::Callback>(
97 &MaterialDrawable::renderLeave));
99 _extMultitexture =
100 Window::registerExtension("GL_ARB_multitexture");
102 _funcglMultiTexCoord3fvARB =
103 Window::registerFunction(
104 OSG_DLSYM_UNDERSCORE"glMultiTexCoord3fvARB", _extMultitexture);
108 /***************************************************************************\
109 * Instance methods *
110 \***************************************************************************/
112 /*-------------------------------------------------------------------------*\
113 - private -
114 \*-------------------------------------------------------------------------*/
116 Particles::Particles(void) :
117 Inherited()
121 Particles::Particles(const Particles &source) :
122 Inherited(source)
126 Particles::~Particles(void)
130 /*------------------------------- Sync -----------------------------------*/
132 void Particles::changed(ConstFieldMaskArg whichField,
133 UInt32 origin,
134 BitVector details)
136 if(whichField & PositionsFieldMask)
138 for(UInt32 i = 0; i < _mfParents.size(); i++)
140 _mfParents[i]->invalidateVolume();
143 editBsp().destroy();
146 Inherited::changed(whichField, origin, details);
149 /*------------------------------ Output ----------------------------------*/
151 void Particles::dump( UInt32 ,
152 const BitVector ) const
154 SLOG << "Dump Particles NI" << std::endl;
158 void Particles::adjustVolume( Volume & volume )
160 GeoVectorProperty *pos = getPositions();
162 if ( pos == NULL )
163 return; // Node has no particles, no volume
165 volume.setValid();
166 volume.setEmpty();
168 const MFVec3f *sizes = getMFSizes();
170 if(sizes->size() == pos->size())
172 Vec3f p;
173 Real32 s;
175 for(UInt32 i = 0; i < pos->size(); i++)
177 pos->getValue(p, i);
178 // make the size bigger to accomodate rotations
179 s=(*sizes)[i][0]*Sqrt2;
181 p[0]+=s/2;
182 p[1]+=s/2;
183 p[2]+=s/2;
184 volume.extendBy(p);
185 p[0]-=s;
186 volume.extendBy(p);
187 p[1]-=s;
188 volume.extendBy(p);
189 p[0]+=s;
190 volume.extendBy(p);
191 p[2]-=s;
192 volume.extendBy(p);
193 p[0]-=s;
194 volume.extendBy(p);
195 p[1]+=s;
196 volume.extendBy(p);
197 p[0]+=s;
198 volume.extendBy(p);
202 else if(sizes->size() == 1)
204 Vec3f p;
205 Real32 s,s2;
206 // make the size bigger to accomodate rotations
207 s=(*sizes)[0][0]*Sqrt2;
208 s2=s/2;
210 for(UInt32 i = 0; i < pos->size(); i++)
212 pos->getValue(p, i);
214 p[0]+=s2;
215 p[1]+=s2;
216 p[2]+=s2;
217 volume.extendBy(p);
218 p[0]-=s;
219 volume.extendBy(p);
220 p[1]-=s;
221 volume.extendBy(p);
222 p[0]+=s;
223 volume.extendBy(p);
224 p[2]-=s;
225 volume.extendBy(p);
226 p[0]-=s;
227 volume.extendBy(p);
228 p[1]+=s;
229 volume.extendBy(p);
230 p[0]+=s;
231 volume.extendBy(p);
235 else
237 Vec3f p;
239 for(UInt32 i = 0; i < pos->size32(); i++)
241 pos->getValue(p, i);
243 volume.extendBy(p);
248 void Particles::fill(DrawableStatsAttachment *pStat)
250 if(pStat == NULL)
252 FINFO(("Particles::fill(DrawableStatsAttachment *): "
253 "No attachment given.\n"));
254 return;
257 const GeoVectorProperty *positions = getPositions();
258 const MFInt32 *indices = getMFIndices();
260 if(positions == NULL)
262 FINFO(("Particles::fill(DrawableStatsAttachment *): "
263 "No positions.\n"));
264 return;
267 UInt32 verts = 0;
268 UInt32 points = 0;
269 UInt32 lines = 0;
270 UInt32 triangles = 0;
272 if(indices->size() > 0)
274 verts += indices->size32();
276 else
278 verts += positions->size32();
281 switch(getMode())
283 case Points:
285 points += verts;
286 break;
289 case Lines:
291 lines += verts;
292 break;
295 case ViewDirQuads:
296 case ViewerQuads:
297 case Rectangles:
298 case ShaderQuads:
300 triangles += verts * 2;
301 break;
304 case Arrows:
305 case ViewerArrows:
307 triangles += verts * 5;
308 break;
311 case ShaderStrips:
313 triangles += verts - 2;
314 break;
317 default:
319 FWARNING(("Particles::fill(DrawableStatsAttachment *): "
320 "Invalid sfMode value.\n"));
321 break;
325 pStat->setVertices (verts );
326 pStat->setPoints (points );
327 pStat->setLines (lines );
328 pStat->setTriangles(triangles);
331 /*---------------------------- pumps -----------------------------------*/
333 /*! \name Drawing Pumps */
334 /*! \{ */
336 /*! The pumps use a trait system to create specialized code for important
337 cases. The general idea is to keep decision out of the inner loops
338 and make special versions for the most common data types. Not for
339 everything, as that creates big time code bloat.
342 /*! Base class for the particle rendering traits. Does nothing, just needed to
343 have a common base class.
346 /*! \ingroup GrpDrawablesParticlesHelpers
349 class ParticleTraits
353 /*! Color trait base, keep the static data needed for color handling
354 \ingroup GrpDrawablesParticlesHelpers
357 struct ColTraitBase : public ParticleTraits
359 typedef void (OSG_APIENTRY *pumpFunc)( GLubyte * data );
360 static const int formatBase;
361 enum { numFormats = GL_DOUBLE - GL_BYTE + 1 };
363 static const char *formatNames[];
365 static pumpFunc ColorFuncs[numFormats][4];
368 /*! The smallest enum for data types, used as a base for the formatNames map.
370 const int ColTraitBase::formatBase = GL_BYTE;
372 /*! A map from the OpenGL data type to the corresponding name
374 const char *ColTraitBase::formatNames[] =
375 { "GL_BYTE", "GL_UNSIGNED_BYTE", "GL_SHORT", "GL_UNSIGNED_SHORT",
376 "GL_INT", "GL_UNSIGNED_INT", "GL_FLOAT", "GL_2_BYTES",
377 "GL_3_BYTES", "GL_4_BYTES", "GL_DOUBLE"
380 /*! The pump functions for colors, indexed by data type and dimensionality
382 ColTraitBase::pumpFunc
383 ColTraitBase::ColorFuncs[ColTraitBase::numFormats][4] = {
384 { NULL,
385 NULL,
386 reinterpret_cast<pumpFunc>(glColor3bv),
387 reinterpret_cast<pumpFunc>(glColor4bv) }, // GL_BYTE
388 { NULL,
389 NULL,
390 reinterpret_cast<pumpFunc>(glColor3ubv),
391 reinterpret_cast<pumpFunc>(glColor4ubv) }, // GL_UNSIGNED_BYTE
392 { NULL,
393 NULL,
394 reinterpret_cast<pumpFunc>(glColor3sv),
395 reinterpret_cast<pumpFunc>(glColor4sv) }, // GL_SHORT
396 { NULL,
397 NULL,
398 reinterpret_cast<pumpFunc>(glColor3usv),
399 reinterpret_cast<pumpFunc>(glColor4usv) }, // GL_UNSIGNED_SHORT
400 { NULL,
401 NULL,
402 reinterpret_cast<pumpFunc>(glColor3iv),
403 reinterpret_cast<pumpFunc>(glColor4iv) }, // GL_INT
404 { NULL,
405 NULL,
406 reinterpret_cast<pumpFunc>(glColor3uiv),
407 reinterpret_cast<pumpFunc>(glColor4uiv) }, // GL_UNSIGNED_INT
408 { NULL,
409 NULL,
410 reinterpret_cast<pumpFunc>(glColor3fv),
411 reinterpret_cast<pumpFunc>(glColor4fv) }, // GL_FLOAT
412 { NULL, NULL, NULL, NULL }, // GL_2_BYTES
413 { NULL, NULL, NULL, NULL }, // GL_3_BYTES
414 { NULL, NULL, NULL, NULL }, // GL_4_BYTES
415 { NULL, NULL,
416 reinterpret_cast<pumpFunc>(glColor3dv),
417 reinterpret_cast<pumpFunc>(glColor4dv) }, // GL_DOUBLE
420 /*! \ingroup GrpDrawablesParticlesHelpers
423 struct ColTraitNone : public ColTraitBase
425 typedef UInt8 dataType; // no data needed, but can't instantiate void
427 static inline void init(Particles *, DrawEnv *, dataType &)
431 static inline bool particle(dataType &, UInt32)
433 return false;
436 static inline void vertex(dataType &, UInt32, UInt32)
441 /*! \ingroup GrpDrawablesParticlesHelpers
444 struct ColTraitSingle : public ColTraitBase
446 typedef UInt8 dataType; // no data needed, but can't instantiate void
448 static inline void init(Particles *part, DrawEnv *, dataType &)
450 GeoVectorProperty *col = part->getColors();
452 if(col != NULL)
454 pumpFunc col_func;
456 col_func = ColorFuncs[ col->getFormat() - formatBase ]
457 [ col->getDimension() - 1 ];
459 if(col_func == NULL)
461 SWARNING << "Particles " << part << "have illegal "
462 << "colors: " << col->getDimension()
463 << "D " << formatNames[col->getFormat() - formatBase]
464 << "!" << std::endl;
465 return;
467 else
469 col_func(const_cast<GLubyte*>(col->getData()));
474 static inline bool particle(dataType &, UInt32)
476 return false;
479 static inline void vertex(dataType &, UInt32, UInt32)
484 /*! \ingroup GrpDrawablesParticlesHelpers
487 struct ColTraitParticle : public ColTraitBase
489 /*! \nohierarchy
491 typedef struct
493 const UInt8 *data;
494 UInt32 stride;
495 pumpFunc func;
497 dataType;
499 static inline void init(Particles *part, DrawEnv *, dataType &data)
501 GeoVectorProperty *col = part->getColors();
503 data.data = col->getData();
504 if((data.stride = col->getStride()) == 0)
505 data.stride = col->getFormatSize() * col->getDimension();
507 data.func = ColorFuncs[ col->getFormat() - formatBase ]
508 [ col->getDimension() - 1 ];
510 if(data.func == NULL)
512 SWARNING << "Particles " << part << "have illegal "
513 << "colors: " << col->getDimension()
514 << "D " << formatNames[ col->getFormat() - formatBase ]
515 << "!" << std::endl;
516 return;
520 static inline bool particle(dataType &data, UInt32 particle)
522 data.func(const_cast<GLubyte *>(data.data + particle * data.stride));
524 return false;
527 static inline void vertex(dataType &, UInt32, UInt32)
532 /*! \ingroup GrpDrawablesParticlesHelpers
535 struct ColTraitGeneric : public ColTraitBase
537 /*! \nohierarchy
539 struct dataType
541 const UInt8 *data;
542 UInt32 stride;
543 pumpFunc func;
544 bool perParticle;
547 static inline void init(Particles *part, DrawEnv *, dataType &data)
549 GeoVectorProperty *col = part->getColors();
551 data.perParticle = false;
553 if(col != NULL)
555 data.data = col->getData();
556 if((data.stride = col->getStride()) == 0)
557 data.stride = col->getFormatSize() * col->getDimension();
559 data.func = ColorFuncs[ col->getFormat() - formatBase ]
560 [ col->getDimension() - 1 ];
562 if(data.func == NULL)
564 SWARNING << "Particles " << part << "have illegal "
565 << "colors: " << col->getDimension()
566 << "D " << formatNames[ col->getFormat() - formatBase ]
567 << "!" << std::endl;
568 return;
571 if(col->size() == 1)
573 data.func(const_cast<GLubyte *>(col->getData()));
575 else if(col->size() == part->getPositions()->size())
577 data.perParticle = true;
582 static inline bool particle(dataType &data, UInt32 particle)
584 if(data.perParticle == true)
586 data.func(
587 const_cast<GLubyte *>(data.data + particle * data.stride));
589 return false;
592 static inline void vertex(dataType &, UInt32, UInt32)
597 /*! Position Particle Traits
598 \ingroup GrpDrawablesParticlesHelpers
601 struct PosTraitNone : public ParticleTraits
603 /*! \nohierarchy
605 typedef struct
608 dataType;
610 static inline void init(Particles *, DrawEnv *, dataType &data,
611 GeoVectorProperty *pos)
615 static inline bool particle(dataType &data, UInt32 particle)
617 return false;
620 static inline Pnt3f &position(dataType &data)
622 static Pnt3f null(0,0,0);
623 return null;
626 static inline void vertex(dataType &data, UInt32 , Vec4f &dir,
627 Real32 s)
631 static inline void vertex(dataType &data)
636 /*! \ingroup GrpDrawablesParticlesHelpers
638 struct PosTraitGeneric : public ParticleTraits
640 /*! \nohierarchy
642 struct dataType
644 GeoVectorProperty *pos;
645 Pnt3f p;
647 dataType(void) : pos(NULL), p() {}
649 private:
651 dataType(const dataType &other);
652 void operator =(const dataType &rhs);
655 static inline void init(Particles *, DrawEnv *, dataType &data,
656 GeoVectorProperty *pos)
658 data.pos = pos;
661 static inline bool particle(dataType &data, UInt32 particle)
663 data.pos->getValue(data.p, particle);
665 return false;
668 static inline Pnt3f &position(dataType &data)
670 return data.p;
673 static inline void vertex(dataType &data, UInt32 , Vec4f &dir,
674 Real32 s)
676 glVertex3f( data.p[0] + dir[0] * s,
677 data.p[1] + dir[1] * s,
678 data.p[2] + dir[2] * s);
681 static inline void vertex(dataType &data)
683 glVertex3fv(static_cast<GLfloat *>(data.p.getValues()));
687 /*! \ingroup GrpDrawablesParticlesHelpers
689 struct PosTrait3f : public ParticleTraits
691 /*! \nohierarchy
693 struct dataType
695 const MFPnt3f *pos;
696 const Pnt3f *p;
699 static inline void init(Particles *,
700 DrawEnv *,
701 dataType &data,
702 GeoVectorProperty *pos)
704 GeoPnt3fProperty *pos3f = dynamic_cast<GeoPnt3fProperty *>(pos);
706 data.pos = pos3f->getFieldPtr();
709 static inline bool particle(dataType &data, UInt32 particle)
711 data.p = & (*(data.pos))[particle];
712 return false;
715 static inline const Pnt3f &position(dataType &data)
717 return *data.p;
720 static inline void vertex(dataType &data, UInt32 , Vec4f &dir, Real32 s)
722 glVertex3f( (*data.p)[0] + dir[0] * s,
723 (*data.p)[1] + dir[1] * s,
724 (*data.p)[2] + dir[2] * s);
727 static inline void vertex(dataType &data)
729 glVertex3fv(static_cast<const GLfloat *>((*data.p).getValues()));
733 /*! Particle Size Traits
734 \ingroup GrpDrawablesParticlesHelpers
736 struct SizeTraitGeneric : public ParticleTraits
738 /*! \nohierarchy
740 struct dataType
742 const MFVec3f *sizes;
743 Vec3f s;
744 bool perParticle;
746 dataType(void): sizes(NULL), s(), perParticle(true) {}
748 private:
749 dataType(const dataType &other);
750 void operator =(const dataType &rhs);
753 static inline void init(Particles *part, DrawEnv *, dataType &data)
755 data.sizes = part->getMFSizes();
757 if(data.sizes != NULL)
759 if(data.sizes->size() == 1)
761 data.s = (*(data.sizes))[0];
762 data.perParticle = false;
764 else if(data.sizes->size() == part->getPositions()->size())
766 data.perParticle = true;
768 else
770 data.s.setValues(1,1,1);
771 data.perParticle = false;
774 else
776 data.s.setValues(1,1,1);
777 data.perParticle = false;
781 static inline bool particle(dataType &, UInt32)
783 return false;
786 static inline const Vec3f &size(dataType &data, UInt32 particle)
788 if(data.perParticle)
789 return (*(data.sizes))[particle];
790 return data.s;
794 /*! \ingroup GrpDrawablesParticlesHelpers
796 struct SizeTraitSingle : public ParticleTraits
798 /*! \nohierarchy
800 struct dataType
802 Vec3f s;
804 dataType(void) : s() {}
807 static inline void init(Particles *part, DrawEnv *, dataType &data)
809 data.s = (*part->getMFSizes())[0];
812 static inline bool particle(dataType &, UInt32)
814 return false;
817 static inline Vec3f &size(dataType &data, UInt32)
819 return data.s;
823 /*! \ingroup GrpDrawablesParticlesHelpers
825 struct SizeTraitParticle : public ParticleTraits
827 /*! \nohierarchy
829 struct dataType
831 const MFVec3f *sizes;
832 Vec3f s;
834 dataType(void) : sizes(NULL), s(){}
836 private:
837 dataType(const dataType &other);
838 void operator =(const dataType &rhs);
841 static inline void init(Particles *part, DrawEnv *, dataType &data)
843 data.sizes = part->getMFSizes();
846 static inline bool particle(dataType &, UInt32)
848 return false;
851 static inline const Vec3f &size(dataType &data, UInt32 particle)
853 return (*(data.sizes))[particle];
857 /*! \ingroup GrpDrawablesParticlesHelpers
859 struct SizeTraitNone : public ParticleTraits
861 typedef UInt8 dataType;
863 static inline void init(Particles *, DrawEnv *, dataType &)
867 static inline bool particle(dataType &, UInt32)
869 return false;
872 static inline Vec3f &size(dataType &, UInt32 )
874 static Vec3f s(1,1,1);
875 return s;
879 /*! Particle Texture Traits
880 \ingroup GrpDrawablesParticlesHelpers
882 struct TexTraitGeneric : public ParticleTraits
884 /*! \nohierarchy
886 struct dataType
888 const MFReal32 *texzs;
889 Real32 z;
890 bool perParticle;
893 static inline void init(Particles *part, DrawEnv *, dataType &data)
895 data.texzs = part->getMFTextureZs();
897 data.perParticle = false;
899 if(data.texzs != NULL)
901 if(data.texzs->size() == 1)
903 data.z = (*(data.texzs))[0];
905 else if(data.texzs->size() == part->getPositions()->size())
907 data.perParticle = true;
908 data.z = 0;
910 else
912 data.z = 0;
915 else
917 data.z = 0;
921 static inline bool particle(dataType &data, UInt32 particle)
923 if(data.perParticle)
925 data.z = (*(data.texzs))[particle];
927 return false;
930 static inline void vertex(dataType &data)
932 glTexCoord1f(data.z);
935 static inline void vertex(dataType &data, UInt32 , Real32 u,
936 Real32 v)
938 glTexCoord3f(u, v, data.z);
942 /*! \ingroup GrpDrawablesParticlesHelpers
944 struct TexTraitParticle : public ParticleTraits
946 /*! \nohierarchy
948 struct dataType
950 const MFReal32 *texzs;
951 Real32 z;
954 static inline void init(Particles *part, DrawEnv *, dataType &data)
956 data.texzs = part->getMFTextureZs();
959 static inline bool particle(dataType &data, UInt32 particle)
961 data.z = (*(data.texzs))[particle];
962 return false;
965 static inline void vertex(dataType &data)
967 glTexCoord1f(data.z);
970 static inline void vertex(dataType &data, UInt32 , Real32 u,
971 Real32 v)
973 glTexCoord3f(u, v, data.z);
977 /*! \ingroup GrpDrawablesParticlesHelpers
979 struct TexTraitSingle : public ParticleTraits
981 /*! \nohierarchy
983 typedef struct
985 Real32 z;
987 dataType;
989 static inline void init(Particles *part, DrawEnv *, dataType &data)
991 data.z = (*(part->getMFTextureZs()))[0];
994 static inline bool particle(dataType &, UInt32)
996 return false;
999 static inline void vertex(dataType &data)
1001 glTexCoord1f(data.z);
1004 static inline void vertex(dataType &data, UInt32 , Real32 u,
1005 Real32 v)
1007 glTexCoord3f(u, v, data.z);
1011 /*! \ingroup GrpDrawablesParticlesHelpers
1013 struct TexTraitNone : public ParticleTraits
1015 typedef UInt8 dataType;
1017 static inline void init(Particles *, DrawEnv *, dataType &)
1021 static inline bool particle(dataType &, UInt32)
1023 return false;
1026 static inline void vertex(dataType &, UInt32 )
1028 glTexCoord1f(0);
1031 static inline void vertex(dataType &, UInt32, Real32 u, Real32 v)
1033 glTexCoord2f(u, v);
1038 /*! Normal Particle Traits
1039 \ingroup GrpDrawablesParticlesHelpers
1041 struct NormalTraitGeneric : public ParticleTraits
1043 /*! \nohierarchy
1045 struct dataType
1047 GeoVectorProperty *norms;
1048 Vec3f n;
1049 bool perParticle;
1051 dataType(void) : norms(NULL), n(), perParticle(true) {}
1053 private:
1055 dataType(const dataType &other);
1056 void operator =(const dataType &rhs);
1059 static inline void init(Particles *part, DrawEnv *, dataType &data)
1061 data.norms = part->getNormals();
1063 data.perParticle = false;
1065 if(data.norms != NULL)
1067 if(data.norms->size() == 1)
1069 data.norms->getValue(data.n, 0);
1071 else if(data.norms->size() == part->getPositions()->size())
1073 data.perParticle = true;
1075 else
1077 data.n.setValues(0,1,0);
1080 else
1082 data.n.setValues(0,1,0);
1086 static inline bool particle(dataType &data, UInt32 particle)
1088 if(data.perParticle)
1089 data.norms->getValue(data.n, particle);
1091 return false;
1094 static inline Vec3f &normal(dataType &data)
1096 return data.n;
1099 static inline void normal(dataType &data, UInt32 )
1101 glNormal3fv(static_cast<GLfloat *>(data.n.getValues()));
1105 /*! \ingroup GrpDrawablesParticlesHelpers
1107 struct NormalTraitGeneric3f : public ParticleTraits
1109 /*! \nohierarchy
1111 struct dataType
1113 const MFVec3f *norms;
1114 const Vec3f *n;
1115 bool perParticle;
1116 Vec3f const_n;
1119 static inline void init(Particles *part, DrawEnv *, dataType &data)
1121 GeoVec3fProperty *norms3f =
1122 dynamic_cast<GeoVec3fProperty *>(part->getNormals());
1124 data.norms = norms3f->getFieldPtr();
1126 data.perParticle = false;
1128 if(norms3f != NULL)
1130 if(norms3f->size() == 1)
1132 data.n = &(*(data.norms))[0];
1134 else if(data.norms->size() == part->getPositions()->size())
1136 data.perParticle = true;
1138 else
1140 data.const_n.setValues(0,1,0);
1141 data.n = &data.const_n;
1144 else
1146 data.const_n.setValues(0,1,0);
1147 data.n = &data.const_n;
1151 static inline bool particle(dataType &data, UInt32 particle)
1153 if(data.perParticle)
1154 data.n = &(*(data.norms))[particle];
1156 return false;
1159 static inline const Vec3f &normal(dataType &data)
1161 return *data.n;
1164 static inline void normal(dataType &data, UInt32 )
1166 glNormal3fv(static_cast<const GLfloat *>(data.n->getValues()));
1170 /*! ParticlesDrawer base classes, define the common interface(s)
1171 \ingroup GrpDrawablesParticlesHelpers
1173 struct ParticlesDrawer
1175 virtual void draw(Particles *part,
1176 DrawEnv *pEnv,
1177 UInt32 length) = 0;
1179 virtual void drawIndexed( Particles *part,
1180 DrawEnv *pEnv,
1181 const Int32 *index,
1182 UInt32 length) = 0;
1184 virtual ~ParticlesDrawer()
1189 /*! View-Dir aligned, indexed quad rendering
1190 \ingroup GrpDrawablesParticlesHelpers
1192 template <class posTrait, class colTrait, class texTrait, class sizeTrait>
1193 struct drawViewDirQuads : public ParticlesDrawer
1195 virtual void drawIndexed( Particles *part,
1196 DrawEnv *pEnv,
1197 const Int32 *index,
1198 UInt32 length)
1200 // get ModelView matrix to define the direction vectors
1201 Matrix camera = pEnv->getCameraToWorld();
1202 Matrix toworld = pEnv->getObjectToWorld();
1206 DrawActionBase *action = pEnv->getOldAction();
1208 RenderAction *ra = dynamic_cast<RenderAction *>(action);
1210 if(ra != NULL)
1212 toworld = ra->top_matrix();
1214 else
1216 action->getActNode()->getToWorld(toworld);
1220 // normalize them, we don't want to neutralize scales in toworld
1221 toworld[0].normalize();
1222 toworld[1].normalize();
1223 toworld[2].normalize();
1224 toworld.transpose();
1225 camera.multLeft(toworld);
1227 // Direction vectors
1228 Vec4f d1, d2, d3, d4;
1230 d1 = -1.0f * camera[0] + -1.0f * camera[1];
1231 d2 = 1.0f * camera[0] + -1.0f * camera[1];
1232 d3 = 1.0f * camera[0] + 1.0f * camera[1];
1233 d4 = -1.0f * camera[0] + 1.0f * camera[1];
1235 // some variables for faster access
1236 GeoVectorProperty *pos = part->getPositions();
1238 // init traits
1239 typename colTrait::dataType colData;
1240 colTrait::init(part, pEnv, colData);
1242 typename texTrait::dataType texData;
1243 texTrait::init(part, pEnv, texData);
1245 typename sizeTrait::dataType sizeData;
1246 sizeTrait::init(part, pEnv, sizeData);
1248 typename posTrait::dataType posData;
1249 posTrait::init(part, pEnv, posData, part->getPositions());
1251 glBegin(GL_QUADS);
1253 Int32 i;
1255 for(UInt32 ii = 0; ii < length; ++ii)
1257 i = index[ii];
1259 if(i < 0 || i > Int32(pos->size32()))
1260 continue;
1262 if(colTrait::particle (colData, i))
1263 continue;
1265 if(texTrait::particle (texData, i))
1266 continue;
1268 if(sizeTrait::particle(sizeData, i))
1269 continue;
1271 if(posTrait::particle(posData, i))
1272 continue;
1274 Real32 s = sizeTrait::size(sizeData, i)[0] / 2.f;
1276 if(s == 0)
1277 continue;
1279 colTrait::vertex(colData, i, 0);
1280 texTrait::vertex(texData, 0, 0, 0);
1281 posTrait::vertex(posData, 0, d1, s);
1283 colTrait::vertex(colData, i, 1);
1284 texTrait::vertex(texData, 1, 1, 0);
1285 posTrait::vertex(posData, 1, d2, s);
1287 colTrait::vertex(colData, i, 2);
1288 texTrait::vertex(texData, 2, 1, 1);
1289 posTrait::vertex(posData, 2, d3, s);
1291 colTrait::vertex(colData, i, 3);
1292 texTrait::vertex(texData, 3, 0, 1);
1293 posTrait::vertex(posData, 3, d4, s);
1296 glEnd();
1299 virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
1301 // get ModelView matrix to define the direction vectors
1303 Matrix camera = pEnv->getCameraToWorld();
1304 Matrix toworld = pEnv->getObjectToWorld();
1307 DrawActionBase *action = pEnv->getOldAction();
1309 RenderAction *ra = dynamic_cast<RenderAction *>(action);
1311 if(ra != NULL)
1313 toworld = ra->top_matrix();
1315 else
1317 action->getActNode()->getToWorld(toworld);
1321 // normalize them, we don't want to neutralize scales in toworld
1322 toworld[0].normalize();
1323 toworld[1].normalize();
1324 toworld[2].normalize();
1325 toworld.transpose();
1326 camera.multLeft(toworld);
1328 // Direction vectors
1329 Vec4f d1, d2, d3, d4;
1331 d1 = -1.0f * camera[0] + -1.0f * camera[1];
1332 d2 = 1.0f * camera[0] + -1.0f * camera[1];
1333 d3 = 1.0f * camera[0] + 1.0f * camera[1];
1334 d4 = -1.0f * camera[0] + 1.0f * camera[1];
1336 // some variables for faster access
1338 // init traits
1339 typename colTrait::dataType colData;
1340 colTrait::init(part, pEnv, colData);
1342 typename texTrait::dataType texData;
1343 texTrait::init(part, pEnv, texData);
1345 typename sizeTrait::dataType sizeData;
1346 sizeTrait::init(part, pEnv, sizeData);
1348 typename posTrait::dataType posData;
1349 posTrait::init(part, pEnv, posData, part->getPositions());
1351 glBegin(GL_QUADS);
1353 for(UInt32 i = 0; i < length; ++i)
1355 if(colTrait::particle (colData, i))
1356 continue;
1358 if(texTrait::particle (texData, i))
1359 continue;
1361 if(sizeTrait::particle(sizeData, i))
1362 continue;
1364 if(posTrait::particle(posData, i))
1365 continue;
1367 Real32 s = sizeTrait::size(sizeData, i)[0] / 2.f;
1369 if(s == 0)
1370 continue;
1372 colTrait::vertex(colData, i, 0);
1373 texTrait::vertex(texData, 0, 0, 0);
1374 posTrait::vertex(posData, 0, d1, s);
1376 colTrait::vertex(colData, i, 1);
1377 texTrait::vertex(texData, 1, 1, 0);
1378 posTrait::vertex(posData, 1, d2, s);
1380 colTrait::vertex(colData, i, 2);
1381 texTrait::vertex(texData, 2, 1, 1);
1382 posTrait::vertex(posData, 2, d3, s);
1384 colTrait::vertex(colData, i, 3);
1385 texTrait::vertex(texData, 3, 0, 1);
1386 posTrait::vertex(posData, 3, d4, s);
1389 glEnd();
1394 /*! Viewer aligned, indexed quad rendering
1395 \ingroup GrpDrawablesParticlesHelpers
1397 template <class posTrait, class colTrait, class texTrait, class sizeTrait>
1398 struct drawViewerQuads : public ParticlesDrawer
1400 virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
1401 const Int32 *index, UInt32 length)
1403 // get ModelView matrix to define the direction vectors
1404 // Matrix camera,toworld;
1406 Matrix camera = pEnv->getCameraToWorld();
1407 Matrix toworld = pEnv->getObjectToWorld();
1410 DrawActionBase *action = pEnv->getOldAction();
1412 RenderAction *ra = dynamic_cast<RenderAction *>(action);
1414 if(ra != NULL)
1416 toworld = ra->top_matrix();
1418 else
1420 action->getActNode()->getToWorld(toworld);
1424 // normalize them, we don't want to neutralize scales in toworld
1425 toworld[0].normalize();
1426 toworld[1].normalize();
1427 toworld[2].normalize();
1428 toworld.invert();
1429 camera.multLeft(toworld);
1431 // Viewer position & up
1432 Pnt3f vpos(camera[3]);
1433 Vec3f vup (camera[1]);
1434 vup.normalize();
1435 Vec3f vdir,vnorm;
1437 // direction vector
1438 Vec4f d;
1440 // some variables for faster access
1441 GeoVectorProperty *pos = part->getPositions();
1443 // init traits
1444 typename colTrait::dataType colData;
1445 colTrait::init(part, pEnv, colData);
1447 typename texTrait::dataType texData;
1448 texTrait::init(part, pEnv, texData);
1450 typename sizeTrait::dataType sizeData;
1451 sizeTrait::init(part, pEnv, sizeData);
1453 typename posTrait::dataType posData;
1454 posTrait::init(part, pEnv, posData, part->getPositions());
1456 glBegin(GL_QUADS);
1458 Int32 i;
1460 for(UInt32 ii = 0; ii < length; ++ii)
1462 i = index[ii];
1464 if(i < 0 || i > Int32(pos->size32()))
1465 continue;
1467 if(colTrait::particle (colData, i))
1468 continue;
1470 if(texTrait::particle (texData, i))
1471 continue;
1473 if(sizeTrait::particle(sizeData, i))
1474 continue;
1476 if(posTrait::particle(posData, i))
1477 continue;
1479 Real32 s = sizeTrait::size(sizeData, i)[0] / 2.f;
1481 if(s == 0)
1482 continue;
1484 // calc viewer-relative coord system
1486 Pnt3f p = pos->getValue<Pnt3f>(i);
1487 vdir = vpos - p;
1488 vdir.normalize();
1489 vnorm = vup.cross(vdir);
1491 d.setValues( -vnorm[0] - vup[0],
1492 -vnorm[1] - vup[1],
1493 -vnorm[2] - vup[2],
1494 1 );
1495 colTrait::vertex(colData, i, 0);
1496 texTrait::vertex(texData, 0, 0, 0);
1497 posTrait::vertex(posData, 0, d, s);
1499 d.setValues( vnorm[0] - vup[0],
1500 vnorm[1] - vup[1],
1501 vnorm[2] - vup[2],
1502 1 );
1503 colTrait::vertex(colData, i, 1);
1504 texTrait::vertex(texData, 1, 1, 0);
1505 posTrait::vertex(posData, 1, d, s);
1507 d.setValues( vnorm[0] + vup[0],
1508 vnorm[1] + vup[1],
1509 vnorm[2] + vup[2],
1510 1 );
1511 colTrait::vertex(colData, i, 2);
1512 texTrait::vertex(texData, 2, 1, 1);
1513 posTrait::vertex(posData, 2, d, s);
1515 d.setValues( -vnorm[0] + vup[0],
1516 -vnorm[1] + vup[1],
1517 -vnorm[2] + vup[2],
1518 1 );
1519 colTrait::vertex(colData, i, 3);
1520 texTrait::vertex(texData, 3, 0, 1);
1521 posTrait::vertex(posData, 3, d, s);
1524 glEnd();
1527 virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
1529 // get ModelView matrix to define the direction vectors
1531 Matrix camera = pEnv->getCameraToWorld();
1532 Matrix toworld = pEnv->getObjectToWorld();
1535 DrawActionBase *action = pEnv->getOldAction();
1537 RenderAction *ra = dynamic_cast<RenderAction *>(action);
1539 if(ra != NULL)
1541 toworld = ra->top_matrix();
1543 else
1545 action->getActNode()->getToWorld(toworld);
1549 // normalize them, we don't want to neutralize scales in toworld
1550 toworld[0].normalize();
1551 toworld[1].normalize();
1552 toworld[2].normalize();
1553 toworld.invert();
1554 camera.multLeft(toworld);
1556 // Viewer position & up
1557 Pnt3f vpos(camera[3]);
1558 Vec3f vup (camera[1]);
1559 vup.normalize();
1560 Vec3f vdir,vnorm;
1562 // direction vector
1563 Vec4f d;
1565 // some variables for faster access
1566 GeoVectorProperty *pos = part->getPositions();
1568 // init traits
1569 typename colTrait::dataType colData;
1570 colTrait::init(part, pEnv, colData);
1572 typename texTrait::dataType texData;
1573 texTrait::init(part, pEnv, texData);
1575 typename sizeTrait::dataType sizeData;
1576 sizeTrait::init(part, pEnv, sizeData);
1578 typename posTrait::dataType posData;
1579 posTrait::init(part, pEnv, posData, part->getPositions());
1581 glBegin(GL_QUADS);
1583 for(UInt32 i = 0; i < length; ++i)
1585 if(colTrait::particle (colData, i))
1586 continue;
1588 if(texTrait::particle (texData, i))
1589 continue;
1591 if(sizeTrait::particle(sizeData, i))
1592 continue;
1594 if(posTrait::particle(posData, i))
1595 continue;
1597 Real32 s = sizeTrait::size(sizeData, i)[0] / 2.f;
1599 if(s == 0)
1600 continue;
1602 // calc viewer-relative coord system
1604 Pnt3f p = pos->getValue<Pnt3f>(i);
1605 vdir = vpos - p;
1606 vdir.normalize();
1607 vnorm = vup.cross(vdir);
1609 d.setValues( -vnorm[0] - vup[0],
1610 -vnorm[1] - vup[1],
1611 -vnorm[2] - vup[2],
1612 1 );
1613 colTrait::vertex(colData, i, 0);
1614 texTrait::vertex(texData, 0, 0, 0);
1615 posTrait::vertex(posData, 0, d, s);
1617 d.setValues( vnorm[0] - vup[0],
1618 vnorm[1] - vup[1],
1619 vnorm[2] - vup[2],
1620 1 );
1621 colTrait::vertex(colData, i, 1);
1622 texTrait::vertex(texData, 1, 1, 0);
1623 posTrait::vertex(posData, 1, d, s);
1625 d.setValues( vnorm[0] + vup[0],
1626 vnorm[1] + vup[1],
1627 vnorm[2] + vup[2],
1628 1 );
1629 colTrait::vertex(colData, i, 2);
1630 texTrait::vertex(texData, 2, 1, 1);
1631 posTrait::vertex(posData, 2, d, s);
1633 d.setValues( -vnorm[0] + vup[0],
1634 -vnorm[1] + vup[1],
1635 -vnorm[2] + vup[2],
1636 1 );
1637 colTrait::vertex(colData, i, 3);
1638 texTrait::vertex(texData, 3, 0, 1);
1639 posTrait::vertex(posData, 3, d, s);
1642 glEnd();
1648 /*! Single color lines between secPos and pos
1649 \ingroup GrpDrawablesParticlesHelpers
1653 template <class posTrait, class colTrait, class texTrait, class sizeTrait>
1654 struct drawLines : public ParticlesDrawer
1656 virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
1658 // some variables for faster access
1660 // init traits
1661 typename colTrait::dataType colData;
1662 colTrait::init(part, pEnv, colData);
1664 typename texTrait::dataType texData;
1665 texTrait::init(part, pEnv, texData);
1667 typename sizeTrait::dataType sizeData;
1668 sizeTrait::init(part, pEnv, sizeData);
1670 typename posTrait::dataType posData;
1671 posTrait::init(part, pEnv, posData, part->getPositions());
1673 typename posTrait::dataType secPosData;
1674 posTrait::init(part, pEnv, secPosData, part->getSecPositions());
1676 Real32 s = sizeTrait::size(sizeData, 0)[0];
1678 glPushAttrib(GL_LINE_BIT);
1679 glLineWidth(s);
1681 glBegin(GL_LINES);
1683 for(UInt32 i = 0; i < length; ++i)
1685 if(colTrait::particle (colData, i))
1686 continue;
1688 if(texTrait::particle (texData, i))
1689 continue;
1691 if(sizeTrait::particle(sizeData, i))
1692 continue;
1694 if(posTrait::particle(posData, i))
1695 continue;
1697 if(posTrait::particle(secPosData, i))
1698 continue;
1700 posTrait::vertex(posData);
1701 posTrait::vertex(secPosData);
1704 glEnd();
1706 glPopAttrib();
1709 virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
1710 const Int32 *index, UInt32 length)
1712 // some variables for faster access
1713 GeoVectorProperty *pos = part->getPositions();
1715 // init traits
1716 typename colTrait::dataType colData;
1717 colTrait::init(part, pEnv, colData);
1719 typename texTrait::dataType texData;
1720 texTrait::init(part, pEnv, texData);
1722 typename sizeTrait::dataType sizeData;
1723 sizeTrait::init(part, pEnv, sizeData);
1725 typename posTrait::dataType posData;
1726 posTrait::init(part, pEnv, posData, part->getPositions());
1728 typename posTrait::dataType secPosData;
1729 posTrait::init(part, pEnv, secPosData, part->getSecPositions());
1731 Real32 s = sizeTrait::size(sizeData, 0)[0];
1733 glPushAttrib(GL_LINE_BIT);
1734 glLineWidth(s);
1736 glBegin(GL_LINES);
1738 Int32 i;
1740 for(UInt32 ii = 0; ii < length; ++ii)
1742 i = index[ii];
1744 if(i < 0 || i > Int32(pos->size32()))
1745 continue;
1747 if(colTrait::particle (colData, i))
1748 continue;
1750 if(texTrait::particle (texData, i))
1751 continue;
1753 if(sizeTrait::particle(sizeData, i))
1754 continue;
1756 if(posTrait::particle(posData, i))
1757 continue;
1759 if(posTrait::particle(secPosData, i))
1760 continue;
1762 posTrait::vertex(posData);
1763 posTrait::vertex(secPosData);
1766 glEnd();
1768 glPopAttrib();
1772 /*! Points at pos
1773 \ingroup GrpDrawablesParticlesHelpers
1775 template <class posTrait, class colTrait, class texTrait, class sizeTrait>
1776 struct drawPoints : public ParticlesDrawer
1778 virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
1780 // some variables for faster access
1781 // init traits
1782 typename posTrait::dataType posData;
1783 posTrait::init(part, pEnv, posData, part->getPositions());
1785 typename colTrait::dataType colData;
1786 colTrait::init(part, pEnv, colData);
1788 typename sizeTrait::dataType sizeData;
1789 sizeTrait::init(part, pEnv, sizeData);
1791 typename texTrait::dataType texData;
1792 texTrait::init(part, pEnv, texData);
1794 sizeTrait::particle(sizeData, 0);
1795 Real32 s = sizeTrait::size(sizeData, 0)[0];
1797 glPushAttrib(GL_POINT_BIT);
1798 glPointSize(s);
1800 glBegin(GL_POINTS);
1802 for(UInt32 i = 0; i < length; ++i)
1804 if(colTrait::particle(colData, i))
1805 continue;
1807 if(posTrait::particle(posData, i))
1808 continue;
1810 if(texTrait::particle(texData, i))
1811 continue;
1813 texTrait::vertex(texData);
1814 posTrait::vertex(posData);
1817 glEnd();
1819 glPopAttrib();
1822 virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
1823 const Int32 *index, UInt32 length)
1825 // some variables for faster access
1826 GeoVectorProperty *pos = part->getPositions();
1828 // init traits
1829 typename posTrait::dataType posData;
1830 posTrait::init(part, pEnv, posData, part->getPositions());
1832 typename colTrait::dataType colData;
1833 colTrait::init(part, pEnv, colData);
1835 typename sizeTrait::dataType sizeData;
1836 sizeTrait::init(part, pEnv, sizeData);
1838 sizeTrait::particle(sizeData, 0);
1839 Real32 s = sizeTrait::size(sizeData, 0)[0];
1841 glPushAttrib(GL_POINT_BIT);
1842 glPointSize(s);
1844 glBegin(GL_POINTS);
1846 Int32 i;
1848 for(UInt32 ii = 0; ii < length; ++ii)
1850 i = index[ii];
1852 if(i < 0 || i > Int32(pos->size()))
1853 continue;
1855 if(colTrait::particle(colData, i))
1856 continue;
1858 if(posTrait::particle(posData, i))
1859 continue;
1861 posTrait::vertex(posData);
1864 glEnd();
1866 glPopAttrib();
1870 /*! Geometry traits for drawing objects
1871 \ingroup GrpDrawablesParticlesHelpers
1873 struct GeoTraitArrow : public ParticleTraits
1875 typedef UInt8 dataType;
1877 static inline void init(Particles *, DrawEnv *, dataType &)
1881 static inline void exit(Particles *, DrawEnv *, dataType &)
1885 static inline bool particle(dataType &, UInt32)
1887 return false;
1890 static inline void draw( dataType &,
1891 const Pnt3f &p,
1892 const Pnt3f &,
1893 Vec3f &dx,
1894 Vec3f &dy,
1895 Vec3f &dz,
1896 const Vec3f &s)
1898 dz*=s[2];
1899 dx*=s[0];
1901 glNormal3fv(static_cast<GLfloat *>(dy.getValues()));
1903 glBegin(GL_TRIANGLE_FAN);
1905 glVertex3fv(static_cast<const GLfloat *>(p.getValues()));
1907 glVertex3f(p[0] + dz[0] * .5f + dx[0] ,
1908 p[1] + dz[1] * .5f + dx[1] ,
1909 p[2] + dz[2] * .5f + dx[2] );
1911 glVertex3f(p[0] + dz[0] * .5f + dx[0] * .5f ,
1912 p[1] + dz[1] * .5f + dx[1] * .5f ,
1913 p[2] + dz[2] * .5f + dx[2] * .5f );
1915 glVertex3f(p[0] + dz[0] + dx[0] * .5f ,
1916 p[1] + dz[1] + dx[1] * .5f ,
1917 p[2] + dz[2] + dx[2] * .5f );
1919 glVertex3f(p[0] + dz[0] - dx[0] * .5f ,
1920 p[1] + dz[1] - dx[1] * .5f ,
1921 p[2] + dz[2] - dx[2] * .5f );
1923 glVertex3f(p[0] + dz[0] * .5f - dx[0] * .5f ,
1924 p[1] + dz[1] * .5f - dx[1] * .5f ,
1925 p[2] + dz[2] * .5f - dx[2] * .5f );
1927 glVertex3f(p[0] + dz[0] * .5f - dx[0] ,
1928 p[1] + dz[1] * .5f - dx[1] ,
1929 p[2] + dz[2] * .5f - dx[2] );
1931 glEnd();
1936 /*! Geometry traits for drawing rectangles
1937 \ingroup GrpDrawablesParticlesHelpers
1940 struct GeoTraitRectangle : public ParticleTraits
1942 typedef UInt8 dataType;
1944 static inline void init(Particles *, DrawEnv *, dataType &)
1946 glBegin(GL_QUADS);
1949 static inline void exit(Particles *, DrawEnv *, dataType &)
1951 glEnd();
1954 static inline bool particle(dataType &, UInt32)
1956 return false;
1959 static inline void draw( dataType &,
1960 const Pnt3f &p,
1961 const Pnt3f &sp,
1962 Vec3f &dx,
1963 Vec3f &dy,
1964 Vec3f &,
1965 const Vec3f &s)
1967 dx *= s[0] * .5f;
1969 glNormal3fv(static_cast<GLfloat *>(dy.getValues()));
1971 glVertex3f( p[0] - dx[0],
1972 p[1] - dx[1],
1973 p[2] - dx[2]);
1975 glVertex3f( p[0] + dx[0],
1976 p[1] + dx[1],
1977 p[2] + dx[2]);
1979 glVertex3f(sp[0] + dx[0],
1980 sp[1] + dx[1],
1981 sp[2] + dx[2]);
1983 glVertex3f(sp[0] - dx[0],
1984 sp[1] - dx[1],
1985 sp[2] - dx[2]);
1991 /*! Objects using the pos/secpos/normal coordinate system for rendering
1992 \ingroup GrpDrawablesParticlesHelpers
1994 template <class posTrait, class colTrait, class sizeTrait, class normalTrait,
1995 class geoTrait>
1996 struct drawObjects : public ParticlesDrawer
1998 virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
2000 // some variables for faster access
2002 // init traits
2003 typename geoTrait::dataType geoData;
2004 geoTrait::init(part, pEnv, geoData);
2006 typename colTrait::dataType colData;
2007 colTrait::init(part, pEnv, colData);
2009 typename sizeTrait::dataType sizeData;
2010 sizeTrait::init(part, pEnv, sizeData);
2012 typename normalTrait::dataType normalData;
2013 normalTrait::init(part, pEnv, normalData);
2015 typename posTrait::dataType posData, secPosData;
2016 posTrait::init(part, pEnv, posData , part->getPositions());
2017 posTrait::init(part, pEnv, secPosData, part->getSecPositions());
2019 for(UInt32 i = 0; i < length; ++i)
2021 if(geoTrait::particle (geoData, i))
2022 continue;
2024 if(colTrait::particle (colData, i))
2025 continue;
2027 if(sizeTrait::particle(sizeData, i))
2028 continue;
2030 if(normalTrait::particle(normalData, i))
2031 continue;
2033 if(posTrait::particle (posData, i))
2034 continue;
2036 if(posTrait::particle (secPosData, i))
2037 continue;
2039 // calc the coordinate system
2041 Pnt3f &p = posTrait ::position(posData );
2042 Pnt3f &sp = posTrait ::position(secPosData);
2043 Vec3f &n = normalTrait::normal (normalData);
2045 Vec3f dz(sp - p);
2046 dz.normalize();
2048 Vec3f dx(n.cross(dz));
2049 if(dx.isZero())
2051 dx=Vec3f(1,0,0).cross(dz);
2052 if(dx.isZero())
2054 dx=Vec3f(0,1,0).cross(dz);
2055 if(dx.isZero())
2057 dx=Vec3f(0,0,1).cross(dz);
2059 else
2061 dx.setValues(0,0,0);
2065 dx.normalize();
2067 Vec3f dy(dx.cross(dz));
2069 // now draw the geometry;
2070 geoTrait::draw(geoData, p, sp, dx, dy, dz,
2071 sizeTrait::size(sizeData, i));
2074 geoTrait::exit(part, pEnv, geoData);
2077 virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
2078 const Int32 *index, UInt32 length)
2080 // some variables for faster access
2081 GeoVectorProperty *pos = part->getPositions();
2083 // init traits
2084 typename geoTrait::dataType geoData;
2085 geoTrait::init(part, pEnv, geoData);
2087 typename colTrait::dataType colData;
2088 colTrait::init(part, pEnv, colData);
2090 typename sizeTrait::dataType sizeData;
2091 sizeTrait::init(part, pEnv, sizeData);
2093 typename normalTrait::dataType normalData;
2094 normalTrait::init(part, pEnv, normalData);
2096 typename posTrait::dataType posData, secPosData;
2097 posTrait::init(part, pEnv, posData , part->getPositions());
2098 posTrait::init(part, pEnv, secPosData, part->getSecPositions());
2100 Int32 i;
2102 for(UInt32 ii = 0; ii < length; ++ii)
2104 i = index[ii];
2106 if(i < 0 || i > Int32(pos->size32()))
2107 continue;
2109 if(geoTrait::particle (geoData, i))
2110 continue;
2112 if(colTrait::particle (colData, i))
2113 continue;
2115 if(sizeTrait::particle(sizeData, i))
2116 continue;
2118 if(normalTrait::particle(normalData, i))
2119 continue;
2121 if(posTrait::particle (posData, i))
2122 continue;
2124 if(posTrait::particle (secPosData, i))
2125 continue;
2127 // calc the coordinate system
2129 Pnt3f &p = posTrait ::position(posData );
2130 Pnt3f &sp = posTrait ::position(secPosData);
2131 Vec3f &n = normalTrait::normal (normalData);
2133 Vec3f dz(sp - p);
2134 dz.normalize();
2136 Vec3f dx(n.cross(dz));
2137 if(dx.isZero())
2139 dx=Vec3f(1,0,0).cross(dz);
2140 if(dx.isZero())
2142 dx=Vec3f(0,1,0).cross(dz);
2143 if(dx.isZero())
2145 dx=Vec3f(0,0,1).cross(dz);
2147 else
2149 dx.setValues(0,0,0);
2153 dx.normalize();
2155 Vec3f dy(dx.cross(dz));
2157 // now draw the geometry;
2158 geoTrait::draw(geoData, p, sp, dx, dy, dz,
2159 sizeTrait::size(sizeData, i));
2162 geoTrait::exit(part, pEnv, geoData);
2167 /*! Objects using the pos/secpos and viewer-directed coordinate system for
2168 rendering
2169 \ingroup GrpDrawablesParticlesHelpers
2171 template <class posTrait, class colTrait, class sizeTrait,
2172 class geoTrait>
2173 struct drawViewerObjects : public ParticlesDrawer
2175 virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
2177 Matrix camera = pEnv->getCameraToWorld();
2178 Matrix toworld = pEnv->getObjectToWorld();
2180 // DrawActionBase *action = pEnv->getOldAction();
2181 // get ModelView matrix to define the direction vectors
2182 // Matrix camera,toworld;
2183 // action->getCamera()->getBeacon()->getToWorld(camera);
2184 // action->getActNode()->getToWorld(toworld);
2185 // normalize them, we don't want to neutralize scales in toworld
2186 toworld[0].normalize();
2187 toworld[1].normalize();
2188 toworld[2].normalize();
2189 toworld.invert();
2190 camera.multLeft(toworld);
2192 // Viewer position & up
2193 Pnt3f vpos(camera[3]);
2195 // some variables for faster access
2197 // init traits
2198 typename geoTrait::dataType geoData;
2199 geoTrait::init(part, pEnv, geoData);
2201 typename colTrait::dataType colData;
2202 colTrait::init(part, pEnv, colData);
2204 typename sizeTrait::dataType sizeData;
2205 sizeTrait::init(part, pEnv, sizeData);
2207 typename posTrait::dataType posData, secPosData;
2208 posTrait::init(part, pEnv, posData , part->getPositions());
2209 posTrait::init(part, pEnv, secPosData, part->getSecPositions());
2211 for(UInt32 i = 0; i < length; ++i)
2213 if(geoTrait::particle (geoData, i))
2214 continue;
2216 if(colTrait::particle (colData, i))
2217 continue;
2219 if(sizeTrait::particle(sizeData, i))
2220 continue;
2222 if(posTrait::particle (posData, i))
2223 continue;
2225 if(posTrait::particle (secPosData, i))
2226 continue;
2228 // calc the coordinate system
2230 Pnt3f &p = posTrait::position(posData );
2231 Pnt3f &sp = posTrait::position(secPosData);
2232 Vec3f n = vpos - p;
2234 Vec3f dz(sp - p);
2235 dz.normalize();
2237 Vec3f dx(n.cross(dz));
2238 if(dx.isZero())
2240 dx=Vec3f(1,0,0).cross(dz);
2241 if(dx.isZero())
2243 dx=Vec3f(0,1,0).cross(dz);
2244 if(dx.isZero())
2246 dx=Vec3f(0,0,1).cross(dz);
2248 else
2250 dx.setValues(0,0,0);
2254 dx.normalize();
2256 Vec3f dy(dx.cross(dz));
2258 // now draw the geometry;
2259 geoTrait::draw(geoData, p, sp, dx, dy, dz,
2260 sizeTrait::size(sizeData, i));
2263 geoTrait::exit(part, pEnv, geoData);
2266 virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
2267 const Int32 *index, UInt32 length)
2269 Matrix camera = pEnv->getCameraToWorld();
2270 Matrix toworld = pEnv->getObjectToWorld();
2272 // DrawActionBase *action = pEnv->getOldAction();
2273 // get ModelView matrix to define the direction vectors
2274 // Matrix camera,toworld;
2275 // action->getCamera()->getBeacon()->getToWorld(camera);
2276 // action->getActNode()->getToWorld(toworld);
2277 // normalize them, we don't want to neutralize scales in toworld
2278 toworld[0].normalize();
2279 toworld[1].normalize();
2280 toworld[2].normalize();
2281 toworld.invert();
2282 camera.multLeft(toworld);
2284 // Viewer position & up
2285 Pnt3f vpos(camera[3]);
2287 // some variables for faster access
2288 GeoVectorProperty *pos = part->getPositions();
2290 // init traits
2291 typename geoTrait::dataType geoData;
2292 geoTrait::init(part, pEnv, geoData);
2294 typename colTrait::dataType colData;
2295 colTrait::init(part, pEnv, colData);
2297 typename sizeTrait::dataType sizeData;
2298 sizeTrait::init(part, pEnv, sizeData);
2300 typename posTrait::dataType posData, secPosData;
2301 posTrait::init(part, pEnv, posData , part->getPositions());
2302 posTrait::init(part, pEnv, secPosData, part->getSecPositions());
2304 Int32 i;
2306 for(UInt32 ii = 0; ii < length; ++ii)
2308 i = index[ii];
2310 if(i < 0 || i > Int32(pos->size32()))
2311 continue;
2313 if(geoTrait::particle (geoData, i))
2314 continue;
2316 if(colTrait::particle (colData, i))
2317 continue;
2319 if(sizeTrait::particle(sizeData, i))
2320 continue;
2322 if(posTrait::particle (posData, i))
2323 continue;
2325 if(posTrait::particle (secPosData, i))
2326 continue;
2328 // calc the coordinate system
2330 Pnt3f &p = posTrait ::position(posData );
2331 Pnt3f &sp = posTrait ::position(secPosData);
2332 Vec3f n = vpos - p;
2334 Vec3f dz(sp - p);
2335 dz.normalize();
2337 Vec3f dx(n.cross(dz));
2338 if(dx.isZero())
2340 dx=Vec3f(1,0,0).cross(dz);
2341 if(dx.isZero())
2343 dx=Vec3f(0,1,0).cross(dz);
2344 if(dx.isZero())
2346 dx=Vec3f(0,0,1).cross(dz);
2348 else
2350 dx.setValues(0,0,0);
2354 dx.normalize();
2356 Vec3f dy(dx.cross(dz));
2358 // now draw the geometry;
2359 geoTrait::draw(geoData, p, sp, dx, dy, dz,
2360 sizeTrait::size(sizeData, i));
2363 geoTrait::exit(part, pEnv, geoData);
2368 /*! Static coordinates quad, pass all parameters to shader
2369 \ingroup GrpDrawablesParticlesHelpers
2371 template <class posTrait, class secPosTrait, class colTrait, class texTrait,
2372 class sizeTrait, class normalTrait>
2373 struct drawShaderQuads : public ParticlesDrawer
2375 virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
2376 const Int32 *index, UInt32 length)
2378 Window *win = pEnv->getWindow();
2380 osgSinkUnusedWarning(win);
2382 OSGGETGLFUNCBYID_GL3( glMultiTexCoord3fv,
2383 osgGlMultiTexCoord3fv,
2384 _funcglMultiTexCoord3fvARB,
2385 win);
2387 // init traits
2388 typename colTrait::dataType colData;
2389 colTrait::init(part, pEnv, colData);
2391 typename texTrait::dataType texData;
2392 texTrait::init(part, pEnv, texData);
2394 typename sizeTrait::dataType sizeData;
2395 sizeTrait::init(part, pEnv, sizeData);
2397 typename normalTrait::dataType normalData;
2398 normalTrait::init(part, pEnv, normalData);
2400 typename posTrait::dataType posData;
2401 posTrait::init(part, pEnv, posData, part->getPositions());
2403 typename secPosTrait::dataType secPosData;
2404 secPosTrait::init(part, pEnv, secPosData, part->getSecPositions());
2406 GeoVectorProperty *pos = part->getPositions();
2408 glBegin(GL_QUADS);
2410 Int32 i;
2412 for(UInt32 ii = 0; ii < length; ++ii)
2414 i = index[ii];
2416 if(i < 0 || i > Int32(pos->size32()))
2417 continue;
2419 if(colTrait::particle (colData, i))
2420 continue;
2422 if(texTrait::particle(texData, i))
2423 continue;
2425 if(sizeTrait::particle(sizeData, i))
2426 continue;
2428 if(normalTrait::particle(normalData, i))
2429 continue;
2431 if(posTrait::particle(posData, i))
2432 continue;
2434 if(secPosTrait::particle(secPosData, i))
2435 continue;
2438 Vec3f s = sizeTrait::size(sizeData, i);
2440 if(s[0] == 0)
2441 continue;
2443 normalTrait::normal(normalData, 0);
2445 osgGlMultiTexCoord3fv(GL_TEXTURE1_ARB,
2446 posTrait::position(posData).getValues());
2448 osgGlMultiTexCoord3fv(
2449 GL_TEXTURE2_ARB,
2450 secPosTrait::position(secPosData).getValues());
2452 osgGlMultiTexCoord3fv(GL_TEXTURE3_ARB,
2453 s.getValues());
2455 texTrait::vertex(texData, 0, 0, 0);
2456 glVertex2f (-.5f, -.5f);
2457 texTrait::vertex(texData, 0, 1, 0);
2458 glVertex2f ( .5f, -.5f);
2459 texTrait::vertex(texData, 0, 1, 1);
2460 glVertex2f ( .5f, .5f);
2461 texTrait::vertex(texData, 0, 0, 1);
2462 glVertex2f (-.5f, .5f);
2465 glEnd();
2468 virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
2470 Window *win = pEnv->getWindow();
2472 osgSinkUnusedWarning(win);
2474 OSGGETGLFUNCBYID_GL3( glMultiTexCoord3fv,
2475 osgGlMultiTexCoord3fv,
2476 _funcglMultiTexCoord3fvARB,
2477 win);
2479 // init traits
2480 typename colTrait::dataType colData;
2481 colTrait::init(part, pEnv, colData);
2483 typename texTrait::dataType texData;
2484 texTrait::init(part, pEnv, texData);
2486 typename sizeTrait::dataType sizeData;
2487 sizeTrait::init(part, pEnv, sizeData);
2489 typename normalTrait::dataType normalData;
2490 normalTrait::init(part, pEnv, normalData);
2492 typename posTrait::dataType posData;
2493 posTrait::init(part, pEnv, posData, part->getPositions());
2495 typename secPosTrait::dataType secPosData;
2496 secPosTrait::init(part, pEnv, secPosData, part->getSecPositions());
2498 glBegin(GL_QUADS);
2500 for(UInt32 i = 0; i < length; ++i)
2502 if(colTrait::particle (colData, i))
2503 continue;
2505 if(texTrait::particle(texData, i))
2506 continue;
2508 if(sizeTrait::particle(sizeData, i))
2509 continue;
2511 if(normalTrait::particle(normalData, i))
2512 continue;
2514 if(posTrait::particle(posData, i))
2515 continue;
2517 if(secPosTrait::particle(secPosData, i))
2518 continue;
2521 Vec3f s = sizeTrait::size(sizeData, i);
2523 if(s[0] == 0)
2524 continue;
2526 normalTrait::normal(normalData, 0);
2528 osgGlMultiTexCoord3fv(GL_TEXTURE1_ARB,
2529 posTrait::position(posData).getValues());
2531 osgGlMultiTexCoord3fv(
2532 GL_TEXTURE2_ARB,
2533 secPosTrait::position(secPosData).getValues());
2535 osgGlMultiTexCoord3fv(GL_TEXTURE3_ARB,
2536 s.getValues());
2538 texTrait::vertex(texData, 0, 0, 0);
2539 glVertex2f (-.5f, -.5f);
2540 texTrait::vertex(texData, 0, 1, 0);
2541 glVertex2f ( .5f, -.5f);
2542 texTrait::vertex(texData, 0, 1, 1);
2543 glVertex2f ( .5f, .5f);
2544 texTrait::vertex(texData, 0, 0, 1);
2545 glVertex2f (-.5f, .5f);
2548 glEnd();
2553 /*! Static coordinates strips with y coordinates between -.5 and .5, split
2554 into size[2] parts, pass all parameters to shader
2555 \ingroup GrpDrawablesParticlesHelpers
2557 template <class posTrait, class secPosTrait, class colTrait, class texTrait,
2558 class sizeTrait, class normalTrait>
2559 struct drawShaderStrips : public ParticlesDrawer
2561 virtual void drawIndexed(Particles *part, DrawEnv *pEnv,
2562 const Int32 *index, UInt32 length)
2564 Window *win = pEnv->getWindow();
2566 osgSinkUnusedWarning(win);
2568 OSGGETGLFUNCBYID_GL3( glMultiTexCoord3fv,
2569 osgGlMultiTexCoord3fv,
2570 _funcglMultiTexCoord3fvARB,
2571 win);
2573 // init traits
2574 typename colTrait::dataType colData;
2575 colTrait::init(part, pEnv, colData);
2577 typename texTrait::dataType texData;
2578 texTrait::init(part, pEnv, texData);
2580 typename sizeTrait::dataType sizeData;
2581 sizeTrait::init(part, pEnv, sizeData);
2583 typename normalTrait::dataType normalData;
2584 normalTrait::init(part, pEnv, normalData);
2586 typename posTrait::dataType posData;
2587 posTrait::init(part, pEnv, posData, part->getPositions());
2589 typename secPosTrait::dataType secPosData;
2590 secPosTrait::init(part, pEnv, secPosData, part->getSecPositions());
2592 GeoVectorProperty *pos = part->getPositions();
2594 Int32 i;
2596 for(UInt32 ii = 0; ii < length; ++ii)
2598 i = index[ii];
2600 if(i < 0 || i > Int32(pos->size()))
2601 continue;
2603 if(colTrait::particle (colData, i))
2604 continue;
2606 if(texTrait::particle(texData, i))
2607 continue;
2609 if(sizeTrait::particle(sizeData, i))
2610 continue;
2612 if(normalTrait::particle(normalData, i))
2613 continue;
2615 if(posTrait::particle(posData, i))
2616 continue;
2618 if(secPosTrait::particle(secPosData, i))
2619 continue;
2622 Vec3f s = sizeTrait::size(sizeData, i);
2624 if(s[0] == 0)
2625 continue;
2627 normalTrait::normal(normalData, 0);
2629 osgGlMultiTexCoord3fv(GL_TEXTURE1_ARB,
2630 posTrait::position(posData).getValues());
2632 osgGlMultiTexCoord3fv(
2633 GL_TEXTURE2_ARB,
2634 secPosTrait::position(secPosData).getValues());
2636 osgGlMultiTexCoord3fv(GL_TEXTURE3_ARB,
2637 s.getValues());
2639 glBegin(GL_QUAD_STRIP);
2641 UInt32 n = static_cast<UInt32>(s[2]);
2642 Real32 step = 1.f / (n-1);
2643 Real32 v = 0.f;
2644 for(UInt32 y = 0; y < n; ++y, v += step)
2646 texTrait::vertex(texData, 0, 0, v);
2647 glVertex2f (-.5f, v-.5f);
2648 texTrait::vertex(texData, 0, 1, v);
2649 glVertex2f ( .5f, v-.5f);
2652 glEnd();
2657 virtual void draw(Particles *part, DrawEnv *pEnv, UInt32 length)
2659 Window *win = pEnv->getWindow();
2661 osgSinkUnusedWarning(win);
2663 OSGGETGLFUNCBYID_GL3( glMultiTexCoord3fv,
2664 osgGlMultiTexCoord3fv,
2665 _funcglMultiTexCoord3fvARB,
2666 win);
2668 // init traits
2669 typename colTrait::dataType colData;
2670 colTrait::init(part, pEnv, colData);
2672 typename texTrait::dataType texData;
2673 texTrait::init(part, pEnv, texData);
2675 typename sizeTrait::dataType sizeData;
2676 sizeTrait::init(part, pEnv, sizeData);
2678 typename normalTrait::dataType normalData;
2679 normalTrait::init(part, pEnv, normalData);
2681 typename posTrait::dataType posData;
2682 posTrait::init(part, pEnv, posData, part->getPositions());
2684 typename secPosTrait::dataType secPosData;
2685 secPosTrait::init(part, pEnv, secPosData, part->getSecPositions());
2687 for(UInt32 i = 0; i < length; ++i)
2689 if(colTrait::particle (colData, i))
2690 continue;
2692 if(texTrait::particle(texData, i))
2693 continue;
2695 if(sizeTrait::particle(sizeData, i))
2696 continue;
2698 if(normalTrait::particle(normalData, i))
2699 continue;
2701 if(posTrait::particle(posData, i))
2702 continue;
2704 if(secPosTrait::particle(secPosData, i))
2705 continue;
2708 Vec3f s = sizeTrait::size(sizeData, i);
2710 if(s[0] == 0)
2711 continue;
2713 normalTrait::normal(normalData, 0);
2715 osgGlMultiTexCoord3fv(GL_TEXTURE1_ARB,
2716 posTrait::position(posData).getValues());
2718 osgGlMultiTexCoord3fv(
2719 GL_TEXTURE2_ARB,
2720 secPosTrait::position(secPosData).getValues());
2722 osgGlMultiTexCoord3fv(GL_TEXTURE3_ARB,
2723 s.getValues());
2725 glBegin(GL_QUAD_STRIP);
2727 UInt32 n = static_cast<UInt32>(s[2]);
2728 Real32 step = 1.f / (n-1);
2729 Real32 v = 0.f;
2730 for(UInt32 y = 0; y < n; ++y, v += step)
2732 texTrait::vertex(texData, 0, 0, v);
2733 glVertex2f (-.5f, v-.5f);
2734 texTrait::vertex(texData, 0, 1, v);
2735 glVertex2f ( .5f, v-.5f);
2738 glEnd();
2743 /*! \} */
2746 /* Sorting functions */
2748 /*! \ingroup GrpDrawablesParticlesHelpers
2749 \nohierarchy
2752 struct sorter
2754 sorter() : _value(0.f), _index(0) {}
2756 sorter(Real32 value, Int32 index) :
2757 _value(value),
2758 _index(index)
2762 bool operator<(const sorter &a) const
2764 if(_value < a._value)
2765 return true;
2767 return false;
2770 bool operator<=(const sorter &a) const
2772 if(_value <= a._value)
2773 return true;
2775 return false;
2778 bool operator>(const sorter &a) const
2780 return ! (a < *this);
2783 bool operator>=(const sorter &a) const
2785 return ! (a <= *this);
2788 Real32 _value;
2789 Int32 _index;
2792 Int32 *Particles::calcIndex(DrawEnv *pEnv,
2793 UInt32 &len,
2794 Int32 *index)
2796 // some variables for faster access
2797 GeoVectorProperty *pos = getPositions();
2798 const MFInt32 *indices = getMFIndices();
2800 // get ModelView matrix to define the direction vectors
2801 // Matrix camera,toworld;
2803 Matrix camera = pEnv->getCameraToWorld();
2804 Matrix toworld = pEnv->getObjectToWorld();
2807 RenderAction *ra = dynamic_cast<RenderAction *>(pEnv->getOldAction());
2809 if(ra != NULL)
2811 toworld = ra->top_matrix();
2815 toworld.invert();
2816 camera.multLeft(toworld);
2818 Pnt3f refpoint(camera[3].getValues());
2820 if(getMode() == ViewDirQuads)
2821 camera.invert();
2823 Pnt3f p,q;
2824 UInt32 size;
2826 if(indices->size() > 0)
2828 if(getNumParticles() == -1)
2830 size = indices->size32();
2832 else
2834 size = getNumParticles();
2837 else
2839 if(getNumParticles() == -1)
2841 size = pos->size32();
2843 else
2845 size = getNumParticles();
2849 std::vector<sorter> sorterList(size);
2851 len = 0;
2852 UInt32 i;
2854 if(getMode() == ViewDirQuads)
2856 if(indices->size() > 0)
2858 for(i = 0; i < size; i++)
2860 if((*(indices))[i] < 0 ||
2861 (*(indices))[i] > Int32(pos->size()))
2862 continue;
2864 sorterList[len]._index = (*(indices))[i];
2866 pos->getValue(p,i);
2867 camera.mult(p, p);
2868 sorterList[len]._value = p[2];
2870 len++;
2873 else
2875 for(i = 0; i < size; i++)
2877 sorterList[len]._index = i;
2879 pos->getValue(p,i);
2880 camera.mult(p, p);
2881 sorterList[len]._value = p[2];
2883 len++;
2887 else
2889 if(indices->size() > 0)
2891 for(i = 0; i < size; i++)
2893 if((*(indices))[i] < 0 ||
2894 (*(indices))[i] > Int32(pos->size()))
2895 continue;
2897 sorterList[len]._index = (*(indices))[i];
2899 pos->getValue(p,i);
2900 sorterList[len]._value = - refpoint.dist2(p);
2902 len++;
2905 else
2907 for(i = 0; i < size; i++)
2909 sorterList[len]._index = i;
2911 pos->getValue(p,i);
2912 sorterList[len]._value = - refpoint.dist2(p);
2914 len++;
2919 std::sort(sorterList.begin(), sorterList.begin() + len);
2921 if(index == NULL)
2922 index=new Int32[len];
2924 if(getDrawOrder() == FrontToBack)
2926 for(i = 0; i<len; i++)
2928 index[i] = sorterList[len - 1 - i]._index;
2931 else
2933 for(i = 0; i<len; i++)
2935 index[i] = sorterList[i]._index;
2939 return index;
2943 /*! Low-level Draw method that pumps OpenGL commands.
2945 void Particles::drawPrimitives(DrawEnv *pEnv)
2947 // some variables for faster access
2948 GeoVectorProperty *pos = getPositions();
2949 GeoVectorProperty *col = getColors();
2950 GeoVectorProperty *norm = getNormals();
2951 const MFVec3f *size = getMFSizes();
2953 if((size ->size() > 1 && size ->size() != pos->size()) ||
2954 (col != NULL && col->size() != 1 &&
2955 col->size() != pos->size()) ||
2956 (norm != NULL && norm->size() != 1 &&
2957 norm->size() != pos->size())
2960 FWARNING(("Particles::draw: inconsistent attributes "
2961 "(p:%" PRISize " s:%" PRISize " c:%d)!\n",
2962 pos->size(), size->size(),
2963 (col != NULL)? int(col->size()) : -1));
2964 return;
2967 ParticlesDrawer *drawer = findDrawer();
2969 if(drawer == NULL)
2971 FWARNING(("Particles 0x%p: couldn't find drawer!\n",
2972 static_cast<void *>(this)));
2973 return;
2976 const Int32 *index = NULL;
2977 UInt32 length = 0;
2978 bool freeIndex = false;
2980 if(_sfDrawOrder.getValue() != Particles::Any)
2982 if(getDynamic())
2984 index = calcIndex(pEnv,length);
2986 else
2988 if(!getBsp().created())
2990 editBsp().build(this);
2993 // Matrix modelview,toworld;
2995 Matrix modelview = pEnv->getCameraToWorld();
2996 Matrix toworld = pEnv->getObjectToWorld();
2999 RenderAction *ra = dynamic_cast<RenderAction *>(
3000 pEnv->getOldAction());
3002 if(ra != NULL)
3004 toworld = ra->top_matrix();
3006 else
3008 pEnv->getOldAction()->getActNode()->getToWorld(toworld);
3011 // action->getCamera()->getBeacon()->getToWorld(modelview);
3012 // action->getActNode()->getToWorld(toworld);
3014 toworld.invert();
3015 modelview.mult(toworld);
3017 Pnt3f ref(modelview[3][0],modelview[3][1],
3018 modelview[3][2]);
3019 Vec3f refvec( modelview[2][0],modelview[2][1],
3020 modelview[2][2]);
3022 index = getBsp().traverse(ref,length);
3024 freeIndex = true;
3026 else if (getMFIndices()->size() > 0)
3028 index = &(getMFIndices()->getValues()[0]);
3029 if(getNumParticles() == -1)
3031 length = getMFIndices()->size32();
3033 else
3035 length = getNumParticles();
3039 if(index != NULL)
3041 if(length > 0)
3042 drawer->drawIndexed(this,pEnv,index,length);
3044 else
3046 if(getNumParticles() == -1)
3048 drawer->draw(this,pEnv,pos->size32());
3050 else if(getNumParticles() > 0)
3052 drawer->draw(this,pEnv,getNumParticles());
3056 if(freeIndex)
3057 delete [] index;
3059 return;
3062 /*! find the drawer object for the actual configuration of parameters */
3064 ParticlesDrawer *Particles::findDrawer(void)
3066 if(getPositions() == NULL)
3067 return NULL;
3069 UInt8 mode;
3070 enum { part = 0, sing, none } size,normal,color,tex,secpos;
3072 mode = getMode();
3074 // find the parameters' use
3076 size = (getMFSizes()->size() == getPositions()->size()) ? part :
3077 (getMFSizes()->size() == 1 ) ? sing :
3078 none;
3079 normal = (getNormals() != NULL &&
3080 getNormals()->size() == getPositions()->size()) ? part :
3081 (getNormals() != NULL &&
3082 getNormals()->size() == 1 ) ? sing :
3083 none;
3084 secpos = (getSecPositions() != NULL &&
3085 getSecPositions()->size()== getPositions()->size()) ? part :
3086 (getSecPositions() != NULL &&
3087 getSecPositions()->size()== 1 ) ? sing :
3088 none;
3089 color = (getColors() != NULL &&
3090 getColors()->size() == getPositions()->size()) ? part :
3091 (getColors() != NULL &&
3092 getColors()->size() == 1 ) ? sing :
3093 none;
3094 tex = (getMFTextureZs()->size() == getPositions()->size()) ? part :
3095 (getMFTextureZs()->size() == 1 ) ? sing :
3096 none;
3098 // check if the used types are common cases
3101 bool normalIs3f = (getNormals() != NULL &&
3102 getNormals()->getFormat() == GL_FLOAT);
3104 bool colorIs3f = (getColors() != NULL &&
3105 getColors()->getFormat() == GL_FLOAT &&
3106 getColors()->getDimension() == 3);
3109 bool posIs3f = (getPositions() != NULL &&
3110 getPositions()->getFormat() == GL_FLOAT &&
3111 getPositions()->getDimension() == 3);
3113 // now find the drawer
3115 // main difference: mode, as only a subset of the attributes is used
3116 // in the different modes
3118 // this is where to add fast pathes...
3119 // don't go overboard, as every path adds code, and code bloat is
3120 // easily obtained here.
3122 switch(mode)
3124 case Points:
3126 static ParticlesDrawer *fallback =
3127 new drawPoints<PosTraitGeneric,ColTraitGeneric,
3128 TexTraitGeneric,SizeTraitGeneric>;
3130 return fallback;
3133 case Lines:
3135 if(secpos == none)
3137 FWARNING(("Particles::findDrawer: Need secondary positions for "
3138 "type Lines!\n"));
3139 return NULL;
3142 static ParticlesDrawer *fallback =
3143 new drawLines<PosTraitGeneric,ColTraitGeneric,
3144 TexTraitGeneric,SizeTraitGeneric>;
3146 return fallback;
3149 case ViewDirQuads:
3151 static ParticlesDrawer *fallback =
3152 new drawViewDirQuads<PosTraitGeneric,ColTraitGeneric,
3153 TexTraitGeneric,SizeTraitGeneric>;
3155 if(posIs3f && tex == none && size != none)
3157 static ParticlesDrawer *pumps[] = {
3158 new drawViewDirQuads<PosTrait3f,ColTraitParticle,
3159 TexTraitNone,SizeTraitParticle>,
3160 new drawViewDirQuads<PosTrait3f,ColTraitSingle,
3161 TexTraitNone,SizeTraitParticle>,
3162 new drawViewDirQuads<PosTrait3f,ColTraitNone,
3163 TexTraitNone,SizeTraitParticle>,
3165 new drawViewDirQuads<PosTrait3f,ColTraitParticle,
3166 TexTraitNone,SizeTraitSingle>,
3167 new drawViewDirQuads<PosTrait3f,ColTraitSingle,
3168 TexTraitNone,SizeTraitSingle>,
3169 new drawViewDirQuads<PosTrait3f,ColTraitNone,
3170 TexTraitNone,SizeTraitSingle>,
3173 return pumps[size * 3 + color];
3176 return fallback;
3179 case ViewerQuads:
3181 static ParticlesDrawer *fallback =
3182 new drawViewerQuads<PosTraitGeneric,ColTraitGeneric,
3183 TexTraitGeneric,SizeTraitGeneric>;
3185 if(posIs3f && tex == none && size != none)
3187 static ParticlesDrawer *pumps[] = {
3188 new drawViewerQuads<PosTrait3f,ColTraitParticle,
3189 TexTraitNone,SizeTraitParticle>,
3190 new drawViewerQuads<PosTrait3f,ColTraitSingle,
3191 TexTraitNone,SizeTraitParticle>,
3192 new drawViewerQuads<PosTrait3f,ColTraitNone,
3193 TexTraitNone,SizeTraitParticle>,
3195 new drawViewerQuads<PosTrait3f,ColTraitParticle,
3196 TexTraitNone,SizeTraitSingle>,
3197 new drawViewerQuads<PosTrait3f,ColTraitSingle,
3198 TexTraitNone,SizeTraitSingle>,
3199 new drawViewerQuads<PosTrait3f,ColTraitNone,
3200 TexTraitNone,SizeTraitSingle>,
3203 return pumps[size * 3 + color];
3206 return fallback;
3209 case Arrows:
3211 if(secpos == none)
3213 FWARNING(("Particles::findDrawer: Need secondary positions for "
3214 "type Arrows!\n"));
3215 return NULL;
3218 if(normal == none)
3220 FWARNING(("Particles::findDrawer: Need normals for "
3221 "type Arrows!\n"));
3222 return NULL;
3225 static ParticlesDrawer *fallback =
3226 new drawObjects<PosTraitGeneric,ColTraitGeneric,
3227 SizeTraitGeneric,NormalTraitGeneric,
3228 GeoTraitArrow>;
3230 return fallback;
3233 case ViewerArrows:
3235 if(secpos == none)
3237 FWARNING(("Particles::findDrawer: Need secondary positions for "
3238 "type ViewerArrows!\n"));
3239 return NULL;
3242 if(normal == none)
3244 FWARNING(("Particles::findDrawer: Need normals for "
3245 "type ViewerArrows!\n"));
3246 return NULL;
3249 static ParticlesDrawer *fallback =
3250 new drawViewerObjects<PosTraitGeneric,ColTraitGeneric,
3251 SizeTraitGeneric,GeoTraitArrow>;
3253 return fallback;
3256 case Rectangles:
3258 if(secpos == none)
3260 FWARNING(("Particles::findDrawer: Need secondary positions for "
3261 "type Rectangles!\n"));
3262 return NULL;
3265 if(normal == none)
3267 FWARNING(("Particles::findDrawer: Need normals for "
3268 "type Rectangles!\n"));
3269 return NULL;
3272 static ParticlesDrawer *fallback =
3273 new drawObjects<PosTraitGeneric,ColTraitGeneric,
3274 SizeTraitGeneric,NormalTraitGeneric,
3275 GeoTraitRectangle>;
3277 return fallback;
3280 case ShaderQuads:
3282 static ParticlesDrawer *fallback =
3283 new drawShaderQuads<PosTraitGeneric,PosTraitGeneric,
3284 ColTraitGeneric, TexTraitGeneric,
3285 SizeTraitGeneric,NormalTraitGeneric>,
3286 *nosecfallback =
3287 new drawShaderQuads<PosTraitGeneric,PosTraitNone,
3288 ColTraitGeneric, TexTraitGeneric,
3289 SizeTraitGeneric,NormalTraitGeneric>;
3291 if(secpos == none)
3293 return nosecfallback;
3295 else
3297 return fallback;
3301 case ShaderStrips:
3303 static ParticlesDrawer *fallback =
3304 new drawShaderStrips<PosTraitGeneric,PosTraitGeneric,
3305 ColTraitGeneric, TexTraitGeneric,
3306 SizeTraitGeneric,NormalTraitGeneric>,
3307 *nosecfallback =
3308 new drawShaderStrips<PosTraitGeneric,PosTraitNone,
3309 ColTraitGeneric, TexTraitGeneric,
3310 SizeTraitGeneric,NormalTraitGeneric>;
3312 if(secpos == none)
3314 return nosecfallback;
3316 else
3318 return fallback;
3325 if (normal) return NULL; // make picky compilers happy
3326 return NULL;
3329 OSG_END_NAMESPACE