/* PARTICLES.C */ #include "glut.h" #include #include #include #define MAX_PARTICLES 1000 #define BIRTHS_PER_FRAME 3 #define MINIMUM_COLOR 0.2 #define PI 3.1415926535 #define EPSILON 0.001 #define RAND ((rand()*1.0)/(RAND_MAX)) #define CONSTANT 1 #define LINEAR 2 #define NORMAL 3 typedef struct xyz_struct { float x,y,z; } xyz_td; typedef struct rgb_struct { float r,g,b; } rgb_td; typedef struct particle_struct { xyz_td position; xyz_td velocity; xyz_td force; int age; int terminalAge; float mass; rgb_td color; } particle_td; // source definition assumes oriented disk typedef struct source_struct { xyz_td location; int locationDistribution; float radius; xyz_td direction; int directionDistribution; float angularCutoff; int startFrame; int endFrame; int frameDistribution; float mass; float massDeviation; int massDistribution; int terminalAge; int terminalAgeDeviation; int terminalAgeDistribution; rgb_td color; rgb_td colorDeviation; int colorDistribution; } source_td; void remove_dead_particles(); void update_particles(); void birth_particles(); void display_particles(); void initialize_particles(); particle_td particles[MAX_PARTICLES]; source_td source; float deltaTime = 1.0/120; xyz_td gravity = {0.0, -32.0, 0.0}; // --------------------------------------------------------------------- // INITIALIZE PARTICLES // --------------------------------------------------------------------- void initialize_particles() { int i; float d,theta; srand(17); // initialize each particle to non-existence for (i=0; i 0) { if (particles[i].age >= particles[i].terminalAge) particles[i].mass = -1; number++; } } // printf(" dead: %d\n",number); } // --------------------------------------------------------------------- // UPDATE PARTICLES // need source location, direction, radius, distribution // --------------------------------------------------------------------- void update_particles() { int i; float attenuation; int number; xyz_td acceleration; acceleration.x = gravity.x; acceleration.y = gravity.y; acceleration.z = gravity.z; number = 0; for (i=0; i= 0) { attenuation = (particles[i].terminalAge-particles[i].age)/particles[i].terminalAge; particles[i].color.r *= attenuation; particles[i].color.g *= attenuation; particles[i].color.b *= attenuation; if (particles[i].color.r < MINIMUM_COLOR) particles[i].color.r = MINIMUM_COLOR; if (particles[i].color.g < MINIMUM_COLOR) particles[i].color.g = MINIMUM_COLOR; if (particles[i].color.b < MINIMUM_COLOR) particles[i].color.b = MINIMUM_COLOR; particles[i].age++; particles[i].position.x += particles[i].velocity.x*deltaTime; particles[i].position.y += particles[i].velocity.y*deltaTime; particles[i].position.z += particles[i].velocity.z*deltaTime; particles[i].velocity.x += acceleration.x*deltaTime; particles[i].velocity.y += acceleration.y*deltaTime; particles[i].velocity.z += acceleration.z*deltaTime; number++; } } // printf(" updated: %d\n",number); } // --------------------------------------------------------------------- // BIRTH PARTICLES // need source location, direction, radius, distribution */ // --------------------------------------------------------------------- void birth_particles() { int i; int tobirth; xyz_td location; xyz_td velocity; int mass; int terminalAge; int number; xyz_td s,u,v,w; float theta,d,sa,ca,ssa,cca; float len,wlen; number = 0; // get number of particles to birth tobirth = BIRTHS_PER_FRAME; // compute local coordinate system at location w.x = source.direction.x; w.y = source.direction.y; w.z = source.direction.z; wlen = sqrt(w.x*w.x+w.y*w.y+w.z*w.z); s.x = 1.0; s.y = 0.0; s.z = 0.0; u.x = w.y*s.z + w.z*s.y; u.y = w.z*s.x + w.x*s.z; u.z = w.x*s.y + w.y*s.x; len = sqrt(u.x*u.x+u.y*u.y+u.z*u.z); if (fabs(len) < EPSILON) { s.x = 0.0; s.y = 1.0; s.z = 0.0; u.x = w.y*s.z + w.z*s.y; u.y = w.z*s.x + w.x*s.z; u.z = w.x*s.y + w.y*s.x; } u.x = w.y*s.z + w.z*s.y; u.y = w.z*s.x + w.x*s.z; u.z = w.x*s.y + w.y*s.x; len = sqrt(u.x*u.x+u.y*u.y+u.z*u.z); u.x /= len; u.y /= len; u.z /= len; v.x = u.y*w.z + u.z*w.y; v.y = u.z*w.x + u.x*w.z; v.z = u.x*w.y + u.y*w.x; len = sqrt(v.x*v.x+v.y*v.y+v.z*v.z); v.x /= len; v.y /= len; v.z /= len; i=0; while ( (i0) ) { if (particles[i].mass < 0) { // get pseudo random position, velocity, direction, mass, terminal age // get randomized location of birth // get randomized angle around location d = RAND; theta = 2.0*d*PI; // get randomized radius d = RAND; d = source.radius*d; sa = sin(theta); ca = cos(theta); // calculate randomized location location.x = source.location.x + d*ca*u.x + d*sa*v.x; location.y = source.location.y + d*ca*u.y + d*sa*v.y; location.z = source.location.z + d*ca*u.z + d*sa*v.z; // printf(" born: %f %f %f\n",location.x,location.y,location.z); // scanf("%d",&mass); // get randomized angular deviation from direction d = RAND; d = source.angularCutoff*d*PI/180; ssa = wlen*sin(d); cca = cos(d); // get randomized angle around direction theta = RAND; theta = 2*theta*PI; sa = sin(theta); ca = cos(theta); // calculate velocity vector velocity.x = ssa*ca*u.x + ssa*sa*v.x + cca*source.direction.x; velocity.y = ssa*ca*u.y + ssa*sa*v.y + cca*source.direction.y; velocity.z = ssa*ca*u.z + ssa*sa*v.z + cca*source.direction.z; // get mass mass = source.mass; // get terminalAge terminalAge = source.terminalAge; // get initial color; particles[i].position.x = location.x; particles[i].position.y = location.y; particles[i].position.z = location.z; particles[i].velocity.x = velocity.x; particles[i].velocity.y = velocity.y; particles[i].velocity.z = velocity.z; particles[i].mass = mass; particles[i].age = 0; particles[i].terminalAge = terminalAge; tobirth--; number++; // printf(" born: %f %f %f\n",particles[i].position.x,particles[i].position.y,particles[i].position.z); } i++; } } // --------------------------------------------------------------------- // DISPLAY PARTICLES // --------------------------------------------------------------------- void display_particles() { int i; // printf("display particles\n"); remove_dead_particles(); update_particles(); birth_particles(); glNewList(1,GL_COMPILE); glPushMatrix(); glScalef(0.2,0.2,0.2); draw_tetrahedron(); glPopMatrix(); glEndList(); set_material("bluePlasticMaterial"); for (i=0; i 0) { glPushMatrix(); glTranslatef(particles[i].position.x,particles[i].position.y,particles[i].position.z); glCallList(1); glPopMatrix(); } } }