void init_sphere_2D() /* initialisation of window */ { glLineWidth(3); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glOrtho(0.0, NX, DPOLE, NY-DPOLE, -1.0, 1.0); } void draw_vertex_sphere(double xyz[3]) { double xy_screen[2]; xyz_to_xy(xyz[0], xyz[1], xyz[2], xy_screen); glVertex2d(xy_screen[0], xy_screen[1]); } void init_wave_sphere(t_wave_sphere wsphere[NX*NY]) /* initialize sphere data */ { int i, j; double dphi, dtheta, theta0, xy[2], phishift; printf("Initializing wsphere\n"); dphi = DPI/(double)NX; // dtheta = PI/(double)NY; dtheta = PI/(double)(NY-2*(DPOLE)); theta0 = (double)(DPOLE)*dtheta; phishift = PHISHIFT*(XMAX-XMIN)/360.0; #pragma omp parallel for private(i,j) for (i=0; i XMAX) xy[0] += XMIN - XMAX; xy[1] *= (double)NY/(double)(NY-2*DPOLE); wsphere[i*NY+j].x2d = xy[0]; wsphere[i*NY+j].y2d = xy[1]; wsphere[i*NY+j].cos_angle_sphere = wsphere[i*NY+j].x*light[0] + wsphere[i*NY+j].y*light[1] + wsphere[i*NY+j].z*light[2]; } /* cotangent, taking care of not dividing by zero */ for (j=1; j nmaxpixels) { printf("bathymetric data file too large, increase nmaxpixels in read_negative_dem_values()\n"); exit(0); } /* shift due to min/max latitudes of image */ sshift = 0 + DPOLE; nshift = 0 + DPOLE; /* choice of zero meridian */ ishift = (int)(nx*ZERO_MERIDIAN/360.0); /* read rgb values */ for (j=0; j hcont)) hmin = rgbtot; if (rgbtot > hmax) hmax = rgbtot; int_height_values[3*(j*nx+i)] = rgbtot; } printf("hmin = %i, hmax = %i\n", hmin, hmax); /* remove remaining black continents */ for (i=0; i<3*nx*ny; i++) if (int_height_values[i] < hcont) int_height_values[i] = hmax; cratio = 1.0/(double)(hmax-hmin); rx = (double)nx/(double)NX; ry = (double)ny/(double)(NY - sshift - nshift); /* option: set continents color to white */ // for (i=0; i nx-1) ii -= nx; jj = (int)(ry*(double)(NY-nshift - j)); if (jj > ny-1) jj = ny-1; if (jj < 0) jj = 0; if (wsphere[i*NY+j].indomain) { /* set height to zero if color is black (due to black patches in bathymetric map) */ if (int_height_values[3*(jj*nx+ii)] < hcont) height = 0.0; else height = -1.0 + (double)(int_height_values[3*(jj*nx+ii)])*cratio; if (height > 0.0) height = 0.0; height_values_tmp[i*NY+j] = height; wsphere[i*NY+j].altitude = height; if (int_height_values[3*(jj*nx+ii)] > hcont) { wsphere[i*NY+j].r = 0.9*(double)rgb_values[3*(jj*nx+ii)]*cratio; wsphere[i*NY+j].g = 0.9*(double)rgb_values[3*(jj*nx+ii)+1]*cratio; wsphere[i*NY+j].b = 0.9*(double)rgb_values[3*(jj*nx+ii)+2]*cratio; } else { wsphere[i*NY+j].r = 0.29; wsphere[i*NY+j].g = 0.29; wsphere[i*NY+j].b = 0.29; } } else { height_values_tmp[i*NY+j] = 0.0; height_values_tmp2[i*NY+j] = 0.0; } } /* smoothen values at low depth */ if (SMOOTH_DEM) for (k=1; k= -0.25)) { height_values_tmp2[i*NY+j] = height_values_tmp[i*NY+j] + 0.1*(height_values_tmp[(i+1)*NY+j] + height_values_tmp[(i-1)*NY+j] + height_values_tmp[i*NY+j+1] + height_values_tmp[i*NY+j-1] - 4.0*height_values_tmp[i*NY+j]); height_values_tmp[i*NY+j] = height_values_tmp2[i*NY+j] + 0.1*(height_values_tmp2[(i+1)*NY+j] + height_values_tmp2[(i-1)*NY+j] + height_values_tmp2[i*NY+j+1] + height_values_tmp2[i*NY+j-1] - 4.0*height_values_tmp2[i*NY+j]); } } if (SMOOTH_DEM) for (i=1; i= -0.25)) { wsphere[i*NY+j].altitude = height_values_tmp[i*NY+j]; } for (i=0; i nmaxpixels) { printf("DEM too large, increase nmaxpixels in init_dem()\n"); exit(0); } /* shift due to min/max latitudes of image */ sshift = 0 + DPOLE; nshift = 0 + DPOLE; /* choice of zero meridian */ ishift = (int)(nx*ZERO_MERIDIAN/360.0); printf("Reading RGB values\n"); /* read rgb values */ for (j=0; j hmax) hmax = rgbval; } printf("hmin = %i, hmax = %i, hsea = %i\n", hmin, hmax, (int)hsea); cratio = 1.0/(double)(hmax-hmin); rx = (double)nx/(double)NX; ry = (double)ny/(double)(NY - sshift - nshift); /* build height table */ for (i=0; i nx-1) ii -= nx; if (ii < 0) ii = 0; jj = (int)(ry*(double)(NY-nshift - j)); if (jj > ny-1) jj = ny-1; if (jj < 0) jj = 0; height_values[i*NY+j] = ((double)rgb_values[3*(jj*nx+ii)]-hsea)*cratio; wsphere[i*NY+j].altitude = ((double)rgb_values[3*(jj*nx+ii)]-hsea)*cratio; if (OTHER_PLANET) wsphere[i*NY+j].indomain = (wsphere[i*NY+j].altitude < 0.0); // if (wsphere[i*NY+j].indomain) printf("rgb = %i, altitude = %.3lg\n", rgb_values[3*(jj*nx+ii)], height_values[i*NY+j]); } /* smooth values in case of high resolution */ if ((NX > nx)||(NY > ny)) { for (i=1; i 0.0)&&(wsphere[i*NY+j].altitude <= 0.15)) // printf("Smoothed altitude at (%i, %i): %.3lg\n", i, j, wsphere[i*NY+j].altitude); if ((ADD_NEGATIVE_DEM)&&(dem_number == DEM_EARTH)) read_negative_dem_values(height_values, wsphere); /* set radius */ for (i=0; i nmaxpixels) { printf("Image too large, increase nmaxpixels in init_earth_map()\n"); exit(0); } /* shift due to min/max latitudes of image */ sshift = 0 + DPOLE; nshift = 0 + DPOLE; /* choice of zero meridian */ ishift = (int)(nx*ZERO_MERIDIAN/360.0); /* read rgb values */ for (j=0; j nx-1) ii -= nx; // jj = (int)(-ry*(double)j + cy); // jj = (int)(ry*(double)(NY-nshift - j)) + sshift; jj = (int)(ry*(double)(NY-nshift - j)); if (jj > ny-1) jj = ny-1; if (jj < 0) jj = 0; wsphere[i*NY+j].r = (double)rgb_values[3*(jj*nx+ii)]*cratio; wsphere[i*NY+j].g = (double)rgb_values[3*(jj*nx+ii)+1]*cratio; wsphere[i*NY+j].b = (double)rgb_values[3*(jj*nx+ii)+2]*cratio; /* decide which points are in the Sea */ diff = iabs(rgb_values[3*(jj*nx+ii)] - 10); diff += iabs(rgb_values[3*(jj*nx+ii)+1] - 10); diff += iabs(rgb_values[3*(jj*nx+ii)+2] - 51); wsphere[i*NY+j].indomain = (diff < 15); } /* smooth colors in case of high resolution */ if ((NX > nx)||(NY > ny)) for (i=1; i nmaxpixels) { printf("Image too large, increase nmaxpixels in init_planet_map()\n"); exit(0); } /* shift due to min/max latitudes of image */ sshift = 0 + DPOLE; nshift = 0 + DPOLE; /* choice of zero meridian */ ishift = (int)(nx*ZERO_MERIDIAN/360.0); /* read rgb values */ for (j=0; j nx-1) ii -= nx; // jj = (int)(-ry*(double)j + cy); // jj = (int)(ry*(double)(NY-nshift - j)) + sshift; jj = (int)(ry*(double)(NY-nshift - j)); if (jj > ny-1) jj = ny-1; if (jj < 0) jj = 0; wsphere[i*NY+j].r = (double)rgb_values[3*(jj*nx+ii)]*cratio; wsphere[i*NY+j].g = (double)rgb_values[3*(jj*nx+ii)+1]*cratio; wsphere[i*NY+j].b = (double)rgb_values[3*(jj*nx+ii)+2]*cratio; // printf("RGB = (%.2f, %.2f, %.2f)\n", wsphere[i*NY+j].r, wsphere[i*NY+j].g, wsphere[i*NY+j].b); /* decide which points are in the Sea */ wsphere[i*NY+j].indomain = 1; // wsphere[i*NY+j].indomain = 0; // wsphere[i*NY+j].indomain = (diff < 15); } /* smooth colors in case of high resolution */ if ((NX > nx)||(NY > ny)) for (i=1; i COS_VISIBLE); } int init_circle_sphere(t_circles_sphere *circles, int circle_pattern) /* initialise circles on sphere */ /* for billiard shape D_SPHERE_CIRCLES */ { int ncircles, k; double alpha, beta, gamma; switch (circle_pattern) { case (C_SPH_DODECA): { alpha = acos(sqrt(5.0)/3.0); beta = acos(1.0/3.0); gamma = asin(sqrt(3.0/8.0)); circles[0].theta = 0.0; circles[0].phi = 0.0; for (k=0; k<3; k++) { circles[1+k].theta = alpha; circles[1+k].phi = (double)k*DPI/3.0; } for (k=0; k<3; k++) { circles[4+k].theta = beta; circles[4+k].phi = (double)k*DPI/3.0 + gamma; circles[7+k].theta = beta; circles[7+k].phi = (double)k*DPI/3.0 - gamma; } for (k=0; k<3; k++) { circles[10+k].theta = PI - beta; circles[10+k].phi = (double)k*DPI/3.0 + PI/3.0 + gamma; circles[13+k].theta = PI - beta; circles[13+k].phi = (double)k*DPI/3.0 + PI/3.0 - gamma; } for (k=0; k<3; k++) { circles[16+k].theta = PI - alpha; circles[16+k].phi = (double)k*DPI/3.0 + PI/3.0; } circles[19].theta = PI; circles[19].phi = 0.0; for (k=0; k<20; k++) { circles[k].radius = MU; circles[k].x = sin(circles[k].theta)*cos(circles[k].phi); circles[k].y = sin(circles[k].theta)*sin(circles[k].phi); circles[k].z = cos(circles[k].theta); } ncircles = 20; break; } case (C_SPH_ICOSA): { alpha = acos(1.0/sqrt(5.0)); circles[0].theta = 0.0; circles[0].phi = 0.0; for (k=0; k<5; k++) { circles[1+k].theta = alpha; circles[1+k].phi = (double)k*DPI/5.0; } for (k=0; k<5; k++) { circles[6+k].theta = PI - alpha; circles[6+k].phi = (double)k*DPI/5.0 + PI/5.0; } circles[11].theta = PI; circles[11].phi = 0.0; for (k=0; k<12; k++) { circles[k].radius = MU; circles[k].x = sin(circles[k].theta)*cos(circles[k].phi); circles[k].y = sin(circles[k].theta)*sin(circles[k].phi); circles[k].z = cos(circles[k].theta); } ncircles = 12; break; } case (C_SPH_OCTA): { circles[0].theta = 0.0; circles[0].phi = 0.0; for (k=0; k<4; k++) { circles[1+k].theta = PID; circles[1+k].phi = (double)k*PID; } circles[5].theta = PI; circles[5].phi = 0.0; for (k=0; k<6; k++) { circles[k].radius = MU; circles[k].x = sin(circles[k].theta)*cos(circles[k].phi); circles[k].y = sin(circles[k].theta)*sin(circles[k].phi); circles[k].z = cos(circles[k].theta); } ncircles = 6; break; } case (C_SPH_CUBE): { alpha = acos(1.0/3.0); circles[0].theta = 0.0; circles[0].phi = 0.0; for (k=0; k<3; k++) { circles[1+k].theta = alpha; circles[1+k].phi = (double)k*DPI/3.0; circles[4+k].theta = PI - alpha; circles[4+k].phi = (double)k*DPI/3.0 + PI/3.0; } circles[7].theta = PI; circles[7].phi = 0.0; for (k=0; k<8; k++) { circles[k].radius = MU; circles[k].x = sin(circles[k].theta)*cos(circles[k].phi); circles[k].y = sin(circles[k].theta)*sin(circles[k].phi); circles[k].z = cos(circles[k].theta); } ncircles = 8; break; } default: { printf("Function init_circle_sphere not defined for this pattern \n"); } } return(ncircles); } int xy_in_billiard_sphere(int i, int j, t_wave_sphere wsphere[NX*NY]) /* returns 1 if (x,y) represents a point in the billiard */ { int k; double pscal, dist, r, u, v, u1, v1; static double cos_rot, sin_rot; static int first = 1; if (first) { if (B_DOMAIN == D_SPHERE_EARTH) init_earth_map(wsphere); else if (OTHER_PLANET) init_planet_map(wsphere, B_DOMAIN); else if ((B_DOMAIN == D_SPHERE_JULIA)||(B_DOMAIN == D_SPHERE_JULIA_INV)||(B_DOMAIN == D_SPHERE_JULIA_CUBIC)) { cos_rot = cos(JULIA_ROT*DPI/360.0); sin_rot = sin(JULIA_ROT*DPI/360.0); } first = 0; } switch (B_DOMAIN) { case (D_NOTHING): { return(1); } case (D_LATITUDE): { return(vabs(wsphere[i*NY+j].theta - PID) < LAMBDA*PID); } case (D_SPHERE_CIRCLES): { for (k=0; k RMAX) r = RMAX; wsphere[i*NY+j].radius = r; } if (SHADE_WAVE) { #pragma omp parallel for private(i,j,norm,pscal,deltar,deltai,deltaj,n) for (i=0; i= wsphere[i*NY+j].altitude + 0.001)) if (FLOODING) draw = ((wsphere[i*NY+j].indomain)||(phi[i*NY+j] >= wsphere[i*NY+j].altitude + 0.001)); else draw = ((TWOSPEEDS)||(xy_in[i*NY+j])); if (draw) { gradx = (*wave[(i+1)*NY+j].p_zfield[movie] - *wave[(i-1)*NY+j].p_zfield[movie])/dx; grady = (*wave[i*NY+j+1].p_zfield[movie] - *wave[i*NY+j-1].p_zfield[movie])/dy; norm = sqrt(vscale2 + gradx*gradx + grady*grady); pscal = -gradx*light[0] - grady*light[1] + SHADE_SCALE_2D; wave[i*NY+j].cos_angle = pscal/norm; } else wave[i*NY+j].cos_angle = wsphere[i*NY+j].cos_angle; } /* i=0 */ for (j=1; j= wsphere[j].altitude + 0.001)) { gradx = (*wave[NY+j].p_zfield[movie] - *wave[(NY-1)*NY+j].p_zfield[movie])/dx; grady = (*wave[j+1].p_zfield[movie] - *wave[j-1].p_zfield[movie])/dy; norm = sqrt(vscale2 + gradx*gradx + grady*grady); pscal = -gradx*light[0] - grady*light[1] + SHADE_SCALE_2D; wave[j].cos_angle = pscal/norm; } else wave[j].cos_angle = wsphere[j].cos_angle; } /* i=NX-1 */ for (j=1; j= wsphere[(NX-1)*NY+j].altitude + 0.001)) { gradx = (*wave[j].p_zfield[movie] - *wave[(NX-2)*NY+j].p_zfield[movie])/dx; grady = (*wave[(NX-1)*NY+j+1].p_zfield[movie] - *wave[(NX-1)*NY+j-1].p_zfield[movie])/dy; norm = sqrt(vscale2 + gradx*gradx + grady*grady); pscal = -gradx*light[0] - grady*light[1] + SHADE_SCALE_2D; wave[(NX-1)*NY+j].cos_angle = pscal/norm; } else wave[(NX-1)*NY+j].cos_angle = wsphere[(NX-1)*NY+j].cos_angle; } } void compute_cfield_sphere(short int xy_in[NX*NY], int cplot, int palette, t_wave wave[NX*NY], int fade, double fade_value, int movie) /* compute the colors */ { int i, j, k; double ca; static double fact_max; static int first = 1; if (first) { fact_max = 0.5*COS_LIGHT_MAX; first = 0; } #pragma omp parallel for private(i,j,ca) for (i=0; i= wsphere[i*NY+j].altitude + 0.001); else draw = (TWOSPEEDS)||(xy_in[i*NY+j]); if (draw) glColor3f(wave[i*NY+j].rgb[0], wave[i*NY+j].rgb[1], wave[i*NY+j].rgb[2]); else { ca = wave[i*NY+j].cos_angle; ca = (ca + 1.0)*0.4 + 0.2; if (fade) ca *= fade_value; if (PLANET) glColor3f(wsphere[i*NY+j].r*ca, wsphere[i*NY+j].g*ca, wsphere[i*NY+j].b*ca); else glColor3f(COLOR_OUT_R*ca, COLOR_OUT_G*ca, COLOR_OUT_B*ca); } x = wsphere[i*NY+j].x2d; y = wsphere[i*NY+j].y2d; ii = NX-i-1+ishift; if (ii > NX) ii -= NX; glVertex2i(ii, j); glVertex2i(ii+1, j); glVertex2i(ii+1, j+1); glVertex2i(ii, j+1); } glEnd (); } void draw_wave_sphere_ij(int i, int iplus, int j, int jplus, int jcolor, int movie, double phi[NX*NY], double psi[NX*NY], short int xy_in[NX*NY], t_wave wave[NX*NY], t_wave_sphere wsphere[NX*NY], int zplot, int cplot, int palette, int fade, double fade_value) /* draw wave at simulation grid point (i,j) */ { int k, l; short int draw; double xyz[3], ca; // if ((TWOSPEEDS)||(xy_in[i*NY+j])) // if (wsphere[i*NY+j].indomain) // if ((wsphere[i*NY+j].indomain)||(phi[i*NY+j] >= wsphere[i*NY+j].altitude + 0.001)) if (FLOODING) draw = (wsphere[i*NY+j].indomain)||(phi[i*NY+j] >= wsphere[i*NY+j].altitude + 0.001); else draw = ((TWOSPEEDS)||(xy_in[i*NY+j])); if (draw) glColor3f(wave[i*NY+jcolor].rgb[0], wave[i*NY+jcolor].rgb[1], wave[i*NY+jcolor].rgb[2]); else { // ca = wave[i*NY+j].cos_angle; ca = wsphere[i*NY+j].cos_angle; ca = (ca + 1.0)*0.4 + 0.2; if (fade) ca *= fade_value; if (PLANET) glColor3f(wsphere[i*NY+j].r*ca, wsphere[i*NY+j].g*ca, wsphere[i*NY+j].b*ca); else glColor3f(COLOR_OUT_R*ca, COLOR_OUT_G*ca, COLOR_OUT_B*ca); } glBegin(GL_TRIANGLE_FAN); if (ij_to_sphere(i, j, *wave[i*NY+j].p_zfield[movie], wsphere, xyz)) draw_vertex_sphere(xyz); if (ij_to_sphere(iplus, j, *wave[iplus*NY+j].p_zfield[movie], wsphere, xyz)) draw_vertex_sphere(xyz); if (ij_to_sphere(iplus, jplus, *wave[iplus*NY+j+1].p_zfield[movie], wsphere, xyz)) draw_vertex_sphere(xyz); if (ij_to_sphere(i, jplus, *wave[i*NY+j+1].p_zfield[movie], wsphere, xyz)) draw_vertex_sphere(xyz); glEnd (); } void draw_wave_sphere_3D(int movie, double phi[NX*NY], double psi[NX*NY], short int xy_in[NX*NY], t_wave wave[NX*NY], t_wave_sphere wsphere[NX*NY], int zplot, int cplot, int palette, int fade, double fade_value, int refresh) { int i, j, imax, imin; double observer_angle, angle2; blank(); if (refresh) { compute_wave_fields(phi, psi, xy_in, zplot, cplot, wave); if (SHADE_3D) compute_light_angle_sphere(xy_in, wave, wsphere, movie); else if (SHADE_2D) compute_light_angle_sphere_2d(xy_in, phi, wave, wsphere, movie); compute_cfield_sphere(xy_in, cplot, palette, wave, fade, fade_value, movie); } observer_angle = argument(observer[0], observer[1]); if (observer_angle < 0.0) observer_angle += DPI; angle2 = observer_angle + PI; if (angle2 > DPI) angle2 -= DPI; imin = (int)(observer_angle*(double)NX/DPI); imax = (int)(angle2*(double)NX/DPI); if (imin >= NX-1) imin = NX-2; if (imax >= NX-1) imax = NX-2; // printf("Angle = %.5lg, angle2 = %.5lg, imin = %i, imax = %i\n", observer_angle, angle2, imin, imax); if (observer[2] > 0.0) { if (imin < imax) { for (i=imax; i>imin; i--) for (j=0; j=0; i--) for (j=0; j=imin; i--) for (j=0; jimin; i--) for (j=NY-3; j>=0; j--) draw_wave_sphere_ij(i, i+1, j, j+1, j+1, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); for (i=imax+1; i=0; j--) draw_wave_sphere_ij(i, i+1, j, j+1, j+1, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); for (j=NY-3; j>=0; j--) draw_wave_sphere_ij(NX-1, 0, j, j+1, j+1, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); for (i=0; i<=imin; i++) for (j=NY-3; j>=0; j--) draw_wave_sphere_ij(i, i+1, j, j+1, j+1, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); } else { for (i=imax; i=0; j--) draw_wave_sphere_ij(i, i+1, j, j+1, j+1, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); for (i=imax-1; i>=0; i--) for (j=NY-3; j>=0; j--) draw_wave_sphere_ij(i, i+1, j, j+1, j+1, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); for (j=NY-3; j>=0; j--) draw_wave_sphere_ij(NX-1, 0, j, j+1, j+1, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); for (i=NX-2; i>=imin; i--) for (j=NY-3; j>=0; j--) draw_wave_sphere_ij(i, i+1, j, j+1, j+1, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); } /* South pole */ for (i=0; i0; j--) draw_wave_sphere_ij(i, i+1, j-1, j, j, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); for (j=2; j>0; j--) draw_wave_sphere_ij(NX-1, 0, j-1, j, DPOLE, movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade, fade_value); } } void draw_wave_sphere(int movie, double phi[NX*NY], double psi[NX*NY], short int xy_in[NX*NY], t_wave wave[NX*NY], t_wave_sphere wsphere[NX*NY], int zplot, int cplot, int palette, int fade, double fade_value, int refresh) { if (PLOT_2D) draw_wave_sphere_2D(movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade,fade_value, refresh); else draw_wave_sphere_3D(movie, phi, psi, xy_in, wave, wsphere, zplot, cplot, palette, fade,fade_value, refresh); }