/* sphere.c - Sphere particle module - Don Yang (uguu.org) v1.1 (9/9/98) 08/31/98: InitSphere UninitSphere GetSphereParticle GetAllSphereParticles TranslateSphere 09/09/98: MorphSphere GetSphereParticle deleted */ /********************************* Header **********************************/ /* Includes */ #include #include #include #include"particle.h" #include"sphere.h" /* Globals */ static int _far *SphereX; static int _far *SphereY; static int _far *SphereZ; static int lon, lat; /************************** GetAllSphereParticles ************************** Get all particle coordinates. * * IN: (global) (SphereX[], SphereY[], SphereZ[]) = source. * (particle.c) NumberOfParticles = number of particles. * OUT: (particle.c) (ParticleX[], ParticleY[], ParticleZ[]) = target. */ void GetAllSphereParticles(void) { Rotate(SphereY, SphereZ, ParticleY, ParticleZ, NumberOfParticles, lat); Rotate(SphereX, ParticleZ, ParticleX, ParticleZ, NumberOfParticles, lon); /* (particle.c) */ } /* GetAllSphereParticles() */ /******************************* InitSphere ******************************** Initialize particles. * * IN: (particles.c) NumberOfParticles = number of sphere points. * OUT: 0 = success. * (global) (SphereX[], SphereY[], SphereZ[]) = particles. * (global) (lon, lat) = (0, 0). * 1 = not enough memory. */ int InitSphere(void) { int x, y, c; int i, ix, iy, lon, lat; long r; /* Allocate memory */ SphereX = _fcalloc((size_t)NumberOfParticles, sizeof(int)); SphereY = _fcalloc((size_t)NumberOfParticles, sizeof(int)); SphereZ = _fcalloc((size_t)NumberOfParticles, sizeof(int)); if( SphereX == NULL || SphereY == NULL || SphereZ == NULL ) { _ffree(SphereX); _ffree(SphereY); _ffree(SphereZ); return 1; } /* Generate coordinates */ Factor(NumberOfParticles, &y, &x, &c); /* (particle.c) */ if( c == 0 ) { i = 0; for(iy = 0; iy < y; iy++) { lat = (int)((180L * iy / y) + (180 / (y * 2))); r = SPACE_L * Sine(lat) / SINE_SCALE; /* (particle.h) */ for(ix = 0; ix < x; ix++) { lon = (int)(360L * ix / x); SphereX[i] = (int)(r * Cosine(lon) / SINE_SCALE); SphereZ[i] = (int)(r * Sine(lon) / SINE_SCALE); SphereY[i] = (int)(SPACE_L * Cosine(lat) / SINE_SCALE); i++; } } } if( c == 1 ) { SphereX[0] = 0; SphereY[0] = SPACE_L; SphereZ[0] = 0; i = 1; for(iy = 0; iy < y; iy++) { lat = (int)(360L * (iy + 1) / (2 * y + 2)); r = SPACE_L * Sine(lat) / SINE_SCALE; for(ix = 0; ix < x; ix++) { lon = (int)(360L * ix / x); SphereX[i] = (int)(r * Cosine(lon) / SINE_SCALE); SphereZ[i] = (int)(r * Sine(lon) / SINE_SCALE); SphereY[i] = (int)(SPACE_L * Cosine(lat) / SINE_SCALE); i++; } } } if( c > 1 ) { SphereX[0] = SphereZ[0] = 0; SphereY[0] = SPACE_L; SphereX[1] = SphereZ[1] = 0; SphereY[1] = -SPACE_L; i = 2; for(iy = 1; iy <= y; iy++) { lat = (int)(180L * iy / (y + 1)); r = SPACE_L * Sine(lat) / SINE_SCALE; for(ix = 0; ix < x; ix++) { lon = (int)(360L * ix / x); SphereX[i] = (int)(r * Cosine(lon) / SINE_SCALE); SphereZ[i] = (int)(r * Sine(lon) / SINE_SCALE); SphereY[i] = (int)(SPACE_L * Cosine(lat) / SINE_SCALE); i++; } } while( i < NumberOfParticles ) { ix = rand() % i; SphereX[i] = SphereX[ix]; SphereY[i] = SphereY[ix]; SphereZ[i] = SphereZ[ix]; i++; } } /* Reset rotation */ lon = lat = 0; return 0; } /* InitSphere() */ /******************************* MorphSphere ******************************* Blend particle systems. * * IN: frame = current morphing animation frame. * target = end animation frame. * (global) (SphereX[], SphereY[], SphereZ[]) = target. * (global) (lon, lat) = rotation. * (particle.c) NumberOfParticles = number of particles. * (particle.c) (ParticleX[], ParticleY[], ParticleZ[]) = source. * OUT: (particle.c) (ParticleX[], ParticleY[], ParticleZ[]) updated. */ void MorphSphere(int frame, int target) { int i, x, y, z; long cx, sx, cy, sy; cy = Cosine(lon); sy = Sine(lon); /* (particle.h) */ cx = Cosine(lat); sx = Sine(lat); for(i = 0; i < NumberOfParticles; i++) { /* Rotate in X axis */ y = (int)(cx * SphereY[i] / SINE_SCALE - sx * SphereZ[i] / SINE_SCALE); z = (int)(cx * SphereZ[i] / SINE_SCALE + sx * SphereY[i] / SINE_SCALE); /* Rotate in Y axis */ x = (int)(cy * SphereX[i] / SINE_SCALE - sy * z / SINE_SCALE); z = (int)(cy * z / SINE_SCALE + sy * SphereX[i] / SINE_SCALE); /* Morph */ ParticleX[i] = Morph(ParticleX[i], x, frame, target); /* (particle.h) */ ParticleY[i] = Morph(ParticleY[i], y, frame, target); ParticleZ[i] = Morph(ParticleZ[i], z, frame, target); } } /* MorphSphere() */ /***************************** TranslateSphere ***************************** Move sphere particles. * * IN: (global) (lon, lat) = rotation. * (particle.c) NumberOfParticles = number of particles. * OUT: (global) (SphereX[], SphereY[], SphereZ[]) = particle coordinates. */ void TranslateSphere(void) { static int dlon = 1, dlat = 0; static int frame = 0, target = SPHERE_TIME_I, phase = SPHERE_IDLE; int i; /* Rotate */ if( phase == SPHERE_IDLE ) { lon += dlon; lat += dlat; if( lon >= 360 ) lon -= 360; if( lat >= 360 ) lat -= 360; } else { i = 0; if( phase == SPHERE_DECELERATE ) { if( frame > (target / 2) ) { if( frame > (3 * target / 4) ) { if( (frame % 8) == 0 ) i = 1; } else { if( (frame % 4) == 0 ) i = 1; } } else { if( (frame % 2) == 0 ) i = 1; } } else { if( frame < (target / 2) ) { if( frame < (target / 4) ) { if( (frame % 8) == 0 ) i = 1; } else { if( (frame % 4) == 0 ) i = 1; } } else { if( (frame % 2) == 0 ) i = 1; } } if( i ) { lon += dlon; lat += dlat; if( lon >= 360 ) lon -= 360; if( lat >= 360 ) lat -= 360; } } /* Set velocity */ frame++; if( frame == target ) { frame = 0; target = rand() % SPHERE_TIME_E; if( phase == SPHERE_IDLE ) { target += SPHERE_TIME_A; phase = SPHERE_DECELERATE; } else { if( phase == SPHERE_DECELERATE ) { do { dlon = rand() % 3 - 1; dlat = rand() % 3 - 1; } while( dlon == 0 && dlat == 0 ); if( dlon < 0 ) dlon += 360; if( dlat < 0 ) dlat += 360; target += SPHERE_TIME_A; phase = SPHERE_ACCELERATE; } else { target += SPHERE_TIME_I; phase = SPHERE_IDLE; } } } } /* TranslateSphere() */ /****************************** UninitSphere ******************************* Uninitialize (reverses InitSphere). * * IN: (global) (SphereX[], SphereY[], SphereZ[]) = particle coordinates. * OUT: None. */ void UninitSphere(void) { _ffree(SphereX); _ffree(SphereY); _ffree(SphereZ); } /* UninitSphere() */