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_particle_basic.h"
00029 #include "3d/ps_macro.h"
00030 #include "3d/driver.h"
00031 #include "3d/texture_grouped.h"
00032 #include "3d/texture_bump.h"
00033 #include "3d/texture_mem.h"
00034 #include "3d/particle_system.h"
00035
00036
00037
00038 namespace NL3D
00039 {
00040
00041
00042
00044
00046
00047
00048 CPSParticle::CPSParticle() : _DisableAutoLOD(false)
00049 {
00050
00051 }
00052
00053
00054 void CPSParticle::showTool()
00055 {
00056 PARTICLES_CHECK_MEM;
00057
00058 CVector I = CVector::I;
00059 CVector J = CVector::J;
00060
00061 const CVector tab[] = { 2 * J, I + J
00062 , I + J, 2 * I + J
00063 , 2 * I + J, I
00064 , I, 2 * I - J
00065 , 2 * I - J, - .5f * J
00066 , - .5f * J, -2 * I - J
00067 , -2 * I - J, - I
00068 , - I, -2 * I + J
00069 , -2 * I + J, - I + J
00070 , - I + J, 2 * J
00071 };
00072 const uint tabSize = sizeof(tab) / (2 * sizeof(CVector));
00073
00074 const float sSize = 0.1f;
00075 displayIcon2d(tab, tabSize, sSize);
00076
00077 PARTICLES_CHECK_MEM;
00078 }
00079
00080
00081 void CPSParticle::computeSrcStep(uint32 &step, uint &numToProcess)
00082 {
00083 nlassert(_Owner && _Owner->getOwner());
00084 const CParticleSystem &ps = *(_Owner->getOwner());
00085 if (_DisableAutoLOD || !ps.isAutoLODEnabled() || _Owner->getSize() == 0)
00086 {
00087 step = (1 << 16);
00088 numToProcess = _Owner->getSize();
00089 }
00090 else
00091 {
00092 float oneMinusLODRatio = ps.getOneMinusCurrentLODRatio();
00093 float LODRatio = 1.f - oneMinusLODRatio;
00094 if (LODRatio > ps.getAutoLODStartDistPercent())
00095 {
00096 float factor = (LODRatio - 1.f) / (ps.getAutoLODStartDistPercent() - 1.f);
00097 NLMISC::clamp(factor, 0.f, 1.f);
00098 float r = factor;
00099 for (uint k = 0; k < ps.getAutoLODDegradationExponent(); ++k)
00100 {
00101 r *= factor;
00102 }
00103 numToProcess = (uint) (_Owner->getSize() * r);
00104 if (numToProcess < 1) { numToProcess = 1; }
00105
00106 step = ps.getAutoLODMode() ?
00107 (_Owner->getSize() << 16) / numToProcess :
00108 (1<<16);
00109 }
00110 else
00111 {
00112 step = (1 << 16);
00113 numToProcess = _Owner->getSize();
00114 }
00115 }
00116
00117 }
00118
00120
00122
00123
00124 void CPSColoredParticle::setColorScheme(CPSAttribMaker<CRGBA> *col)
00125 {
00126 nlassert(col);
00127 delete _ColorScheme;
00128 _ColorScheme = col;
00129 if (getColorOwner() && col->hasMemory()) col->resize(getColorOwner()->getMaxSize(), getColorOwner()->getSize());
00130 updateMatAndVbForColor();
00131 }
00132
00133
00134 void CPSColoredParticle::setColor(NLMISC::CRGBA col)
00135 {
00136 delete _ColorScheme;
00137 _ColorScheme = NULL;
00138 _Color = col;
00139 updateMatAndVbForColor();
00140 }
00141
00142
00143 CPSColoredParticle::CPSColoredParticle() : _Color(CRGBA(255, 255, 255)), _ColorScheme(NULL)
00144 {
00145 }
00146
00147
00148 CPSColoredParticle::~CPSColoredParticle()
00149 {
00150 delete _ColorScheme;
00151 }
00152
00153
00154 void CPSColoredParticle::serialColorScheme(NLMISC::IStream &f) throw(NLMISC::EStream)
00155 {
00156 f.serialVersion(1);
00157 if (f.isReading())
00158 {
00159 if (_ColorScheme)
00160 {
00161 delete _ColorScheme;
00162 _ColorScheme = NULL;
00163 }
00164 }
00165 bool useColorScheme = _ColorScheme != NULL;
00166 f.serial(useColorScheme);
00167 if (useColorScheme)
00168 {
00169 f.serialPolyPtr(_ColorScheme);
00170 }
00171 else
00172 {
00173 f.serial(_Color);
00174 }
00175 }
00176
00178
00180
00181
00182 void CPSSizedParticle::setSizeScheme(CPSAttribMaker<float> *size)
00183 {
00184 nlassert(size != NULL);
00185 delete _SizeScheme;
00186 _SizeScheme = size;
00187 if (getSizeOwner() && size->hasMemory()) size->resize(getSizeOwner()->getMaxSize(), getSizeOwner()->getSize());
00188 }
00189
00190
00191 void CPSSizedParticle::setSize(float size)
00192 {
00193 delete _SizeScheme;
00194 _SizeScheme = NULL;
00195 _ParticleSize = size;
00196 }
00197
00198
00199 CPSSizedParticle::CPSSizedParticle() : _ParticleSize(0.3f), _SizeScheme(NULL)
00200 {
00201 }
00202
00203
00204 CPSSizedParticle::~CPSSizedParticle()
00205 {
00206 delete _SizeScheme;
00207 }
00208
00209
00210 void CPSSizedParticle::serialSizeScheme(NLMISC::IStream &f) throw(NLMISC::EStream)
00211 {
00212 f.serialVersion(1);
00213 if (f.isReading())
00214 {
00215 if (_SizeScheme)
00216 {
00217 delete _SizeScheme;
00218 _SizeScheme = NULL;
00219 }
00220 }
00221 bool useSizeScheme = _SizeScheme != NULL;
00222 f.serial(useSizeScheme);
00223 if (useSizeScheme)
00224 {
00225 f.serialPolyPtr(_SizeScheme);
00226 }
00227 else
00228 {
00229 f.serial(_ParticleSize);
00230 }
00231 };
00232
00234
00236
00237 float CPSRotated2DParticle::_RotTable[256 * 4];
00238 bool CPSRotated2DParticle::_InitializedRotTab = false;
00239
00241 void CPSRotated2DParticle::setAngle2DScheme(CPSAttribMaker<float> *angle2DScheme)
00242 {
00243 nlassert(angle2DScheme);
00244 delete _Angle2DScheme;
00245 _Angle2DScheme = angle2DScheme;
00246 if (getAngle2DOwner() && angle2DScheme->hasMemory()) angle2DScheme->resize(getAngle2DOwner()->getMaxSize(), getAngle2DOwner()->getSize());
00247 }
00248
00250 void CPSRotated2DParticle::setAngle2D(float angle2DScheme)
00251 {
00252 delete _Angle2DScheme;
00253 _Angle2DScheme = NULL;
00254 _Angle2D = angle2DScheme;
00255 }
00256
00258 CPSRotated2DParticle::CPSRotated2DParticle() : _Angle2D(0), _Angle2DScheme(NULL)
00259 {
00260 }
00261
00263 CPSRotated2DParticle::~CPSRotated2DParticle()
00264 {
00265 delete _Angle2DScheme;
00266 }
00267
00269 void CPSRotated2DParticle::serialAngle2DScheme(NLMISC::IStream &f) throw(NLMISC::EStream)
00270 {
00271 f.serialVersion(1);
00272 if (f.isReading())
00273 {
00274 if (_Angle2DScheme)
00275 {
00276 delete _Angle2DScheme;
00277 _Angle2DScheme = NULL;
00278 }
00279 }
00280 bool useAngle2DScheme = _Angle2DScheme != NULL;
00281 f.serial(useAngle2DScheme);
00282 if (useAngle2DScheme)
00283 {
00284 f.serialPolyPtr(_Angle2DScheme);
00285 }
00286 else
00287 {
00288 f.serial(_Angle2D);
00289 }
00290 }
00291
00293 void CPSRotated2DParticle::initRotTable(void)
00294 {
00295 float *ptFloat = _RotTable;
00296 for (uint32 k = 0; k < 256; ++k)
00297 {
00298 const float ca = (float) cos(k * (1.0f / 256.0f) * 2.0f * NLMISC::Pi);
00299 const float sa = (float) sin(k * (1.0f / 256.0f) * 2.0f * NLMISC::Pi);
00300
00301 *ptFloat++ = -ca - sa;
00302 *ptFloat++ = -sa + ca;
00303
00304 *ptFloat++ = ca - sa;
00305 *ptFloat++ = sa + ca;
00306 }
00307 _InitializedRotTab = true;
00308 }
00309
00311
00313
00315
00316 {
00317 nlassert(animOrder);
00318 nlassert(_TexGroup);
00319 delete _TextureIndexScheme;
00320 _TextureIndexScheme = animOrder;
00321 if (getTextureIndexOwner() && animOrder->hasMemory()) animOrder->resize(getTextureIndexOwner()->getMaxSize(), getTextureIndexOwner()->getSize());
00322
00323
00324 updateMatAndVbForTexture();
00325 }
00326
00328 void CPSTexturedParticle::setTextureIndex(sint32 index)
00329 {
00330 delete _TextureIndexScheme;
00331 _TextureIndexScheme = NULL;
00332 _TextureIndex = index;
00333 }
00334
00336 void CPSTexturedParticle::setTextureGroup(NLMISC::CSmartPtr<CTextureGrouped> texGroup)
00337 {
00338 nlassert(texGroup);
00339 if (_Tex)
00340 {
00341 _Tex = NULL;
00342 }
00343 _TexGroup = texGroup;
00344 }
00345
00347 void CPSTexturedParticle::setTexture(CSmartPtr<ITexture> tex)
00348 {
00349 delete _TextureIndexScheme;
00350 _TextureIndexScheme = NULL;
00351 _Tex = tex;
00352 _TexGroup = NULL;
00353 updateMatAndVbForTexture();
00354 }
00355
00357 CPSTexturedParticle::CPSTexturedParticle() : _TexGroup(NULL),
00358 _TextureIndexScheme(NULL),
00359 _TextureIndex(0)
00360 {
00361 }
00362
00364 CPSTexturedParticle::~CPSTexturedParticle()
00365 {
00366 delete _TextureIndexScheme;
00367 }
00368
00370 void CPSTexturedParticle::serialTextureScheme(NLMISC::IStream &f) throw(NLMISC::EStream)
00371 {
00372 f.serialVersion(1);
00373 if (f.isReading())
00374 {
00375 if (_TextureIndexScheme)
00376 {
00377 delete _TextureIndexScheme;
00378 _TextureIndexScheme = NULL;
00379 _Tex = NULL;
00380 _TexGroup = NULL;
00381 }
00382 }
00383
00384 bool useAnimatedTexture;
00385 if (!f.isReading())
00386 {
00387 useAnimatedTexture = (_TexGroup != NULL);
00388 }
00389 f.serial(useAnimatedTexture);
00390 if (useAnimatedTexture)
00391 {
00392 if (f.isReading())
00393 {
00394 CTextureGrouped *ptTex = NULL;
00395 f.serialPolyPtr(ptTex);
00396 _TexGroup = ptTex;
00397 }
00398 else
00399 {
00400 CTextureGrouped *ptTex = _TexGroup;
00401 f.serialPolyPtr(ptTex);
00402 }
00403
00404 bool useTextureIndexScheme = _TextureIndexScheme != NULL;
00405 f.serial(useTextureIndexScheme);
00406 if (useTextureIndexScheme)
00407 {
00408 f.serialPolyPtr(_TextureIndexScheme);
00409 _TextureIndex = 0;
00410 }
00411 else
00412 {
00413 f.serial(_TextureIndex);
00414 }
00415 }
00416 else
00417 {
00418 if (f.isReading())
00419 {
00420 ITexture *ptTex = NULL;
00421 f.serialPolyPtr(ptTex);
00422 _Tex = ptTex;
00423 }
00424 else
00425 {
00426 ITexture *ptTex = _Tex;
00427 f.serialPolyPtr(ptTex);
00428 }
00429 }
00430 }
00431
00433
00435
00437
00438 {
00439 nlassert(basisMaker);
00440 delete _PlaneBasisScheme;
00441 _PlaneBasisScheme = basisMaker;
00442 if (getPlaneBasisOwner() && basisMaker->hasMemory()) basisMaker->resize(getPlaneBasisOwner()->getMaxSize(), getPlaneBasisOwner()->getSize());
00443 }
00444
00446 void CPSRotated3DPlaneParticle::setPlaneBasis(const CPlaneBasis &basis)
00447 {
00448 delete _PlaneBasisScheme;
00449 _PlaneBasisScheme = NULL;
00450 _PlaneBasis = basis;
00451 }
00452
00454 CPSRotated3DPlaneParticle::CPSRotated3DPlaneParticle() : _PlaneBasisScheme(NULL)
00455 {
00456 _PlaneBasis.X = CVector::I;
00457 _PlaneBasis.Y = CVector::J;
00458 }
00459
00461 CPSRotated3DPlaneParticle::~CPSRotated3DPlaneParticle()
00462 {
00463 delete _PlaneBasisScheme;
00464 }
00465
00467 void CPSRotated3DPlaneParticle::serialPlaneBasisScheme(NLMISC::IStream &f) throw(NLMISC::EStream)
00468 {
00469 f.serialVersion(1);
00470 f.serialPolyPtr(_PlaneBasisScheme);
00471 bool usePlaneBasisScheme = _PlaneBasisScheme != NULL;
00472 if (!usePlaneBasisScheme)
00473 {
00474 f.serial(_PlaneBasis);
00475 }
00476 }
00477
00479
00481
00483
00484 {
00485 _Mat.setBlend(true);
00486 _Mat.setBlendFunc(CMaterial::one, CMaterial::one);
00487 _Mat.setZWrite(false);
00488 }
00489
00491 void CPSMaterial::serialMaterial(NLMISC::IStream &f) throw(NLMISC::EStream)
00492 {
00493 f.serialVersion(1);
00494 TBlendingMode m = getBlendingMode();
00495 f.serialEnum(m);
00496 setBlendingMode(m);
00497 }
00498
00500 void CPSMaterial::setBlendingMode(CPSMaterial::TBlendingMode mode)
00501 {
00502 switch (mode)
00503 {
00504 case add:
00505 _Mat.setBlend(true);
00506 _Mat.setBlendFunc(CMaterial::one, CMaterial::one);
00507 _Mat.setZWrite(false);
00508 _Mat.setAlphaTest(false);
00509 break;
00510 case modulate:
00511 _Mat.setBlend(true);
00512 _Mat.setBlendFunc(CMaterial::zero, CMaterial::srccolor);
00513 _Mat.setZWrite(false);
00514 _Mat.setAlphaTest(false);
00515 break;
00516 case alphaBlend:
00517 _Mat.setBlend(true);
00518 _Mat.setBlendFunc(CMaterial::srcalpha, CMaterial::invsrcalpha);
00519 _Mat.setZWrite(false);
00520 _Mat.setAlphaTest(false);
00521 break;
00522 case alphaTest:
00523 _Mat.setBlend(false);
00524 _Mat.setZWrite(true);
00525 _Mat.setAlphaTest(true);
00526 break;
00527 }
00528 }
00529
00531 CPSMaterial::TBlendingMode CPSMaterial::getBlendingMode(void) const
00532 {
00533 if (_Mat.getBlend())
00534 {
00535 CMaterial::TBlend srcBlend = _Mat.getSrcBlend();
00536 CMaterial::TBlend destBlend = _Mat.getDstBlend();
00537
00538 if (srcBlend == CMaterial::one && destBlend == CMaterial::one) return add;
00539 if (srcBlend == CMaterial::zero && destBlend == CMaterial::srccolor) return modulate;
00540 if (srcBlend == CMaterial::srcalpha && destBlend == CMaterial::invsrcalpha) return alphaBlend;
00541
00542
00543 nlassert(0);
00544 return alphaTest;
00545 }
00546 else
00547 {
00548 return alphaTest;
00549 }
00550 }
00551
00553 void CPSMaterial::forceModulateConstantColor(bool force, const NLMISC::CRGBA &col)
00554 {
00555 if (force)
00556 {
00558 _Mat.texConstantColor(1, col);
00559 _Mat.texEnvOpRGB(1, CMaterial::Modulate);
00560 _Mat.texEnvOpAlpha(1, CMaterial::Modulate);
00561 _Mat.texEnvArg0RGB(1, CMaterial::Previous, CMaterial::SrcColor);
00562 _Mat.texEnvArg1RGB(1, CMaterial::Constant, CMaterial::SrcColor);
00563 _Mat.texEnvArg0Alpha(1, CMaterial::Previous, CMaterial::SrcAlpha);
00564 _Mat.texEnvArg1Alpha(1, CMaterial::Constant, CMaterial::SrcAlpha);
00565 forceTexturedMaterialStages(2);
00566 }
00567 else
00568 {
00569 if (_Mat.getTexture(1) != NULL)
00570 {
00571 _Mat.setTexture(1, NULL);
00572 }
00573 }
00574 }
00575
00576
00578 void CPSMaterial::forceTexturedMaterialStages(uint numStages)
00579 {
00580 ITexture *blankTex = NULL;
00581 uint k;
00582 for (k = 0; k < numStages; ++k)
00583 {
00584 if (_Mat.getTexture(k) == NULL)
00585 {
00586 if (!blankTex)
00587 {
00588 blankTex = CTextureMem::Create1x1WhiteTex();
00589 }
00590 _Mat.setTexture(k, blankTex);
00591 }
00592 }
00593 for (; k < IDRV_MAT_MAXTEXTURES; ++k)
00594 {
00595 if (_Mat.getTexture(k) != NULL)
00596 {
00597 _Mat.setTexture(k, NULL);
00598 }
00599 }
00600 }
00601
00602
00604
00606
00607
00608 bool CPSMultiTexturedParticle::_ForceBasicCaps = false;
00609
00610
00611 CPSMultiTexturedParticle::CPSMultiTexturedParticle() : _MultiTexState(TouchFlag), _BumpFactor(1.f)
00612 {
00613 }
00614
00615
00616 void CPSMultiTexturedParticle::enableMultiTexture(bool enabled )
00617 {
00618 if (isMultiTextureEnabled() == enabled) return;
00619 if (!enabled)
00620 {
00621 _Texture2 = NULL;
00622 _AlternateTexture2 = NULL;
00623 _MultiTexState = 0;
00624 }
00625 else
00626 {
00627 _MainOp = Modulate;
00628 _TexScroll[0].set(0, 0);
00629 _TexScroll[1].set(0, 0);
00630 _MultiTexState = (uint8) MultiTextureEnabled;
00631 }
00632 touch();
00633 }
00634
00635
00636 void CPSMultiTexturedParticle::enableAlternateTex(bool enabled )
00637 {
00638 nlassert(isMultiTextureEnabled());
00639 if (enabled == isAlternateTexEnabled()) return;
00640
00641 if (enabled)
00642 {
00643 _TexScrollAlternate[0].set(0, 0);
00644 _TexScrollAlternate[1].set(0, 0);
00645 _AlternateOp = Modulate;
00646 _MultiTexState |= (uint8) AlternateTextureEnabled;
00647 }
00648 else
00649 {
00650 _Texture2 = NULL;
00651 _MultiTexState &= ~(uint8) AlternateTextureEnabled;
00652 }
00653 touch();
00654 }
00655
00656
00657 void CPSMultiTexturedParticle::serialMultiTex(NLMISC::IStream &f) throw(NLMISC::EStream)
00658 {
00660 sint ver = f.serialVersion(1);
00661 f.serial(_MultiTexState);
00662 if (isMultiTextureEnabled())
00663 {
00664 f.serialEnum(_MainOp);
00665 if (_MainOp == EnvBumpMap && ver >= 1)
00666 {
00667 f.serial(_BumpFactor);
00668 }
00669 ITexture *tex = NULL;
00670 if (f.isReading())
00671 {
00672 f.serialPolyPtr(tex);
00673 _Texture2 = tex;
00674 }
00675 else
00676 {
00677 tex = _Texture2;
00678 f.serialPolyPtr(tex);
00679 }
00680 f.serial(_TexScroll[0], _TexScroll[1]);
00681
00682 if (isAlternateTexEnabled())
00683 {
00684 f.serialEnum(_AlternateOp);
00685 if (f.isReading())
00686 {
00687 f.serialPolyPtr(tex);
00688 _AlternateTexture2 = tex;
00689 }
00690 else
00691 {
00692 tex = _AlternateTexture2;
00693 f.serialPolyPtr(tex);
00694 }
00695 f.serial(_TexScrollAlternate[0], _TexScrollAlternate[1]);
00696 }
00697 else
00698 {
00699 _AlternateTexture2 = NULL;
00700 }
00701 }
00702 else
00703 {
00704 if (f.isReading())
00705 {
00706 _Texture2 = NULL;
00707 _AlternateTexture2 = NULL;
00708 }
00709 }
00710 }
00711
00712
00713 void CPSMultiTexturedParticle::setupMaterial(ITexture *primary, IDriver *driver, CMaterial &mat)
00714 {
00716 if (isMultiTextureEnabled() && _MainOp == EnvBumpMap && driver->isTextureAddrModeSupported(CMaterial::OffsetTexture))
00717 {
00718 CTextureBump *tb = dynamic_cast<CTextureBump *>((ITexture *) _Texture2);
00719 if (tb != NULL)
00720 {
00721 float normFactor = tb->getNormalizationFactor();
00722 if (normFactor == 0.f)
00723 {
00725 tb->generate();
00726 normFactor = tb->getNormalizationFactor();
00727 tb->release();
00728 }
00729 const float bMat[] = { _BumpFactor * normFactor, 0.f, 0.f, _BumpFactor * normFactor};
00730 driver->setMatrix2DForTextureOffsetAddrMode(1, bMat);
00731 }
00732 }
00733
00734 if (!isTouched() && areBasicCapsForcedLocal() == areBasicCapsForced()) return;
00735 if (!isMultiTextureEnabled())
00736 {
00737 mat.setTexture(0, primary);
00738 mat.texEnvOpRGB(0, CMaterial::Modulate);
00739 mat.setTexture(1, NULL);
00740 }
00741 else
00742 {
00743 if (_MainOp != EnvBumpMap)
00744 {
00745 setupMultiTexEnv(_MainOp, primary, _Texture2, mat);
00746 _MultiTexState &= ~(uint8) EnvBumpMapUsed;
00747 _MultiTexState &= ~(uint8) AlternateTextureUsed;
00748 }
00749 else
00750 {
00751 if (!_ForceBasicCaps && driver->isTextureAddrModeSupported(CMaterial::OffsetTexture))
00752 {
00753 CTextureBump *tb = dynamic_cast<CTextureBump *>((ITexture *) _Texture2);
00754 if (tb != NULL)
00755 {
00756 float normFactor = tb->getNormalizationFactor();
00757 if (normFactor == 0.f)
00758 {
00760 tb->generate();
00761 normFactor = tb->getNormalizationFactor();
00762 tb->release();
00763 }
00764 setupMultiTexEnv(_MainOp, primary, _Texture2, mat);
00765 }
00766 _MultiTexState &= ~(uint8) AlternateTextureUsed;
00767 _MultiTexState |= (uint8) EnvBumpMapUsed;
00768 }
00769 else
00770 {
00771 if (isAlternateTexEnabled())
00772 {
00773 _MultiTexState |= (uint8) AlternateTextureUsed;
00774 setupMultiTexEnv(_AlternateOp, primary, _AlternateTexture2, mat);
00775 _MultiTexState &= ~(uint8) EnvBumpMapUsed;
00776 }
00777 else
00778 {
00779 setupMultiTexEnv(Decal, primary, NULL, mat);
00780 _MultiTexState &= ~(uint8) AlternateTextureUsed;
00781 _MultiTexState &= ~(uint8) EnvBumpMapUsed;
00782 }
00783 }
00784 }
00785 }
00786
00787 (areBasicCapsForced());
00788 unTouch();
00789 }
00790
00791
00792 void CPSMultiTexturedParticle::setupMultiTexEnv(TOperator op, ITexture *tex1, ITexture *tex2, CMaterial &mat)
00793 {
00794 switch (op)
00795 {
00796 case Add:
00797 mat.setTexture(0, tex1);
00798 mat.setTexture(1, tex2);
00799 mat.texEnvOpRGB(0, CMaterial::Modulate);
00800 mat.texEnvOpRGB(1, CMaterial::Add);
00801 mat.enableTexAddrMode(false);
00802 break;
00803 case Modulate:
00804 mat.setTexture(0, tex1);
00805 mat.setTexture(1, tex2);
00806 mat.texEnvOpRGB(0, CMaterial::Modulate);
00807 mat.texEnvOpRGB(1, CMaterial::Modulate);
00808 mat.enableTexAddrMode(false);
00809 break;
00810 case EnvBumpMap:
00811 mat.setTexture(0, tex2);
00812 mat.setTexture(1, tex1);
00813 mat.texEnvOpRGB(0, CMaterial::Replace);
00814 mat.texEnvOpRGB(1, CMaterial::Modulate);
00815 mat.enableTexAddrMode(true);
00816 mat.setTexAddressingMode(0, CMaterial::FetchTexture);
00817 mat.setTexAddressingMode(1, CMaterial::OffsetTexture);
00818 break;
00819 case Decal:
00820 mat.setTexture(0, tex1);
00821 mat.texEnvOpRGB(0, CMaterial::Replace);
00822 mat.setTexture(1, NULL);
00823 mat.enableTexAddrMode(false);
00824 break;
00825 default: break;
00826 }
00827 }
00828
00829
00830 static void ConvertToBumpMap(NLMISC::CSmartPtr<ITexture> &ptr)
00831 {
00832 if (!dynamic_cast<CTextureBump *>( (ITexture *) ptr))
00833 {
00834
00835 CTextureBump *tb = new CTextureBump;
00836 tb->setAbsoluteOffsets();
00837 tb->setHeightMap((ITexture *) ptr);
00838 ptr = tb;
00839 }
00840 }
00841
00842
00843 static void ConvertFromBumpMap(NLMISC::CSmartPtr<ITexture> &ptr)
00844 {
00845 CTextureBump *bm = dynamic_cast<CTextureBump *>( (ITexture *) ptr);
00846 if (bm)
00847 {
00848
00849 NLMISC::CSmartPtr<ITexture> hm = bm->getHeightMap();
00850 ptr = hm;
00851 }
00852 }
00853
00854
00855 void CPSMultiTexturedParticle::setTexture2Alternate(ITexture *tex)
00856 {
00857 _AlternateTexture2 = tex;
00858 if (_AlternateOp != EnvBumpMap)
00859 {
00860 ConvertFromBumpMap(_AlternateTexture2);
00861 }
00862 else
00863 {
00864 ConvertToBumpMap(_AlternateTexture2);
00865 }
00866 touch();
00867 }
00868
00869
00870 void CPSMultiTexturedParticle::setTexture2(ITexture *tex)
00871 {
00872 _Texture2 = tex;
00873 if (_MainOp != EnvBumpMap)
00874 {
00875 ConvertFromBumpMap(_Texture2);
00876 }
00877 else
00878 {
00879 if (!dynamic_cast<NL3D::CTextureBump *>((ITexture *) _Texture2))
00880 {
00881 ConvertToBumpMap(_Texture2);
00882 }
00883 }
00884 touch();
00885 }
00886
00887
00888 void CPSMultiTexturedParticle::setMainTexOp(TOperator op)
00889 {
00890 _MainOp = op;
00891 if (_MainOp == EnvBumpMap)
00892 {
00893 ConvertToBumpMap(_Texture2);
00894 }
00895 else
00896 {
00897 ConvertFromBumpMap(_Texture2);
00898 }
00899 touch();
00900 }
00901
00902
00903 void CPSMultiTexturedParticle::setAlternateTexOp(TOperator op)
00904 {
00905 _AlternateOp = op;
00906 if (_AlternateOp == EnvBumpMap)
00907 {
00908 ConvertToBumpMap(_AlternateTexture2);
00909 }
00910 else
00911 {
00912 ConvertFromBumpMap(_AlternateTexture2);
00913 }
00914 touch();
00915 }
00916
00917
00918
00919
00920 void CPSMultiTexturedParticle::setUseLocalDate(bool use)
00921 {
00922 if (use) _MultiTexState |= ScrollUseLocalDate;
00923 else _MultiTexState &= ~ ScrollUseLocalDate;
00924 }
00925
00926
00927
00928 void CPSMultiTexturedParticle::setUseLocalDateAlt(bool use)
00929 {
00930 if (use) _MultiTexState |= ScrollUseLocalDateAlternate;
00931 else _MultiTexState &= ~ ScrollUseLocalDateAlternate;
00932 }
00933
00934 }
00935
00936
00937
00938
00939