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 */ /* TODO clean up cottheta range ? */ for (j=DPOLE; 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 0) hmin = rgbval; } else hmin = rgbval; } if (rgbval > hmax) hmax = rgbval; } printf("hmin = %i, hmax = %i, hsea = %i\n", hmin, hmax, (int)hsea); if (B_DOMAIN == D_SPHERE_VENUS) { hsum = 0; for (j=0; j 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; /* take care of black areas (missing data) on venus */ if ((B_DOMAIN == D_SPHERE_VENUS)&&(rgb_values[3*(jj*nx+ii)] == 0)) { height_values[i*NY+j] = VENUS_NODATA_FACTOR*hmean*cratio; wsphere[i*NY+j].altitude = VENUS_NODATA_FACTOR*hmean*cratio; } if (OTHER_PLANET) wsphere[i*NY+j].indomain = (wsphere[i*NY+j].altitude < vshift); // 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].draw_wave = 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 ij_to_sphere_r(int i, int j, double r, t_wave_sphere wsphere[NX*NY], double xyz[3]) /* convert spherical to rectangular coordinates */ { double pscal, newr; static double norm_observer; static int first = 1; if (first) { norm_observer = sqrt(observer[0]*observer[0] + observer[1]*observer[1] + observer[2]*observer[2]); first = 0; } xyz[0] = wsphere[i*NY+j].x; xyz[1] = wsphere[i*NY+j].y; xyz[2] = wsphere[i*NY+j].z; pscal = xyz[0]*observer[0] + xyz[1]*observer[1] + xyz[2]*observer[2]; xyz[0] *= r; xyz[1] *= r; xyz[2] *= r; return(pscal/norm_observer > 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); } void init_sphere_maze(t_wave_sphere wsphere[NX*NY], int spiral, int wave, int npole) /* initialize maze on sphere */ { int nblocks, block, i, j, k, n, p, q, np, na, inrect; double rmin, rmax, angle, r, dr, phi, dphi, phi1, ww, width = 0.02, theta, theta1, phaseshift; t_maze* maze; t_rectangle* polyrect; maze = (t_maze *)malloc(NXMAZE*NYMAZE*sizeof(t_maze)); polyrect = (t_rectangle *)malloc(NMAXPOLY*sizeof(t_rectangle)); printf("Initializing maze\n"); init_circular_maze(maze); printf("Maze initialized\n"); printf("Building maze walls\n"); /* build walls of maze */ np = 0; na = 0; /* build walls of maze */ nblocks = NYMAZE/NXMAZE; rmin = 0.3; rmax = PID + 0.2; angle = DPI/(double)nblocks; dr = (rmax - rmin)/(double)(NXMAZE); /* add straight walls */ for (block = 0; block < nblocks; block++) { printf("Block %i\n", block); dphi = angle; /* first circle */ n = nmaze(0, block*NXMAZE); r = rmin - 0.5*width; phi = (double)block*angle; if (maze[n].south) { polyrect[np].x1 = phi - 0.5*width; polyrect[np].y1 = r; polyrect[np].x2 = phi + 0.5*width; polyrect[np].y2 = r+dr+width; // printf("Adding rectangle at (%.3f, %.3f) - (%.3f, %.3f)\n", polyrect[np].x1, polyrect[np].y1, polyrect[np].x2, polyrect[np].y2); np++; } /* second circle */ r = rmin + dr - 0.5*width; dphi *= 0.5; for (q=0; q<2; q++) { n = nmaze(1, block*NXMAZE + q); phi = (double)(block)*angle + (double)q*dphi; if (maze[n].south) { polyrect[np].x1 = phi - 0.5*width; polyrect[np].y1 = r; polyrect[np].x2 = phi + 0.5*width; polyrect[np].y2 = r+dr+width; // printf("Adding rectangle at (%.3f, %.3f) - (%.3f, %.3f)\n", polyrect[np].x1, polyrect[np].y1, polyrect[np].x2, polyrect[np].y2); np++; } } /* other circles */ ww = 2; i = 2; while (ww < NXMAZE) { dphi *= 0.5; for (p = 0; p < ww; p++) { r = rmin + (double)i*dr - 0.5*width; // printf("Segment, i = %i, dphi = %.2lg, r = %.2lg\n", i, dphi, r); for (q = 0; q < 2*ww; q++) { j = block*NXMAZE + q; n = nmaze(i,j); phi = (double)(block)*angle + (double)q*dphi; if (maze[n].south) { polyrect[np].x1 = phi - 0.5*width; polyrect[np].y1 = r; polyrect[np].x2 = phi + 0.5*width; polyrect[np].y2 = r+dr+width; // printf("Adding rectangle at (%.3f, %.3f) - (%.3f, %.3f)\n", polyrect[np].x1, polyrect[np].y1, polyrect[np].x2, polyrect[np].y2); np++; } } i++; } ww *= 2; } } /* add circular arcs */ for (block = 0; block < nblocks; block++) { dphi = angle; /* first circle */ n = nmaze(0, block*NXMAZE); r = rmin; phi = (double)block*angle; if ((block > 0)&&(maze[n].west)) { polyrect[np].x1 = phi; polyrect[np].y1 = r - 0.5*width; polyrect[np].x2 = phi + dphi + 0.05*width; polyrect[np].y2 = r + 0.5*width; np++; } /* second circle */ r = rmin + dr; dphi *= 0.5; for (q=0; q<2; q++) { n = nmaze(1, block*NXMAZE + q); phi = (double)(block)*angle + (double)q*dphi; if (maze[n].west) { polyrect[np].x1 = phi; polyrect[np].y1 = r - 0.5*width; polyrect[np].x2 = phi + dphi + 0.05*width; polyrect[np].y2 = r + 0.5*width; np++; } } /* other circles */ ww = 2; i = 2; while (ww < NXMAZE) { dphi *= 0.5; for (p = 0; p < ww; p++) { r = rmin + (double)i*dr; printf("Circle, i = %i, dphi = %.2lg, r = %.2lg\n", i, dphi, r); for (q = 0; q < 2*ww; q++) { j = block*NXMAZE + q; n = nmaze(i,j); phi = (double)(block)*angle + (double)q*dphi; if (maze[n].west) { polyrect[np].x1 = phi; polyrect[np].y1 = r - 0.5*width; polyrect[np].x2 = phi + dphi + 0.05*width; polyrect[np].y2 = r + 0.5*width; np++; } } i++; } ww *= 2; } } /* outer boundary of maze */ polyrect[np].x1 = dphi; polyrect[np].y1 = rmax - 0.5*width; polyrect[np].x2 = DPI; polyrect[np].y2 = rmax + 0.5*width; np++; printf("Maze walls built\n"); phaseshift = ZERO_MERIDIAN*PI/180.0; for (i=0; i DPI) phi -= DPI; for (j=0; j PI) theta = PI; phi += 0.00075*cos(20.0*theta1)*theta1; // if (phi > DPI) phi -= DPI; if (phi < 0.0) phi += DPI; } inrect = 0; for (n=0; n polyrect[n].x1)&&(phi1 < polyrect[n].x2)&&(theta > polyrect[n].y1)&&(theta < polyrect[n].y2))) inrect = 1; } wsphere[i*NY+j].indomain = 1-inrect; } if (npole) for (j=NY-DPOLE*3/2; j RMAX) r = RMAX; if (r < RMIN) r = RMIN; wsphere[i*NY+j].radius = r; if (FLOODING) wsphere[i*NY+j].draw_wave = (phi[i*NY+j] >= wsphere[i*NY+j].altitude - vshift); // wsphere[i*NY+j].draw_wave = ((wsphere[i*NY+j].indomain)||(phi[i*NY+j] >= wsphere[i*NY+j].altitude - vshift)); } /* TODO ? Avoid artifacts due to singularity at north pole */ for (j=NY - DPOLE; j RMAX) r = RMAX; if (r < 1.0) r = 1.0; wsphere[i*NY+j].radius = r; if (FLOODING) wsphere[i*NY+j].draw_wave = (phi[i*NY+j] >= wsphere[i*NY+j].altitude - vshift); // wsphere[i*NY+j].draw_wave = ((wsphere[i*NY+j].indomain)||(phi[i*NY+j] >= wsphere[i*NY+j].altitude - vshift)); } } 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 = (phi[i*NY+j] >= wsphere[i*NY+j].altitude - vshift); wsphere[i*NY+j].draw_wave = draw; } // else draw = ((TWOSPEEDS)||(xy_in[i*NY+j])); else draw = ((xy_in[i*NY+j])); if (draw) { if (transparent) { gradx = (wsphere[(i+1)*NY+j].radius_dem - wsphere[(i-1)*NY+j].radius_dem)/dx; grady = (wsphere[i*NY+j+1].radius_dem - wsphere[i*NY+j-1].radius_dem)/dy; } else { 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 - vshift); wsphere[j].draw_wave = draw; } else draw = ((xy_in[j])); if (draw) { if (transparent) { gradx = (wsphere[NY+j].radius_dem - wsphere[(NX-1)*NY+j].radius_dem)/dx; grady = (wsphere[j+1].radius_dem - wsphere[j-1].radius_dem)/dy; } else { 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 - vshift); wsphere[(NX-1)*NY+j].draw_wave = draw; } else draw = ((xy_in[(NX-1)*NY+j])); if (draw) { if (transparent) { gradx = (wsphere[j].radius_dem - wsphere[(NX-2)*NY+j].radius_dem)/dx; grady = (wsphere[(NX-1)*NY+j+1].radius_dem - wsphere[(NX-1)*NY+j-1].radius_dem)/dy; } else { 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[(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 (FLOODING) draw = wsphere[i*NY+j].draw_wave; else draw = (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 (); if (DRAW_MOON_POSITION) { ii = NX-moon_position-1+ishift; if (ii > NX) ii -= NX; else if (ii < 0) ii += NX; glColor3f(fade_value, fade_value, fade_value); glBegin(GL_LINE_STRIP); glVertex2i(ii, 0); glVertex2i(ii, NY); 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, notdraw, draw_bc=1; double xyz[3], ca; if (NON_DIRICHLET_BC) draw_bc = (xy_in[i*NY+j])&&(xy_in[iplus*NY+j])&&(xy_in[i*NY+jplus])&&(xy_in[iplus*NY+jplus]); // 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); // if (FLOODING) draw = (wsphere[i*NY+j].indomain)||(phi[i*NY+j] >= wsphere[i*NY+j].altitude); if (FLOODING) draw = wsphere[i*NY+j].draw_wave; // else draw = ((TWOSPEEDS)||(xy_in[i*NY+j])); else draw = (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); } if (FLOODING) { glBegin(GL_TRIANGLE_FAN); if (ij_to_sphere(i, j, *wave[i*NY+j].p_zfield[movie], wsphere, xyz, wsphere[i*NY+j].draw_wave)) draw_vertex_sphere(xyz); if (ij_to_sphere(iplus, j, *wave[iplus*NY+j].p_zfield[movie], wsphere, xyz, wsphere[iplus*NY+j].draw_wave)) draw_vertex_sphere(xyz); if (ij_to_sphere(iplus, jplus, *wave[iplus*NY+j+1].p_zfield[movie], wsphere, xyz, wsphere[iplus*NY+j+1].draw_wave)) draw_vertex_sphere(xyz); if (ij_to_sphere(i, jplus, *wave[i*NY+j+1].p_zfield[movie], wsphere, xyz, wsphere[i*NY+j+1].draw_wave)) draw_vertex_sphere(xyz); glEnd (); } else if (draw_bc) { notdraw = (!draw); glBegin(GL_TRIANGLE_FAN); if (ij_to_sphere(i, j, *wave[i*NY+j].p_zfield[movie], wsphere, xyz, notdraw)) draw_vertex_sphere(xyz); if (ij_to_sphere(iplus, j, *wave[iplus*NY+j].p_zfield[movie], wsphere, xyz, notdraw)) draw_vertex_sphere(xyz); if (ij_to_sphere(iplus, jplus, *wave[iplus*NY+j+1].p_zfield[movie], wsphere, xyz, notdraw)) draw_vertex_sphere(xyz); if (ij_to_sphere(i, jplus, *wave[i*NY+j+1].p_zfield[movie], wsphere, xyz, notdraw)) 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, jmax; double observer_angle, angle2; blank(); if (refresh) { compute_wave_fields(phi, psi, xy_in, zplot, cplot, wave); if (SHADE_3D) compute_light_angle_sphere(phi, xy_in, wave, wsphere, movie, TRANSPARENT_WAVE); else if (SHADE_2D) compute_light_angle_sphere_2d(xy_in, phi, wave, wsphere, movie, TRANSPARENT_WAVE); 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; // jmax = NY-25; jmax = NY-3; // 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<=jmax; 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=0; j<=jmax; 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=0; j<=jmax; 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=0; j<=jmax; 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); } /* North pole */ for (i=0; iimin; i--) for (j=jmax; 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=jmax; 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=jmax; 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=jmax; 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=jmax; 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 (i=NX-2; i>=imin-1; i--) for (j=jmax; 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); }