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_face.h"
00029 #include "3d/ps_macro.h"
00030 #include "3d/driver.h"
00031 #include "3d/ps_iterator.h"
00032 #include "nel/misc/quat.h"
00033
00034
00035
00036 namespace NL3D
00037 {
00038
00039 using NLMISC::CQuat;
00040
00042
00044
00050 class CPSFaceHelper
00051 {
00052 public:
00053 template <class T, class U>
00054 static void drawFaces(T posIt, U indexIt, CPSFace &f, uint size, uint32 srcStep)
00055 {
00056 PARTICLES_CHECK_MEM;
00057 nlassert(f._Owner);
00058 IDriver *driver = f.getDriver();
00059
00060 f.updateMatBeforeRendering(driver);
00061
00062 CVertexBuffer &vb = f.getNeededVB();
00063 uint8 *currVertex;
00064
00065
00066 uint32 leftFaces = size, toProcess;
00067 f._Owner->incrementNbDrawnParticles(size);
00068 f.setupDriverModelMatrix();
00069 driver->activeVertexBuffer(vb);
00070 if (f.isMultiTextureEnabled())
00071 {
00072 f.setupMaterial(f._Tex, driver, f._Mat);
00073 }
00074 float sizeBuf[CPSQuad::quadBufSize];
00075 float *ptSize;
00076 T endPosIt;
00077
00078
00079 uint32 ptSizeIncrement = f._SizeScheme ? 1 : 0;
00080
00081 if (f._PrecompBasis.size())
00082 {
00083 do
00084 {
00085 toProcess = leftFaces > CPSQuad::quadBufSize ? CPSQuad::quadBufSize : leftFaces;
00086 currVertex = (uint8 *) vb.getVertexCoordPointer() ;
00087 if (f._SizeScheme)
00088 {
00089 ptSize = (float *) (f._SizeScheme->make(f._Owner, size - leftFaces, sizeBuf, sizeof(float), toProcess, true, srcStep));
00090 }
00091 else
00092 {
00093 ptSize = &f._ParticleSize;
00094 }
00095 f.updateVbColNUVForRender(vb, size - leftFaces, toProcess, srcStep);
00096 const uint32 stride = vb.getVertexSize();
00097 endPosIt = posIt + toProcess;
00098 do
00099 {
00100 const CPlaneBasis &currBasis = f._PrecompBasis[*indexIt].Basis;
00101 CHECK_VERTEX_BUFFER(vb, currVertex);
00102 ((CVector *) currVertex)->x = (*posIt).x + *ptSize * currBasis.X.x;
00103 ((CVector *) currVertex)->y = (*posIt).y + *ptSize * currBasis.X.y;
00104 ((CVector *) currVertex)->z = (*posIt).z + *ptSize * currBasis.X.z;
00105 currVertex += stride;
00106
00107 CHECK_VERTEX_BUFFER(vb, currVertex);
00108 ((CVector *) currVertex)->x = (*posIt).x + *ptSize * currBasis.Y.x;
00109 ((CVector *) currVertex)->y = (*posIt).y + *ptSize * currBasis.Y.y;
00110 ((CVector *) currVertex)->z = (*posIt).z + *ptSize * currBasis.Y.z;
00111 currVertex += stride;
00112
00113 CHECK_VERTEX_BUFFER(vb, currVertex);
00114 ((CVector *) currVertex)->x = (*posIt).x - *ptSize * currBasis.X.x;
00115 ((CVector *) currVertex)->y = (*posIt).y - *ptSize * currBasis.X.y;
00116 ((CVector *) currVertex)->z = (*posIt).z - *ptSize * currBasis.X.z;
00117 currVertex += stride;
00118
00119 CHECK_VERTEX_BUFFER(vb, currVertex);
00120 ((CVector *) currVertex)->x = (*posIt).x - *ptSize * currBasis.Y.x;
00121 ((CVector *) currVertex)->y = (*posIt).y - *ptSize * currBasis.Y.y;
00122 ((CVector *) currVertex)->z = (*posIt).z - *ptSize * currBasis.Y.z;
00123 currVertex += stride;
00124 ptSize += ptSizeIncrement;
00125 ++indexIt;
00126 ++posIt;
00127 }
00128 while (posIt != endPosIt);
00129 driver->renderQuads(f._Mat, 0, toProcess);
00130 leftFaces -= toProcess;
00131 }
00132 while (leftFaces);
00133 }
00134 else
00135 {
00136
00137 static CPlaneBasis planeBasis[CPSQuad::quadBufSize];
00138 CPlaneBasis *currBasis;
00139 uint32 ptPlaneBasisIncrement = f._PlaneBasisScheme ? 1 : 0;
00140 const uint32 vSize = vb.getVertexSize();
00141 do
00142 {
00143 toProcess = leftFaces > CPSQuad::quadBufSize ? CPSQuad::quadBufSize : leftFaces;
00144 currVertex = (uint8 *) vb.getVertexCoordPointer() ;
00145 if (f._SizeScheme)
00146 {
00147 ptSize = (float *) (f._SizeScheme->make(f._Owner, size - leftFaces, sizeBuf, sizeof(float), toProcess, true, srcStep));
00148 }
00149 else
00150 {
00151 ptSize = &f._ParticleSize;
00152 }
00153
00154 if (f._PlaneBasisScheme)
00155 {
00156 currBasis = (CPlaneBasis *) (f._PlaneBasisScheme->make(f._Owner, size - leftFaces, planeBasis, sizeof(CPlaneBasis), toProcess, true, srcStep));
00157 }
00158 else
00159 {
00160 currBasis = &f._PlaneBasis;
00161 }
00162 f.updateVbColNUVForRender(vb, size - leftFaces, toProcess, srcStep);
00163 endPosIt = posIt + toProcess;
00164 do
00165 {
00166
00167 CHECK_VERTEX_BUFFER(vb, currVertex);
00168 ((CVector *) currVertex)->x = (*posIt).x + *ptSize * currBasis->X.x;
00169 ((CVector *) currVertex)->y = (*posIt).y + *ptSize * currBasis->X.y;
00170 ((CVector *) currVertex)->z = (*posIt).z + *ptSize * currBasis->X.z;
00171 currVertex += vSize;
00172
00173 CHECK_VERTEX_BUFFER(vb, currVertex);
00174 ((CVector *) currVertex)->x = (*posIt).x + *ptSize * currBasis->Y.x;
00175 ((CVector *) currVertex)->y = (*posIt).y + *ptSize * currBasis->Y.y;
00176 ((CVector *) currVertex)->z = (*posIt).z + *ptSize * currBasis->Y.z;
00177 currVertex += vSize;
00178
00179 CHECK_VERTEX_BUFFER(vb, currVertex);
00180 ((CVector *) currVertex)->x = (*posIt).x - *ptSize * currBasis->X.x;
00181 ((CVector *) currVertex)->y = (*posIt).y - *ptSize * currBasis->X.y;
00182 ((CVector *) currVertex)->z = (*posIt).z - *ptSize * currBasis->X.z;
00183 currVertex += vSize;
00184
00185 CHECK_VERTEX_BUFFER(vb, currVertex);
00186 ((CVector *) currVertex)->x = (*posIt).x - *ptSize * currBasis->Y.x;
00187 ((CVector *) currVertex)->y = (*posIt).y - *ptSize * currBasis->Y.y;
00188 ((CVector *) currVertex)->z = (*posIt).z - *ptSize * currBasis->Y.z;
00189 currVertex += vSize;
00190 ptSize += ptSizeIncrement;
00191 ++posIt;
00192 currBasis += ptPlaneBasisIncrement;
00193 }
00194 while (posIt != endPosIt);
00195 driver->renderQuads(f._Mat, 0, toProcess);
00196 leftFaces -= toProcess;
00197 }
00198 while (leftFaces);
00199 }
00200 PARTICLES_CHECK_MEM;
00201 }
00202 };
00203
00205 CPSFace::CPSFace(CSmartPtr<ITexture> tex) : CPSQuad(tex)
00206 {
00207 _Name = std::string("Face");
00208 }
00209
00211 void CPSFace::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime)
00212 {
00213 if (pass == PSToolRender)
00214 {
00215 showTool();
00216 return;
00217 }
00218 else if (pass == PSMotion)
00219 {
00220
00221 if (_PrecompBasis.size())
00222 {
00223
00224 for (std::vector< CPlaneBasisPair >::iterator it = _PrecompBasis.begin(); it != _PrecompBasis.end(); ++it)
00225 {
00226
00227 CMatrix mat;
00228 mat.rotate(CQuat(it->Axis, ellapsedTime * it->AngularVelocity));
00229 CVector n = mat * it->Basis.getNormal();
00230 it->Basis = CPlaneBasis(n);
00231 }
00232 }
00233 return;
00234 }
00235 else
00236 if (!
00237 ( (pass == PSBlendRender && hasTransparentFaces())
00238 || (pass == PSSolidRender && hasOpaqueFaces())
00239 )
00240 )
00241 {
00242 return;
00243 }
00244
00245
00246
00247 if (!_Owner->getSize()) return;
00248 uint32 step;
00249 uint numToProcess;
00250 computeSrcStep(step, numToProcess);
00251 if (!numToProcess) return;
00252
00253
00254 if (step == (1 << 16))
00255 {
00257 std::vector<uint32>::const_iterator indexIt = _IndexInPrecompBasis.begin();
00258
00260 CPSFaceHelper::drawFaces(_Owner->getPos().begin(),
00261 indexIt,
00262 *this,
00263 numToProcess,
00264 step
00265 );
00266 }
00267 else
00268 {
00270 CAdvance1616Iterator<std::vector<uint32>::const_iterator, const uint32>
00271 indexIt(_IndexInPrecompBasis.begin(), 0, step);
00272 CPSFaceHelper::drawFaces(TIteratorVectStep1616(_Owner->getPos().begin(), 0, step),
00273 indexIt,
00274 *this,
00275 numToProcess,
00276 step
00277 );
00278 }
00279
00280 }
00281
00282
00284 void CPSFace::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00285 {
00286 f.serialVersion(1);
00287 CPSQuad::serial(f);
00288 CPSRotated3DPlaneParticle::serialPlaneBasisScheme(f);
00289
00290 if (f.isReading())
00291 {
00292 uint32 nbConfigurations;
00293 f.serial(nbConfigurations);
00294 if (nbConfigurations)
00295 {
00296 f.serial(_MinAngularVelocity, _MaxAngularVelocity);
00297 }
00298 hintRotateTheSame(nbConfigurations, _MinAngularVelocity, _MaxAngularVelocity);
00299
00300 init();
00301 }
00302 else
00303 {
00304 uint32 nbConfigurations = _PrecompBasis.size();
00305 f.serial(nbConfigurations);
00306 if (nbConfigurations)
00307 {
00308 f.serial(_MinAngularVelocity, _MaxAngularVelocity);
00309 }
00310 }
00311 }
00312
00313
00316 static CVector MakeRandomUnitVect(void)
00317 {
00318 CVector v((float) ((rand() % 20000) - 10000)
00319 ,(float) ((rand() % 20000) - 10000)
00320 ,(float) ((rand() % 20000) - 10000)
00321 );
00322 v.normalize();
00323 return v;
00324 }
00325
00327 void CPSFace::hintRotateTheSame(uint32 nbConfiguration
00328 , float minAngularVelocity
00329 , float maxAngularVelocity
00330 )
00331 {
00332 _MinAngularVelocity = minAngularVelocity;
00333 _MaxAngularVelocity = maxAngularVelocity;
00334 _PrecompBasis.resize(nbConfiguration);
00335 if (nbConfiguration)
00336 {
00337
00338 for (uint k = 0; k < nbConfiguration; ++k)
00339 {
00340 CVector v = MakeRandomUnitVect();
00341 _PrecompBasis[k].Basis = CPlaneBasis(v);
00342 _PrecompBasis[k].Axis = MakeRandomUnitVect();
00343 _PrecompBasis[k].AngularVelocity = minAngularVelocity
00344 + (rand() % 20000) / 20000.f * (maxAngularVelocity - minAngularVelocity);
00345
00346 }
00347
00348 fillIndexesInPrecompBasis();
00349 }
00350 }
00351
00353 void CPSFace::fillIndexesInPrecompBasis(void)
00354 {
00355 const uint32 nbConf = _PrecompBasis.size();
00356 if (_Owner)
00357 {
00358 _IndexInPrecompBasis.resize( _Owner->getMaxSize() );
00359 }
00360 for (std::vector<uint32>::iterator it = _IndexInPrecompBasis.begin(); it != _IndexInPrecompBasis.end(); ++it)
00361 {
00362 *it = rand() % nbConf;
00363 }
00364 }
00365
00367 void CPSFace::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
00368 {
00369 CPSQuad::newElement(emitterLocated, emitterIndex);
00370 newPlaneBasisElement(emitterLocated, emitterIndex);
00371 const uint32 nbConf = _PrecompBasis.size();
00372 if (nbConf)
00373 {
00374 _IndexInPrecompBasis[_Owner->getNewElementIndex()] = rand() % nbConf;
00375 }
00376 }
00377
00379 void CPSFace::deleteElement(uint32 index)
00380 {
00381 CPSQuad::deleteElement(index);
00382 deletePlaneBasisElement(index);
00383 if (_PrecompBasis.size())
00384 {
00385
00386 _IndexInPrecompBasis[index] = _IndexInPrecompBasis[_Owner->getSize() - 1];
00387 }
00388 }
00389
00391 void CPSFace::resize(uint32 size)
00392 {
00393 nlassert(size < (1 << 16));
00394 resizePlaneBasis(size);
00395 if (_PrecompBasis.size())
00396 {
00397 _IndexInPrecompBasis.resize(size);
00398 }
00399 CPSQuad::resize(size);
00400 }
00401
00402 }