ps_ribbon.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "std3d.h"
00025 
00026 #include "nel/3d/ps_ribbon.h"
00027 #include "nel/3d/ps_macro.h"
00028 #include "nel/3d/particle_system.h"
00029 #include "nel/3d/driver.h"
00030 #include "nel/3d/ps_util.h"
00031 #include "nel/3d/texture_mem.h"
00032 #include "nel/misc/matrix.h"
00033 
00034 namespace NL3D
00035 {
00036 
00037 static NLMISC::CRGBA GradientB2W[] = {NLMISC::CRGBA(0, 0, 0, 0), NLMISC::CRGBA(255, 255, 255, 255) };
00038 
00039 CPSRibbon::TVBMap CPSRibbon::_VBMaps[16];
00040 
00041 
00043 static ITexture *CreateGradientTexture()
00044 {
00045     NL_PS_FUNC(CreateGradientTexture)
00046     std::auto_ptr<CTextureMem> tex(new CTextureMem((uint8 *) &GradientB2W,
00047                                                    sizeof(GradientB2W),
00048                                                    false, /* dont delete */
00049                                                    false, /* not a file */
00050                                                    2, 1)
00051                                   );
00052     //tex->setWrapS(ITexture::Clamp);
00053     tex->setShareName("#GradBW");
00054     return tex.release();
00055 }
00056 
00057 
00059 // ribbon implementation //
00061 
00062 // predifined shapes
00063 const NLMISC::CVector CPSRibbon::Triangle[] =
00064 {
00065     NLMISC::CVector(0, 1, 0),
00066     NLMISC::CVector(1, -1, 0),
00067     NLMISC::CVector(-1, -1, 0),
00068 };
00069 
00070 const NLMISC::CVector CPSRibbon::Losange[] =
00071 {
00072     NLMISC::CVector(0, 1.f, 0),
00073     NLMISC::CVector(1.f, 0, 0),
00074     NLMISC::CVector(0, -1.f, 0),
00075     NLMISC::CVector(-1.f, 0, 0)
00076 };
00077 
00078 const NLMISC::CVector  CPSRibbon::HeightSides[] =
00079 {
00080     NLMISC::CVector(-0.5f, 1, 0),
00081     NLMISC::CVector(0.5f, 1, 0),
00082     NLMISC::CVector(1, 0.5f, 0),
00083     NLMISC::CVector(1, -0.5f, 0),
00084     NLMISC::CVector(0.5f, -1, 0),
00085     NLMISC::CVector(-0.5f, -1, 0),
00086     NLMISC::CVector(-1, -0.5f, 0),
00087     NLMISC::CVector(-1, 0.5f, 0)
00088 };
00089 
00090 
00091 const NLMISC::CVector CPSRibbon::Pentagram[] =
00092 {
00093     NLMISC::CVector(0, 1, 0),
00094     NLMISC::CVector(1, -1, 0),
00095     NLMISC::CVector(-1, 0, 0),
00096     NLMISC::CVector(1, 0, 0),
00097     NLMISC::CVector(-1, -1, 0)
00098 };
00099 
00100 const NLMISC::CVector CPSRibbon::SimpleSegmentX[] =
00101 {
00102     NLMISC::CVector(1, 0, 0),
00103     NLMISC::CVector(-1, 0, 0),
00104 };
00105 const uint CPSRibbon::NbVerticesInSimpleSegmentX = sizeof(CPSRibbon::SimpleSegmentX) / sizeof(CVector);
00106 
00107 const NLMISC::CVector CPSRibbon::SimpleSegmentY[] =
00108 {
00109     NLMISC::CVector(0, 1, 0),
00110     NLMISC::CVector(0, -1, 0),
00111 };
00112 const uint CPSRibbon::NbVerticesInSimpleSegmentY = sizeof(CPSRibbon::SimpleSegmentY) / sizeof(CVector);
00113 
00114 const NLMISC::CVector CPSRibbon::SimpleSegmentZ[] =
00115 {
00116     NLMISC::CVector(0, 0, 1),
00117     NLMISC::CVector(0, 0, -1),
00118 };
00119 const uint CPSRibbon::NbVerticesInSimpleSegmentZ = sizeof(CPSRibbon::SimpleSegmentZ) / sizeof(CVector);
00120 
00121 const NLMISC::CVector CPSRibbon::SimpleBrace[] =
00122 {
00123     NLMISC::CVector(1, 0, 0),
00124     NLMISC::CVector(-1, 0, 0),
00125     NLMISC::CVector(0, 1, 0),
00126     NLMISC::CVector(0, -1, 0)
00127 };
00128 const uint CPSRibbon::NbVerticesInSimpleBrace = sizeof(CPSRibbon::SimpleBrace) / sizeof(CVector);
00129 
00130 const uint CPSRibbon::NbVerticesInTriangle = sizeof(CPSRibbon::Triangle) / sizeof(CVector);
00131 const uint CPSRibbon::NbVerticesInLosange = sizeof(Losange) / sizeof(CVector);
00132 const uint CPSRibbon::NbVerticesInHeightSide = sizeof(CPSRibbon::HeightSides) / sizeof(CVector);
00133 const uint CPSRibbon::NbVerticesInPentagram = sizeof(CPSRibbon::Pentagram) / sizeof(CVector);
00134 
00135 
00136 struct CDummy2DAngle : CPSRotated2DParticle
00137 {
00138     CPSLocated *getAngle2DOwner(void) { return NULL; }
00139 };
00140 
00142 void CPSRibbon::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00143 {
00144     NL_PS_FUNC(CPSRibbon_serial)
00145     // Version 3 : - added brace mode
00146     //             - added orientation enum
00147     sint ver = f.serialVersion(3);
00148     if (ver == 1)
00149     {
00150         nlassert(f.isReading());
00151 
00154         sint ver2 = f.serialVersion(2);
00155 
00156         // here is CPSLocatedBindable::serial(f)
00157         sint ver3 = f.serialVersion(4);
00158         f.serialPtr(_Owner);
00159         if (ver3 > 1) f.serialEnum(_LOD);
00160         if (ver3 > 2) f.serial(_Name);
00161         if (ver3 > 3)
00162         {
00163             if (f.isReading())
00164             {
00165                 uint32 id;
00166                 f.serial(id);
00167                 setExternID(id);
00168             }
00169             else
00170             {
00171                 f.serial(_ExternID);
00172             }
00173         }
00174 
00175         if (ver2 >= 2)
00176         {
00177             bool bDisableAutoLOD;
00178             f.serial(bDisableAutoLOD);
00179             disableAutoLOD(bDisableAutoLOD);
00180         }
00181 
00182         uint32 tailNbSegs;
00183         bool   colorFading;
00184         bool   systemBasisEnabled;
00185         bool   drEnabled; // dying ribbons, not supported in this version
00186 
00187         CPSColoredParticle::serialColorScheme(f);
00188         CPSSizedParticle::serialSizeScheme(f);
00189 
00190         // we dont use the 2d angle anymore...serial a dummy one
00191         {
00192              CDummy2DAngle _Dummy2DAngle;
00193             _Dummy2DAngle.serialAngle2DScheme(f);
00194         }
00195 
00196         f.serial(colorFading, systemBasisEnabled);
00197         serialMaterial(f);
00198 
00199         f.serial(drEnabled);
00200         f.serial(tailNbSegs);
00201         ITexture *tex = NULL;
00202         f.serialPolyPtr(tex);
00203         _Tex = tex;
00204         if (_Tex != NULL)
00205         {
00206             f.serial(_UFactor, _VFactor) ;
00207         }
00208 
00209         // shape serialization
00210         f.serialCont(_Shape);
00211 
00212 
00213         _NbSegs = tailNbSegs >> 1;
00214         if (_NbSegs < 1) _NbSegs = 2;
00215         setInterpolationMode(Linear);
00216 
00217         nlassert(_Owner);
00218         resize(_Owner->getMaxSize());
00219         initDateVect();
00220         resetFromOwner();
00221     }
00222 
00223 
00224     if (ver >= 2)
00225     {
00226         CPSRibbonBase::serial(f);
00227         CPSColoredParticle::serialColorScheme(f);
00228         CPSSizedParticle::serialSizeScheme(f);
00229         CPSMaterial::serialMaterial(f);
00230         f.serialCont(_Shape);
00231         bool colorFading = _ColorFading;
00232         f.serial(colorFading);
00233         _ColorFading = colorFading;
00234         uint32 tailNbSegs = _NbSegs;
00235         f.serial(tailNbSegs);
00236         if (f.isReading())
00237         {
00238             setTailNbSeg(_NbSegs);
00239             touch();
00240         }
00241         ITexture *tex = _Tex;
00242         f.serialPolyPtr(tex);
00243         _Tex = tex;
00244         if (_Tex != NULL)
00245         {
00246             f.serial(_UFactor, _VFactor) ;
00247         }
00248     }
00249 
00250     if (ver >= 3)
00251     {
00252         bool braceMode = _BraceMode;
00253         f.serial(braceMode);
00254         _BraceMode = braceMode;
00255         f.serialEnum(_Orientation);
00256     }
00257 
00258     if (f.isReading())
00259     {
00260         touch();
00261     }
00262 }
00263 
00264 
00265 //=======================================================
00266 CPSRibbon::CPSRibbon() : _UFactor(1.f),
00267                          _VFactor(1.f),
00268                          _Orientation(FollowPath),
00269                          _BraceMode(true),
00270                          _ColorFading(true),
00271                          _GlobalColor(false),
00272                          _Lighted(false),
00273                          _ForceLighted(false),
00274                          _Touch(true)
00275 {
00276     NL_PS_FUNC(CPSRibbon_CPSRibbon)
00277     setInterpolationMode(Linear);
00278     setSegDuration(0.06f);
00279     if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("Ribbon");
00280     setShape(Triangle, NbVerticesInTriangle);
00281     _Mat.setDoubleSided(true);
00282 }
00283 
00284 
00285 //=======================================================
00286 CPSRibbon::~CPSRibbon()
00287 {
00288     NL_PS_FUNC(CPSRibbon_CPSRibbonDtor)
00289 }
00290 
00291 
00292 //==========================================================================
00293 inline uint CPSRibbon::getNumVerticesInSlice() const
00294 {
00295     NL_PS_FUNC(CPSRibbon_getNumVerticesInSlice)
00296     if (_BraceMode)
00297     {
00298         return _Shape.size();
00299     }
00300     else
00301     {
00302         return _Shape.size() + (_Tex == NULL ? 0 : 1);
00303     }
00304 }
00305 
00306 
00307 
00308 
00309 
00310 //=======================================================
00311 void CPSRibbon::step(TPSProcessPass pass)
00312 {
00313     NL_PS_FUNC(CPSRibbon_step)
00314     if (pass == PSMotion)
00315     {
00316         if (!_Parametric)
00317         {
00318             updateGlobals();
00319         }
00320     }
00321     else
00322     if (
00323         (pass == PSBlendRender && hasTransparentFaces())
00324         || (pass == PSSolidRender && hasOpaqueFaces())
00325         )
00326     {
00327         uint32 step;
00328         uint   numToProcess;
00329         computeSrcStep(step, numToProcess);
00330         if (!numToProcess) return;
00331 
00333         CParticleSystem &ps = *(_Owner->getOwner());
00334         if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
00335         {
00336             _Mat.setColor(ps.getGlobalColorLighted());
00337         }
00338         else
00339         {
00340             _Mat.setColor(ps.getGlobalColor());
00341         }
00342 
00347         displayRibbons(numToProcess, step);
00348 
00349     }
00350     else
00351     if (pass == PSToolRender) // edition mode only
00352     {
00353         //showTool();
00354     }
00355 }
00356 
00357 
00358 //=======================================================
00359 void CPSRibbon::newElement(const CPSEmitterInfo &info)
00360 {
00361     NL_PS_FUNC(CPSRibbon_newElement)
00362     CPSRibbonBase::newElement(info);
00363     newColorElement(info);
00364     newSizeElement(info);
00365 }
00366 
00367 
00368 //=======================================================
00369 void CPSRibbon::deleteElement(uint32 index)
00370 {
00371     NL_PS_FUNC(CPSRibbon_deleteElement)
00372     CPSRibbonBase::deleteElement(index);
00373     deleteColorElement(index);
00374     deleteSizeElement(index);
00375 }
00376 
00377 
00378 //=======================================================
00379 void CPSRibbon::resize(uint32 size)
00380 {
00381     NL_PS_FUNC(CPSRibbon_resize)
00382     nlassert(size < (1 << 16));
00383     CPSRibbonBase::resize(size);
00384     resizeColor(size);
00385     resizeSize(size);
00386 }
00387 
00388 //=======================================================
00389 void CPSRibbon::updateMatAndVbForColor(void)
00390 {
00391     NL_PS_FUNC(CPSRibbon_updateMatAndVbForColor)
00392     touch();
00393 }
00394 
00395 
00397 // Create the start slice of a ribbon (all vertices at the same pos)
00398 static inline uint8 *BuildRibbonFirstSlice(const NLMISC::CVector &pos,
00399                                            uint  numVerts,
00400                                            uint8 *dest,
00401                                            uint  vertexSize
00402                                           )
00403 {
00404     NL_PS_FUNC(BuildRibbonFirstSlice)
00405     do
00406     {
00407         * (NLMISC::CVector *) dest = pos;
00408         dest += vertexSize;
00409     }
00410     while (--numVerts);
00411     return dest;
00412 }
00413 
00414 
00416 // This compute one slice of a ribbon, and return the next vertex to be filled
00417 static inline uint8 *ComputeRibbonSliceFollowPath(const NLMISC::CVector &prev,
00418                                         const NLMISC::CVector &next,
00419                                         const NLMISC::CVector *shape,
00420                                         uint  numVerts,
00421                                         uint8 *dest,
00422                                         uint  vertexSize,
00423                                         float size,
00424                                         NLMISC::CMatrix &basis
00425                                        )
00426 {
00427     NL_PS_FUNC(ComputeRibbonSliceFollowPath)
00428     // compute a basis from the next and previous position.
00429     // (not optimized for now, but not widely used, either...)
00430     const float epsilon = 10E-5f;
00431     if (fabsf(next.x - prev.x) > epsilon
00432         || fabsf(next.y - prev.y) > epsilon
00433         || fabsf(next.z - prev.z) > epsilon)
00434     {
00435         // build a new basis, or use the previous one otherwise
00436         CPSUtil::buildSchmidtBasis(next - prev, basis);
00437     }
00438     basis.setPos(next);
00439 
00440     const NLMISC::CVector *shapeEnd = shape + numVerts;
00441     do
00442     {
00443         *(NLMISC::CVector *) dest = basis * (size * (*shape));
00444         ++shape;
00445         dest += vertexSize;
00446     }
00447     while (shape != shapeEnd);
00448     return dest;
00449 }
00450 
00452 // This compute one slice of a ribbon, and return the next vertex to be filled
00453 static inline uint8 *ComputeRibbonSliceIdentity(const NLMISC::CVector &prev,
00454                                                const NLMISC::CVector &next,
00455                                                const NLMISC::CVector *shape,
00456                                                uint  numVerts,
00457                                                uint8 *dest,
00458                                                uint  vertexSize,
00459                                                float size
00460                                               )
00461 {
00462     NL_PS_FUNC(ComputeRibbonSliceIdentity)
00463     const NLMISC::CVector *shapeEnd = shape + numVerts;
00464     do
00465     {
00466         ((NLMISC::CVector *) dest)->set(size * shape->x + next.x,
00467                                         size * shape->y + next.y,
00468                                         size * shape->z + next.z);
00469         ++shape;
00470         dest += vertexSize;
00471     }
00472     while (shape != shapeEnd);
00473     return dest;
00474 }
00475 
00477 static inline uint8 *ComputeRibbonSliceFollowPathXY(const NLMISC::CVector &prev,
00478                                                   const NLMISC::CVector &next,
00479                                                   const NLMISC::CVector *shape,
00480                                                   uint  numVerts,
00481                                                   uint8 *dest,
00482                                                   uint  vertexSize,
00483                                                   float size,
00484                                                   NLMISC::CMatrix &basis
00485                                                   )
00486 {
00487     NL_PS_FUNC(ComputeRibbonSliceFollowPathXY)
00488     float deltaX = next.x - prev.x;
00489     float deltaY = next.y - prev.y;
00490     const float epsilon = 10E-5f;
00491     if (fabsf(deltaX) > epsilon
00492         || fabsf(deltaY) > epsilon)
00493     {
00494         float norm = sqrtf(NLMISC::sqr(deltaX) + NLMISC::sqr(deltaY));
00495         float invNorm = (norm != 0.f) ? 1.f / norm : 0.f;
00496         NLMISC::CVector I, J;
00497         J.set(deltaX * invNorm, deltaY * invNorm, 0.f);
00498         I.set(-J.y, J.x, 0.f);
00499         basis.setRot(I, CVector::K, J, true);
00500     }
00501     basis.setPos(next);
00502     const NLMISC::CVector *shapeEnd = shape + numVerts;
00503     do
00504     {
00505         *(NLMISC::CVector *) dest = basis * (size * (*shape));
00506         ++shape;
00507         dest += vertexSize;
00508     }
00509     while (shape != shapeEnd);
00510     return dest;
00511 }
00512 
00513 
00514 
00515 
00517 // This is used to compute a ribbon mesh from its curve and its base shape.
00518 // This is for untextured versions (no need to duplicate the last vertex of each slice)
00519 static inline uint8 *ComputeUntexturedRibbonMesh(uint8 *destVb,
00520                                                  uint  vertexSize,
00521                                                  const NLMISC::CVector *curve,
00522                                                  const NLMISC::CVector *shape,
00523                                                  uint  numSegs,
00524                                                  uint  numVerticesInShape,
00525                                                  float sizeIncrement,
00526                                                  float size,
00527                                                  CPSRibbon::TOrientation orientation
00528                                                 )
00529 {
00530     NL_PS_FUNC(ComputeUntexturedRibbonMesh)
00531     CMatrix basis;
00532     basis.scale(0);
00533     switch(orientation)
00534     {
00535         case CPSRibbon::FollowPath:
00536             do
00537             {
00538                 destVb = ComputeRibbonSliceFollowPath(curve[1],
00539                                                      curve[0],
00540                                                      shape,
00541                                                      numVerticesInShape,
00542                                                      destVb,
00543                                                      vertexSize,
00544                                                      size,
00545                                                      basis);
00546                 ++ curve;
00547                 size -= sizeIncrement;
00548             }
00549             while (--numSegs);
00550         break;
00551         case CPSRibbon::FollowPathXY:
00552             do
00553             {
00554                 destVb = ComputeRibbonSliceFollowPathXY(curve[1],
00555                                                      curve[0],
00556                                                      shape,
00557                                                      numVerticesInShape,
00558                                                      destVb,
00559                                                      vertexSize,
00560                                                      size,
00561                                                      basis);
00562                 ++ curve;
00563                 size -= sizeIncrement;
00564             }
00565             while (--numSegs);
00566         break;
00567         case CPSRibbon::Identity:
00568             do
00569             {
00570                 destVb = ComputeRibbonSliceIdentity(curve[1],
00571                                                     curve[0],
00572                                                     shape,
00573                                                     numVerticesInShape,
00574                                                     destVb,
00575                                                     vertexSize,
00576                                                     size
00577                                                    );
00578                 ++ curve;
00579                 size -= sizeIncrement;
00580             }
00581             while (--numSegs);
00582         break;
00583         default:
00584             nlassert(0);
00585         break;
00586     }
00587     return BuildRibbonFirstSlice(curve[0], numVerticesInShape, destVb, vertexSize);
00588 }
00589 
00591 // This is used to compute a ribbon mesh from its curve and its base shape.
00592 // (Textured Version)
00593 static inline uint8 *ComputeTexturedRibbonMesh(uint8 *destVb,
00594                                                uint  vertexSize,
00595                                                const NLMISC::CVector *curve,
00596                                                const NLMISC::CVector *shape,
00597                                                uint  numSegs,
00598                                                uint  numVerticesInShape,
00599                                                float sizeIncrement,
00600                                                float size,
00601                                                CPSRibbon::TOrientation orientation
00602                                               )
00603 {
00604     NL_PS_FUNC(ComputeTexturedRibbonMesh)
00605     CMatrix basis;
00606     basis.scale(0);
00607     switch(orientation)
00608     {
00609         case CPSRibbon::FollowPath:
00610             do
00611             {
00612                 uint8 *nextDestVb = ComputeRibbonSliceFollowPath(curve[1],
00613                                                        curve[0],
00614                                                        shape,
00615                                                        numVerticesInShape,
00616                                                        destVb,
00617                                                        vertexSize,
00618                                                        size,
00619                                                        basis
00620                                                       );
00621                 // duplicate last vertex ( equal first)
00622                 * (NLMISC::CVector *) nextDestVb = * (NLMISC::CVector *) destVb;
00623                 destVb = nextDestVb + vertexSize;
00624                 //
00625                 ++ curve;
00626                 size -= sizeIncrement;
00627             }
00628             while (--numSegs);
00629         break;
00630         case CPSRibbon::FollowPathXY:
00631             do
00632             {
00633                 uint8 *nextDestVb = ComputeRibbonSliceFollowPathXY(curve[1],
00634                     curve[0],
00635                     shape,
00636                     numVerticesInShape,
00637                     destVb,
00638                     vertexSize,
00639                     size,
00640                     basis
00641                     );
00642                 // duplicate last vertex ( equal first)
00643                 * (NLMISC::CVector *) nextDestVb = * (NLMISC::CVector *) destVb;
00644                 destVb = nextDestVb + vertexSize;
00645                 //
00646                 ++ curve;
00647                 size -= sizeIncrement;
00648             }
00649             while (--numSegs);
00650         break;
00651         case CPSRibbon::Identity:
00652             do
00653             {
00654                 uint8 *nextDestVb = ComputeRibbonSliceIdentity(curve[1],
00655                     curve[0],
00656                     shape,
00657                     numVerticesInShape,
00658                     destVb,
00659                     vertexSize,
00660                     size
00661                     );
00662                 // duplicate last vertex ( equal first)
00663                 * (NLMISC::CVector *) nextDestVb = * (NLMISC::CVector *) destVb;
00664                 destVb = nextDestVb + vertexSize;
00665                 //
00666                 ++ curve;
00667                 size -= sizeIncrement;
00668             }
00669             while (--numSegs);
00670         break;
00671         default:
00672             nlassert(0);
00673         break;
00674     }
00675     return BuildRibbonFirstSlice(curve[0], numVerticesInShape + 1, destVb, vertexSize);
00676 }
00677 
00678 //==========================================================================
00679 void CPSRibbon::displayRibbons(uint32 nbRibbons, uint32 srcStep)
00680 {
00681 //  if (!FilterPS[5]) return;
00682     NL_PS_FUNC(CPSRibbon_displayRibbons)
00683     if (!nbRibbons) return;
00684     nlassert(_Owner);
00685     CPSRibbonBase::updateLOD();
00686     if (_UsedNbSegs < 2) return;
00687     const float date = _Owner->getOwner()->getSystemDate();
00688     uint8                       *currVert;
00689     CVBnPB                      &VBnPB = getVBnPB(); // get the appropriate vb (built it if needed)
00690     CVertexBuffer               &VB = VBnPB.VB;
00691     CIndexBuffer                &PB = VBnPB.PB;
00692     const uint32                vertexSize  = VB.getVertexSize();
00693     uint                        colorOffset=0;
00694 
00695     IDriver *drv = this->getDriver();
00696     #ifdef NL_DEBUG
00697         nlassert(drv);
00698     #endif
00699     drv->setupModelMatrix(getLocalToWorldTrailMatrix());
00700     _Owner->incrementNbDrawnParticles(nbRibbons); // for benchmark purpose
00701     const uint numRibbonBatch = getNumRibbonsInVB(); // number of ribons to process at once
00702     if (_UsedNbSegs == 0) return;
00704     // Material setup //
00706         CParticleSystem &ps = *(_Owner->getOwner());
00707         bool useGlobalColor = ps.getColorAttenuationScheme() != NULL || ps.isUserColorUsed();
00708         if (useGlobalColor != _GlobalColor)
00709         {
00710             _GlobalColor = useGlobalColor;
00711             touch();
00712         }
00713         if (usesGlobalColorLighting() != _Lighted)
00714         {
00715             _Lighted = usesGlobalColorLighting();
00716             touch();
00717         }
00718         if (ps.getForceGlobalColorLightingFlag() != _ForceLighted)
00719         {
00720             _ForceLighted = ps.getForceGlobalColorLightingFlag();
00721             touch();
00722         }
00723         updateMaterial();
00724         setupGlobalColor();
00725         //
00726         if (_ColorScheme)
00727         {
00728             colorOffset = VB.getColorOff();
00729         }
00731     // Compute ribbons //
00733         const uint numVerticesInSlice = getNumVerticesInSlice();
00734         const uint numVerticesInShape = _Shape.size();
00735         //
00736         static std::vector<float> sizes;
00737         static std::vector<NLMISC::CVector> ribbonPos;  // this is where the position of each ribbon slice center i stored
00738         ribbonPos.resize(_UsedNbSegs + 1); // make sure we have enough room
00739         sizes.resize(numRibbonBatch);
00740 
00741         //
00742         uint toProcess;
00743         uint ribbonIndex = 0; // index of the first ribbon in the batch being processed
00744         uint32 fpRibbonIndex = 0; // fixed point index in source
00745         if (_ColorScheme)
00746         {
00747             _ColorScheme->setColorType(drv->getVertexColorFormat());
00748         }
00749         do
00750         {
00751             toProcess = std::min((uint) (nbRibbons - ribbonIndex) , numRibbonBatch);
00752             VB.setNumVertices((_UsedNbSegs + 1) * toProcess * numVerticesInSlice);
00753             {
00754                 CVertexBufferReadWrite vba;
00755                 VB.lock(vba);
00756                 currVert = (uint8 *) vba.getVertexCoordPointer();
00758                 const float *ptCurrSize;
00759                 uint32  ptCurrSizeIncrement;
00760                 if (_SizeScheme)
00761                 {
00762                     ptCurrSize = (float *) _SizeScheme->make(this->_Owner, ribbonIndex, &sizes[0], sizeof(float), toProcess, true, srcStep);
00763                     ptCurrSizeIncrement = 1;
00764                 }
00765                 else
00766                 {
00767                     ptCurrSize = &_ParticleSize;
00768                     ptCurrSizeIncrement = 0;
00769                 }
00770 
00772                 if (_ColorScheme)
00773                 {
00774                     _ColorScheme->makeN(this->_Owner, ribbonIndex, currVert + colorOffset, vertexSize, toProcess, numVerticesInSlice * (_UsedNbSegs + 1), srcStep);
00775                 }
00776                 uint k = toProcess;
00778                 // interpolate and project points the result is directly setup in the vertex buffer //
00780                 if (!_Parametric)
00781                 {
00783                     // INCREMENTAL CASE //
00785                     if (_Tex != NULL && !_BraceMode) // textured case : must duplicate last vertex, unless in brace mod
00786                     {
00787                         do
00788                         {
00789                             const float ribbonSizeIncrement = *ptCurrSize / (float) _UsedNbSegs;
00790                             ptCurrSize += ptCurrSizeIncrement;
00791                             // the parent class has a method to get the ribbons positions
00792                             computeRibbon((uint) (fpRibbonIndex >> 16), &ribbonPos[0], sizeof(NLMISC::CVector));
00793                             currVert = ComputeTexturedRibbonMesh(currVert,
00794                                                                  vertexSize,
00795                                                                  &ribbonPos[0],
00796                                                                  &_Shape[0],
00797                                                                  _UsedNbSegs,
00798                                                                  numVerticesInShape,
00799                                                                  ribbonSizeIncrement,
00800                                                                  *ptCurrSize,
00801                                                                  _Orientation
00802                                                                 );
00803                             fpRibbonIndex += srcStep;
00804                         }
00805                         while (--k);
00806                     }
00807                     else // untextured case
00808                     {
00809                         do
00810                         {
00811                             const float ribbonSizeIncrement = *ptCurrSize / (float) _UsedNbSegs;
00812                             ptCurrSize += ptCurrSizeIncrement;
00813                             // the parent class has a method to get the ribbons positions
00814                             computeRibbon((uint) (fpRibbonIndex >> 16), &ribbonPos[0], sizeof(NLMISC::CVector));
00815                             currVert = ComputeUntexturedRibbonMesh(currVert,
00816                                                                    vertexSize,
00817                                                                    &ribbonPos[0],
00818                                                                    &_Shape[0],
00819                                                                    _UsedNbSegs,
00820                                                                    numVerticesInShape,
00821                                                                    ribbonSizeIncrement,
00822                                                                    *ptCurrSize,
00823                                                                    _Orientation
00824                                                                   );
00825                             fpRibbonIndex += srcStep;
00826                         }
00827                         while (--k);
00828                     }
00829                 }
00830                 else
00831                 {
00833                     // PARAMETRIC  CASE //
00835                     if (_Tex != NULL) // textured case
00836                     {
00837                         do
00838                         {
00839                             const float ribbonSizeIncrement = *ptCurrSize / (float) _UsedNbSegs;
00840                             ptCurrSize += ptCurrSizeIncrement;
00841                             _Owner->integrateSingle(date - _UsedSegDuration * (_UsedNbSegs + 1),
00842                                                     _UsedSegDuration,
00843                                                     _UsedNbSegs + 1,
00844                                                     (uint) (fpRibbonIndex >> 16),
00845                                                     &ribbonPos[0]);
00846 
00847                             currVert = ComputeTexturedRibbonMesh(currVert,
00848                                                                  vertexSize,
00849                                                                  &ribbonPos[0],
00850                                                                  &_Shape[0],
00851                                                                  _UsedNbSegs,
00852                                                                  numVerticesInShape,
00853                                                                  ribbonSizeIncrement,
00854                                                                  *ptCurrSize,
00855                                                                  _Orientation
00856                                                                 );
00857                             fpRibbonIndex += srcStep;
00858                         }
00859                         while (--k);
00860                     }
00861                     else // untextured case
00862                     {
00863                         do
00864                         {
00865                             const float ribbonSizeIncrement = *ptCurrSize / (float) _UsedNbSegs;
00866                             ptCurrSize += ptCurrSizeIncrement;
00867                             _Owner->integrateSingle(date - _UsedSegDuration * (_UsedNbSegs + 1),
00868                                                     _UsedSegDuration,
00869                                                     _UsedNbSegs + 1,
00870                                                     (uint) (fpRibbonIndex >> 16),
00871                                                     &ribbonPos[0]);
00872 
00873                             currVert = ComputeUntexturedRibbonMesh(currVert,
00874                                                                    vertexSize,
00875                                                                    &ribbonPos[0],
00876                                                                    &_Shape[0],
00877                                                                    _UsedNbSegs,
00878                                                                    numVerticesInShape,
00879                                                                    ribbonSizeIncrement,
00880                                                                    *ptCurrSize,
00881                                                                    _Orientation
00882                                                                   );
00883                             fpRibbonIndex += srcStep;
00884                         }
00885                         while (--k);
00886                     }
00887                 }
00888             }
00889             // display the result
00890             uint numTri = numVerticesInShape * _UsedNbSegs * toProcess;
00891             if (!_BraceMode)
00892             {
00893                 numTri <<= 1;
00894             }
00895             PB.setNumIndexes(3 * numTri);
00896             drv->activeIndexBuffer(PB);
00897             drv->activeVertexBuffer(VB);
00898             drv->renderTriangles(_Mat, 0, numTri);
00899             ribbonIndex += toProcess;
00900         }
00901         while (ribbonIndex != nbRibbons);
00902 
00903 }
00904 
00905 //==========================================================================
00906 bool CPSRibbon::hasTransparentFaces(void)
00907 {
00908     NL_PS_FUNC(CPSRibbon_hasTransparentFaces)
00909     return getBlendingMode() != CPSMaterial::alphaTest ;
00910 }
00911 
00912 
00913 //==========================================================================
00914 bool CPSRibbon::hasOpaqueFaces(void)
00915 {
00916     NL_PS_FUNC(CPSRibbon_hasOpaqueFaces)
00917     return !hasTransparentFaces();
00918 }
00919 
00920 //==========================================================================
00921 uint32 CPSRibbon::getNumWantedTris() const
00922 {
00923     NL_PS_FUNC(CPSRibbon_getNumWantedTris)
00924     nlassert(_Owner);
00925     //return _Owner->getMaxSize() * _NbSegs;
00926     return _Owner->getSize() * _NbSegs;
00927 }
00928 
00929 //==========================================================================
00930 // Set a tri in ribbon with check added
00931 static inline void setTri(CIndexBufferReadWrite &ibrw, const CVertexBuffer &vb, uint32 triIndex, uint32 i0, uint32 i1, uint32 i2)
00932 {
00933     nlassert(i0 < vb.getNumVertices());
00934     nlassert(i1 < vb.getNumVertices());
00935     nlassert(i2 < vb.getNumVertices());
00936     ibrw.setTri(triIndex, i0, i1, i2);
00937 }
00938 
00939 //==========================================================================
00940 CPSRibbon::CVBnPB &CPSRibbon::getVBnPB()
00941 {
00942     NL_PS_FUNC(CPSRibbon_getVBnPB)
00943     // TODO : vb pointer caching ?
00944     // TODO : better vb reuse ?
00946     TVBMap &map = _VBMaps[ (_BraceMode               ? 8 : 0)  | // set bit 3 if brace mode
00947                            (_Tex != NULL             ? 4 : 0)  | // set bit 2 if textured
00948                            (_ColorScheme != NULL     ? 2 : 0)  | // set bit 1 if per ribbon color
00949                            (_ColorFading             ? 1 : 0)           // set bit 0 if color fading
00950                          ];
00951 
00952     const uint numVerticesInSlice = getNumVerticesInSlice(); 
00953     const uint numVerticesInShape = _Shape.size();
00954 
00955 
00956     // The number of slice is encoded in the upper word of the vb index
00957     // The number of vertices per slices is encoded in the lower word
00958     uint VBnPDIndex = ((_UsedNbSegs + 1) << 16) | numVerticesInSlice;
00959     TVBMap::iterator it = map.find(VBnPDIndex);
00960     if (it != map.end())
00961     {
00962         return it->second;
00963     }
00964     else    // must create this vb, with few different size, it is still interseting, though they are only destroyed at exit
00965     {
00966         const uint numRibbonInVB = getNumRibbonsInVB();
00967         CVBnPB &VBnPB = map[VBnPDIndex]; // make an entry
00968         CIndexBuffer &pb = VBnPB.PB;
00969         CVertexBuffer &vb = VBnPB.VB;
00970         vb.setPreferredMemory(CVertexBuffer::AGPVolatile, true); // keep local memory because of interleaved format
00974         vb.setVertexFormat(CVertexBuffer::PositionFlag  | /* alway need position */
00975                            (_ColorScheme || _ColorFading ? CVertexBuffer::PrimaryColorFlag : 0) | /* need a color ? */
00976                            ((_ColorScheme && _ColorFading) ||  _Tex != NULL ? CVertexBuffer::TexCoord0Flag : 0) | /* need texture coordinates ? */
00977                            (_Tex != NULL && _ColorScheme && _ColorFading ? CVertexBuffer::TexCoord1Flag : 0) /* need 2nd texture coordinates ? */
00978                           );
00979         vb.setNumVertices((_UsedNbSegs + 1) * numRibbonInVB * numVerticesInSlice); // 1 seg = 1 line + terminal vertices
00980         pb.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
00981         // set the primitive block size
00982         if (_BraceMode)
00983         {
00984             pb.setNumIndexes(6 * _UsedNbSegs * numRibbonInVB * (_Shape.size() / 2));
00985         }
00986         else
00987         {
00988             pb.setNumIndexes(6 * _UsedNbSegs * numRibbonInVB * _Shape.size());
00989         }
00990         //
00991         CIndexBufferReadWrite ibaWrite;
00992         pb.lock (ibaWrite);
00993         CVertexBufferReadWrite vba;
00994         vb.lock(vba);
00996         uint vbIndex = 0;
00997         uint pbIndex = 0;
00998         uint i, k, l;
00999         for (i = 0; i < numRibbonInVB; ++i)
01000         {
01001             for (k = 0; k < (_UsedNbSegs + 1); ++k)
01002             {
01003 
01005                 if (k != _UsedNbSegs) 
01006                 {
01007                     if (_BraceMode)
01008                     {
01009                         uint vIndex = vbIndex;
01010                         for (l = 0; l < numVerticesInShape / 2; ++l) 
01011                         {
01012                             setTri(ibaWrite, vb, pbIndex, vIndex, vIndex + numVerticesInSlice, vIndex + numVerticesInSlice + 1);
01013                             pbIndex+=3;
01014                             setTri(ibaWrite, vb, pbIndex, vIndex, vIndex + numVerticesInSlice + 1, vIndex + 1);
01015                             pbIndex+=3;
01016                             vIndex += 2;
01017                         }
01018                     }
01019                     else
01020                     {
01021                         uint vIndex = vbIndex;
01022                         for (l = 0; l < (numVerticesInShape - 1); ++l) 
01023                         {
01024                             setTri(ibaWrite, vb, pbIndex, vIndex, vIndex + numVerticesInSlice, vIndex + numVerticesInSlice + 1);
01025                             pbIndex+=3;
01026                             setTri(ibaWrite, vb, pbIndex, vIndex, vIndex + numVerticesInSlice + 1, vIndex + 1);
01027                             pbIndex+=3;
01028                             ++ vIndex;
01029                         }
01030 
01032                         uint nextVertexIndex = (numVerticesInShape == numVerticesInSlice) ? vIndex + 1 - numVerticesInShape // no texture -> we loop
01033                                                : vIndex + 1; // a texture is used : use onemore vertex
01034                         setTri(ibaWrite, vb, pbIndex, vIndex, vIndex + numVerticesInSlice, nextVertexIndex + numVerticesInSlice);
01035                         pbIndex+=3;
01036                         setTri(ibaWrite, vb, pbIndex, vIndex, nextVertexIndex + numVerticesInSlice, nextVertexIndex);
01037                         pbIndex+=3;
01038                     }
01039                 }
01040 
01042                 if (_BraceMode)
01043                 {
01044                     for (l = 0; l < numVerticesInSlice / 2; ++l) 
01045                     {
01046                         nlassert(vbIndex < vb.getNumVertices());
01048                         if (_Tex != NULL)
01049                         {
01050                             vba.setTexCoord(vbIndex,
01051                                             _ColorScheme && _ColorFading ? 1 : 0,       // must we use the second texture coord ? (when 1st one used by the gradient texture : we can't encode it in the diffuse as it encodes each ribbon color)
01052                                             (float) k / _UsedNbSegs,                    // u
01053                                             0.f                                         // v
01054                                            );
01055                             vba.setTexCoord(vbIndex + 1,
01056                                             _ColorScheme && _ColorFading ? 1 : 0,
01057                                             (float) k / _UsedNbSegs,
01058                                             1.f
01059                                            );
01060                         }
01062                         if (_ColorFading)
01063                         {
01064                             // If not per ribbon color, we can encode it in the diffuse
01065                             if (_ColorScheme == NULL)
01066                             {
01067                                 uint8 intensity = (uint8) (255 * (1.f - ((float) k / _UsedNbSegs)));
01068                                 NLMISC::CRGBA col(intensity, intensity, intensity, intensity);
01069                                 vba.setColor(vbIndex, col);
01070                                 vba.setColor(vbIndex + 1, col);
01071                             }
01072                             else // encode it in the first texture
01073                             {
01074                                 vba.setTexCoord(vbIndex, 0, 0.5f - 0.5f * ((float) k / _UsedNbSegs), 0);
01075                                 vba.setTexCoord(vbIndex + 1, 0, 0.5f - 0.5f * ((float) k / _UsedNbSegs), 0);
01076                             }
01077                         }
01078                         vbIndex += 2;
01079                     }
01080                 }
01081                 else
01082                 {
01083                     for (l = 0; l < numVerticesInSlice; ++l) 
01084                     {
01085                         nlassert(vbIndex < vb.getNumVertices());
01087                         if (_Tex != NULL)
01088                         {
01089                             vba.setTexCoord(vbIndex,
01090                                            _ColorScheme && _ColorFading ? 1 : 0,        // must we use the second texture coord ? (when 1st one used by the gradient texture : we can't encode it in the diffuse as it encodes each ribbon color)
01091                                            (float) k / _UsedNbSegs,               // u
01092                                            1.f - (l / (float) numVerticesInShape) // v
01093                                           );
01094                         }
01096                         if (_ColorFading)
01097                         {
01098                             // If not per ribbon color, we can encode it in the diffuse
01099                             if (_ColorScheme == NULL)
01100                             {
01101                                 uint8 intensity = (uint8) (255 * (1.f - ((float) k / _UsedNbSegs)));
01102                                 NLMISC::CRGBA col(intensity, intensity, intensity, intensity);
01103                                 vba.setColor(vbIndex, col);
01104                             }
01105                             else // encode it in the first texture
01106                             {
01107                                 vba.setTexCoord(vbIndex, 0, 0.5f - 0.5f * ((float) k / _UsedNbSegs), 0);
01108                             }
01109                         }
01110                         ++ vbIndex;
01111                     }
01112                 }
01113             }
01114         }
01115         return VBnPB;
01116     }
01117 }
01118 
01119 //==========================================================================
01120 uint    CPSRibbon::getNumRibbonsInVB() const
01121 {
01122     NL_PS_FUNC(CPSRibbon_getNumRibbonsInVB)
01123     const uint numVerticesInSlice = getNumVerticesInSlice(); 
01124     const uint vertexInVB = 512;
01125     return std::max(1u, (uint) (vertexInVB / (numVerticesInSlice * (_UsedNbSegs + 1))));
01126 }
01127 
01128 
01129 //==========================================================================
01130 inline void CPSRibbon::updateUntexturedMaterial()
01131 {
01132     NL_PS_FUNC(CPSRibbon_updateUntexturedMaterial)
01134     // UNTEXTURED RIBBON //
01136 
01137     static NLMISC::CRefPtr<ITexture> ptGradTexture;
01138 
01139     CParticleSystem &ps = *(_Owner->getOwner());
01140     if (_ColorScheme)
01141     {   // PER RIBBON COLOR
01142         if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting() || ps.getColorAttenuationScheme() || ps.isUserColorUsed())
01143         {
01144             if (_ColorFading) // global color + fading + per ribbon color
01145             {
01146                 // the first stage is used to get fading * global color
01147                 // the second stage multiply the result by the diffuse colot
01148                 if (ptGradTexture == NULL) // have we got a gradient texture ?
01149                 {
01150                     ptGradTexture = CreateGradientTexture();
01151                 }
01152                 _Mat.setTexture(0, ptGradTexture);
01153                 CPSMaterial::forceTexturedMaterialStages(2); // use constant color 0 * diffuse, 1 stage needed
01154                 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Constant);
01155                 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Diffuse);
01156             }
01157             else // per ribbon color with global color
01158             {
01159                 CPSMaterial::forceTexturedMaterialStages(1); // use constant color 0 * diffuse, 1 stage needed
01160                 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
01161             }
01162         }
01163         else
01164         {
01165             if (_ColorFading) // per ribbon color, no fading
01166             {
01167                 if (ptGradTexture == NULL) // have we got a gradient texture ?
01168                 {
01169                     ptGradTexture = CreateGradientTexture();
01170                 }
01171                 _Mat.setTexture(0, ptGradTexture);
01172                 ptGradTexture->setWrapS(ITexture::Clamp);
01173                 ptGradTexture->setWrapT(ITexture::Clamp);
01174                 CPSMaterial::forceTexturedMaterialStages(1);
01175                 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
01176             }
01177             else // per color ribbon with no fading, and no global color
01178             {
01179                 CPSMaterial::forceTexturedMaterialStages(0); // no texture use constant diffuse only
01180             }
01181         }
01182     }
01183     else // GLOBAL COLOR
01184     {
01185         if (_ColorFading)
01186         {
01187             CPSMaterial::forceTexturedMaterialStages(1); // use constant color 0 * diffuse, 1 stage needed
01188             SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
01189         }
01190         else // color attenuation, no fading :
01191         {
01192             CPSMaterial::forceTexturedMaterialStages(0); // no texture use constant diffuse only
01193         }
01194     }
01195     _Touch = false;
01196 }
01197 
01198 //==========================================================================
01199 inline void CPSRibbon::updateTexturedMaterial()
01200 {
01201     NL_PS_FUNC(CPSRibbon_updateTexturedMaterial)
01203     // TEXTURED RIBBON //
01205     if (_Tex)
01206     {
01207         //_Tex->setWrapS(ITexture::Clamp);
01208         //_Tex->setWrapT(ITexture::Clamp);
01209     }
01210     static NLMISC::CRefPtr<ITexture> ptGradTexture;
01211     CParticleSystem &ps = *(_Owner->getOwner());
01212     if (_ColorScheme)
01213     {   // PER RIBBON COLOR
01214         if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting() || ps.getColorAttenuationScheme() || ps.isUserColorUsed())
01215         {
01216             if (_ColorFading) // global color + fading + per ribbon color
01217             {
01218                 if (ptGradTexture == NULL) // have we got a gradient texture ?
01219                 {
01220                     ptGradTexture = CreateGradientTexture(); // create it
01221                 }
01223                 _Mat.setTexture(0, ptGradTexture);
01224                 ptGradTexture->setWrapS(ITexture::Clamp);
01225                 ptGradTexture->setWrapT(ITexture::Clamp);
01226                 _Mat.setTexture(1, _Tex);
01227                 CPSMaterial::forceTexturedMaterialStages(3); // use constant color 0 * diffuse, 1 stage needed
01228                 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
01229                 SetupModulatedStage(_Mat, 1, CMaterial::Texture, CMaterial::Previous);
01230                 SetupModulatedStage(_Mat, 2, CMaterial::Previous, CMaterial::Constant);
01231             }
01232             else // per ribbon color with global color
01233             {
01234                 _Mat.setTexture(0, _Tex);
01235 
01236                 CPSMaterial::forceTexturedMaterialStages(2); // use constant color 0 * diffuse, 1 stage needed
01237                 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
01238                 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Constant);
01239             }
01240         }
01241         else
01242         {
01243             if (_ColorFading) // per ribbon color, fading : 2 textures needed
01244             {
01245                 if (ptGradTexture == NULL) // have we got a gradient texture ?
01246                 {
01247                     ptGradTexture = CreateGradientTexture(); // create it
01248                 }
01249                 _Mat.setTexture(0, ptGradTexture);
01250                 ptGradTexture->setWrapS(ITexture::Clamp);
01251                 ptGradTexture->setWrapT(ITexture::Clamp);
01252                 _Mat.setTexture(1, _Tex);
01253                 CPSMaterial::forceTexturedMaterialStages(2);
01254                 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse); // texture * ribbon color
01255                 SetupModulatedStage(_Mat, 1, CMaterial::Texture, CMaterial::Previous);  // * gradient
01256             }
01257             else // per color ribbon with no fading, and no global color
01258             {
01259                 _Mat.setTexture(0, _Tex);
01260                 CPSMaterial::forceTexturedMaterialStages(1); // no texture use constant diffuse only
01261                 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
01262             }
01263         }
01264     }
01265     else // GLOBAL COLOR
01266     {
01267 
01268         if (_ColorFading) // gradient is encoded in diffuse
01269         {
01270             _Mat.setTexture(0, _Tex);
01271             CPSMaterial::forceTexturedMaterialStages(2); // use constant color 0 * diffuse, 1 stage needed
01272             SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
01273             SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Constant);
01274         }
01275         else // constant color
01276         {
01277             _Mat.setTexture(0, _Tex);
01278             CPSMaterial::forceTexturedMaterialStages(1); // no texture use constant diffuse only
01279             SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
01280         }
01281     }
01282     _Touch = false;
01283 }
01284 
01285 //==========================================================================
01286 void    CPSRibbon::updateMaterial()
01287 {
01288     NL_PS_FUNC(CPSRibbon_updateMaterial)
01289     if (!_Touch) return;
01290     if (_Tex != NULL)
01291     {
01292         updateTexturedMaterial();
01293         setupTextureMatrix();
01294     }
01295     else
01296     {
01297         updateUntexturedMaterial();
01298     }
01299 }
01300 
01301 
01302 
01303 //==========================================================================
01304 inline void CPSRibbon::setupUntexturedGlobalColor()
01305 {
01306     NL_PS_FUNC(CPSRibbon_setupUntexturedGlobalColor)
01308     CParticleSystem &ps = *(_Owner->getOwner());
01309     if (_ColorScheme)
01310     {
01311         if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
01312         {
01313             _Mat.texConstantColor(0, ps.getGlobalColorLighted());
01314         }
01315         else
01316         {
01317             _Mat.texConstantColor(0, ps.getGlobalColor());
01318         }
01319     }
01320     else // GLOBAL COLOR with / without fading
01321     {
01322         NLMISC::CRGBA col;
01323         if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
01324         {
01325             col.modulateFromColor(ps.getGlobalColorLighted(), _Color);
01326         }
01327         else if (ps.getColorAttenuationScheme() || ps.isUserColorUsed())
01328         {
01329             col.modulateFromColor(ps.getGlobalColor(), _Color);
01330         }
01331         else
01332         {
01333             col = _Color;
01334         }
01335         if (_ColorFading)
01336         {
01337             _Mat.texConstantColor(0, col);
01338         }
01339         else // color attenuation, no fading :
01340         {
01341             _Mat.setColor(col);
01342         }
01343     }
01344 }
01345 
01346 //==========================================================================
01347 inline void CPSRibbon::setupTexturedGlobalColor()
01348 {
01349     NL_PS_FUNC(CPSRibbon_setupTexturedGlobalColor)
01351     CParticleSystem &ps = *(_Owner->getOwner());
01352     if (_ColorScheme)
01353     {
01354         if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
01355         {
01356             if (_ColorFading)
01357             {
01358                 _Mat.texConstantColor(2, ps.getGlobalColorLighted());
01359             }
01360             else
01361             {
01362                 _Mat.texConstantColor(1, ps.getGlobalColorLighted());
01363             }
01364         }
01365         else
01366         {
01367             if (_ColorFading)
01368             {
01369                 _Mat.texConstantColor(2, ps.getGlobalColor());
01370             }
01371             else
01372             {
01373                 _Mat.texConstantColor(1, ps.getGlobalColor());
01374             }
01375         }
01376     }
01377     else // GLOBAL COLOR with / without fading
01378     {
01379         if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
01380         {
01381             NLMISC::CRGBA col;
01382             col.modulateFromColor(ps.getGlobalColorLighted(), _Color);
01383             if (_ColorFading)
01384             {
01385                 _Mat.texConstantColor(1, col);
01386             }
01387             else // color attenuation, no fading :
01388             {
01389                 _Mat.setColor(col);
01390             }
01391         }
01392         else
01393         if (ps.getColorAttenuationScheme() || ps.isUserColorUsed())
01394         {
01395             NLMISC::CRGBA col;
01396             col.modulateFromColor(ps.getGlobalColor(), _Color);
01397             if (_ColorFading)
01398             {
01399                 _Mat.texConstantColor(1, col);
01400             }
01401             else // color attenuation, no fading :
01402             {
01403                 _Mat.setColor(col);
01404             }
01405         }
01406         else
01407         {
01408             if (_ColorFading)
01409             {
01410                 _Mat.texConstantColor(1, _Color);
01411             }
01412             else // constant color
01413             {
01414                 _Mat.setColor(_Color);
01415             }
01416         }
01417     }
01418 }
01419 
01420 
01421 //==========================================================================
01422 void    CPSRibbon::setupGlobalColor()
01423 {
01424     NL_PS_FUNC(CPSRibbon_setupGlobalColor)
01425     if (_Tex != NULL) setupTexturedGlobalColor();
01426         else setupUntexturedGlobalColor();
01427 }
01428 
01429 //==========================================================================
01430 void CPSRibbon::setupTextureMatrix()
01431 {
01432     NL_PS_FUNC(CPSRibbon_setupTextureMatrix)
01433     uint stage = (_ColorScheme != NULL && _ColorFading == true) ? 1 : 0;
01434     if (_UFactor != 1.f || _VFactor != 1.f)
01435     {
01436         _Mat.enableUserTexMat(stage);
01437         CMatrix texMat;
01438         texMat.setRot(_UFactor  * NLMISC::CVector::I,
01439                       _VFactor  * NLMISC::CVector::J,
01440                       NLMISC::CVector::K
01441                      );
01442         _Mat.setUserTexMat(stage, texMat);
01443     }
01444     else
01445     {
01446         _Mat.enableUserTexMat(stage, false);
01447     }
01448     _Mat.enableUserTexMat(1 - stage, false);
01449 }
01450 
01451 //==========================================================================
01453 void CPSRibbon::setShape(const CVector *shape, uint32 nbPointsInShape, bool braceMode)
01454 {
01455     NL_PS_FUNC(CPSRibbon_setShape)
01456     if (!braceMode)
01457     {
01458         nlassert(nbPointsInShape >= 3);
01459     }
01460     else
01461     {
01462         nlassert(nbPointsInShape >= 2);
01463         nlassert(!(nbPointsInShape & 1)); // must be even
01464     }
01465     _Shape.resize(nbPointsInShape);
01466     std::copy(shape, shape + nbPointsInShape, _Shape.begin());
01467     _BraceMode = braceMode;
01468 }
01469 
01471 void CPSRibbon::getShape(CVector *shape) const
01472 {
01473     NL_PS_FUNC(CPSRibbon_getShape)
01474     std::copy(_Shape.begin(), _Shape.end(), shape);
01475 }
01476 
01478 void CPSRibbon::enumTexs(std::vector<NLMISC::CSmartPtr<ITexture> > &dest, IDriver &drv)
01479 {
01480     NL_PS_FUNC(CPSRibbon_enumTexs)
01481     if (_Tex)
01482     {
01483         dest.push_back(_Tex);
01484     }
01485 }
01486 
01487 
01488 } // NL3D

Generated on Thu Jan 7 08:26:29 2010 for NeL by  doxygen 1.6.1