Well, we could have put a method template in CPSFanLight, but some compilers want the definition of the methods in the header, and some compilers don't want friend with function template, so we use a static method template of a friend class instead, which gives us the same result :)
Definition at line 68 of file ps_fan_light.cpp.
Static Public Member Functions | |
template<class T, class U> void | drawFanLight (T posIt, U timeIt, CPSFanLight &f, uint size, uint32 srcStep) |
|
Definition at line 72 of file ps_fan_light.cpp. References NL3D::CPSRotated2DParticle::_Angle2D, NL3D::CPSRotated2DParticle::_Angle2DScheme, NL3D::CPSColoredParticle::_ColorScheme, NL3D::CPSMaterial::_Mat, NL3D::CPSFanLight::_MoveIntensity, NL3D::CPSFanLight::_NbFans, NL3D::CPSLocatedBindable::_Owner, NL3D::CPSSizedParticle::_ParticleSize, NL3D::CPSFanLight::_PhaseSmoothness, NL3D::CPSFanLight::_PhaseSpeed, NL3D::CPSFanLight::_RandomPhaseTab, NL3D::CPSFanLight::_RandomPhaseTabInitialized, NL3D::CPSSizedParticle::_SizeScheme, NL3D::IDriver::activeVertexBuffer(), CHECK_VERTEX_BUFFER, NL3D::CPSLocatedBindable::computeI(), NL3D::CPSLocatedBindable::computeK(), NL3D::FanLightBufSize, NL3D::CVertexBuffer::getColorPointer(), NL3D::CPSLocatedBindable::getDriver(), NL3D::CPSFanLight::getNumFanlightsInVB(), NL3D::CPSFanLight::getVBnIB(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexSize(), NL3D::CPSLocated::incrementNbDrawnParticles(), NL3D::CPSAttribMaker< float >::make(), NL3D::CPSAttribMaker< CRGBA >::make(), min, nlassert, PARTICLES_CHECK_MEM, NL3D::IDriver::renderTriangles(), NL3D::CPSLocatedBindable::setupDriverModelMatrix(), sint32, size, stride, NL3D::CPSFanLight::TIndexBuffer, uint, uint32, and uint8.
00073 { 00074 PARTICLES_CHECK_MEM; 00075 nlassert(f._RandomPhaseTabInitialized); 00076 // 00077 f.setupDriverModelMatrix(); 00078 const CVector I = f.computeI(); 00079 const CVector K = f.computeK(); 00080 // 00081 CVertexBuffer *vb; 00082 CPSFanLight::TIndexBuffer *ib; 00083 // get (and build if necessary) the vb and the ib 00084 f.getVBnIB(vb, ib); 00085 IDriver *driver = f.getDriver(); 00086 driver->activeVertexBuffer(*vb); 00087 const uint maxNumFanLightToDealWith = std::min(FanLightBufSize, f.getNumFanlightsInVB()); 00088 uint8 *randomPhaseTab = &f._RandomPhaseTab[f._PhaseSmoothness][0]; 00089 f._Owner->incrementNbDrawnParticles(size); // for benchmark purpose 00090 float pSizes[FanLightBufSize]; 00091 float pAngles[FanLightBufSize]; 00092 T endPosIt; 00093 00094 sint32 k; // helps to count the fans 00095 00096 00097 // if so, we need to deal process separatly group of particles 00098 const uint32 stride = vb->getVertexSize(); 00099 00100 float currentAngle; 00101 const float angleStep = 256.0f / f._NbFans; 00102 00103 00104 float *currentSizePt; // it points either the particle constant size, or a size in a table 00105 float *currentAnglePt; // it points either the particle constant angle, or an angle in a table 00106 00107 00108 const uint32 currentSizePtIncrement = f._SizeScheme ? 1 : 0; // increment to get the next size for the size pointer. It is 0 if the size is constant 00109 const uint32 currentAnglePtIncrement = f._Angle2DScheme ? 1 : 0; // increment to get the next angle for the angle pointer. It is 0 if the size is constant 00110 00111 00112 uint leftToDo = size; 00113 do 00114 { 00115 uint8 *ptVect = (uint8 *) vb->getVertexCoordPointer(); 00116 uint toProcess = std::min(leftToDo, maxNumFanLightToDealWith); 00117 // compute individual colors if needed 00118 if (f._ColorScheme) 00119 { 00120 // we change the color at each fan light center 00121 f._ColorScheme->make(f._Owner, size - leftToDo, vb->getColorPointer(), vb->getVertexSize() * (f._NbFans + 2), toProcess, false, srcStep); 00122 } 00123 if (f._SizeScheme) 00124 { 00125 currentSizePt = (float *) (f._SizeScheme->make(f._Owner, size - leftToDo, pSizes, sizeof(float), toProcess, true, srcStep)); 00126 currentSizePt = pSizes; 00127 } 00128 else 00129 { 00130 currentSizePt = &f._ParticleSize; 00131 } 00132 if (f._Angle2DScheme) 00133 { 00134 currentAnglePt = (float *) (f._Angle2DScheme->make(f._Owner, size - leftToDo, pAngles, sizeof(float), toProcess, true, srcStep)); 00135 } 00136 else 00137 { 00138 currentAnglePt = &f._Angle2D; 00139 } 00140 // 00141 float fSize, firstSize, sizeStepBase=0.0, sizeStep; 00142 if (f._PhaseSmoothness) 00143 { 00144 sizeStepBase = 1.f / f._PhaseSmoothness; 00145 } 00146 endPosIt = posIt + toProcess; 00147 for (;posIt != endPosIt; ++posIt, ++timeIt) 00148 { 00149 00150 CHECK_VERTEX_BUFFER(*vb, ptVect); 00151 *(CVector *) ptVect = *posIt; 00152 // the start angle 00153 currentAngle = *currentAnglePt; 00154 const uint8 phaseAdd = (uint8) (f._PhaseSpeed * (*timeIt)); 00155 ptVect += stride; 00156 const float fanSize = *currentSizePt * 0.5f; 00157 const float moveIntensity = f._MoveIntensity * fanSize; 00158 // compute radius & vect for first fan 00159 firstSize = fanSize + (moveIntensity * CPSUtil::getCos(randomPhaseTab[0] + phaseAdd)); 00160 *(CVector *) ptVect = (*posIt) + I * firstSize * (CPSUtil::getCos((sint32) currentAngle)) 00161 + K * firstSize * (CPSUtil::getSin((sint32) currentAngle)); 00162 currentAngle += angleStep; 00163 ptVect += stride; 00164 fSize = firstSize; 00165 // computes other fans 00166 const sint32 upperBound = (sint32) (f._NbFans - f._PhaseSmoothness - 1); 00167 for (k = 1; k <= upperBound; ++k) 00168 { 00169 fSize = fanSize + (moveIntensity * CPSUtil::getCos(randomPhaseTab[k] + phaseAdd)); 00170 *(CVector *) ptVect = (*posIt) + I * fSize * (CPSUtil::getCos((sint32) currentAngle)) 00171 + K * fSize * (CPSUtil::getSin((sint32) currentAngle)); 00172 currentAngle += angleStep; 00173 ptVect += stride; 00174 } 00175 00176 // interpolate radius, so that the fanlight loops correctly 00177 sizeStep = sizeStepBase * (firstSize - fSize); 00178 for (; k <= (sint32) (f._NbFans - 1); ++k) 00179 { 00180 *(CVector *) ptVect = (*posIt) + I * fSize * (CPSUtil::getCos((sint32) currentAngle)) 00181 + K * fSize * (CPSUtil::getSin((sint32) currentAngle)); 00182 currentAngle += angleStep; 00183 ptVect += stride; 00184 fSize += sizeStep; 00185 } 00186 // last fan 00187 *(CVector *) ptVect = (*posIt) + I * firstSize * (CPSUtil::getCos((sint32) *currentAnglePt)) 00188 + K * firstSize * (CPSUtil::getSin((sint32) *currentAnglePt)); 00189 ptVect += stride; 00190 currentSizePt += currentSizePtIncrement; 00191 currentAnglePt += currentAnglePtIncrement; 00192 } 00193 driver->renderTriangles(f._Mat, &((*ib)[0]), toProcess * f._NbFans); 00194 leftToDo -= toProcess; 00195 } 00196 while (leftToDo != 0); 00197 PARTICLES_CHECK_MEM; 00198 } |