00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/ps_ribbon.h"
00029 #include "3d/ps_macro.h"
00030 #include "3d/particle_system.h"
00031 #include "3d/driver.h"
00032 #include "3d/ps_util.h"
00033 #include "3d/texture_mem.h"
00034 #include "nel/misc/matrix.h"
00035
00036 namespace NL3D
00037 {
00038
00039 static NLMISC::CRGBA GradientB2W[] = {NLMISC::CRGBA(0, 0, 0, 0), NLMISC::CRGBA(255, 255, 255, 255) };
00040
00042 static ITexture *CreateGradientTexture()
00043 {
00044 std::auto_ptr<CTextureMem> tex(new CTextureMem((uint8 *) &GradientB2W,
00045 sizeof(GradientB2W),
00046 false,
00047 false,
00048 2, 1)
00049 );
00050 tex->setWrapS(ITexture::Clamp);
00051 tex->setShareName("#GradBW");
00052 return tex.release();
00053 }
00054
00055
00057
00059
00060
00061 const NLMISC::CVector CPSRibbon::Triangle[] =
00062 {
00063 NLMISC::CVector(0, 1, 0),
00064 NLMISC::CVector(1, -1, 0),
00065 NLMISC::CVector(-1, -1, 0),
00066 };
00067
00068 const NLMISC::CVector CPSRibbon::Losange[] =
00069 {
00070 NLMISC::CVector(0, 1.f, 0),
00071 NLMISC::CVector(1.f, 0, 0),
00072 NLMISC::CVector(0, -1.f, 0),
00073 NLMISC::CVector(-1.f, 0, 0)
00074 };
00075
00076 const NLMISC::CVector CPSRibbon::HeightSides[] =
00077 {
00078 NLMISC::CVector(-0.5f, 1, 0),
00079 NLMISC::CVector(0.5f, 1, 0),
00080 NLMISC::CVector(1, 0.5f, 0),
00081 NLMISC::CVector(1, -0.5f, 0),
00082 NLMISC::CVector(0.5f, -1, 0),
00083 NLMISC::CVector(-0.5f, -1, 0),
00084 NLMISC::CVector(-1, -0.5f, 0),
00085 NLMISC::CVector(-1, 0.5f, 0)
00086 };
00087
00088
00089 const NLMISC::CVector CPSRibbon::Pentagram[] =
00090 {
00091 NLMISC::CVector(0, 1, 0),
00092 NLMISC::CVector(1, -1, 0),
00093 NLMISC::CVector(-1, 0, 0),
00094 NLMISC::CVector(1, 0, 0),
00095 NLMISC::CVector(-1, -1, 0)
00096 };
00097
00098 const uint CPSRibbon::NbVerticesInTriangle = sizeof(CPSRibbon::Triangle) / sizeof(CVector);
00099 const uint CPSRibbon::NbVerticesInLosange = sizeof(Losange) / sizeof(CVector);
00100 const uint CPSRibbon::NbVerticesInHeightSide = sizeof(CPSRibbon::HeightSides) / sizeof(CVector);
00101 const uint CPSRibbon::NbVerticesInPentagram = sizeof(CPSRibbon::Pentagram) / sizeof(CVector);
00102
00103
00104 CPSRibbon::TVBMap CPSRibbon::_VBMap;
00105 CPSRibbon::TVBMap CPSRibbon::_FadedVBMap;
00106 CPSRibbon::TVBMap CPSRibbon::_ColoredVBMap;
00107 CPSRibbon::TVBMap CPSRibbon::_FadedColoredVBMap;
00108
00109 CPSRibbon::TVBMap CPSRibbon::_TexVBMap;
00110 CPSRibbon::TVBMap CPSRibbon::_TexFadedVBMap;
00111 CPSRibbon::TVBMap CPSRibbon::_TexColoredVBMap;
00112 CPSRibbon::TVBMap CPSRibbon::_TexFadedColoredVBMap;
00113
00114
00115 struct CDummy2DAngle : CPSRotated2DParticle
00116 {
00117 CPSLocated *getAngle2DOwner(void) { return NULL; }
00118 };
00119
00121 void CPSRibbon::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00122 {
00123 sint ver = f.serialVersion(2);
00124 if (ver == 1)
00125 {
00126 nlassert(f.isReading());
00127
00130 sint ver2 = f.serialVersion(2);
00131
00132
00133 sint ver3 = f.serialVersion(4);
00134 f.serialPtr(_Owner);
00135 if (ver3 > 1) f.serialEnum(_LOD);
00136 if (ver3 > 2) f.serial(_Name);
00137 if (ver3 > 3)
00138 {
00139 if (f.isReading())
00140 {
00141 uint32 id;
00142 f.serial(id);
00143 setExternID(id);
00144 }
00145 else
00146 {
00147 f.serial(_ExternID);
00148 }
00149 }
00150
00151 if (ver2 >= 2)
00152 {
00153 bool bDisableAutoLOD;
00154 f.serial(bDisableAutoLOD);
00155 disableAutoLOD(bDisableAutoLOD);
00156 }
00157
00158 uint32 tailNbSegs;
00159 bool colorFading;
00160 bool systemBasisEnabled;
00161 bool drEnabled;
00162
00163 CPSColoredParticle::serialColorScheme(f);
00164 CPSSizedParticle::serialSizeScheme(f);
00165
00166
00167 {
00168 CDummy2DAngle _Dummy2DAngle;
00169 _Dummy2DAngle.serialAngle2DScheme(f);
00170 }
00171
00172 f.serial(colorFading, systemBasisEnabled);
00173 serialMaterial(f);
00174
00175 f.serial(drEnabled);
00176 f.serial(tailNbSegs);
00177 ITexture *tex;
00178 f.serialPolyPtr(tex);
00179 _Tex = tex;
00180 if (_Tex != NULL)
00181 {
00182 f.serial(_UFactor, _VFactor) ;
00183 }
00184
00185
00186 f.serialCont(_Shape);
00187
00188
00189 _NbSegs = tailNbSegs >> 1;
00190 if (_NbSegs < 1) _NbSegs = 2;
00191 setInterpolationMode(Linear);
00192
00193 nlassert(_Owner);
00194 resize(_Owner->getMaxSize());
00195 initDateVect();
00196 resetFromOwner();
00197 }
00198
00199
00200 if (ver >= 2)
00201 {
00202 CPSRibbonBase::serial(f);
00203 CPSColoredParticle::serialColorScheme(f);
00204 CPSSizedParticle::serialSizeScheme(f);
00205 CPSMaterial::serialMaterial(f);
00206 f.serialCont(_Shape);
00207 bool colorFading = _ColorFading;
00208 f.serial(colorFading);
00209 _ColorFading = colorFading;
00210 uint32 tailNbSegs = _NbSegs;
00211 f.serial(tailNbSegs);
00212 if (f.isReading())
00213 {
00214 setTailNbSeg(_NbSegs);
00215 touch();
00216 }
00217 ITexture *tex = _Tex;
00218 f.serialPolyPtr(tex);
00219 _Tex = tex;
00220 if (_Tex != NULL)
00221 {
00222 f.serial(_UFactor, _VFactor) ;
00223 }
00224 }
00225
00226 }
00227
00228
00229
00230 CPSRibbon::CPSRibbon() : _UFactor(1.f),
00231 _VFactor(1.f),
00232 _ColorFading(true),
00233 _GlobalColor(false),
00234 _Touch(true)
00235 {
00236 setInterpolationMode(Linear);
00237 setSegDuration(0.06f);
00238 _Name = std::string("Ribbon");
00239 setShape(Triangle, NbVerticesInTriangle);
00240 _Mat.setDoubleSided(true);
00241 }
00242
00243
00244
00245 CPSRibbon::~CPSRibbon()
00246 {
00247 }
00248
00249
00250
00251 inline uint CPSRibbon::getNumVerticesInSlice() const
00252 {
00253 return _Shape.size() + (_Tex == NULL ? 0 : 1);
00254 }
00255
00256
00257
00258
00259
00260
00261 void CPSRibbon::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEt)
00262 {
00263 if (pass == PSMotion)
00264 {
00265 if (!_Parametric)
00266 {
00267 updateGlobals();
00268 }
00269 }
00270 else
00271 if (
00272 (pass == PSBlendRender && hasTransparentFaces())
00273 || (pass == PSSolidRender && hasOpaqueFaces())
00274 )
00275 {
00276 uint32 step;
00277 uint numToProcess;
00278 computeSrcStep(step, numToProcess);
00279 if (!numToProcess) return;
00280
00282 CParticleSystem &ps = *(_Owner->getOwner());
00283 _Mat.setColor(ps.getGlobalColor());
00284
00289 displayRibbons(numToProcess, step);
00290
00291 }
00292 else
00293 if (pass == PSToolRender)
00294 {
00295
00296 }
00297 }
00298
00299
00300
00301 void CPSRibbon::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
00302 {
00303 CPSRibbonBase::newElement(emitterLocated, emitterIndex);
00304 newColorElement(emitterLocated, emitterIndex);
00305 newSizeElement(emitterLocated, emitterIndex);
00306 }
00307
00308
00309
00310 void CPSRibbon::deleteElement(uint32 index)
00311 {
00312 CPSRibbonBase::deleteElement(index);
00313 deleteColorElement(index);
00314 deleteSizeElement(index);
00315 }
00316
00317
00318
00319 void CPSRibbon::resize(uint32 size)
00320 {
00321 nlassert(size < (1 << 16));
00322 CPSRibbonBase::resize(size);
00323 resizeColor(size);
00324 resizeSize(size);
00325 }
00326
00327
00328 void CPSRibbon::updateMatAndVbForColor(void)
00329 {
00330 touch();
00331 }
00332
00333
00335
00336 static inline uint8 *BuildRibbonFirstSlice(const NLMISC::CVector &pos,
00337 uint numVerts,
00338 uint8 *dest,
00339 uint vertexSize
00340 )
00341 {
00342 do
00343 {
00344 * (NLMISC::CVector *) dest = pos;
00345 dest += vertexSize;
00346 }
00347 while (--numVerts);
00348 return dest;
00349 }
00350
00351
00353
00354 static inline uint8 *ComputeRibbonSlice(const NLMISC::CVector &prev,
00355 const NLMISC::CVector &next,
00356 const NLMISC::CVector *shape,
00357 uint numVerts,
00358 uint8 *dest,
00359 uint vertexSize,
00360 float size
00361 )
00362 {
00363
00364
00365 static NLMISC::CMatrix m;
00366 m.setPos(next);
00367 CPSUtil::buildSchmidtBasis(next - prev, m);
00368 m.scale(size);
00369
00370 const NLMISC::CVector *shapeEnd = shape + numVerts;
00371 do
00372 {
00373 *(NLMISC::CVector *) dest = m * (*shape);
00374 ++shape;
00375 dest += vertexSize;
00376 }
00377 while (shape != shapeEnd);
00378 return dest;
00379 }
00380
00381
00382
00384
00385
00386 static inline uint8 *ComputeUntexturedRibbonMesh(uint8 *destVb,
00387 uint vertexSize,
00388 const NLMISC::CVector *curve,
00389 const NLMISC::CVector *shape,
00390 uint numSegs,
00391 uint numVerticesInShape,
00392 float sizeIncrement,
00393 float size
00394 )
00395 {
00396 do
00397 {
00398 destVb = ComputeRibbonSlice(curve[1],
00399 curve[0],
00400 shape,
00401 numVerticesInShape,
00402 destVb,
00403 vertexSize,
00404 size);
00405 ++ curve;
00406 size -= sizeIncrement;
00407 }
00408 while (--numSegs);
00409 return BuildRibbonFirstSlice(curve[0], numVerticesInShape, destVb, vertexSize);
00410 }
00411
00413
00414
00415 static inline uint8 *ComputeTexturedRibbonMesh(uint8 *destVb,
00416 uint vertexSize,
00417 const NLMISC::CVector *curve,
00418 const NLMISC::CVector *shape,
00419 uint numSegs,
00420 uint numVerticesInShape,
00421 float sizeIncrement,
00422 float size
00423 )
00424 {
00425
00426 do
00427 {
00428 uint8 *nextDestVb = ComputeRibbonSlice(curve[1],
00429 curve[0],
00430 shape,
00431 numVerticesInShape,
00432 destVb,
00433 vertexSize,
00434 size
00435 );
00436
00437 * (NLMISC::CVector *) nextDestVb = * (NLMISC::CVector *) destVb;
00438 destVb = nextDestVb + vertexSize;
00439
00440 ++ curve;
00441 size -= sizeIncrement;
00442 }
00443 while (--numSegs);
00444 return BuildRibbonFirstSlice(curve[0], numVerticesInShape + 1, destVb, vertexSize);
00445 }
00446
00447
00448 void CPSRibbon::displayRibbons(uint32 nbRibbons, uint32 srcStep)
00449 {
00450 if (!nbRibbons) return;
00451 nlassert(_Owner);
00452 CPSRibbonBase::updateLOD();
00453 if (_UsedNbSegs < 2) return;
00454 const float date = _Owner->getOwner()->getSystemDate();
00455 uint8 *currVert;
00456 CVBnPB &VBnPB = getVBnPB();
00457 CVertexBuffer &VB = VBnPB.VB;
00458 CPrimitiveBlock &PB = VBnPB.PB;
00459 const uint32 vertexSize = VB.getVertexSize();
00460 uint colorOffset=0;
00461
00462 IDriver *drv = this->getDriver();
00463 setupDriverModelMatrix();
00464 drv->activeVertexBuffer(VB);
00465 _Owner->incrementNbDrawnParticles(nbRibbons);
00466 const uint numRibbonBatch = getNumRibbonsInVB();
00467 if (_UsedNbSegs == 0) return;
00469
00471
00472 bool useGlobalColor = ps.getColorAttenuationScheme() != NULL;
00473 if (useGlobalColor != _GlobalColor)
00474 {
00475 touch();
00476 }
00477 updateMaterial();
00478 setupGlobalColor();
00479
00480 if (_ColorScheme)
00481 {
00482 colorOffset = VB.getColorOff();
00483 }
00485
00487
00488 const uint numVerticesInShape = _Shape.size();
00489
00490 static std::vector<float> sizes;
00491 static std::vector<NLMISC::CVector> ribbonPos;
00492 ribbonPos.resize(_UsedNbSegs + 1);
00493 sizes.resize(numRibbonBatch);
00494
00495
00496 uint toProcess;
00497 uint ribbonIndex = 0;
00498 uint32 fpRibbonIndex = 0;
00499 do
00500 {
00501 toProcess = std::min((uint) (nbRibbons - ribbonIndex) , numRibbonBatch);
00502 currVert = (uint8 *) VB.getVertexCoordPointer();
00503
00505 const float *ptCurrSize;
00506 uint32 ptCurrSizeIncrement;
00507 if (_SizeScheme)
00508 {
00509 ptCurrSize = (float *) _SizeScheme->make(this->_Owner, ribbonIndex, &sizes[0], sizeof(float), toProcess, true, srcStep);
00510 ptCurrSizeIncrement = 1;
00511 }
00512 else
00513 {
00514 ptCurrSize = &_ParticleSize;
00515 ptCurrSizeIncrement = 0;
00516 }
00517
00519 if (_ColorScheme)
00520 {
00521 _ColorScheme->makeN(this->_Owner, ribbonIndex, currVert + colorOffset, vertexSize, toProcess, numVerticesInSlice * (_UsedNbSegs + 1), srcStep);
00522 }
00523 uint k = toProcess;
00525
00527
00528 {
00530
00532
00533 {
00534 do
00535 {
00536 const float ribbonSizeIncrement = *ptCurrSize / (float) _UsedNbSegs;
00537 ptCurrSize += ptCurrSizeIncrement;
00538
00539 computeRibbon((uint) (fpRibbonIndex >> 16), &ribbonPos[0], sizeof(NLMISC::CVector));
00540 currVert = ComputeTexturedRibbonMesh(currVert,
00541 vertexSize,
00542 &ribbonPos[0],
00543 &_Shape[0],
00544 _UsedNbSegs,
00545 numVerticesInShape,
00546 ribbonSizeIncrement,
00547 *ptCurrSize
00548 );
00549 fpRibbonIndex += srcStep;
00550 }
00551 while (--k);
00552 }
00553 else
00554 {
00555 do
00556 {
00557 const float ribbonSizeIncrement = *ptCurrSize / (float) _UsedNbSegs;
00558 ptCurrSize += ptCurrSizeIncrement;
00559
00560 computeRibbon((uint) (fpRibbonIndex >> 16), &ribbonPos[0], sizeof(NLMISC::CVector));
00561 currVert = ComputeUntexturedRibbonMesh(currVert,
00562 vertexSize,
00563 &ribbonPos[0],
00564 &_Shape[0],
00565 _UsedNbSegs,
00566 numVerticesInShape,
00567 ribbonSizeIncrement,
00568 *ptCurrSize
00569 );
00570 fpRibbonIndex += srcStep;
00571 }
00572 while (--k);
00573 }
00574 }
00575 else
00576 {
00578
00580
00581 {
00582 do
00583 {
00584 const float ribbonSizeIncrement = *ptCurrSize / (float) _UsedNbSegs;
00585 ptCurrSize += ptCurrSizeIncrement;
00586 _Owner->integrateSingle(date - _UsedSegDuration * (_UsedNbSegs + 1),
00587 _UsedSegDuration,
00588 _UsedNbSegs + 1,
00589 (uint) (fpRibbonIndex >> 16),
00590 &ribbonPos[0]);
00591
00592 currVert = ComputeTexturedRibbonMesh(currVert,
00593 vertexSize,
00594 &ribbonPos[0],
00595 &_Shape[0],
00596 _UsedNbSegs,
00597 numVerticesInShape,
00598 ribbonSizeIncrement,
00599 *ptCurrSize
00600 );
00601 fpRibbonIndex += srcStep;
00602 }
00603 while (--k);
00604 }
00605 else
00606 {
00607 do
00608 {
00609 const float ribbonSizeIncrement = *ptCurrSize / (float) _UsedNbSegs;
00610 ptCurrSize += ptCurrSizeIncrement;
00611 _Owner->integrateSingle(date - _UsedSegDuration * (_UsedNbSegs + 1),
00612 _UsedSegDuration,
00613 _UsedNbSegs + 1,
00614 (uint) (fpRibbonIndex >> 16),
00615 &ribbonPos[0]);
00616
00617 currVert = ComputeUntexturedRibbonMesh(currVert,
00618 vertexSize,
00619 &ribbonPos[0],
00620 &_Shape[0],
00621 _UsedNbSegs,
00622 numVerticesInShape,
00623 ribbonSizeIncrement,
00624 *ptCurrSize
00625 );
00626 fpRibbonIndex += srcStep;
00627 }
00628 while (--k);
00629 }
00630 }
00631
00632 PB.setNumTri((numVerticesInShape * _UsedNbSegs * toProcess) << 1);
00633 drv->render(PB, _Mat);
00634 ribbonIndex += toProcess;
00635 }
00636 while (ribbonIndex != nbRibbons);
00637
00638 }
00639
00640
00641 bool CPSRibbon::hasTransparentFaces(void)
00642 {
00643 return getBlendingMode() != CPSMaterial::alphaTest ;
00644 }
00645
00646
00647
00648 bool CPSRibbon::hasOpaqueFaces(void)
00649 {
00650 return !hasTransparentFaces();
00651 }
00652
00653
00654 uint32 CPSRibbon::getMaxNumFaces(void) const
00655 {
00656 nlassert(_Owner);
00657 return _Owner->getMaxSize() * _NbSegs;
00658 }
00659
00660
00661 CPSRibbon::CVBnPB &CPSRibbon::getVBnPB()
00662 {
00663 static TVBMap * const vbMaps[] =
00664 {
00666 &_VBMap,
00667 &_FadedVBMap,
00668 &_ColoredVBMap,
00669 &_FadedColoredVBMap,
00671 &_TexVBMap,
00672 &_TexFadedVBMap,
00673 &_TexColoredVBMap,
00674 &_TexFadedColoredVBMap
00675 };
00676
00678 TVBMap &map = *vbMaps[ (_Tex != NULL ? (1 << 2) : 0) |
00679 (_ColorScheme != NULL ? (1 << 1) : 0) |
00680 (_ColorFading ? 1 : 0)
00681 ];
00682
00683 const uint numVerticesInSlice = getNumVerticesInSlice();
00684 const uint numVerticesInShape = _Shape.size();
00685
00686
00687
00688
00689 uint VBnPDIndex = ((_UsedNbSegs + 1) << 16) | numVerticesInSlice;
00690 TVBMap::iterator it = map.find(VBnPDIndex);
00691 if (it != map.end())
00692 {
00693 return it->second;
00694 }
00695 else
00696 {
00697 const uint numRibbonInVB = getNumRibbonsInVB();
00698 CVBnPB &VBnPB = map[VBnPDIndex];
00699
00703 CVertexBuffer &vb = VBnPB.VB;
00704 vb.setVertexFormat(CVertexBuffer::PositionFlag |
00705 (_ColorScheme || _ColorFading ? CVertexBuffer::PrimaryColorFlag : 0) |
00706 ((_ColorScheme && _ColorFading) || _Tex != NULL ? CVertexBuffer::TexCoord0Flag : 0) |
00707 (_Tex != NULL && _ColorScheme && _ColorFading ? CVertexBuffer::TexCoord1Flag : 0)
00708 );
00709 vb.setNumVertices((_UsedNbSegs + 1) * numRibbonInVB * numVerticesInSlice);
00710
00711
00712 CPrimitiveBlock &pb = VBnPB.PB;
00713 pb.setNumTri((_UsedNbSegs * numRibbonInVB * _Shape.size()) << 1);
00715 uint vbIndex = 0;
00716 uint pbIndex = 0;
00717 uint i, k, l;
00718 for (i = 0; i < numRibbonInVB; ++i)
00719 {
00720 for (k = 0; k < (_UsedNbSegs + 1); ++k)
00721 {
00722
00724 if (k != _UsedNbSegs)
00725 {
00726 uint vIndex = vbIndex;
00727 for (l = 0; l < (numVerticesInShape - 1); ++l)
00728 {
00729 pb.setTri(pbIndex ++, vIndex, vIndex + numVerticesInSlice, vIndex + numVerticesInSlice + 1);
00730 pb.setTri(pbIndex ++, vIndex, vIndex + numVerticesInSlice + 1, vIndex + 1);
00731 ++ vIndex;
00732 }
00733
00735 uint nextVertexIndex = (numVerticesInShape == numVerticesInSlice) ? vIndex + 1 - numVerticesInShape
00736 : vIndex + 1;
00737 pb.setTri(pbIndex ++, vIndex, vIndex + numVerticesInSlice, nextVertexIndex + numVerticesInSlice);
00738 pb.setTri(pbIndex ++, vIndex, nextVertexIndex + numVerticesInSlice, nextVertexIndex);
00739
00740 }
00741
00743 for (l = 0; l < numVerticesInSlice; ++l)
00744 {
00745 nlassert(vbIndex < vb.getNumVertices());
00747 if (_Tex != NULL)
00748 {
00749 vb.setTexCoord(vbIndex,
00750 _ColorScheme && _ColorFading ? 1 : 0,
00751 (float) k / _UsedNbSegs,
00752 1.f - (l / (float) numVerticesInShape)
00753 );
00754 }
00755
00757 if (_ColorFading)
00758 {
00759
00760 if (_ColorScheme == NULL)
00761 {
00762 uint8 intensity = (uint8) (255 * (1.f - ((float) k / _UsedNbSegs)));
00763 NLMISC::CRGBA col(intensity, intensity, intensity, intensity);
00764 vb.setColor(vbIndex, col);
00765 }
00766 else
00767 {
00768 vb.setTexCoord(vbIndex, 0, 0.5f - 0.5f * ((float) k / _UsedNbSegs), 0);
00769 }
00770 }
00771 ++ vbIndex;
00772 }
00773
00774 }
00775 }
00776 return VBnPB;
00777 }
00778 }
00779
00780
00781 uint CPSRibbon::getNumRibbonsInVB() const
00782 {
00783 const uint numVerticesInSlice = getNumVerticesInSlice();
00784 const uint vertexInVB = 512;
00785 return std::max(1u, (uint) (vertexInVB / (numVerticesInSlice * (_UsedNbSegs + 1))));
00786 }
00787
00788
00789
00790 inline void CPSRibbon::updateUntexturedMaterial()
00791 {
00793
00795
00796 static NLMISC::CRefPtr<ITexture> ptGradTexture;
00797
00798 CParticleSystem &ps = *(_Owner->getOwner());
00799 if (_ColorScheme)
00800 {
00801 if (ps.getColorAttenuationScheme())
00802 {
00803 if (_ColorFading)
00804 {
00805
00806
00807 if (ptGradTexture == NULL)
00808 {
00809 ptGradTexture = CreateGradientTexture();
00810 }
00811 _Mat.setTexture(0, ptGradTexture);
00812 CPSMaterial::forceTexturedMaterialStages(2);
00813 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Constant);
00814 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Diffuse);
00815 }
00816 else
00817 {
00818 CPSMaterial::forceTexturedMaterialStages(1);
00819 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00820 }
00821 }
00822 else
00823 {
00824 if (_ColorFading)
00825 {
00826 if (ptGradTexture == NULL)
00827 {
00828 ptGradTexture = CreateGradientTexture();
00829 }
00830 _Mat.setTexture(0, ptGradTexture);
00831 CPSMaterial::forceTexturedMaterialStages(1);
00832 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00833 }
00834 else
00835 {
00836 CPSMaterial::forceTexturedMaterialStages(0);
00837 }
00838 }
00839 }
00840 else
00841 {
00842 if (_ColorFading)
00843 {
00844 CPSMaterial::forceTexturedMaterialStages(1);
00845 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00846 }
00847 else
00848 {
00849 CPSMaterial::forceTexturedMaterialStages(0);
00850 }
00851 }
00852 _Touch = false;
00853 }
00854
00855
00856 inline void CPSRibbon::updateTexturedMaterial()
00857 {
00859
00861
00862 static NLMISC::CRefPtr<ITexture> ptGradTexture;
00863 CParticleSystem &ps = *(_Owner->getOwner());
00864 if (_ColorScheme)
00865 {
00866 if (ps.getColorAttenuationScheme())
00867 {
00868 if (_ColorFading)
00869 {
00870 if (ptGradTexture == NULL)
00871 {
00872 ptGradTexture = CreateGradientTexture();
00873 }
00875 _Mat.setTexture(0, ptGradTexture);
00876 _Mat.setTexture(1, _Tex);
00877 CPSMaterial::forceTexturedMaterialStages(3);
00878 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00879 SetupModulatedStage(_Mat, 1, CMaterial::Texture, CMaterial::Previous);
00880 SetupModulatedStage(_Mat, 2, CMaterial::Previous, CMaterial::Constant);
00881 }
00882 else
00883 {
00884 _Mat.setTexture(0, _Tex);
00885 CPSMaterial::forceTexturedMaterialStages(2);
00886 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00887 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Constant);
00888 }
00889 }
00890 else
00891 {
00892 if (_ColorFading)
00893 {
00894 if (ptGradTexture == NULL)
00895 {
00896 ptGradTexture = CreateGradientTexture();
00897 }
00898 _Mat.setTexture(0, ptGradTexture);
00899 _Mat.setTexture(1, _Tex);
00900 CPSMaterial::forceTexturedMaterialStages(2);
00901 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00902 SetupModulatedStage(_Mat, 1, CMaterial::Texture, CMaterial::Previous);
00903 }
00904 else
00905 {
00906 _Mat.setTexture(0, _Tex);
00907 CPSMaterial::forceTexturedMaterialStages(1);
00908 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00909 }
00910 }
00911 }
00912 else
00913 {
00914
00915 if (_ColorFading)
00916 {
00917 _Mat.setTexture(0, _Tex);
00918 CPSMaterial::forceTexturedMaterialStages(2);
00919 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00920 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Constant);
00921 }
00922 else
00923 {
00924 _Mat.setTexture(0, _Tex);
00925 CPSMaterial::forceTexturedMaterialStages(1);
00926 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00927 }
00928 }
00929 _Touch = false;
00930 }
00931
00932
00933 void CPSRibbon::updateMaterial()
00934 {
00935 if (!_Touch) return;
00936 if (_Tex != NULL)
00937 {
00938 updateTexturedMaterial();
00939 setupTextureMatrix();
00940 }
00941 else
00942 {
00943 updateUntexturedMaterial();
00944 }
00945 }
00946
00947
00948
00949
00950 inline void CPSRibbon::setupUntexturedGlobalColor()
00951 {
00953 CParticleSystem &ps = *(_Owner->getOwner());
00954 if (_ColorScheme)
00955 {
00956 _Mat.texConstantColor(0, ps.getGlobalColor());
00957 }
00958 else
00959 {
00960 if (ps.getColorAttenuationScheme())
00961 {
00962 NLMISC::CRGBA col;
00963 col.modulateFromColor(ps.getGlobalColor(), _Color);
00964 if (_ColorFading)
00965 {
00966 _Mat.texConstantColor(0, col);
00967 }
00968 else
00969 {
00970 _Mat.setColor(col);
00971 }
00972 }
00973 else
00974 {
00975 if (_ColorFading)
00976 {
00977 _Mat.texConstantColor(0, _Color);
00978 }
00979 else
00980 {
00981 _Mat.setColor(_Color);
00982 }
00983 }
00984 }
00985 }
00986
00987
00988 inline void CPSRibbon::setupTexturedGlobalColor()
00989 {
00991 CParticleSystem &ps = *(_Owner->getOwner());
00992 if (_ColorScheme)
00993 {
00994 if (ps.getColorAttenuationScheme() && _ColorFading)
00995 {
00996 _Mat.texConstantColor(2, ps.getGlobalColor());
00997 }
00998 else
00999 {
01000 _Mat.texConstantColor(1, ps.getGlobalColor());
01001 }
01002 }
01003 else
01004 {
01005 if (ps.getColorAttenuationScheme())
01006 {
01007 NLMISC::CRGBA col;
01008 col.modulateFromColor(ps.getGlobalColor(), _Color);
01009 if (_ColorFading)
01010 {
01011 _Mat.texConstantColor(1, col);
01012 }
01013 else
01014 {
01015 _Mat.setColor(col);
01016 }
01017 }
01018 else
01019 {
01020 if (_ColorFading)
01021 {
01022 _Mat.texConstantColor(1, _Color);
01023 }
01024 else
01025 {
01026 _Mat.setColor(_Color);
01027 }
01028 }
01029 }
01030 }
01031
01032
01033
01034 void CPSRibbon::setupGlobalColor()
01035 {
01036 if (_Tex != NULL) setupTexturedGlobalColor();
01037 else setupUntexturedGlobalColor();
01038 }
01039
01040
01041 void CPSRibbon::setupTextureMatrix()
01042 {
01043 uint stage = (_ColorScheme != NULL && _ColorFading == true) ? 1 : 0;
01044 if (_UFactor != 1.f || _VFactor != 1.f)
01045 {
01046 _Mat.enableUserTexMat(stage);
01047 CMatrix texMat;
01048 texMat.setRot(_UFactor * NLMISC::CVector::I,
01049 _VFactor * NLMISC::CVector::J,
01050 NLMISC::CVector::K
01051 );
01052 _Mat.setUserTexMat(stage, texMat);
01053 }
01054 else
01055 {
01056 _Mat.enableUserTexMat(stage, false);
01057 }
01058 _Mat.enableUserTexMat(1 - stage, false);
01059 }
01060
01061
01063
01064 {
01065 nlassert(nbPointsInShape >= 3);
01066 _Shape.resize(nbPointsInShape);
01067 std::copy(shape, shape + nbPointsInShape, _Shape.begin());
01068 }
01069
01071 void CPSRibbon::getShape(CVector *shape) const
01072 {
01073 std::copy(_Shape.begin(), _Shape.end(), shape);
01074 }
01075
01076
01077
01078 }