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