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_quad.h"
00029 #include "3d/ps_macro.h"
00030 #include "3d/driver.h"
00031 #include "3d/ps_attrib_maker.h"
00032 #include "3d/texture_grouped.h"
00033 #include "3d/particle_system.h"
00034 #include "3d/ps_iterator.h"
00035
00036 namespace NL3D
00037 {
00038
00039
00040
00042
00044
00045
00046 static const uint dotBufSize = 1024;
00047
00049
00051
00053
00054 CVertexBuffer CPSQuad::_VBPosCol;
00055 CVertexBuffer CPSQuad::_VBPosTex1;
00056 CVertexBuffer CPSQuad::_VBPosTex1Col;
00057 CVertexBuffer CPSQuad::_VBPosTex1Anim;
00058 CVertexBuffer CPSQuad::_VBPosTex1AnimCol;
00059
00060 CVertexBuffer CPSQuad::_VBPosTex1Tex2;
00061 CVertexBuffer CPSQuad::_VBPosTex1ColTex2;
00062 CVertexBuffer CPSQuad::_VBPosTex1AnimTex2;
00063 CVertexBuffer CPSQuad::_VBPosTex1AnimColTex2;
00064
00065 CVertexBuffer CPSQuad::_VBPosTex1Tex2Anim;
00066 CVertexBuffer CPSQuad::_VBPosTex1ColTex2Anim;
00067 CVertexBuffer CPSQuad::_VBPosTex1AnimTex2Anim;
00068 CVertexBuffer CPSQuad::_VBPosTex1AnimColTex2Anim;
00069
00070 CVertexBuffer * const CPSQuad::_VbTab[] =
00071 {
00072
00073 &_VBPos, &_VBPosCol, &_VBPosTex1, &_VBPosTex1Col,
00074 NULL, NULL, &_VBPosTex1Anim, &_VBPosTex1AnimCol,
00075
00076 NULL, NULL, &_VBPosTex1Tex2, &_VBPosTex1ColTex2,
00077 NULL, NULL, &_VBPosTex1AnimTex2, &_VBPosTex1AnimColTex2,
00078
00079 NULL, NULL, NULL, NULL,
00080 NULL, NULL, NULL, NULL,
00081
00082
00083 NULL, NULL, &_VBPosTex1Tex2Anim, &_VBPosTex1ColTex2Anim,
00084 NULL, NULL, &_VBPosTex1AnimTex2Anim, &_VBPosTex1AnimColTex2Anim,
00085 };
00086
00087
00088
00089
00090
00092
00094
00095
00098 static void SetupQuadVBTexCoords(CVertexBuffer &vb, uint texCoordSet)
00099 {
00100 nlassert(texCoordSet < 2);
00101
00102
00103 for (uint32 k = 0; k < CPSQuad::quadBufSize; ++k)
00104 {
00105
00106 vb.setTexCoord(k * 4, texCoordSet, CUV(0, 0));
00107 vb.setTexCoord(k * 4 + 1, texCoordSet, CUV(1, 0));
00108 vb.setTexCoord(k * 4 + 2, texCoordSet, CUV(1, 1));
00109 vb.setTexCoord(k * 4 + 3, texCoordSet, CUV(0, 1));
00110 }
00111 }
00112
00115 void CPSQuad::initVertexBuffers()
00116 {
00117 for (uint k = 0; k < 32; ++k)
00118 {
00119 CVertexBuffer *vb = _VbTab[k];
00120 if (_VbTab[k])
00121 {
00122 uint32 vf = CVertexBuffer::PositionFlag;
00124 if (k & (uint) VBCol) vf |= CVertexBuffer::PrimaryColorFlag;
00125 if (k & (uint) VBTex || k & (uint) VBTexAnimated) vf |= CVertexBuffer::TexCoord0Flag;
00126 if (k & (uint) VBTex2 || k & (uint) VBTex2Animated) vf |= CVertexBuffer::TexCoord1Flag;
00127 vb->setVertexFormat(vf);
00128 vb->setNumVertices(quadBufSize << 2);
00129
00130 if ((k & (uint) VBTex) && !(k & (uint) VBTexAnimated))
00131 {
00132 SetupQuadVBTexCoords(*vb, 0);
00133 }
00134
00135 if ((k & (uint) VBTex2) && !(k & (uint) VBTex2Animated))
00136 {
00137 SetupQuadVBTexCoords(*vb, 1);
00138 }
00139
00140 }
00141 }
00142 }
00143
00146 CVertexBuffer &CPSQuad::getNeededVB()
00147 {
00148 uint flags = 0;
00149 if (_ColorScheme) flags |= (uint) VBCol;
00150 if (_TexGroup)
00151 {
00152 flags |= VBTex | VBTexAnimated;
00153 }
00154 else if (_Tex)
00155 {
00156
00157 flags |= VBTex;
00158
00160 if (CPSMultiTexturedParticle::isMultiTextureEnabled())
00161 {
00162 if (!isAlternateTextureUsed())
00163 {
00164 if ((flags & VBTex) && (_TexScroll[0].x != 0 || _TexScroll[0].y != 0)) flags |= VBTexAnimated;
00165 if (_Texture2)
00166 {
00167 if (_MainOp != Decal && (_TexScroll[1].x != 0 || _TexScroll[1].y != 0))
00168 {
00169 flags |= VBTex2 | VBTex2Animated;
00170 }
00171 else
00172 {
00173 flags |= VBTex2;
00174 }
00175 }
00176 }
00177 else
00178 {
00179 if ((flags & VBTex) && (_TexScrollAlternate[0].x != 0 || _TexScrollAlternate[0].y != 0)) flags |= VBTexAnimated;
00180 if (_AlternateTexture2)
00181 {
00182 if (_AlternateOp != Decal && (_TexScrollAlternate[1].x != 0 || _TexScrollAlternate[1].y != 0))
00183 {
00184 flags |= VBTex2 | VBTex2Animated;
00185 }
00186 else
00187 {
00188 flags |= VBTex2;
00189 }
00190 }
00191 }
00192 }
00193 }
00194 nlassert(_VbTab[flags] != NULL);
00195 return *(_VbTab[flags]);
00196 }
00197
00199 CPSQuad::CPSQuad(CSmartPtr<ITexture> tex)
00200 {
00201 setTexture(tex);
00202 init();
00203
00204 _Name = std::string("quad");
00205 }
00206
00207
00209 CPSQuad::~CPSQuad()
00210 {
00211 }
00212
00214 uint32 CPSQuad::getMaxNumFaces(void) const
00215 {
00216 nlassert(_Owner);
00217 return _Owner->getMaxSize() << 1;
00218 }
00219
00221 bool CPSQuad::hasTransparentFaces(void)
00222 {
00223 return getBlendingMode() != CPSMaterial::alphaTest ;
00224 }
00225
00227 bool CPSQuad::hasOpaqueFaces(void)
00228 {
00229 return !hasTransparentFaces();
00230 }
00231
00233 void CPSQuad::init(void)
00234 {
00235 _Mat.setLighting(false);
00236 _Mat.setZFunc(CMaterial::less);
00237 _Mat.setDoubleSided(true);
00238
00239
00240 updateMatAndVbForColor();
00241 updateMatAndVbForTexture();
00242 }
00243
00245 void CPSQuad::updateMatAndVbForTexture(void)
00246 {
00247 if (CPSMultiTexturedParticle::isMultiTextureEnabled())
00248 {
00249 touch();
00250 }
00251 else
00252 {
00253 _Mat.setTexture(0, _TexGroup ? (ITexture *) _TexGroup : (ITexture *) _Tex);
00254 }
00255 }
00256
00258 bool CPSQuad::completeBBox(NLMISC::CAABBox &box) const
00259 {
00260 if (!_SizeScheme)
00261 {
00262 CPSUtil::addRadiusToAABBox(box, _ParticleSize);
00263 }
00264 else
00265 {
00266 CPSUtil::addRadiusToAABBox(box, _SizeScheme->getMaxValue());
00267 }
00268 return true ;
00269 }
00270
00272 void CPSQuad::resize(uint32 size)
00273 {
00274 nlassert(size < (1 << 16));
00275 resizeSize(size);
00276 resizeColor(size);
00277 resizeTextureIndex(size);
00278 }
00279
00280
00281 void CPSQuad::updateMatAndVbForColor(void)
00282 {
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 }
00293
00294
00295 void CPSQuad::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00296 {
00297 sint ver = f.serialVersion(2);
00298 CPSParticle::serial(f);
00299 CPSSizedParticle::serialSizeScheme(f);
00300 CPSColoredParticle::serialColorScheme(f);
00301 CPSTexturedParticle::serialTextureScheme(f);
00302 serialMaterial(f);
00303 if (ver > 1)
00304 {
00305 CPSMultiTexturedParticle::serialMultiTex(f);
00306 }
00307 }
00308
00309
00310
00311 static void FillQuadCoords(uint8 *dest, uint stride, const NLMISC::CVector2f &speed, float time, uint num)
00312 {
00313 if (!num) return;
00314 const float topV = speed.y * time;
00315 const float bottomV = topV + 1.f;
00316 const float leftU = speed.x * time;
00317 const float rightU = leftU + 1.f;
00318
00319
00320 do
00321 {
00322 ((NLMISC::CUV *) dest)->set(leftU, topV);
00323 ((NLMISC::CUV *) (dest + stride))->set(rightU, topV);
00324 ((NLMISC::CUV *) (dest + (stride << 1)))->set(rightU, bottomV);
00325 ((NLMISC::CUV *) (dest + (stride * 3)))->set(leftU, bottomV);
00326
00327
00328 dest += stride << 2;
00329 }
00330 while (--num);
00331 }
00332
00333
00334
00335 static void FillQuadCoordsLocalTime(uint8 *dest, uint stride, const NLMISC::CVector2f &speed, CPSLocated &srcLoc, uint startIndex, uint num, uint32 srcStep)
00336 {
00337 if (!num) return;
00338
00339 if (srcStep == (1 << 16))
00340 {
00341 TPSAttribTime::iterator timePt = srcLoc.getTime().begin() + startIndex;
00342 do
00343 {
00344 const float topV = speed.y * *timePt;
00345 const float bottomV = topV + 1.f;
00346 const float leftU = speed.x * *timePt;
00347 const float rightU = leftU + 1.f;
00348
00349 ((NLMISC::CUV *) dest)->set(leftU, topV);
00350 ((NLMISC::CUV *) (dest + stride))->set(rightU, topV);
00351 ((NLMISC::CUV *) (dest + (stride << 1)))->set(rightU, bottomV);
00352 ((NLMISC::CUV *) (dest + (stride * 3)))->set(leftU, bottomV);
00353
00354 dest += stride << 2;
00355 ++timePt;
00356 }
00357 while (--num);
00358 }
00359 else
00360 {
00361 TIteratorTimeStep1616 timePt(srcLoc.getTime().begin(), startIndex, srcStep);
00362 do
00363 {
00364 const float topV = speed.y * *timePt;
00365 const float bottomV = topV + 1.f;
00366 const float leftU = speed.x * *timePt;
00367 const float rightU = leftU + 1.f;
00368
00369 ((NLMISC::CUV *) dest)->set(leftU, topV);
00370 ((NLMISC::CUV *) (dest + stride))->set(rightU, topV);
00371 ((NLMISC::CUV *) (dest + (stride << 1)))->set(rightU, bottomV);
00372 ((NLMISC::CUV *) (dest + (stride * 3)))->set(leftU, bottomV);
00373
00374 dest += stride << 2;
00375 ++timePt;
00376 }
00377 while (--num);
00378 }
00379 }
00380
00381
00382 void CPSQuad::updateVbColNUVForRender(CVertexBuffer &vb, uint32 startIndex, uint32 size, uint32 srcStep)
00383 {
00384 nlassert(_Owner);
00385
00386 if (!size) return;
00387
00388 if (_ColorScheme)
00389 {
00390
00391 _ColorScheme->make4(_Owner, startIndex, vb.getColorPointer(), vb.getVertexSize(), size, srcStep);
00392 }
00393
00394
00395 if (_TexGroup)
00396 {
00397 sint32 textureIndex[quadBufSize];
00398 const uint32 stride = vb.getVertexSize(), stride2 = stride << 1, stride3 = stride2 + stride, stride4 = stride2 << 1;
00399 uint8 *currUV = (uint8 *) vb.getTexCoordPointer();
00400
00401
00402 const sint32 *currIndex;
00403 uint32 currIndexIncr;
00404
00405 if (_TextureIndexScheme)
00406 {
00407 currIndex = (sint32 *) _TextureIndexScheme->make(_Owner, startIndex, textureIndex, sizeof(sint32), size, true, srcStep);
00408 currIndexIncr = 1;
00409 }
00410 else
00411 {
00412 currIndex = &_TextureIndex;
00413 currIndexIncr = 0;
00414 }
00415
00416 while (size--)
00417 {
00418
00419 const CTextureGrouped::TFourUV &uvGroup = _TexGroup->getUVQuad((uint32) *currIndex);
00420
00421
00422 *(CUV *) currUV = uvGroup.uv0;
00423 *(CUV *) (currUV + stride) = uvGroup.uv1;
00424 *(CUV *) (currUV + stride2) = uvGroup.uv2;
00425 *(CUV *) (currUV + stride3) = uvGroup.uv3;
00426
00427
00428 currUV += stride4;
00429 currIndex += currIndexIncr;
00430 }
00431 }
00432
00433 nlassert(_Owner && _Owner->getOwner());
00434 const float date= (float) _Owner->getOwner()->getSystemDate();
00435
00436
00438
00439 if (CPSMultiTexturedParticle::isMultiTextureEnabled())
00440 {
00441
00442
00443 if (!_TexGroup)
00444 {
00445 if (!isAlternateTextureUsed())
00446 {
00447 if (_Tex && (_TexScroll[0].x != 0 || _TexScroll[0].y != 0))
00448 {
00449
00450 if (!getUseLocalDate())
00451 {
00452 FillQuadCoords((uint8 *) vb.getTexCoordPointer(0, 0), vb.getVertexSize(), _TexScroll[0], date, size);
00453 }
00454 else
00455 {
00456 FillQuadCoordsLocalTime((uint8 *) vb.getTexCoordPointer(0, 0), vb.getVertexSize(), _TexScroll[0], *_Owner, startIndex, size, srcStep);
00457 }
00458 }
00459 }
00460 else
00461 {
00462 if (_Tex && (_TexScrollAlternate[0].x != 0 || _TexScrollAlternate[0].y != 0))
00463 {
00464
00465 if (!getUseLocalDateAlt())
00466 {
00467 FillQuadCoords((uint8 *) vb.getTexCoordPointer(0, 0), vb.getVertexSize(), _TexScrollAlternate[0], date, size);
00468 }
00469 else
00470 {
00471 FillQuadCoordsLocalTime((uint8 *) vb.getTexCoordPointer(0, 0), vb.getVertexSize(), _TexScrollAlternate[0], *_Owner, startIndex, size, srcStep);
00472 }
00473 }
00474 }
00475 }
00476
00477
00478 if (!isAlternateTextureUsed())
00479 {
00480 if (_Texture2 && (_TexScroll[1].x != 0 || _TexScroll[1].y != 0))
00481 {
00482
00483 if (!getUseLocalDate())
00484 {
00485 FillQuadCoords((uint8 *) vb.getTexCoordPointer(0, 1), vb.getVertexSize(), _TexScroll[1], date, size);
00486 }
00487 else
00488 {
00489 FillQuadCoordsLocalTime((uint8 *) vb.getTexCoordPointer(0, 1), vb.getVertexSize(), _TexScroll[1], *_Owner, startIndex, size, srcStep);
00490 }
00491 }
00492 }
00493 else
00494 {
00495 if (_AlternateTexture2 && (_TexScrollAlternate[1].x != 0 || _TexScrollAlternate[1].y != 0))
00496 {
00497
00498 if (!getUseLocalDateAlt())
00499 {
00500 FillQuadCoords((uint8 *) vb.getTexCoordPointer(0, 1), vb.getVertexSize(), _TexScrollAlternate[1], date, size);
00501 }
00502 else
00503 {
00504 FillQuadCoordsLocalTime((uint8 *) vb.getTexCoordPointer(0, 1), vb.getVertexSize(), _TexScrollAlternate[1], *_Owner, startIndex, size, srcStep);
00505 }
00506 }
00507 }
00508
00509 }
00510 }
00511
00512
00513
00515 void CPSQuad::updateMatBeforeRendering(IDriver *drv)
00516 {
00517 nlassert(_Owner && _Owner->getOwner());
00518 CParticleSystem &ps = *(_Owner->getOwner());
00519 if (isMultiTextureEnabled())
00520 {
00521 setupMaterial(_Tex, drv, _Mat);
00522 _Mat.setColor(ps.getGlobalColor());
00523 }
00524 else
00525 {
00527 if (_ColorScheme != NULL && ps.getColorAttenuationScheme() != NULL)
00528 {
00529 CPSMaterial::forceModulateConstantColor(true, ps.getGlobalColor());
00530 }
00531 else
00532 {
00533 forceModulateConstantColor(false);
00534 if (!ps.getColorAttenuationScheme())
00535 {
00536 _Mat.setColor(_Color);
00537 }
00538 else
00539 {
00540 NLMISC::CRGBA col;
00541 col.modulateFromColor(ps.getGlobalColor(), _Color);
00542 _Mat.setColor(col);
00543 }
00544 }
00545 }
00546 }
00547
00548
00549
00550 }