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