00001
00002
00003 #define MODULE_PARTICLES
00004
00005 #include "render.h"
00006 #include "..\shaders\shaders.h"
00007 #include "..\gl2.h"
00008
00009 extern int RENDERBUFFER_WIDTH;
00010 extern int RENDERBUFFER_HEIGHT;
00011 extern int TEXTUREBUFFER_WIDTH;
00012 extern int TEXTUREBUFFER_HEIGHT;
00013 extern GLuint g_check_texture;
00014 extern GLuint g_map_texture;
00015 extern GLuint g_ref_texture;
00016 extern GLuint g_bump_texture;
00017 extern GLuint g_tran_texture;
00018 extern GLuint g_movie_texture;
00019 extern GLuint g_env_texture;
00020 extern GLuint g_envB_texture;
00021 extern GLuint g_envN_texture;
00022 extern GLuint g_noise_texture;
00023 extern GLuint g_env3D_texture;
00024 extern GLuint g_sky_texture;
00025
00026 extern double DepthScalingGL,FrontDepthGL,BackDepthGL;
00027
00028 extern char gszHomeDir[];
00029 extern double GlobalScale;
00030
00031 #include "particles.h"
00032
00033
00034 #define Clamp(x, min, max) x = (x<min ? min : x<max ? x : max);
00035
00036 #define RAND_N ((float)(rand())/(float)(RAND_MAX))
00037
00038 #define FRAME_TIME 0.04 // 25ms
00039
00040
00041
00042
00043 #define PARTICLE_SCALE 4096.0
00044 #define SIZE_SCALE 2500.0
00045 static long nParticleImages=NP_IMAGES;
00046 static long ParticleImageSize[NP_IMAGES];
00047 static unsigned char *ParticleImages[NP_IMAGES];
00048 static GLuint g_particle_textures[NP_IMAGES];
00049 static BOOL bParticleImageLoaded=FALSE;
00050
00051 static BOOL InitParticleSystem(ParticleSystem *pPS);
00052 static void UpdateParticleSystem(ParticleSystem *pPS, double fTime);
00053 static BOOL UpdateParticle(Particle *p, double fTimeDelta );
00054 static void InterpolateParticleSystemPosition(ParticleSystem *Ps, double ratio);
00055 static void FreeThisParticle(Particle *p, ParticleSystem *Pp);
00056 static void BlendFrameBufferParticle(double, double, double, double, double, long, long,
00057 Particle *, fullscreenbuffer *, float *);
00058
00059 void LoadParticleImages(void){
00060 int i;
00061 long x,y;
00062 char pfile[256];
00063 for(i=0;i<nParticleImages;i++){
00064 ParticleImages[i]=NULL;
00065 strcpy(pfile,gszHomeDir); strcat(pfile,"PBM_"); strcat(pfile,ParticleList[i]),strcat(pfile,".bmp");
00066
00067 ParticleImages[i]=LoadSystemMAP(FALSE,ParticleBits[i],pfile,&x,&y);
00068 ParticleImageSize[i]=x;
00069
00070 }
00071 bParticleImageLoaded=TRUE;
00072 }
00073
00074 void UnloadParticleImages(void){
00075 int i; for(i=0;i<nParticleImages;i++){
00076 if(ParticleImages[i] != NULL){
00077
00078 X__Free(ParticleImages[i]);
00079 ParticleImages[i]=NULL;
00080 }
00081 }
00082 bParticleImageLoaded=FALSE;
00083 }
00084
00085 void MakeParticleTextures(void){
00086 int i,j,k;
00087 unsigned char *tex,*pi,*po;
00088 long gg;
00089 glGenTextures( nParticleImages, &g_particle_textures[0]);
00090 for(i=0;i<nParticleImages;i++){
00091 glBindTexture(GL_TEXTURE_2D,g_particle_textures[i]);
00092 if(ParticleBits[i]){
00093 glTexImage2D(GL_TEXTURE_2D,0,4,ParticleImageSize[i],ParticleImageSize[i],
00094 0,GL_RGBA,GL_UNSIGNED_BYTE,
00095 (GLvoid *)ParticleImages[i]);
00096 }
00097 else{
00098 if((tex=malloc(ParticleImageSize[i]*ParticleImageSize[i]*4*sizeof(unsigned char))) != NULL){
00099 pi=ParticleImages[i]; po=tex;
00100 for(j=0;j<ParticleImageSize[i];j++){
00101 for(k=0;k<ParticleImageSize[i];k++){
00102 *po++ = *pi++;
00103 *po++ = gg= *pi++;
00104 *po++ = *pi++;
00105 *po++ = (unsigned char)(min(255,gg*2));
00106 }
00107 }
00108
00109 if(tex != NULL)glTexImage2D(GL_TEXTURE_2D,0,4,ParticleImageSize[i],ParticleImageSize[i],
00110 0,GL_RGBA,GL_UNSIGNED_BYTE,
00111 (GLvoid *)tex);
00112 free(tex);
00113 }
00114 }
00115 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00116 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00117 }
00118 glBindTexture(GL_TEXTURE_2D,0);
00119 }
00120
00121 void ReleaseParticleTextures(void){
00122
00123 glDeleteTextures(nParticleImages,g_particle_textures);
00124 }
00125
00126 void SetUpSingleParticle(ParticleSystem *ps){
00127 double mr,particle_transformation[4][4],trinv[4][4];
00128 vector Zero_Vector,dc;
00129 int i;
00130 Particle *p;
00131 ps->Rate=0;
00132 InitParticleSystem(ps);
00133 if(ps->particles == NULL)return;
00134 ps->NumP=1;
00135 MakeObjectTransformation(ps->dPhi,ps->dTheta,ps->dAlpha,
00136 ps->im, ps->ima,
00137 ps->sx,ps->sy,ps->sz,
00138 Zero_Vector,ps->pin,
00139 particle_transformation,ps->particle_object_transformation,trinv);
00140 p=&ps->particles[0];
00141 p->fAge=1.0;
00142 mr=ps->mratio;
00143 if(mr > 0.5)mr = (1.0-mr)*2.0;
00144 else mr *= 2.0;
00145
00146 p->fAlpha = ps->fAlphaStart+(ps->fAlphaEnd - ps->fAlphaStart)*mr;
00147 VECSUB(ps->vColorEnd,ps->vColorStart,dc)
00148 VECCOPY(ps->vColorStart,p->c)
00149 VECSUM(p->c,mr*dc,p->c)
00150 p->fSize = ps->fSizeStart+(ps->fSizeEnd - ps->fSizeStart)*mr;
00151
00152 R_m4by4(ViewTransform,ps->particle_object_transformation,particle_transformation);
00153 R_m4by1(particle_transformation,
00154 p->p[0]*PARTICLE_SCALE,p->p[1]*PARTICLE_SCALE,p->p[2]*PARTICLE_SCALE,
00155 &p->pfx[0],&p->pfx[1],&p->pfx[2]);
00156 }
00157
00158 void SetUpParticles(ParticleSystem *ps){
00159 double frame_time,time,delta_time=0.01,time_burst,time_burst_interval,time_burst_pulse;
00160 double particle_transformation[4][4],trinv[4][4];
00161 vector Zero_Vector;
00162 int i,steps,np;
00163 Particle *p;
00164
00165
00166 InitParticleSystem(ps);
00167
00168 frame_time=ps->dframe*FRAME_TIME;
00169 if(ps->bSteadyState)frame_time += ps->fLifeTime;
00170
00171 steps=(int)(frame_time/delta_time);
00172 steps=max(steps,1);
00173
00174 srand((unsigned int)ps->NumP);
00175 if(ps->bBurst){
00176 time_burst=0.0;
00177 time_burst_interval = 1.100*ps->fLifeTime;
00178 time_burst_pulse = 0.075*ps->fLifeTime;
00179 }
00180 ps->bSuppress=FALSE;
00181 time=0.0;
00182 if(!ps->bSpinOff)MakeObjectTransformation(ps->dPhi,ps->dTheta,ps->dAlpha,
00183 ps->im, ps->ima,
00184 ps->sx,ps->sy,ps->sz,
00185 Zero_Vector,ps->pin,
00186 particle_transformation,ps->particle_object_transformation,trinv);
00187
00188 for(i=0;i<steps;i++){
00189 if(ps->bSpinOff){
00190 InterpolateParticleSystemPosition(ps,((double)i/(double)steps));
00191 MakeObjectTransformation(ps->tdPhi,ps->tdTheta,ps->tdAlpha,
00192 ps->tim, ps->tima,
00193 ps->tsx,ps->tsy,ps->tsz,
00194 Zero_Vector,ps->tpin,
00195 particle_transformation,ps->particle_object_transformation,trinv);
00196
00197 }
00198 if(ps->bBurst){
00199 if(time_burst < time_burst_interval){
00200 if(time_burst < time_burst_pulse)ps->bSuppress=FALSE;
00201 else ps->bSuppress=TRUE;
00202 time_burst += delta_time;
00203 }
00204 else time_burst = 0.0;
00205 }
00206 UpdateParticleSystem(ps,time);
00207 time += delta_time;
00208
00209 }
00210 np=ps->NumP;
00211 if(!ps->bSpinOff){
00212 R_m4by4(ViewTransform,ps->particle_object_transformation,particle_transformation);
00213 for(i=0;i<np;i++){
00214 p=&ps->particles[i];
00215 if(p->fAge < 0.0)continue;
00216 R_m4by1(particle_transformation,
00217 p->p[0]*PARTICLE_SCALE,p->p[1]*PARTICLE_SCALE,p->p[2]*PARTICLE_SCALE,
00218 &p->pfx[0],&p->pfx[1],&p->pfx[2]);
00219 }
00220 }
00221 else{
00222 for(i=0;i<np;i++){
00223 p=&ps->particles[i];
00224 if(p->fAge < 0.0)continue;
00225 R_m4by1(ViewTransform,p->p[0],p->p[1],p->p[2],&p->pfx[0],&p->pfx[1],&p->pfx[2]);
00226 }
00227 }
00228 }
00229
00230 static BOOL InitParticleSystem(ParticleSystem *pPS){
00231 int i;
00232 double s;
00233
00234 pPS->bSuppress=FALSE;
00235 pPS->fTimeLastUpdate = 0.0;
00236 pPS->fEmissionResidue = 0.0;
00237 pPS->vLocation[0] = pPS->vLocation[1] = pPS->vLocation[2] = 0.0;
00238 pPS->vPrevLocation[0] = pPS->vPrevLocation[1] = pPS->vPrevLocation[2] = 0.0;
00239 pPS->vTempVelocity[0] = pPS->vTempVelocity[1] = pPS->vTempVelocity[2] = 0.0;
00240
00241 pPS->vColorStart[0] = (double)(pPS->colour_start[0])/255.0;
00242 pPS->vColorStart[1] = (double)(pPS->colour_start[1])/255.0;
00243 pPS->vColorStart[2] = (double)(pPS->colour_start[2])/255.0;
00244 pPS->vColorEnd[0] = (double)(pPS->colour_end[0])/255.0;
00245 pPS->vColorEnd[1] = (double)(pPS->colour_end[1])/255.0;
00246 pPS->vColorEnd[2] = (double)(pPS->colour_end[2])/255.0;
00247 pPS->vColorVar[0] = (double)(pPS->vcolour)*0.001;
00248 pPS->vColorVar[1] = (double)(pPS->vcolour)*0.001;
00249 pPS->vColorVar[2] = (double)(pPS->vcolour)*0.001;
00250 pPS->fAlphaStart = (double)(pPS->alpha_start)*0.001;
00251 pPS->fAlphaVar = (double)(pPS->valpha)*0.001;
00252 pPS->fAlphaEnd = (double)(pPS->alpha_end)*0.001;
00253 pPS->fSizeStart = (double)(pPS->size_start)*0.001*MAX_SIZE; pPS->fSizeStart=max(0.1,pPS->fSizeStart);
00254 pPS->fSizeVar = (double)(pPS->vsize)*0.001*MAX_SIZE;
00255 pPS->fSizeEnd = (double)(pPS->size_end)*0.001*MAX_SIZE; pPS->fSizeEnd=max(0.1,pPS->fSizeEnd);
00256 pPS->fSpeed = (double)(pPS->speed)*0.001*MAX_SPEED;
00257 pPS->fSpeedVar = (double)(pPS->vspeed)*0.001*MAX_SPEED/10.0;
00258 pPS->fTheta = (double)(pPS->theta)*0.001;
00259 pPS->fLifeTime = (double)(pPS->life)*0.001*MAX_LIFETIME; pPS->fLifeTime=max(0.1,pPS->fLifeTime);
00260 pPS->fLifeVar = (double)(pPS->vlife)*0.001*MAX_LIFETIME;
00261 pPS->vGravityStart[0] = (double)(pPS->ew_start)*0.001*(MAX_GRAVITY-MIN_GRAVITY);
00262 pPS->vGravityStart[1] = (double)(pPS->ns_start)*0.001*(MAX_GRAVITY-MIN_GRAVITY);
00263 pPS->vGravityStart[2] = (double)(pPS->ud_start)*0.001*(MAX_GRAVITY-MIN_GRAVITY);
00264 pPS->vGravityEnd[0] = (double)(pPS->ew_end)*0.001*(MAX_GRAVITY-MIN_GRAVITY);
00265 pPS->vGravityEnd[1] = (double)(pPS->ns_end)*0.001*(MAX_GRAVITY-MIN_GRAVITY);
00266 pPS->vGravityEnd[2] = (double)(pPS->ud_end)*0.001*(MAX_GRAVITY-MIN_GRAVITY);
00267 s=(double)(pPS->particle_size_scale)*0.001;
00268 if(s < 0.5){
00269 s=1.0+(0.5-s)*2.0*9.0;
00270 s=1.0/s;
00271 }
00272 else {
00273 s=1.0+((s-0.5)*2.0*9.0);
00274 }
00275 pPS->fSizeScale = s;
00276 pPS->fGravityVar = 0.00f;
00277 pPS->uParticlesPerSec = pPS->Rate;
00278 pPS->NumP=(long)((double)pPS->Rate*pPS->fLifeTime*10.0);
00279 pPS->NumP=max(pPS->NumP,1);
00280 #if 0
00281 if(debug != NULL){
00282 fprintf(debug,"iid=%ld name=[%s] [%s]\n",pPS->iid,ParticleList[pPS->iid],pPS->ImageName);
00283 fprintf(debug,"%lf\n",pPS->vColorStart[0]);
00284 fprintf(debug,"%lf\n",pPS->vColorStart[1]);
00285 fprintf(debug,"%lf\n",pPS->vColorStart[2]);
00286 fprintf(debug,"%lf\n",pPS->vColorEnd[0]);
00287 fprintf(debug,"%lf\n",pPS->vColorEnd[1]);
00288 fprintf(debug,"%lf\n",pPS->vColorEnd[2]);
00289 fprintf(debug,"Color Var %lf\n",pPS->vColorVar[0]);
00290 fprintf(debug,"Rate %ld\n",pPS->uParticlesPerSec);
00291 fprintf(debug,"NumP %ld\n",pPS->NumP);
00292 fprintf(debug,"AS %lf\n",pPS->fAlphaStart);
00293 fprintf(debug,"AV %lf\n",pPS->fAlphaVar);
00294 fprintf(debug,"AE %lf\n",pPS->fAlphaEnd);
00295 fprintf(debug,"size %lf\n",pPS->fSizeStart);
00296 fprintf(debug,"size var %lf\n",pPS->fSizeVar);
00297 fprintf(debug,"size end %lf\n",pPS->fSizeEnd);
00298 fprintf(debug,"speed %lf\n",pPS->fSpeed);
00299 fprintf(debug,"speed var %lf\n",pPS->fSpeedVar);
00300 fprintf(debug,"theta %lf\n",pPS->fTheta);
00301 fprintf(debug,"lifetime %lf\n",pPS->fLifeTime);
00302 fprintf(debug,"life var%lf\n",pPS->fLifeVar);
00303 fprintf(debug,"particle size scale %lf\n",pPS->fSizeScale);
00304 fprintf(debug,"Gravity\n");
00305 fprintf(debug,"s %lf\n",pPS->vGravityStart[0]);
00306 fprintf(debug,"s %lf\n",pPS->vGravityStart[1]);
00307 fprintf(debug,"s %lf\n",pPS->vGravityStart[2]);
00308 fprintf(debug,"e %lf\n",pPS->vGravityEnd[0]);
00309 fprintf(debug,"e %lf\n",pPS->vGravityEnd[1]);
00310 fprintf(debug,"e %lf\n",pPS->vGravityEnd[2]);
00311 }
00312 #endif
00313 if(pPS->NumP > 0){
00314 pPS->particles=(Particle *)X__Malloc(pPS->NumP*sizeof(Particle));
00315 for(i=0;i<pPS->NumP;i++){
00316 pPS->particles[i].fAge = -1.0;
00317 }
00318 }
00319 else pPS->particles=NULL;
00320 return (TRUE);
00321 }
00322
00323
00324
00325
00326 static void UpdateParticleSystem(ParticleSystem *pPS, double fTime){
00327 int i;
00328 vector vLocation;
00329 double fTimeDelta;
00330 double fParticlesNeeded;
00331 double RandomYaw;
00332 double RandomPitch;
00333 double fNewSpeed;
00334 unsigned int uParticlesCreated,uParticlesAlive;
00335 Particle *pP;
00336 fTimeDelta = fTime - pPS->fTimeLastUpdate;
00337 pPS->fTimeLastUpdate = fTime;
00338 vLocation[0] = 0.0f;
00339 vLocation[1] = 0.0f;
00340 vLocation[2] = 0.0f;
00341 uParticlesAlive = 0;
00342 pP = pPS->particles;
00343 if(pP == NULL)return;
00344 for(i=0;i<pPS->NumP;i++){
00345 if (pP[i].fAge >= 0.0f ){
00346 if(UpdateParticle(&(pP[i]),fTimeDelta ))uParticlesAlive++;
00347 }
00348 }
00349 fParticlesNeeded = pPS->uParticlesPerSec * fTimeDelta + pPS->fEmissionResidue;
00350 if(pPS->bSuppress){
00351 uParticlesCreated = 0;
00352 pPS->fEmissionResidue = 0.0;
00353 }
00354 else{
00355 uParticlesCreated = (unsigned int)fParticlesNeeded;
00356 pPS->fEmissionResidue = fParticlesNeeded - uParticlesCreated;
00357 }
00358
00359 if (uParticlesCreated > 0 ) {
00360 for (i=0; i<pPS->NumP; i++ ){
00361 if(!uParticlesCreated)break;
00362 if( pP[i].fAge < 0.0f ) {
00363 pP[i].fAge = 0.0f;
00364 pP[i].fLifetime = pPS->fLifeTime+RAND_N * pPS->fLifeVar;
00365 Clamp( pP[i].fLifetime, MIN_LIFETIME, MAX_LIFETIME );
00366 pP[i].fAlpha = pPS->fAlphaStart + RAND_N * pPS->fAlphaVar;
00367 Clamp( pP[i].fAlpha, MIN_ALPHA, MAX_ALPHA );
00368 pP[i].fAlphaDelta = (pPS->fAlphaEnd - pP[i].fAlpha) / pP[i].fLifetime;
00369 pP[i].c[0] = pPS->vColorStart[0] + RAND_N * pPS->vColorVar[0];
00370 pP[i].c[1] = pPS->vColorStart[1] + RAND_N * pPS->vColorVar[1];
00371 pP[i].c[2] = pPS->vColorStart[2] + RAND_N * pPS->vColorVar[2];
00372 Clamp( pP[i].c[0], 0.0f, 1.0f );
00373 Clamp( pP[i].c[1], 0.0f, 1.0f );
00374 Clamp( pP[i].c[2], 0.0f, 1.0f );
00375 pP[i].dc[0]=((pPS->vColorEnd[0]+RAND_N*pPS->vColorVar[0])-pP[i].c[0])/pP[i].fLifetime;
00376 pP[i].dc[1]=((pPS->vColorEnd[1]+RAND_N*pPS->vColorVar[1])-pP[i].c[1])/pP[i].fLifetime;
00377 pP[i].dc[2]=((pPS->vColorEnd[2]+RAND_N*pPS->vColorVar[2])-pP[i].c[2])/pP[i].fLifetime;
00378 pP[i].fSize= pPS->fSizeStart + RAND_N * pPS->fSizeVar;
00379 Clamp( pP[i].fSize, MIN_SIZE, MAX_SIZE );
00380 pP[i].fSizeDelta = (pPS->fSizeEnd - pP[i].fSize) / pP[i].fLifetime;
00381 pP[i].g[0]=pPS->vGravityStart[0]*GRAVITY+RAND_N*pPS->fGravityVar*GRAVITY;
00382 Clamp( pP[i].g[0], MIN_GRAVITY*GRAVITY, MAX_GRAVITY*GRAVITY );
00383 pP[i].g[1]=pPS->vGravityStart[1]*GRAVITY+RAND_N*pPS->fGravityVar*GRAVITY;
00384 Clamp( pP[i].g[1], MIN_GRAVITY*GRAVITY, MAX_GRAVITY*GRAVITY );
00385 pP[i].g[2]=pPS->vGravityStart[2]*GRAVITY+RAND_N*pPS->fGravityVar*GRAVITY;
00386 Clamp( pP[i].g[2], MIN_GRAVITY*GRAVITY, MAX_GRAVITY*GRAVITY );
00387 pP[i].dg[0] = ( pPS->vGravityEnd[0]*GRAVITY - pP[i].g[0] ) / pP[i].fLifetime;
00388 pP[i].dg[1] = ( pPS->vGravityEnd[1]*GRAVITY - pP[i].g[1] ) / pP[i].fLifetime;
00389 pP[i].dg[2] = ( pPS->vGravityEnd[2]*GRAVITY - pP[i].g[2] ) / pP[i].fLifetime;
00390 pPS->vTempVelocity[0] = (pPS->vLocation[0] - pPS->vPrevLocation[0])/fTimeDelta;
00391 pPS->vTempVelocity[1] = (pPS->vLocation[1] - pPS->vPrevLocation[1])/fTimeDelta;
00392 pPS->vTempVelocity[2] = (pPS->vLocation[2] - pPS->vPrevLocation[2])/fTimeDelta;
00393 pP[i].p[0] = pPS->vPrevLocation[0];
00394 pP[i].p[1] = pPS->vPrevLocation[1];
00395 pP[i].p[2] = pPS->vPrevLocation[2];
00396 pP[i].pl[0] = pP[i].p[0];
00397 pP[i].pl[1] = pP[i].p[1];
00398 pP[i].pl[2] = pP[i].p[2];
00399 RandomYaw = RAND_N * 3.14159f * 2.0f;
00400 RandomPitch = RAND_N * pPS->fTheta * 3.14159f;
00401 pP[i].v[2] = cos( RandomPitch );
00402 pP[i].v[0] = sin(RandomPitch) * cos(RandomYaw);
00403 pP[i].v[1] = sin(RandomPitch) * sin(RandomYaw);
00404 fNewSpeed = pPS->fSpeed + RAND_N * pPS->fSpeedVar;
00405 Clamp( fNewSpeed, MIN_SPEED, MAX_SPEED );
00406 pP[i].v[0] *= fNewSpeed ;
00407 pP[i].v[1] *= fNewSpeed ;
00408 pP[i].v[2] *= fNewSpeed ;
00409 if(pPS->bSpinOff)FreeThisParticle(&(pP[i]),pPS);
00410 else pP[i].bSpin=FALSE;
00411 uParticlesCreated--;
00412 }
00413 }
00414 }
00415 VECCOPY(pPS->vLocation,pPS->vPrevLocation)
00416 }
00417
00418
00419 static BOOL UpdateParticle(Particle *p, double fTimeDelta ){
00420 if ( p->fAge + fTimeDelta >= p->fLifetime ) {
00421 p->fAge = -1.0f;
00422 return FALSE;
00423 }
00424 else{
00425 p->fAge += fTimeDelta;
00426 VECCOPY(p->p,p->pl)
00427 VECSUM(p->p,fTimeDelta*p->v,p->p)
00428 VECSUM(p->v,9.8*fTimeDelta*p->g,p->v)
00429 p->fAlpha += p->fAlphaDelta * fTimeDelta;
00430 VECSUM(p->c,fTimeDelta*p->dc,p->c)
00431 p->fSize += p->fSizeDelta * fTimeDelta;
00432 VECSUM(p->g,fTimeDelta*p->dg,p->g)
00433 if(p->bSpin && R_Nground > 0){
00434 if(p->p[2] < Ground.pin[2]){
00435 p->p[2]=Ground.pin[2];
00436 p->v[2] = -0.5*p->v[2];
00437 }
00438 }
00439 }
00440 return TRUE;
00441 }
00442
00443
00444 static void FreeThisParticle(Particle *p, ParticleSystem *Pp){
00445
00446
00447
00448 vector t;
00449 p->bSpin=TRUE;
00450 R_m4by1(Pp->particle_object_transformation,
00451 p->p[0]*PARTICLE_SCALE,p->p[1]*PARTICLE_SCALE,p->p[2]*PARTICLE_SCALE,
00452 &t[0],&t[1],&t[2]);
00453 VECCOPY(t,p->p);
00454 R_m3by1(Pp->particle_object_transformation,
00455 p->v[0]*PARTICLE_SCALE,p->v[1]*PARTICLE_SCALE,p->v[2]*PARTICLE_SCALE,
00456 &t[0],&t[1],&t[2]);
00457 VECCOPY(t,p->v);
00458 #if 0
00459
00460 R_m3by1(Pp->particle_object_transformation,
00461 p->g[0]*PARTICLE_SCALE,p->g[1]*PARTICLE_SCALE,p->g[2]*PARTICLE_SCALE,
00462 &t[0],&t[1],&t[2]);
00463 VECCOPY(t,p->g);
00464 R_m3by1(Pp->particle_object_transformation,
00465 p->dg[0]*PARTICLE_SCALE,p->dg[1]*PARTICLE_SCALE,p->dg[2]*PARTICLE_SCALE,
00466 &t[0],&t[1],&t[2]);
00467 VECCOPY(t,p->dg);
00468 #else
00469 VECSCALE(PARTICLE_SCALE,p->g,p->g)
00470 VECSCALE(PARTICLE_SCALE,p->dg,p->dg)
00471 #endif
00472
00473 }
00474
00475 static void InterpolateParticleSystemPosition(ParticleSystem *Ps, double ratio){
00476 double dp;
00477 vector dv;
00478 dp = Ps->dPhi - Ps->sdPhi;
00479 if(dp < -180.0)dp += 360.0;
00480 if(dp > 180.0)dp -= 360.0;
00481 dp *= ratio;
00482 dp += Ps->sdPhi;
00483 if(dp < -180.0)dp += 360.0;
00484 if(dp > 180.0)dp -= 360.0;
00485 Ps->tdPhi = dp;
00486 dp = Ps->dAlpha - Ps->sdAlpha;
00487 if(dp < -180.0)dp += 360.0;
00488 if(dp > 180.0)dp -= 360.0;
00489 dp *= ratio;
00490 dp += Ps->sdAlpha;
00491 if(dp < -180.0)dp += 360.0;
00492 if(dp > 180.0)dp -= 360.0;
00493 Ps->tdAlpha = dp;
00494 dp = Ps->dTheta - Ps->sdTheta;
00495 if(dp < -180.0)dp += 360.0;
00496 if(dp > 180.0)dp -= 360.0;
00497 dp *= ratio;
00498 dp += Ps->sdTheta;
00499 if(dp < -180.0)dp += 360.0;
00500 if(dp > 180.0)dp -= 360.0;
00501 Ps->tdTheta = dp;
00502 VECSUB(Ps->pin,Ps->spin,dv)
00503 VECSCALE(ratio,dv,dv)
00504 VECSUM(Ps->spin,dv,Ps->tpin)
00505 Ps->tsx=(Ps->sx-Ps->ssx)*ratio+Ps->ssx;
00506 Ps->tsy=(Ps->sx-Ps->ssy)*ratio+Ps->ssy;
00507 Ps->tsz=(Ps->sx-Ps->ssz)*ratio+Ps->ssz;
00508 }
00509
00510 static void DrawParticleSystemGL(BOOL clip, ParticleSystem *Ps){
00511 int np,i;
00512 Particle *p;
00513 GLfloat xc,yc,zc;
00514 GLfloat psize;
00515 np=Ps->NumP;
00516 if(np < 1 || Ps->particles == NULL)return;
00517 if(R_Nground > 0){
00518 GLdouble GroundClip[4];
00519 GroundClip[0]=-Ground.n[0]; GroundClip[1]=-Ground.n[2]; GroundClip[2]=Ground.n[1];
00520 GroundClip[3]=DOT(Ground.n,Ground.p)*GlobalScale;
00521 glEnable(GL_CLIP_PLANE0);
00522 glClipPlane(GL_CLIP_PLANE0,GroundClip);
00523 }
00524 glBindTexture(GL_TEXTURE_2D,g_particle_textures[Ps->iid]);
00525 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00526 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00527 glEnable(GL_BLEND);
00528 if(Ps->blend_type == 1)glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
00529 else glBlendFunc(GL_SRC_ALPHA,GL_ONE);
00530 glDepthMask(GL_FALSE);
00531 glBegin(GL_QUADS);
00532 for(i=0;i<np;i++){
00533 p=&Ps->particles[i];
00534 if(p->fAge < 0.0)continue;
00535 if(p->pfx[1] < 0.0)continue;
00536 glColor4f(p->c[0],p->c[1],p->c[2],p->fAlpha);
00537 xc = (p->pfx[0])*GlobalScale;
00538 yc = (p->pfx[2])*GlobalScale;
00539 zc = -(p->pfx[1])*GlobalScale;
00540 psize=p->fSize*SIZE_SCALE*PARTICLE_SCALE/p->pfx[1]*Ps->sx*Ps->fSizeScale;
00541 glTexCoord2f(1.0f, 1.0f); glVertex3f(xc+psize, yc+psize, zc);
00542 glTexCoord2f(0.0f, 1.0f); glVertex3f(xc-psize, yc+psize, zc);
00543 glTexCoord2f(0.0f, 0.0f); glVertex3f(xc-psize, yc-psize, zc);
00544 glTexCoord2f(1.0f, 0.0f); glVertex3f(xc+psize, yc-psize, zc);
00545 }
00546 glEnd();
00547 glDepthMask(GL_TRUE);
00548 glDisable(GL_BLEND);
00549 glBindTexture(GL_TEXTURE_2D,0);
00550 if(R_Nground > 0)glDisable(GL_CLIP_PLANE0);
00551 }
00552
00553 void RenderParticlesGL(BOOL clip){
00554 int i;
00555 for(i=0;i<Nparticles;i++){
00556 DrawParticleSystemGL(clip,&(ParticleS[i]));
00557 }
00558 }
00559
00560 static void DrawParticleSystem(ParticleSystem *Ps){
00561 int np,i,ix,iy;
00562 Particle *p;
00563 GLfloat xc,yc,zc;
00564 GLfloat psize;
00565 fullscreenbuffer *S;
00566 float *Z;
00567 double Xscale,Yscale,xxl,yyt,xxr,yyb;
00568 np=Ps->NumP;
00569 if(np < 1 || Ps->particles == NULL)return;
00570 S=FullScreenBuffer;
00571 Z=fszBuffer;
00572 Xscale=scalex; Yscale=scaley;
00573 if(anti_alias == LOW) {Xscale /= 2;}
00574 if(anti_alias == MEDIUM){Xscale /= 2; Yscale /= 2;}
00575 if(anti_alias == HIGH) {Xscale /= 3; Yscale /= 2;}
00576 if(anti_alias == ULTRA) {Xscale /= 3; Yscale /= 3;}
00577 for(i=0;i<np;i++){
00578 p=&Ps->particles[i];
00579 if(p->fAge < 0.0)continue;
00580 if(p->pfx[1] < 0.0)continue;
00581 xc = (p->pfx[0]);
00582 yc = (p->pfx[1]);
00583 zc = (p->pfx[2]);
00584 psize=p->fSize*4.8*PARTICLE_SCALE*Ps->sx*Ps->fSizeScale;
00585 xxl=(double)ResolutionX/2.0 + (Xscale*(xc-psize)/yc);
00586 yyt=(double)ResolutionY/2.0 - (Yscale*(zc+psize)/yc);
00587 xxr=(double)ResolutionX/2.0 + (Xscale*(xc+psize)/yc);
00588 yyb=(double)ResolutionY/2.0 - (Yscale*(zc-psize)/yc);
00589
00590
00591
00592 BlendFrameBufferParticle(xxl,yyt,xxr,yyb,yc,Ps->iid,Ps->blend_type,p,S,Z);
00593 }
00594 }
00595
00596 static void BlendFrameBufferPixel(long ix, long iy, double f, double z, double r, double g, double b, double a,
00597 fullscreenbuffer *S, float *Z, long type){
00598 double R,G,B;
00599 if(ix>=0 && ix<ResolutionX && iy>=0 && iy<ResolutionY){
00600 if((float)z<*(Z+(iy*(ResolutionX))+ix)){
00601 R=(double)( (S+(iy*(ResolutionX))+ix)->R);
00602 G=(double)( (S+(iy*(ResolutionX))+ix)->G);
00603 B=(double)( (S+(iy*(ResolutionX))+ix)->B);
00604 if(type == 1){
00605 R=min(255.0, R*(1.0-a) + 255.0*r*f*a);
00606 G=min(255.0, G*(1.0-a) + 255.0*g*f*a);
00607 B=min(255.0, B*(1.0-a) + 255.0*b*f*a);
00608 }
00609 else{
00610 R=min(255.0, R + 255.0*r*f*a);
00611 G=min(255.0, G + 255.0*g*f*a);
00612 B=min(255.0, B + 255.0*b*f*a);
00613 }
00614 (S+(iy*(ResolutionX))+ix)->R=(unsigned char)R;
00615 (S+(iy*(ResolutionX))+ix)->G=(unsigned char)G;
00616 (S+(iy*(ResolutionX))+ix)->B=(unsigned char)B;
00617
00618 }
00619 }
00620 }
00621
00622 static void BlendFrameBufferParticle(double xxl, double yyt, double xxr, double yyb,
00623 double z, long pid, long blend_type, Particle *p, fullscreenbuffer *S, float *Z){
00624 long i,j,ix,iy,xin;
00625 long idx,idy;
00626 double dx,dy,cr,cg,cb,ca,cr0,cg0,cb0,ca0;
00627 unsigned char *image,*simage,*si;
00628 dx=(xxr-xxl);
00629 dy=(yyb-yyt);
00630 idy=(long)dy+1;
00631 idx=(long)dx+1;
00632 dx=xxr-floor(xxr); dy=yyt-floor(yyt);
00633 if((image=ParticleImages[pid]) == NULL)return;
00634 xin=ParticleImageSize[pid];
00635 if(ParticleBits[pid]){
00636 simage=(unsigned char *)X__Malloc(idx*idy*4);
00637 if(simage == NULL)return;
00638 ScaleImageBuffer4(xin,xin,image,idx,idy,simage);
00639 }
00640 else{
00641 simage=(unsigned char *)X__Malloc(idx*idy*3);
00642 if(simage == NULL)return;
00643 ScaleImageBuffer3(xin,xin,image,idx,idy,simage);
00644 }
00645 cr0=p->c[0]/255.0; cg0=p->c[1]/255.0; cb0=p->c[2]/255.0; ca0=p->fAlpha;
00646 si=simage;
00647 iy=(long)yyt; for(i=0;i<idy;i++){
00648 ix=(long)xxl; for(j=0;j<idx;j++){
00649 cr = cr0*(double)(*si++); cg = cg0*(double)(*si++); cb = cb0*(double)(*si++);
00650 if(ParticleBits[pid]) ca = ca0*(double)(*si++)/255.0; else ca=ca0;
00651 BlendFrameBufferPixel(ix,iy,(1.0-dx)*(1.0-dy),z,cr,cg,cb,ca,S,Z,blend_type);
00652 BlendFrameBufferPixel(ix+1,iy,(dx)*(1.0-dy),z,cr,cg,cb,ca,S,Z,blend_type);
00653 BlendFrameBufferPixel(ix,iy+1,(1.0-dx)*(dy),z,cr,cg,cb,ca,S,Z,blend_type);
00654 BlendFrameBufferPixel(ix+1,iy+1,(dx)*(dy),z,cr,cg,cb,ca,S,Z,blend_type);
00655 ix++;
00656 }
00657 iy++;
00658 }
00659 if(simage != NULL)X__Free(simage);
00660 }
00661
00662
00663 void RenderParticles(void){
00664 int i;
00665 for(i=0;i<Nparticles;i++){
00666 DrawParticleSystem(&(ParticleS[i]));
00667 }
00668 }
00669
00670
00672 #if 0
00673 if ((long)xx>=0 && (long)xx<ResolutionX && (long)yy>=0 && (long)yy<ResolutionY){
00674
00675
00676
00677
00678
00679
00680 ix=(long)xx;
00681 iy=(long)yy;
00682 if((float)yc<*(Z+(iy*(ResolutionX))+ix)){
00683 (S+(iy*(ResolutionX))+ix)->R=255;
00684 (S+(iy*(ResolutionX))+ix)->G=255;
00685 (S+(iy*(ResolutionX))+ix)->B=255;
00686
00687 }
00688 }
00689 #endif
00690
00691 #if 0
00692
00693 GLfloat x[16]={-1.0, 1.0, 1.0,-1.0, -1.0, 1.0, 1.0,-1.0, -1.0, 1.0, 1.0,-1.0, -1.0, 1.0, 1.0,-1.0};
00694 GLfloat y[16]={-1.0,-1.0, 1.0, 1.0, -1.0,-1.0, 1.0, 1.0, -1.0,-1.0,-1.0,-1.0, 1.0, 1.0, 1.0, 1.0};
00695 GLfloat z[16]={-1.0,-1.0,-1.0,-1.0, 1.0, 1.0, 1.0, 1.0, -1.0,-1.0, 1.0, 1.0, -1.0,-1.0, 1.0, 1.0};
00696 glBegin(GL_QUADS);
00697 glColor4ub(0,255,255,255);
00698 for(i=0;i<4*4;i++){
00699 glVertex3f( (x[i]*PARTICLE_SCALE+Ps->p[0])*GlobalScale,
00700 (z[i]*PARTICLE_SCALE+Ps->p[2])*GlobalScale,
00701 -(y[i]*PARTICLE_SCALE+Ps->p[1])*GlobalScale);
00702
00703 }
00704 glEnd();
00705
00706 glPointSize(4.0);
00707 glBegin(GL_POINTS);
00708 glColor4ub(0,255,255,255);
00709 for(i=0;i<np;i++){
00710 p=&Ps->particles[i];
00711 if(p->fAge < 0.0)continue;
00712
00713
00714
00715 glVertex3f( (p->pfx[0])*GlobalScale,
00716 (p->pfx[2])*GlobalScale,
00717 -(p->pfx[1])*GlobalScale);
00718 }
00719 glEnd();
00720
00722
00723
00724 m_rParticles[i].m_vVelocity.y = static_cast<float>(cos( RandomPitch ));
00725 m_rParticles[i].m_vVelocity.x = static_cast<float>(sin(RandomPitch) * cos(RandomYaw));
00726 m_rParticles[i].m_vVelocity.z = static_cast<float>(sin(RandomPitch) * sin(RandomYaw));
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 m_rParticles[i].m_vVelocity.x *= m_fSpeed ;
00737 m_rParticles[i].m_vVelocity.y *= m_fSpeed ;
00738 m_rParticles[i].m_vVelocity.z *= m_fSpeed ;
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 pPS->vColorStart[0] = 0.48f;
00761 pPS->vColorStart[1] = 0.42f;
00762 pPS->vColorStart[2] = 0.10f;
00763 pPS->vColorVar[0] = 0.15f;
00764 pPS->vColorVar[1] = 0.15f;
00765 pPS->vColorVar[2] = 0.15f;
00766 pPS->vColorEnd[0] = 0.04f;
00767 pPS->vColorEnd[1] = 0.22f;
00768 pPS->vColorEnd[2] = 0.81f;
00769 pPS->fAlphaStart = 0.92f;
00770 pPS->fAlphaVar = 0.14f;
00771 pPS->fAlphaEnd = 0.14f;
00772 pPS->fSizeStart = 1.04f;
00773 pPS->fSizeVar = 0.04f;
00774 pPS->fSizeEnd = 1.08f;
00775 pPS->fSpeed = 3.00f;
00776 pPS->fSpeedVar = 0.00f;
00777 pPS->fTheta = 0.20f;
00778 pPS->fLifeTime = 0.60f;
00779 pPS->fLifeVar = 0.10f;
00780 pPS->vGravityStart[0] = 0.00f;
00781 pPS->vGravityStart[1] = 0.00f;
00782 pPS->vGravityStart[2] = 0.00f;
00783 pPS->vGravityEnd[0]= 0.00f;
00784 pPS->vGravityEnd[1]= 0.00f;
00785 pPS->vGravityEnd[2]= 0.00f;
00786 pPS->fGravityVar = 0.00f;
00787 pPS->fSizeScale = 1.0;
00788 pPS->uParticlesPerSec = 20;
00789 pPS->NumP=60;
00791
00792 #endif
00793