39 double fxParticleSystem::_dParticleDensity = 1;
41 laPoint2* fxParticleSystem::_arParticleUV = NULL;
42 unsigned fxParticleSystem::_nCntMax = 0;
44 fxParticleSystem_params::fxParticleSystem_params()
52 gen_linearEmitter = M_FALSE;
54 p_rgb = laColor(255,255,255);
55 p_alpha_filter = 0.005;
69 fxParticleSystem::fxParticleSystem(
void)
72 _bGenEnabled = M_TRUE;
75 _arParticlePos = NULL;
76 _arParticleSize = NULL;
77 _arParticleColors = NULL;
79 _nCnt = _nValidParticles = 0;
82 fxParticleSystem::~fxParticleSystem(
void)
84 if(_particles)
delete [] _particles;
85 if(_arParticlePos)
delete [] _arParticlePos;
86 if(_arParticleSize)
delete [] _arParticleSize;
87 if(_arParticleColors)
delete [] _arParticleColors;
92 void fxParticleSystem::create(fxParticleSystem_params &p)
96 _nCnt = (unsigned)(p.gen_maxcnt*_dParticleDensity);
98 _particles =
new fxParticleSystem_particle [_nCnt];
99 _arParticlePos =
new laPoint3 [_nCnt];
100 _arParticleSize =
new double [_nCnt];
101 _arParticleColors =
new laColor [_nCnt*4];
105 if( _nCntMax < _nCnt )
107 if(_arParticleUV)
delete [] _arParticleUV;
108 _arParticleUV =
new laPoint2 [_nCnt*4];
111 for(
unsigned i=0; i<_nCntMax; i++)
113 _arParticleUV[i*4 + 0] =
laPoint2(0, 0);
114 _arParticleUV[i*4 + 1] =
laPoint2(0, 1);
115 _arParticleUV[i*4 + 2] =
laPoint2(1, 1);
116 _arParticleUV[i*4 + 3] =
laPoint2(1, 0);
122 if(p.ang_var<1) p.ang_var = 1;
124 _nSimGenCnt = (unsigned)((_nCnt/100.0)*p.gen_percent);
126 _nGenCnt = _nSimGenCnt;
130 strcpy(parameters.p_texture, p.p_texture);
132 lnEmitter.build_vec( *
this, laPoint3(parameters.gen_emitter_sz.x(), parameters.gen_emitter_sz.y(), 0) );
141 PROFILE_REN(fxParticleSystem_draw);
142 if(!_bEnabled)
return;
154 glEnable(GL_DEPTH_TEST);
155 glDepthMask(GL_FALSE);
159 if( !texSprite.id() ) texSprite.load(parameters.p_texture,
M_TEX_TMAP);
169 r->
vquadsDraw(_nValidParticles, _arParticleUV, _arParticleColors, M_TRUE, M_TRUE);
174 glEnable(GL_DEPTH_TEST);
175 glDepthMask(GL_TRUE);
181 void fxParticleSystem::animate(laTimer &t)
184 static fxParticleSystem_particle *p;
185 static laPoint3 *ppos;
187 static laColor *pcol;
189 _nValidParticles = 0;
191 if(!_bEnabled)
return;
195 if( _dHoldLeft<t.delta() )
198 _nGenCnt = _nSimGenCnt;
200 else _dHoldLeft -= t.delta();
214 for(
unsigned i=0; i<_nCnt; i++)
217 ppos = _arParticlePos + i;
218 psz = _arParticleSize + i;
219 pcol = _arParticleColors + i*4;
227 if( p->dTTL < t.delta() ) {
231 else _nValidParticles++;
235 p->dTTL -= t.delta();
236 pcol[0][3] = pcol[1][3] = pcol[2][3] = pcol[3][3] = (char)( (p->dTTL/p->dTTL_Total) * parameters.p_rgb[3] );
240 *ppos += t.delta()*p->velocity;
244 p->velocity[0] += t.delta()*((rand()%1000)*(parameters.pv_ramble/1000.0) - parameters.pv_ramble/2);
245 p->velocity[1] += t.delta()*((rand()%1000)*(parameters.pv_ramble/1000.0) - parameters.pv_ramble/2);
249 p->velocity[1] += parameters.p_mass*t.delta();
255 else if( (_nGenCnt>0) && _bGenEnabled )
258 if( (p->bCreatedOnce) && (!parameters.gen_loop))
continue;
262 if(parameters.gen_linearEmitter) lnEmitter.at( (rand()%100)/200.0 + 0.25, ppos );
265 *ppos += ((rand()%100)/100.0 - 0.5) * parameters.gen_emitter_sz * 0.5;
274 f.buildFromAngle( parameters.ang + (rand()%1000)*(parameters.ang_var/1000.0)-parameters.ang_var/2);
276 double speed_randomness = (rand()%1000)*(parameters.pv_speed/1000.0);
278 p->velocity[0] = f.compX()*(parameters.p_speed+speed_randomness);
279 p->velocity[1] = f.compY()*(parameters.p_speed+speed_randomness);
283 *psz = parameters.p_size;
284 if(parameters.pv_size!=0) *psz += (rand()%1000)*(parameters.pv_size/1000);
288 pcol[0] = pcol[1] = pcol[2] = pcol[3] = parameters.p_rgb;
292 double ttl_randomness = (rand()%1000)*(parameters.pv_ttl/1000.0)-parameters.pv_ttl/2;
293 p->dTTL_Total = p->dTTL = parameters.p_ttl + ttl_randomness;
297 p->bValid = p->bCreatedOnce = M_TRUE;
302 if( (_nGenCnt<=0) && (!_bHold))
305 _dHoldLeft = parameters.gen_htime;
310 void fxParticleSystem::destroy()
312 ASSERT(M_FALSE,
"Not implemented");
315 void fxParticleSystem::reset()
317 for(
unsigned i=0; i<_nCnt; i++)
319 _particles[i].bValid = M_FALSE;
320 _particles[i].bCreatedOnce = M_FALSE;
324 void fxParticleSystem_params::load(
class laFileParser *fp)
332 try{ fp->readSectionSeparator(junk); }
catch(
laError& ){
throw laError(
"Section [EMITTER] expected but not found (while parsing '%s')", fp->getFileName()); }
334 if(strcmp(junk,
"EMITTER"))
throw laError(
"Section [EMITTER] expected, [%s] found (while parsing '%s')", junk, fp->getFileName());
336 fp->readDouble(&ang);
337 fp->readDouble(&ang_var);
339 fp->readObj(&gen_emitter_sz);
341 gen_emitter_sz[0] *=
M_UNIT;
342 gen_emitter_sz[1] *=
M_UNIT;
343 gen_emitter_sz[2] *=
M_UNIT;
345 fp->readBool(&gen_loop);
346 fp->readDouble(&gen_maxcnt);
347 fp->readDouble(&gen_percent);
348 fp->readDouble(&gen_htime);
351 try{ fp->readSectionSeparator(junk); }
catch(
laError& ){
throw laError(
"Section [PARTICLE] expected but not found (while parsing '%s')", fp->getFileName()); }
353 if(strcmp(junk,
"PARTICLE"))
throw laError(
"Section [PARTICLE] expected, [%s] found (while parsing '%s')", junk, fp->getFileName());
355 fp->readText(p_texture);
357 fp->readDouble(&p_alpha_filter);
359 fp->readDouble(&p_size);
360 fp->readDouble(&p_speed);
361 fp->readDouble(&p_mass);
362 fp->readDouble(&p_ttl);
368 try{ fp->readSectionSeparator(junk); }
catch(
laError& ){
throw laError(
"Section [VARATION] expected but not found (while parsing '%s')", fp->getFileName()); }
370 if(strcmp(junk,
"VARATION"))
throw laError(
"Section [VARATION] expected, [%s] found (while parsing '%s')", junk, fp->getFileName());
372 fp->readDouble(&pv_size);
373 fp->readDouble(&pv_speed);
374 fp->readDouble(&pv_mass);
375 fp->readDouble(&pv_ttl);
376 fp->readDouble(&pv_ramble);
378 if(pv_ttl>=p_ttl) pv_ttl = p_ttl;
386 void fxParticleSystem::ctlRewind(
unsigned nframes,
double fps)
390 for(
unsigned i=0; i<nframes; i++) animate(t);
396 fxParticleSystem_params parameters;
404 fp->readText(strFxFile, M_FALSE);
405 fp->readObj(&pos, M_FALSE);
406 fp->readObj(&size, M_FALSE);
407 fp->readDouble(&ang, M_FALSE);
411 throw laError(
"FX description appears to be corrupted");
415 strcat(strFilePath, strFxFile);
416 fxp.fileOpen(strFilePath);
417 fxp.readObj(¶meters, M_FALSE);
428 void fxParticleSystem::copyStyle(fxParticleSystem* pSource)
430 parameters.p_rgb = pSource->parameters.p_rgb;
431 texSprite = pSource->texSprite;
#define M_UNIT
Unit of 1 meter.
#define M_DIR_FX
Visual effects directory.
virtual void vquadsDraw(unsigned nQuads, laPoint2 *ar_uv=NULL, laColor *ar_color=NULL, M_BOOL bBillboards=M_FALSE, M_BOOL bUseColorArrays=M_FALSE)=0
Draw an array of VQ, starting with the psecified pointers (or the first VQ if null) ...
Virtual interface for the Engine graphics renderer.
virtual double modeBlendFilter(const double &dMinVisisbleAlpha)=0
Set a "blend filter" (cutting out elements with opacity lower than dMinVisisbleAlpha) ...
#define M_TEX_TMAP
Transparent texture with an alpha channel.
void vquadsMakeBillboards(unsigned nQuads, laPoint3 *ar_pos, double *ar_size)
Use camera data to create an array of camera-facing VQ (handy for particle effects) ...