# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

ps_quad.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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 // constant definition   //
00044 
00045 
00046 static const uint dotBufSize = 1024; // size used for point particles batching
00047 
00049 // vertex buffers //
00051 
00053 CVertexBuffer CPSQuad::_VBPos;
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   // tex1 only
00073   &_VBPos, &_VBPosCol, &_VBPosTex1,  &_VBPosTex1Col,
00074   NULL,   NULL,          &_VBPosTex1Anim, &_VBPosTex1AnimCol,
00075   // tex1 & tex2
00076   NULL, NULL, &_VBPosTex1Tex2, &_VBPosTex1ColTex2,
00077   NULL,   NULL,          &_VBPosTex1AnimTex2, &_VBPosTex1AnimColTex2,
00078   // tex2 & !tex1 (invalid)
00079   NULL, NULL, NULL, NULL,
00080   NULL, NULL, NULL, NULL,
00081   // tex2 & !tex1 (invalid)
00082   // tex1 & tex2
00083   NULL, NULL, &_VBPosTex1Tex2Anim, &_VBPosTex1ColTex2Anim,
00084   NULL,   NULL,          &_VBPosTex1AnimTex2Anim, &_VBPosTex1AnimColTex2Anim,
00085 };
00086 
00087 
00088   
00089 
00090 
00092 // CPSQuad implementation       //
00094 
00095 
00098 static void SetupQuadVBTexCoords(CVertexBuffer &vb, uint texCoordSet)
00099 {
00100         nlassert(texCoordSet < 2);
00101         // the size used for buffer can't be higher than quad buf size
00102         // to have too large buffer will broke the cache
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]) // valid vb ?
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]); // get the vb
00196 }
00197 
00199 CPSQuad::CPSQuad(CSmartPtr<ITexture> tex)
00200 {
00201         setTexture(tex);
00202         init();
00203         // we don't init the _IndexBuffer for now, as it will be when resize is called
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         // no vb to setup, now..
00284 /*      if (!_ColorScheme)
00285         {               
00286                 _Mat.setColor(_Color);
00287         }
00288         else
00289         {       
00290                 _Mat.setColor(CRGBA::White);
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 // static func used to fill texture coordinates of quads, with global time
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 // static func used to fill texture coordinates of quads, with local time
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)) // step = 1.0 ?
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                 // compute the colors, each color is replicated 4 times
00391                 _ColorScheme->make4(_Owner, startIndex, vb.getColorPointer(), vb.getVertexSize(), size, srcStep);
00392         }
00393 
00394 
00395         if (_TexGroup) // if it has a constant texture we are sure it has been setupped before...
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                         // for now, we don't make texture index wrapping
00419                         const CTextureGrouped::TFourUV &uvGroup = _TexGroup->getUVQuad((uint32) *currIndex);
00420 
00421                         // copy the 4 uv's for this face
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                         // point the next face
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                 // perform tex1 animation if needed
00443                 if (!_TexGroup) // doesn't work with texGroup enabled
00444                 {
00445                         if (!isAlternateTextureUsed())
00446                         {
00447                                 if (_Tex && (_TexScroll[0].x != 0 || _TexScroll[0].y != 0))
00448                                 {
00449                                         // animation of texture 1 with main speed
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                                         // animation of texture 1 with alternate speed
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                 // perform tex2 animation if needed
00478                 if (!isAlternateTextureUsed())
00479                 {
00480                         if (_Texture2 && (_TexScroll[1].x != 0 || _TexScroll[1].y != 0))
00481                         {
00482                                 // animation of texture 2 with main speed
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                                 // animation of texture 2 with alternate speed
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 } // NL3D