#include #include #include #include #include #include #include "erosion_particle.h" //#include "cls_RGBA_IMG.h" /***************************************************************************** * Create the background image for povray ****************************************************************************/ void background( FILE *Frame ) { fprintf( Frame, "#include \"colors.inc\"\n" ); fprintf( Frame, "#include \"shapes.inc\"\n" ); fprintf( Frame, "#include \"shapes_old.inc\"\n" ); fprintf( Frame, "#include \"woods.inc\"\n\n"); fprintf( Frame, "camera {\n\tlocation <2.25, 0.5, -2>\n\tlook_at <2.25, 2, 2>\n \tangle 80\n\t}\n"); fprintf( Frame, "light_source { <10, 10, -10> White }\n"); fprintf( Frame, "sky_sphere {\n\tpigment {\n\t gradient y\n\t color_map {\n"); fprintf( Frame, "[0.000 0.0005 color White\n\t\tcolor rgb <1.0,1.0,0.7>]\n"); fprintf( Frame, "\t[0.0005 0.200 color rgb <0.9, 0.9, 1.0>\n\t\tcolor rgb <0.5, 0.5, 1.0>]\n\t}\n"); fprintf( Frame, "\tscale 2\n\ttranslate -1\n}\n"); fprintf( Frame, "\tpigment {\n\t bozo\n\t turbulence 0.65\n\t octaves 6\n"); fprintf( Frame, "\t omega 0.7\n\t lambda 2\n\t color_map {\n"); fprintf( Frame, "\t\t[0.0 0.1 color rgb <0.85, 0.85, 0.85>\n"); fprintf( Frame, "\t\t\tcolor rgb <0.75, 0.75, 0.75>]\n"); fprintf( Frame, "\t\t[0.1 0.5 color rgb <0.75 0.75 0.75>\n"); fprintf( Frame, "\t\t\tcolor rgbt <1, 1, 1, 1>]\n"); fprintf( Frame, "\t\t[0.5 1.0 color rgbt <1, 1, 1, 1>\n"); fprintf( Frame, "\t\t\tcolor rgbt <1, 1, 1, 1>]\n\t\t}\n"); fprintf( Frame, "\t\tscale <0.2, 0.5, 0.2>\n\t}\n"); fprintf( Frame, "\trotate -135*x\n\t}\n\n"); fprintf( Frame, "plane {\n\ty, 0\n\tpigment { color rgb <1.0, 0.7, 0.2> }\n"); fprintf( Frame, "\tfinish { ambient .3 diffuse .7 }\n\t}\n"); } /******************************************************************** * take the number n and convert to a character string *******************************************************************/ void num2string(int n, char returnString[4]) { char c; // Character representation of the current digit int i, m = 1000; // Number to take the modulus of, to remove // unwanted digits n = n%10000; // Used to contain numbers > 3 digits for ( i = 0; i < 4; i ++ ) { c = n/m + '0'; returnString[i] = c; n = n%m; m /= 10; } returnString[4] = '\0'; return; } /************************************************************************* * Write a povray description of the scene for a particular frame given by * frameNumber. ************************************************************************/ void write_frame( int frameNumber, Particle_list heightField[NUM_STEPS] ) { FILE *Frame; char fileNumber[10]; char fileName[14] = "frame"; float x, y, z, x_rotate, y_rotate, z_rotate; int count, count_particles; num2string( frameNumber, fileNumber ); //fprintf(stderr, "%s\n", fileNumber); strcpy(fileName, "frame"); fprintf(stderr, "fileName is %s\n", fileName); strcat( fileName, fileNumber ); fprintf(stderr, "fileName now is %s after adding %s\n", fileName, fileNumber); strcat( fileName, ".pov"); fprintf(stderr, "Opening %s\n", fileName); //fprintf(stderr, "%s\n", fileName); Frame = fopen( fileName, "w" ); background( Frame ); for( count = 0; count < NUM_STEPS; count++ ) { for( count_particles = 0; count_particles < heightField[count].number; count_particles++ ) { x = (count*RADIUS*2.0)/100.0; y = (count_particles*RADIUS*2.0)/100.0; z = 1.0; x_rotate = get_random( 0.0, 90.0 ); y_rotate = get_random( 0.0, 90.0 ); z_rotate = get_random( 0.0, 90.0 ); fprintf( Frame, "sphere {\n\t<%f,%f,%f>, 0.01\n\t", x, y, z); fprintf( Frame, "texture { pigment { color rgb <1.0, 0.7, 0.2> }\n\t"); fprintf( Frame, "\tfinish { specular 0.2 roughness 0.005 ambient 0.4 }\n"); fprintf( Frame, "\trotate <%f, %f, %f>\n", x_rotate, y_rotate, z_rotate); fprintf( Frame, "\t}\n}\n"); fprintf( Frame, "sphere {\n\t<%f,%f,%f>, 0.01\n\t", x+0.01, y-0.01, z); fprintf( Frame, "texture { pigment { color rgb <1.0, 0.7, 0.2> }\n\t"); fprintf( Frame, "\tfinish { specular 0.5 roughness 0.005 ambient 0.4 }\n"); fprintf( Frame, "\trotate <%f, %f, %f>\n", x_rotate, y_rotate, z_rotate); fprintf( Frame, "\t}\n}\n"); } } fclose( Frame ); } /********************************************************************* * Initialize the openGL viewing area as a two dimensional orthogonal * viewing window. ********************************************************************/ void initialize( void ) { //Set the background colour to white glClearColor( 1.0, 1.0, 1.0, 1.0 ); //Default drawing colour set to red glColor3f( 0.0, 0.0, 0.0 ); //Set up viewing area for a projection viewing area, (frustum) glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluOrtho2D( 0.0, SCREEN, 0.0, SCREEN ); glMatrixMode( GL_MODELVIEW ); } /******************************************************************* * OpenGL display function ******************************************************************/ void display( void ) { int base = BASE, count = 0, count2 = 0, countX, collide, pause, rise; float originX = 0, originY = 0, particleX = 0, particleY, height; Particle_list heightField[NUM_STEPS]; float random, testVariable; int total_particles = 0, projectile = 0, counter = 0; Particle *particle; glClear( GL_COLOR_BUFFER_BIT ); srand( time(NULL) ); /* Initialize the terrain structure */ rise = gradient( RUN, SLOPE ); //fprintf(stderr, "about to create the terrain\n"); if( DEFAULTS ) createTerrain( heightField ); else height = (float)createTerrain2( heightField ); redrawTerrain( heightField ); //print_num_particles( heightField ); //fprintf(stderr, "just redrawn terrain\n"); glutSwapBuffers(); //stabilize_all_terrain( rise, heightField ); //fprintf(stderr, "directly after createTerrain: %.2f\n", heightField[20]); fprintf(stderr, "no. of steps: %d\nWaiting for input: ", NUM_STEPS); scanf("%d", &pause ); //stabilize_all_terrain( rise, heightField ); fprintf(stderr, "Finished stabilizing, pausing: "); scanf("%d", &pause ); /* Count the total number of particles in the heap */ total_particles = 0; for( count = 0; count < NUM_STEPS; count++ ) { //fprintf(stderr, "count = %d\n", count ); //fprintf(stderr, "x: %d, y: %.2f\n", count, heightField[count] ); total_particles += heightField[count].number; //fprintf(stderr, "total particles at %d is %d\n", count, total_particles ); } glutSwapBuffers(); //printf("still finished with creating terrain\n"); /* While there are still particles left in the pile */ while( total_particles > 0 ) { for( count = 0; count < NUM_STEPS; count++ ) { //fprintf(stderr, "looking at column %d\n", count ); /* If the current column has no particles, move to the next */ if( heightField[count].number > 0 ) { /* Determine where the particle rolls to, if it rolls at all */ move_particle( count, heightField, &total_particles ); } glClear( GL_COLOR_BUFFER_BIT ); redrawTerrain( heightField ); //fprintf(stderr, "just redrawn terrain\n"); glutSwapBuffers(); //Inject an airborne particle into the system from the left hand side. /* if( projectile < 700 && !DEFAULTS ) { particle = (Particle*)malloc( sizeof(Particle)); createNewParticle( particle, heightField[0].number*RADIUS*2, height+2*RADIUS ); air_borne_particle( particle, heightField ); /*if( projectile % 25 == 0 ) { write_frame( FRAME_NUM, heightField ); FRAME_NUM++; } glClear( GL_COLOR_BUFFER_BIT ); redrawTerrain( heightField ); //fprintf(stderr, "just redrawn terrain\n"); glutSwapBuffers(); } projectile++; fprintf(stderr, "projectile is %d\n", projectile ); */ } //stabilize_all_terrain( rise, heightField ); /*if( projectile >= 700 && counter % 10 == 0 ) { if( FRAME_NUM == 10000 ) exit(1); write_frame( FRAME_NUM, heightField ); FRAME_NUM++; } */ //Inject an airborne particle into the system from the left hand side. //particle = (Particle*)malloc( sizeof(Particle)); //createNewParticle( particle ); //air_borne_particle( particle, heightField ); //fprintf(stderr, "total particles left: %d\n", total_particles ); } } /************************************************************************ * main() ***********************************************************************/ int main( int argc, char** argv ) { FILE *input; FILE *Frame; int frame_number = 0; if( argc < 2 ) { NUM_STEPS = (int)(SCREEN/(RADIUS*2)); VELOCITY_X = RADIUS*2; BASE = 50; DEFAULTS = 1; fprintf(stderr, "No input file given, using defaults\n"); } else if( strcmp( argv[1], "help" )== 0 ) { printf("Input file requires an indication of wind strength, given as an integer\n"); printf("between 0 and 10, with 10 being the maximum strength. Probability of an\n"); printf("unprotected particle being shifted is calculated as wind strength over\n"); printf("21 times the radius. This means there will always be some chance that the\n"); printf("particle will not move even in the strongest wind.\n"); printf("Input file is as follows:\n"); printf("radius(float), wind strength(float between 0 and 20)\n"); exit(1); } else { input = fopen( argv[1], "r" ); if( !input ) { DEFAULTS = 1; fprintf(stderr, "input file did not open, using defaults\n"); } else { DEFAULTS = 0; //fscanf( input, "%f, %f, %f\n", &VELOCITY_X, &VELOCITY_Y, &VELOCITY_Z); //fscanf( input, "%f, %f, %f\n", &ACCELERATION_X, &ACCELERATION_Y, // &ACCELERATION_Z ); fscanf( input, "%f, %f, %d\n", &RADIUS, &WIND_STRENGTH, &BASE ); fclose( input ); NUM_STEPS = (int)(SCREEN/(RADIUS*2)); WIND_STRENGTH *= RADIUS; VELOCITY_X = WIND_STRENGTH; } } fprintf(stderr, "about to start display\n"); glutInit( &argc, argv ); glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB ); glutInitWindowSize( (int)SCREEN, (int)SCREEN ); glutInitWindowPosition( 0, 0); glutCreateWindow("Erosion simulation"); glutDisplayFunc( display ); initialize(); glutMainLoop(); }