/* wave.c - Wave particle module - Don Yang (uguu.org) v1.01 (9/9/98) 09/02/98: InitWave UninitWave GetWaveParticle GetAllWaveParticles TranslateWave 09/08/98: InitWave: sorted particles 09/09/98: MorphWave GetWaveParticle deleted */ /********************************* Header **********************************/ /* Includes */ #include #include #include #include"particle.h" #include"wave.h" /* Globals */ static int _far *WaveX; static int _far *WaveZ; static int angle, amp1, amp2, shf1, shf2, per1, per2; /* Local prototypes */ void SortWaveParticles(void); /*************************** GetAllWaveParticles *************************** Copy all particle coordinates. * * IN: (global) (WaveX[], WaveZ[]) = source. * (global) angle = rotation angle. * (global) amp1, shf1, per1 = wave 1 (horizontal) parameters. * (global) amp2, shf2, per2 = wave 2 (vertical) parameters. * (particle.c) NumberOfParticles = number of particles. * OUT: (particle.c) (ParticleX[], ParticleY[], ParticleZ[]) = target. */ void GetAllWaveParticles(void) { int i; long rx, rz, c, s, a; /* Copy XZ coordinates */ _fmemcpy(ParticleX, WaveX, NumberOfParticles * sizeof(int)); _fmemcpy(ParticleZ, WaveZ, NumberOfParticles * sizeof(int)); /* Generate Y coordinates */ #ifdef ALLOW_WAVE_ROTATION c = Cosine(angle); /* (particle.h) */ s = Sine(angle); #endif for(i = 0; i < NumberOfParticles; i++) { #ifdef ALLOW_WAVE_ROTATION /* Rotate coordinates */ rx = c * WaveX[i] / SINE_SCALE - s * WaveZ[i] / SINE_SCALE; rz = c * WaveZ[i] / SINE_SCALE + s * WaveX[i] / SINE_SCALE; #else rx = WaveX[i]; rz = WaveZ[i]; #endif /* Get amplititude at point */ rx += SPACE_W * 8 + shf1; rz += SPACE_L * 8 + shf2; a = amp1 * Sine((360 * rx / per1) % 360) / SINE_SCALE; a += amp2 * Sine((360 * rz / per2) % 360) / SINE_SCALE; ParticleY[i] = (int)(-SPACE_H / 2 + a); } } /* GetAllWaveParticles() */ /******************************** InitWave ********************************* Initialize particles. XZ coordinates are distributed evenly on one * plane, while Y coordinates are generated at run time (not * precalculated). * * IN: (particles.c) NumberOfParticles = number of wave particles. * OUT: 0 = success. * (global) (WaveX[], WaveZ[]) = particle coordinates. * (global) angle = 0. * (global) amp1, shf1, per1 = wave 1 (horizontal) parameters. * (global) amp2, shf2, per2 = wave 2 (vertical) parameters. * 1 = not enough memory. */ int InitWave(void) { int i, ix, iz; int x, z, c; /* Allocate memory */ WaveX = _fcalloc((size_t)NumberOfParticles, sizeof(int)); WaveZ = _fcalloc((size_t)NumberOfParticles, sizeof(int)); if( WaveX == NULL || WaveZ == NULL ) { _ffree(WaveX); _ffree(WaveZ); return 1; } /* Generate coordinates */ Factor(NumberOfParticles, &z, &x, &c); /* (particle.c) */ /* Fill grid of coordinates from back to front, then from left to middle, then from right to middle. This produces semi-sorted particles. */ i = 0; for(iz = z - 1; iz >= 0; iz--) { for(ix = 0; ix < x / 2; ix++) { WaveX[i] = (int)((long)ix * (SPACE_W * 2) / (x - 1) - SPACE_W); WaveZ[i] = (int)((long)iz * (SPACE_L * 2) / (z - 1) - SPACE_L); i++; } for(ix = x - 1; ix >= x / 2; ix--) { WaveX[i] = (int)((long)ix * (SPACE_W * 2) / (x - 1) - SPACE_W); WaveZ[i] = (int)((long)iz * (SPACE_L * 2) / (z - 1) - SPACE_L); i++; } } /* Generate leftover particle coordinates */ while( c ) { x = rand() % i; WaveX[i] = WaveX[x]; WaveZ[i] = WaveZ[x]; c--; i++; } /* Initialize wave */ angle = 0; amp1 = amp2 = SPACE_H / AMP_RATIO; per1 = per2 = SPACE_W / PER_RATIO; shf1 = shf2 = 0; return 0; } /* InitWave() */ /******************************** MorphWave ******************************** Blend particle systems. * * IN: frame = current morphing animation frame. * target = end animation frame. * (global) (WaveX[], WaveY[], WaveZ[]) = target. * (global) angle = rotation angle. * (global) amp1, shf1, per1 = wave 1 (horizontal) parameters. * (global) amp2, shf2, per2 = wave 2 (vertical) parameters. * (particle.c) NumberOfParticles = number of particles. * (particle.c) (ParticleX[], ParticleY[], ParticleZ[]) = source. * OUT: (particle.c) (ParticleX[], ParticleY[], ParticleZ[]) updated. */ void MorphWave(int frame, int target) { int i, y; long rx, rz, c, s, a; /* Morph XZ coordinates */ for(i = 0; i < NumberOfParticles; i++) { ParticleX[i] = Morph(ParticleX[i], WaveX[i], frame, target); ParticleZ[i] = Morph(ParticleZ[i], WaveZ[i], frame, target); } /* (particle.h) */ /* Generate/morph Y coordinates */ #ifdef ALLOW_WAVE_ROTATION c = Cosine(angle); /* (particle.h) */ s = Sine(angle); #endif for(i = 0; i < NumberOfParticles; i++) { #ifdef ALLOW_WAVE_ROTATION /* Rotate coordinates */ rx = c * WaveX[i] / SINE_SCALE - s * WaveZ[i] / SINE_SCALE; rz = c * WaveZ[i] / SINE_SCALE + s * WaveX[i] / SINE_SCALE; #else rx = WaveX[i]; rz = WaveZ[i]; #endif /* Get amplititude at point */ rx += SPACE_W * 8 + shf1; rz += SPACE_L * 8 + shf2; a = amp1 * Sine((360 * rx / per1) % 360) / SINE_SCALE; a += amp2 * Sine((360 * rz / per2) % 360) / SINE_SCALE; y = (int)(-SPACE_H / 2 + a); ParticleY[i] = Morph(ParticleY[i], y, frame, target); } } /* MorphWave() */ /***************************** TranslateWave ******************************* Move wave particles. * * IN: (particle.c) NumberOfParticles = number of particles. * (global) angle = rotation angle. * (global) amp1, shf1, per1 = wave 1 (horizontal) parameters. * (global) amp2, shf2, per2 = wave 2 (vertical) parameters. * OUT: (global) (WaveX[], WaveZ[]) = wave coordinates. */ void TranslateWave(void) { static int cAmp1 = SPACE_H / AMP_RATIO, cAmp2 = SPACE_H / AMP_RATIO; static int cPer1 = SPACE_W / PER_RATIO, cPer2 = SPACE_L / PER_RATIO; static int cShf1 = 0, cShf2 = 0; static int tAmp1 = SPACE_H / AMP_RATIO, tAmp2 = SPACE_H / AMP_RATIO; static int tPer1 = SPACE_W / PER_RATIO, tPer2 = SPACE_L / PER_RATIO; static int tShf1 = 0, tShf2 = 0; static int frame1 = 0, frame2 = 0; static int target1 = WAVE_TIME, target2 = WAVE_TIME; /* Rotate waves */ angle = (angle == 359) ? 0 : (angle + 1); /* Change parameters */ amp1 = Morph(cAmp1, tAmp1, frame1, target1); /* (particle.h) */ per1 = Morph(cPer1, tPer1, frame1, target1); shf1 = Morph(cShf1, tShf1, frame1, target1); amp2 = Morph(cAmp2, tAmp2, frame2, target2); per2 = Morph(cPer2, tPer2, frame2, target2); shf2 = Morph(cShf2, tShf2, frame2, target2); frame1++; if( frame1 == target1 ) { frame1 = 0; target1 = rand() % WAVE_ERR + WAVE_TIME; cAmp1 = amp1; cPer1 = per1; cShf1 = shf1; tAmp1 = rand() % (SPACE_H / AMP_RATIO); tPer1 = rand() % (SPACE_W / PER_RATIO / 2) + SPACE_W / PER_RATIO; tShf1 = rand() % (SPACE_L / SHF_RATIO); } frame2++; if( frame2 == target2 ) { frame2 = 0; target2 = rand() % WAVE_ERR + WAVE_TIME; cAmp2 = amp2; cPer2 = per2; cShf2 = shf2; tAmp2 = rand() % (SPACE_H / AMP_RATIO); tPer2 = rand() % (SPACE_W / PER_RATIO / 2) + SPACE_W / PER_RATIO; tShf2 = rand() % (SPACE_L / SHF_RATIO); } } /* TranslateWave() */ /******************************* UninitWave ******************************** Uninitialize (reverses InitWave). * * IN: (global) (WaveX[], WaveZ[]) = wave coordinates. * OUT: None. */ void UninitWave(void) { _ffree(WaveX); _ffree(WaveZ); } /* UninitWave() */